Wednesday, December 28, 2011

Windows 8 Slate Review

About a week ago, I purchased a Samsung Series 7 Slate PC to learn more about the Windows 8 operating system and to test applications I will be developing primarily with C# and Xaml. The laptop ships with Windows 7 installed, but I quickly wiped the existing install and overlaid it with Windows 8. The process for the most part went smoothly. I had to acquire some Windows 7 drivers and install them in compatibility mode in order for the tablet to recognize orientation changes, and I still cannot get the hardware Windows start button or the accelerometer to work. I expected some issues like this as Windows 8 is still a preview OS.

I’ve used the combination of the slate and the operating system quite heavily over the past week and I wanted to take the time to share my impressions in a post while they are still fresh. I’m trying to focus this review more on the OS itself and will call out where I think there are substantial hardware differences.

Summary

Overall, I like it. I’ll preface that with the statement that I am a developer so my opinion is certainly biased compared to what consumers might think. The OS provides the perfect balance between a “total slate experience” which I consider to be watching movies, casual browsing, email, and news readers, and “power user features” like developing software or drilling into a complex Excel spreadsheet. All it takes is a simple external keyboard to efficiently write books and articles and even build software. While the new OS is in beta form and there are not many native applications to choose from, the backwards compatibility makes it possible to install any number of existing touch solutions.

Let me break down where this opinion comes from. I’ll start with the cons.

The Bad

  • Price – this is what I believe still stands as the greatest barrier to general adoption by consumers. The price point is just too high. The idea it can run all of Windows may be appealing to businesses, but not to the average consumer who is comparing this against Android tablets, iPads, and newcomers like the Kindle Fire. If you pay a competitive price for a Windows slate today, you get an inferior product. The Samsung performs well but also is priced well above the nearest competition at well over $1,000.
  • Power – unfortunately I have yet to work with an Atom-based slate that performs well. My standard is to pull up Netflix and run a high definition movie full screen. On a Windows tablet this does several things. First, it loads the Silverlight plug-in and extends the browser environment, and second, it tests the combination of processing that takes place in the Netflix app and the graphics processing happening through the hardware. Unfortunately most of the devices fail miserably for this, and you have to go to an i-series chip. That gives you the power, but means a thicker tablet with a fan and vents.
  • Battery – this ties into the issues listed previously. While the battery is certainly longer than a lot of lap tops – I was watching full screen movies in HD and it lasted hours without draining – it does not go anywhere near the 8 – 10 hours users experience with competing tablets. I believe this is due mainly to the processor architecture and while the alternate system-on-chip processors probably will break this barrier, they will need to perform far better than what I’ve seen so far to make the experience worthwhile.
  • Start Menu – I like the start menu. The concept of live tiles is great, because it turns the start menu into an interactive, “at a glance” dashboard. However, it is not without flaws. First, “grouping” tiles together really doesn’t do anything for me except maybe organize them visually. I want a functional way to group so I can drill in. The idea is as few taps and swipes as possible, which means drilling down, not swiping across. Second, everything ends up as a tile. This may be fine for me, a developer, who knows how to unpin and organize but will be overwhelming to the average consumer. If an install like Office drops fifteen apps, why not organize into a folder by default and have the folder appear on the start menu, and let me drill down and bring common applications back to the top as needed? After installing everything I needed to make the slate productive for me – Office, Live Essentials, etc. – the start menu became so huge I found myself doing nothing but swiping and swiping to get to what I needed.
  • Task Switching – Give me a break. Two experiences? The side swipe is fun to demo and cool when you have two applications, but come on, who really only ever runs two applications? After loading up about five or six applications, continuously swiping across to find what I want is ridiculous. What’s worse, there is no integration with the desktop applications. If you have Explorer, Word, and Outlook running, you get one swipe for “Desktop” and then must ALT+TAB to go between your desktop apps, then either swipe or hit the start button to get back into the Metro applications. Not a good experience. Why not provide an aero-like view or cover flow style preview of the applications when I swipe so I can quickly tap on the one I want? Even a grid of thumbs would be preferable to multiple manual swipes.
  • Consistency – While I like the features and customization options that are available, it’s a little weird that half of the control panel is Metro and the other half dumps you to the desktop and back into the familiar Windows 7 dialogs. Why not finish the experience and make it consistent? You also are shifted to the desktop every time you launch a desktop application, which annoyed me at first but I found I quickly got used to and didn’t mind as much – I’m more irritated about the lame experience trying to swap tasks
  • Ribbons – I get it. The ribbon is the Microsoft UI widget of the future. It’s appearing everywhere. I like the ribbon, and it makes sense in a lot of applications. While I resisted the newer Office releases in the beginning because of the new interface, after using it for years now I’ve come to enjoy it. But here’s a news flash: it’s not the same on a slate. On a touch-based device I want to have context where I touch. That means if I’m navigating the file system, I want to be able to tap on a file or folder and right there see my options and quickly tap through. It’s not a smooth experience to tap down there and then look up there to the ribbon and then find the right place on the ribbon to tap. May have worked well on the desktop, not so fun on the slate. This is weird too because it gives the impression of OS schizophrenia. In the “Metro” portion I have an experience highly tailored to touch that feels right, responsive, and is enjoyable. In the file system explorer for the same OS, suddenly I’m forced to a completely different paradigm that doesn’t feel natural at all. Was it two entirely different teams working on these features? Why are they so different? I don’t buy that it’s because “it’s part of the desktop experience” – no, it’s not. Anything I can reach in my slate is part of the slate experience, whether or not it happens to fall into what was the traditional desktop.

The Good

  • Boot Time – while some may say competitive slates boot quickly, the fact that this boots so fast and provides full-blown Windows capabilities to me is amazing. My slate literally boots in seconds – that’s from a complete shut down. It is fantastic and I no longer dread turning on my machine because I have to figure out something to kill time while it’s booting – it’s that fast.
  • Windows – some people argue this is not a feature and may be a detriment to slates, but I disagree. The fact it is full-blown Windows and not a trimmed-down version is why many customers want a Windows-based slate. It was a key driver for the project I did with Rooms-to-Go. I love it. I installed Office and can easily navigate through Word documents, PowerPoint, and Excel. Sure, sometimes it requires using a keyboard, but the option is there. It gives me my built-in Windows security, allows me to use policies and gives me access to a ton of software that simply isn’t available on competing slates.
  • Backwards Compatibility – while this is just a beta the backwards compatibility so far has been outstanding. I’ve not had an issue installing any Windows 7 productivity software I wish to use. Even drivers for the Slate that aren’t yet available in Windows were successfully installed using compatibility mode. My Amazon Kindle for PC application works beautifully so there’s no need to pick up the hardware, I’ve got my “Kindle” right here. I’ve also had a lot of fun playing with the applications that ship with the Microsoft Touch Pack for Windows 7 that uses Microsoft Surface technology.
  • Silverlight – there was a lot of fuss about Silverlight and it being a dead-end but I’m happy to share it is not only fully supported on the slate, but shines. Some of the best applications I have aren’t written for Windows 8; they are written in Silverlight and run fine as Out-of-Browser (OOB) applications on the slate. Some that stand out are the USA Today Windows Touch application, Mosaic by Tribune, and Telerik’s Facedeck Silverlight Client for Facebook. Oh, did I mention I can just chill at night with headphones and watch my favorite Netflix movies in full screen high definition?
  • Metro – I like Metro. There are things that I believe could be improved, but to me the advantages include:
    • Live Tiles create a true “dashboard” and at-a-glance experience, showing me insights without having to open an application. The tiles just need a better way to organize them.
    • The Metro guidelines (no pop-ups, overlapping windows, etc.) make for a very crisp, clean, enjoyable experience. I am able to easily navigate between applications and they are very responsive. The task switching must be improved, however, and better integrated with the desktop experience.
    • Charms and Application Bars to me make sense and once you understand the gestures make it very easy and consistent to navigate within applications. I really found the slow swipe from the right to get a full menu is something I use a lot, and enjoy the at-a-glance signal, battery, and time in addition to quick-jumps to other areas.
  • Keyboard – the Windows 8 keyboard is awesome. It’s nice and big and easy to type. I have long, complicated passwords and tapping them out is a breeze. My only gripe is the fact that you have to switch to get the numeric keyboard which can slow that down. The highlights and sound provide just the right amount of feedback to make the typing feel natural. The split keyboard is awesome for some major thumb-typing while grasping the sides of the tablet.
  • Pen and Handwriting Recognition – the pen is very powerful. I wanted to spend some time with family while I was editing the final chapters of my Designing Silverlight Business Applications book, so I settled down in the family room with my slate and pen. To my surprise, I was able to be very productive. It was easy to highlight with the pen, and the handwriting recognition was superb – I very rarely had to correct it’s interpretation and my handwriting is abysmal. I was able to have a productive, casual editing session without lugging around a laptop or even pulling out a keyboard. The combination of handwriting and touch makes for a very powerful and productive experience.
  • Search – while I still feel the tiles could be better organized in the start menu, I love the integrated search. It’s fast and easy to use and the fact you can search within a context and even pass searches to other applications is awesome (sorry, can’t think of a better way to say it).
  • IE10 – this may be strange coming from someone who listed Silverlight as an advantage when the IE10 Metro implementation does not allow plug-ins, but let’s face it: 2011 was the year of HTML5 and it is rapidly growing with adoption. I have no qualms about switching to my desktop IE version to run Silverlight applications when most of them are OOB applications that I can launch with a single touch from the start menu anyway. For most web sites, the built-in IE10 browser is all I need. It provides a great browsing experience, renders well, and provides all of the interaction I need. I use the built-in browser often and enjoy the browsing experience – I’ve even started to use YouTube in HTML5 mode although not all videos are available and you have less control over the experience. I especially like being able to pin sites from IE10 to my start menu.

As you can see, there are a lot of pros to weigh against the cons. In summary, I’m very pleased with where the slate experience is going but I’m also concerned. I’m a power user – a developer – so I like falling back to heavy desktop applications, don’t mind doing a little extra to get around, and also am used to shelling out more dollars for my toys than average consumers might be willing to. I think the biggest obstacle to overcome is providing performance at a lower cost to increase value and get rid of fans and fat form factors. The Metro experience needs a bit of work before I think my grandmother, grandfather, or niece will be as comfortable with it as they are grabbing an iPad, but I don’t think it’s an impossible task. I’m very excited to see the upcoming beta release that is rumored for February 2012 to see how well Microsoft listened and what steps they were willing to take to improve the quality of the product.

Friday, December 9, 2011

Silverlight 5 Released: Myth vs. Fact

It is very exciting to see the release of Silverlight 5 today, despite all of the rumors flying around the Web. Read the original release announcement from the Silverlight Team here. This is proof positive the team made a commitment to release a new version by the end of the year and stuck to it. This release offers major functionality over prior releases and is something I believe has the potential to revolutionize development for line of business applications, or I wouldn't be writing a book about it. You can download the release here (note that sometimes the servers may take time to synchronize, so if you are not seeing the link, wait a little awhile and refresh ... it will eventually appear for you).

My blog has been covering this for quite some time so I thought it would make sense to recap the coverage I've already provided as well as address some myths vs. facts about this release.

First, a summary of articles I've posted that relate to Silverlight 5:

I will also be releasing a new version of my Jounce MVVM+MEF Framework that fully supports the new capabilities of Silverlight 5 over the next few weeks. You can download the latest source to preview this functionality and I'll consolidate into a 2.0 release probably right after the holidays.

Let's tackle some myths:

Myth: Silverlight is dead.

Fact: Silverlight 5 has just been released. The team has been working hard to implement new features and address issues uncovered through internal and external builds like the beta and release candidates. This release contains significant functionality that make it an ideal platform for building Line of Business applications. Microsoft has also promised to support this version through 2021. That's quite a bit of life!

Myth: Silverlight has no Future.

Fact: We're not sure if Silverlight will have a future release, as Microsoft has not formally addressed this and that is definitely a possibility. That doesn't mean it doesn't have a future. There are plenty of cases where the current version will meet the demands of users sufficiently to warrant future development. The next IDE slated for release, Visual Studio 11, has Silverlight support so the tools are not going away any time soon. Silverlight runs perfectly fine on the new Windows 8 desktop so applications developed using this version will not be obsolete when users move to Windows 8, although by all predictions Windows 7 is going to be around for a long, long time. The biggest enemy of Silverlight right now is not capability nor support, but speculation and rumor.

Myth: The Silverlight team gave up on Mac OSX, this release is for Windows/Internet Explorer only.

Fact: Silverlight 5 is fully supported on Mac OSX and across multiple browsers. The new 3D features rely on DirectX and therefore are not available on the Mac OSX platform, and p/Invoke/COM obviously does not make sense because there is no counterpart. All of the core features including interactivity, printing, etc. are all fully supported as demonstrated by the release candidate (RC). You can see the full list of supported browsers and platforms here.

Myth: Silverlight is no longer the optimal choice for platform reach

Fact: I believe this to be true when you extend reach to smartphones. For desktop applications that will traditionally run on Mac OSX, Windows, and Linux, I still see Silverlight 5 as the viable option for the first two. Obviously lack of Linux support rules that out but I have not found that to be an issue for line of business applications. Most businesses are still putting their heavy applications on Windows with a smaller percentage on Mac OSX and Silverlight provides phenomenal capabilities to build the application once and have it run on both platforms, even out-of-browser in occassionally disconnected scenarios. Silverlight is only a viable target for smartphones on the Windows Phone 7 platform. I don't believe this removes Silverlight as a player as it depends on the level of native touch you want for your application. A high-touch application will likely require developing with Silverlight for Windows Phone, Objective-C for iOS devices and Java for Android unless you are using a tool that provides multi-targeting like the Mono suite. On the other hand, if you can get away with less native touch and functionality, HTML5 is certainly a good option for building a mobile footprint once and having it function consistently across those surfaces. Keep in mind however that this does not mean you can build it once and have it run fine on your desktop targets - you'll still be developing different screens. The ability of Silverlight to connect to existing services like REST and WCF end points still makes it a very viable option for the desktop presentation layer even if the mobile footprints are written using an HTML5-based solution.

Conclusion

It's out, it's loaded with features, and it still has plenty of life left in it. Go out and grab the latest version of Silverlight and see for yourself! I'm interested in all comments and feedback below. Thanks!

Jeremy Likness

Sunday, November 20, 2011

Handling Extremely Large Data Sets in Silverlight

While writing Chapter 14 of my book, Designing Silverlight Business Applications: Best Practices for Using Silverlight Effectively in the Enterprise (Microsoft .NET Development Series) I focused on an area that is quite common with line of business applications: extremely large data sets. In the example I generated almost 1,000,000 contact rows to illustrate how they would be managed by the Silverlight client. Like many software problems, there are many solutions; here is an excerpt of the three I demonstrated in the book.

All of these solutions use the Entity Framework for data access. How that data access is projected to the client is illustrated bythree different patterns: OData (the straight services, not the checkbox on the WCF RIA Services tab), WCF RIA Services, and using the MVVM pattern. To simplify the examples I'm only focused on reads here. Writes do add a layer of complexity and change tracking, but I argue that the problem to solve there is not how to manage a large data set because anything the user actually interacts with is going to be a smaller order of magnitude.

RESTful OData

It's extremely easy to expose an OData end point from a .NET web application. You can simply add a new WCF Data Service and then define what it has access to. In this example I have a Contact table that looks like this:

After generating the data model, the Entity Framework provides this in my ContactModel space:

The underlying context that was generated is called ContactEntities so for my OData service I can simply point to the underlying context and specify which collections are available and what access rights the client should have:

public class ContactOData : DataService<ContactsEntities>
{
    public static void InitializeService(DataServiceConfiguration config)
    {            
        config.SetEntitySetAccessRule("Contacts", EntitySetRights.AllRead);
        config.SetEntitySetPageSize("Contacts", 20);
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    }
}

Note I've specified a page size of 20 records so that the service doesn't return all 1,000,000 records at once. When I hit the service endpoint, I get this:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<service 
   xml:base="http://localhost:59389/ContactOData.svc/" 
   xmlns:atom="http://www.w3.org/2005/Atom" 
   xmlns:app="http://www.w3.org/2007/app" 
   xmlns="http://www.w3.org/2007/app">
  <workspace>
    <atom:title>Default</atom:title>
    <collection href="Contacts">
      <atom:title>Contacts</atom:title>
    </collection>
  </workspace>
</service>

This is all a client needs to begin navigating entities as the location of the first collection, Contacts, is clearly specified. We can now navigate to the contacts and receive something like this:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed 
   xml:base="http://localhost:59389/ContactOData.svc/" 
   xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" 
   xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" 
   xmlns="http://www.w3.org/2005/Atom">
  <title type="text">Contacts</title>
  <id>http://localhost:59389/ContactOData.svc/Contacts</id>
  <updated>2011-11-20T16:24:05Z</updated>
  <link rel="self" title="Contacts" href="Contacts" />
  <entry>
    <id>http://localhost:59389/ContactOData.svc/Contacts(1)</id>
    <title type="text"></title>
    <updated>2011-11-20T16:24:05Z</updated>
    <author>
      <name />
    </author>
    <link rel="edit" title="Contact" href="Contacts(1)" />
    <category term="ContactsModel.Contact" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
    <content type="application/xml">
      <m:properties>
        <d:Id m:type="Edm.Int32">1</d:Id>
        <d:LastName>Alford</d:LastName>
        <d:FirstName>Lucius</d:FirstName>
        <d:Address>Ap #363-9702 Sit Rd.</d:Address>
        <d:City>Jordan Valley</d:City>
        <d:State>CO</d:State>
        <d:Email>[email protected]</d:Email>
      </m:properties>
    </content>
  </entry>
  ...
  <link rel="next" href="http://localhost:59389/ContactOData.svc/Contacts?$skiptoken=20" />
</feed>

Notice that it follows the standard Atom format. Every entry has a clear location including where to go to post updates ("edit"). The full data set includes 20 entries and then specifies a link to grab the next page.

Adding this to the Silverlight client is easy. You can add a service reference, discover it in the current solution and the client will be wired for you automatically. Using a DataGrid that auto-generates the columns, I can write the following code behind:

public partial class ODataClient
{
    private readonly DataServiceCollection<Contact> _contacts;
    private readonly ContactsEntities _context;
    private DataServiceQueryContinuation<Contact> _nextPage;

    public ODataClient()
    {
        InitializeComponent(); 
        _context = new ContactsEntities(new Uri("../ContactOData.svc", UriKind.Relative));
        _contacts = new DataServiceCollection<Contact>();
        _contacts.LoadCompleted += ContactsLoadCompleted;
        var query = _context.Contacts.IncludeTotalCount();
        _contacts.LoadAsync(query);
    }

    void ContactsLoadCompleted(object sender, LoadCompletedEventArgs e)
    {
        _nextPage = _contacts.Continuation;

        if (_nextPage == null)
        {
            NextPage.IsEnabled = false;
        }

        TotalCount.Text = e.QueryOperationResponse.TotalCount.ToString();
        Count.Text = _contacts.Count.ToString();
        dgContacts.ItemsSource = _contacts;
        dgContacts.UpdateLayout();            
    }

    void Button_Click(object sender, RoutedEventArgs e)
    {
        _contacts.LoadNextPartialSetAsync();
    }
}

The fields hold references to the service. It is instantiated with a relative path to the end point. The query is extended to include a total count of records so it can be used to calculate page sizes, and the link to the next page is retrieved and stored for the continuation. When the user clicks the button to load the next block of records, the continuation is called to fetch the next page. The grid and button look like this:

The example is a quick-and-dirty way to parse the OData stream but can be extended to include a proper paging control (instead of simply expanding the grid) as well as edit and update functionality. Now I'll show you how to do the same thing using WCF RIA. The obvious advantage with WCF RIA is that the code projection removes most of the manual steps you need to take.

WCF RIA Services

The domain service for WCF RIA simply maps operations like queries to the corresponding LINQ-to-Entities commands. This example is read-only so the full implementation looks like this:

[EnableClientAccess]
public class ContactService : LinqToEntitiesDomainService<ContactsEntities>
{       
    public IQueryable<Contact> GetContacts()
    {
        return ObjectContext.Contacts.OrderBy(c => c.Id);
    }
}

The service derives from the context for the contact database and the query simply orders the items to allow paging (the result set must be deterministic for paging to work). That's it on the server side. A metadata class is also generated that you can use to apply data annotations to specify column names, validations, etc.

The client automatically has the WCF RIA classes "projected" which is a fancy way of saying the code is generated for the client. In fact, WCF RIA handles so much plubming that the WCF RIA client doesn't have to have a single line of code-behind. Instead, you can drop in a domain data source:

<riaControls:DomainDataSource 
   AutoLoad="true" 
   d:DesignData="{d:DesignInstance Web:Contact, CreateList=true}"                             
   Height="0" 
   Name="contactDataSource" 
   QueryName="GetContacts" 
   Width="0"
   LoadSize="60" 
   PageSize="20">
    <riaControls:DomainDataSource.DomainContext>
        <Web:ContactContext/>
    </riaControls:DomainDataSource.DomainContext>
</riaControls:DomainDataSource> 

By convention, ContactService is renamed to ContactContext on the client. The domain data service uses context as its data source. It is given some design-time data to generate the grid properly, the query to get the list of contacts is specified along with how many records to pre-fetch and how many to show on a page. A DataGrid simply binds to this as the data source along with a DataPager:

<sdk:DataGrid AutoGenerateColumns="True" 
   ItemsSource="{Binding ElementName=contactDataSource, Path=Data}"/>
<sdk:DataPager 
   Source="{Binding ElementName=contactDataSource, Path=Data}"/>

And that is it! It will handle computing total records, managing pages, and generating the grid. The result looks like this:

That provides what I would call the ultimate rapid development experience. It can literally take just five minutes to create the Entity Framework model, map the domain service, then drop the domain data source and grid controls on the client to have a fully functional application. Of course, as a developer you may want more control over how the application works and perhaps need to make sure this fits within your existing patterns. The most popular pattern for Silverlight development is Model-View-ViewModel (MVVM) so here is a quick view model to make it work:

MVVM

Instead of relying on WCF RIA you can abstract the data access layer using a pattern such as repository. This isn't a full implementation but the simple interface looks like this:

public interface IRepository
{
    void ProcessPage(int page, int pageSize, 
       Action<IEnumerable<Contact>> callback);
    int GetTotalPages(int pageSize);
}

Now you can use a mock to test access to the repository and even swap layers if or when it is necessary. Here is an implementation that works directly with WCF RIA:

public class Repository : IRepository
{
    private int _totalCount;
    private readonly ContactContext _contactContext = new ContactContext();

    public Repository()
    {
        var query = (
                        from c
                            in _contactContext.GetContactsQuery()
                        select c).Take(1);
        query.IncludeTotalCount = true;
        _contactContext.Load(
            query,
            callback => { _totalCount = callback.TotalEntityCount; }, null);
    }

    public void ProcessPage(int page, int pageSize, 
        Action<IEnumerable<Contact>> callback)
    {
        var take = pageSize;
        var skip = pageSize*(page - 1);
        var query = (from c in _contactContext.GetContactsQuery()
                        select c).Skip(skip).Take(take);
        query.IncludeTotalCount = true;
        _contactContext.Load(
            query,
            cb =>
                {
                    _totalCount = cb.TotalEntityCount;
                    callback(cb.Entities);
                }, null);
    }

    public int GetTotalPages(int pageSize)
    {
        return (_totalCount/pageSize) + 1;
    }
}

Note when the repository is created, it queries for a single item just to grab the full count for computing the page size. This is updated each subsequent call for a page. The call to grab the page computes how many records to skip and take for a page and then executes the query.

A simple view model can be constructed that uses the repository:

public class ViewModel : INotifyPropertyChanged
{
    private List<Contact> _contacts = new List<Contact>();
    private readonly IRepository _repository;

    public int CurrentPage { get; set; }

    public int TotalPages { get; set; }

    public IActionCommand NextPage { get; set; }

    public IActionCommand PreviousPage { get; set; }

    public IEnumerable<Contact> Contacts
    {
        get
        {
            if (_contacts.Count == 0)
            {
                Refresh();
            }

            return _contacts;
        }

        set { _contacts = new List<Contact>(value); }
    }
}

It exposes current page, total pages, commands to paginate and a list of the current contacts. The constructor sets up the initial conditions and sets a dummy page and page size in the design view:

public ViewModel()
{
    Contacts = new List<Contact>();
    NextPage = new ActionCommand<object>(obj => GoToNextPage(),
                                            obj => CurrentPage < TotalPages);
    PreviousPage = new ActionCommand<object>(obj => GoToPreviousPage(),
                                            obj => CurrentPage > 1);

    if (!DesignerProperties.IsInDesignTool)
    {
        CurrentPage = 1;
        _repository = new Repository();                
    }
    else
    {
        CurrentPage = 2;
        TotalPages = 10;
    }
}

The Refresh method fetches the current page:

private void Refresh()
{
    _repository.ProcessPage(
        CurrentPage,
        20,
        cb =>
            {
                TotalPages = _repository.GetTotalPages(20);
                _contacts = new List<Contact>(cb);
                RaiseChanges();
            });
}       

The commands simply change the current page and call refresh. For example, the command to advance by one page:

private void GoToNextPage()
{
    CurrentPage++;
    Refresh();
}

Now the view model can be bound to a grid. In this example, the current page and page count are used to construct a very simple paging control. All of the information you need to make a full-blown control is available. The MVVM-based view looks like this:

The ease with which it is possible to navigate a large data set from the client is one of the reasons I believe Silverlight is still a strong player in the Line of Business application space. More details and the full source code for this example will be available when my book publishes. As of this writing on November 20, 2011 it is discounted over 40% on Amazon when you pre-order a copy from here. Thanks!

Jeremy Likness

Friday, October 21, 2011

Using Jounce Navigation to Create OOB Child Windows in Silverlight 5

One of the reasons I prefer to manage navigation as an event, rather than a strongly typed interface or handler, is because it allows for so much flexibility and extensibility in the navigation pipeline. In my Jounce framework, for example, the basic navigation event simply wires up an instance of a view to a view model and makes no presumptions about where that view belongs - it leaves positioning the view to the developer. The region manager simply listens for navigation events and passes the views off to region adapters without worrying about how they are wired, so it automatically handles the view simply by extending the pipeline by listening for the message as well. This same model makes it incredibly simple to place views in child windows using the new Silverlight 5 Out-of-Browser feature.

The first thing I'll do is create a controller to listen to navigation messages. It will expect a specific parameter to be passed that indicates when the view should be passed to a window. If that parameter exists, it will use parameters for height, width, and title to spin up the new window. A more complete implementation would store those literals as constants. Here is the shell for the class that implements the listener and subscribes to it:

[Export]
public class WindowController : IEventSink<ViewNavigationArgs>,
                                IPartImportsSatisfiedNotification
{
    [Import]
    public IEventAggregator EventAggregator { get; set; }

    [Import]
    public IViewModelRouter Router { get; set; }
    
    public void OnImportsSatisfied()
    {
        EventAggregator.SubscribeOnDispatcher(this);
    }

Now the handler. The handler will check the parameters for a special "OpenInWindow" parameter that must be set to true. It will only respond when that's the case, and everything else goes through the normal view routing. Because the project uses region management, there is no conflict because these views will not be routed to specific regions. First, if the parameter doesn't exist, the method simply returns. Note the use of the Jounce extension methods that conveniently cast the parameter to a specific type:

public void HandleEvent(ViewNavigationArgs publishedEvent)
{
    var parms = publishedEvent.ViewParameters;
    if (!parms.ContainsKey("OpenInWindow") ||
        !parms.ParameterValue<bool>("OpenInWindow"))
    {
        return;
    }
}

Next, the router is used to get the view model that is mapped to the view, then spin up a non-shared instance of the view and view model. This allows multiple instances to be created and therefore supports multiple windows with the same view/view model combination. The method to get the view takes an object for a parameter that it will set to the data context of the view. Jounce is smart enough to recognize when that object is a Jounce view model, and will take the additional steps of wiring in visual states and calling the InitializeVm and ActivateView methods on the view model. Notice that the parameters are passed into the view model as well - Jounce will pass these in when it attaches the view model to the view.

var viewModelTag = Router.GetViewModelTagForView(
    publishedEvent.ViewType);
var viewModel = Router.GetNonSharedViewModel(viewModelTag);
var view = Router.GetNonSharedView(
    publishedEvent.ViewType,
    viewModel,
    publishedEvent.ViewParameters 
    as Dictionary<string, object>);

Finally, the window is opened with the view set as the content:

new Window
        {
            Title = parms.ParameterValue<string>("WindowTitle"),
            Width = parms.ParameterValue<int>("WindowWidth"),
            Height = parms.ParameterValue<int>("WindowHeight"),
            Content = view,
            Visibility = Visibility.Visible
        };

That's all there is to it. The controller must be imported somewhere to begin listening for events. Then you can simply export the view with a tag like [ExportAsView("MyView")] and publish the navigation using the Jounce extension methods to turn the view tag into a navigation event and add parameters:

var window = "MyView".AsViewNavigationArgs()
    .AddNamedParameter("OpenInWindow", true)
    .AddNamedParameter("WindowTitle", "My View Title")
    .AddNamedParameter("WindowHeight", 300)
    .AddNamedParameter("WindowWidth", 600);
EventAggregator.Publish(window);

Of course you can get even more clever with how you obtain the title or set the sizes, and now opening a child window is not only as easy as publishing an event, but also fully testable in your view models because you can mock the controller for testing.This technique is demonstrated in detail in the chapter about OOB applications in Designing Silverlight Business Applications: Best Practices for Using Silverlight Effectively in the Enterprise (Microsoft .NET Development Series).

Jeremy Likness

Tuesday, October 11, 2011

Quick Tip: Design-Time Views for Regions

If you've worked with the Region Management pattern before, one source of frustration can be the lack of a design-time view. While you can compose individual views to be designer-friendly, the aggregate views that mark regions often end up devoid of anything useful. A simple little trick, however, can change that.

You may be familiar with creating design-friendly view models, but the extensions for Blend work the same with views. For example, consider a main page that has a layout divided into regions that are marked by content controls, like this:

<ContentControl  VerticalAlignment="Center" Margin="20 0 0 0" region:ExportAsRegion.RegionName="SortRegion"/>

There may be one or many views that can fit in the content control, but having it completely empty just doesn't make a good design experience as you cannot tell how components will fit together. With just a little tweak, however, you can change that. Consider this approach instead:

<ContentControl  d:DataContext="{d:DesignInstance Views:SortView,IsDesignTimeCreatable=True}" Content="{Binding}"
VerticalAlignment="Center" Margin="20 0 0 0" region:ExportAsRegion.RegionName="SortRegion"/>

This simple change has done a few things. First, it binds an instance of a reference view to the data context of the control. The binding will only be invoked in the designer and will not be impacted during runtime. Second, the content control is set to the binding, which is the view in the designer, causing it to render the content. With just that simple tweak you now can see how a view will fit into the region!

The view is created directly and is not recursively wired into the design-time experience, so any design-time data within the referenced view will not appear. To get around that you'll need to create a mock view instead and create an instance of that. If the view isn't activated right away, the content control will end up hosting whatever it inherits from the data context of its parents, which may have undesired side effects, but in most cases you will likely activate the view that routes to the region before any artifacts are visible to the end user. If you need to, you can also manually set the data context (the "real" data-context, not the design-time one) to {x:Null} to prevent it from inheriting anything at runtime.

Finally, there is always the option to use a custom markup extension if you really need a more robust view. For me, the trade-off of making a simple tweak is worthwhile.

Here's the design-time view of a small control, showing sample data:

Here's the main page with nothing but regions and design-time views. While the design-time data isn't wired, the views fall into place and I can get a sense of the overall layout (click to see a larger image):

And finally this is the same application at runtime:

So now you don't have to suffer from regions turning their backs on your designer. Enjoy!

Jeremy Likness

Friday, October 7, 2011

Using Visual States to Set Focus on a Control

A common problem encountered in Silverlight applications is how to set the focus properly when transitioning between controls. For example, in the reference application I'm writing for the book Designing Silverlight Business Applications there is the option to either edit an existing record or create a new one. The result of clicking the appropriate button is a panel overlay that zooms into view. Obviously, it makes sense once the panel is rendered to set the focus to the first field so the user can simply begin entering information.

If the control was managed by adding and removing it from the visual tree, the solution would be simple. This is the perfect example I have of not resorting to exotic solutions to a simple problem. The focus problem is not a business problem, it is a user interface problem. It's perfectly valid to wire a loaded event to the control, name the field that requires focus, and call the Focus method on that field when the parent control is loaded. This is an example where even with MVVM, it just doesn't make sense to solve the problem in the view model when it is so simple to add the code-behind. This doesn't change my ability to have a design-time data or to test my view model. It also works well because if I reuse the same control, the loaded event will still fire every time it is added back to the visual tree.

I mentioned this would be simple if the control was managed based on adding and/or removing it ... but that's not how I manage it. Instead, I use the Jounce framework to position it in a region and show or hide it by changing the visual state. What's nice about this is that I can have a state based on the action that the view model is invoked with, for example "New" for a new item, "Edit" to edit an existing item, and "Closed" when the view should go away. These actions are all handled by setting the visual state, so there is no convuluted logic to set visibility properties or wire any other logic. The visual state is wired as a delegate by Jounce, so when I test my view models I can simply mock the delegate and confirm the transition is set without actually loading a view. I can also set different types of animations, such as zooming the control from the "new" button for one mode and having it fade in from the grid in the other mode.

The problem with this approach is that the control never leaves the visual tree. Everything is managed by visual states, so the "Closed" state simply sets the visibility to collapsed, which keeps it in the visual tree but just ignores any rendering or hit testing logic. So how can I effectively set the focus based on a visual state transition?

I've read some interesting solutions that create a special "reverse behavior" that wires to the control and can be data-bound to a property on the view model. The view model can simply set the property and the data-binding will force the action to happen. Personally, I think this is a fine approach but I don't see the need for my view model to have to understand that part of the UI concern is setting a focus. I wanted to approach it from a UI-centric view and only involve the view model if needed.

It turns out the solution is quite simple. All I need to do is create a control to help manage the focus. Call it the "focus helper" and start with a dependency property that points to another control:

public class FocusHelper : Control
{
    public static readonly DependencyProperty TargetElementProperty =
        DependencyProperty.Register(
            "TargetElement",
            typeof (Control),
            typeof (FocusHelper),
            null);
       
    public Control TargetElement
    {
        get { return (Control) GetValue(TargetElementProperty); }
        set { SetValue(TargetElementProperty, value); }            
    }

}

The reason this helper derives from Control is because I want to be able to place it inside a grid. The next thing I'll do is expose a property to set the focus. First, the details of the property itself:

public static readonly DependencyProperty SetFocusProperty =
    DependencyProperty.Register(
        "SetFocus",
        typeof(bool),
        typeof(FocusHelper),
        new PropertyMetadata(false, FocusChanged));

public bool SetFocus
{
    get { return (bool) GetValue(SetFocusProperty); }
    set { SetValue(SetFocusProperty, value);}
}

You'll notice that I set the property metadata to invoke a callback whenever the property changes. In that call, I want to see if I have a control set. If I do, then I'll simply call the Focus method for that control, then reset the flag back to false so it can fire again if it is set in the future;

private static void FocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var targetElement = d.GetValue(TargetElementProperty) as Control;
    if (targetElement == null || e.NewValue == null || (!((bool) e.NewValue)))
    {
        return;
    }
    targetElement.Focus();
    d.SetValue(SetFocusProperty, false);
}

Now I've got a handy control that will fire the focus method on a target element whenever its own SetFocus property is set to true. It's easy to wire it to whatever input control I want, in this case a TextBox called "Title":

<Behaviors:FocusHelper x:Name="FocusHelper" 
       TargetElement="{Binding ElementName=Title}"/>
<TextBox x:Name="Title" Text="{Binding Title,Mode=TwoWay}"/>

Doing the binding this way also makes it Blend-friendly. If the focused element needs to change, the designer will be able to click on the binding and target the property all through the designer without touching the Xaml. The last step is to update the visual state. When the control is shown, the visibility is set to "Visible." I simply add another entry to the storyboard that sets the focus property to "true":

<VisualState x:Name="New">
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" 
                     Storyboard.TargetProperty="(UIElement.Visibility)">
            <DiscreteObjectKeyFrame KeyTime="0:0:0">
                <DiscreteObjectKeyFrame.Value>
                    <Visibility>Visible</Visibility>
                </DiscreteObjectKeyFrame.Value>
            </DiscreteObjectKeyFrame>
        </ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusHelper" 
                      Storyboard.TargetProperty="(FocusHelper.SetFocus)">
                <DiscreteObjectKeyFrame KeyTime="0:0:0">
                    <DiscreteObjectKeyFrame.Value>
                        <System:Boolean>true</System:Boolean>
                    </DiscreteObjectKeyFrame.Value>
                </DiscreteObjectKeyFrame>
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>
</VisualState>

And that's it ... now any time I set the control to a visual state that makes it appear, the focus is set to the input control of my choice and the user is able to start typing or tabbing between fields right away. To learn more about the application, order your copy of Designing Silverlight Business Applications and read how it was constructed with access to the full source code.

Jeremy Likness

Wednesday, September 28, 2011

The Top 10 Over-Engineering Mistakes in Silverlight Applications

Several weeks ago, I tweeted that a lot of people appear to be making their software far more complex than it needs to be. I was asked to elaborate and share details. The comment was prompted by reading dozens of forum posts by desperate developers in over their heads trying to apply enormous and complex frameworks to applications that really could use simple, straightforward solutions. I've witnessed this in projects I've taken over and worked with other developers and of course am guilty of making these same mistakes myself in the past. After years of working with line of business Silverlight applications, and speaking with several of my colleagues, what I thought might be a "Top 5" turned out to be a "Top 10" list. This is not necessarily in a particular order, but here are the ten most common mistakes I see developers make when they tackle enterprise Silverlight applications (and many of these apply to applications in general, regardless of the framework).

1. YAGNI

YAGNI is a fun acronym that stands for, "You aren't going to need it." You've probably suffered a bit from not following YAGNI and that is one mistake I've definitely been guilty of in the past. YAGNI is why my Jounce framework is so lightweight, because I don't want to have another bloated framework with a dozen features when most people will only ever use one or two. YAGNI is violated by the framework you build that has this awesome policy-based logging engine that allows dynamic configuration and multiple types of logs ... even though in production you always dump it to the same rolling text file. YAGNI is violated by the complex workflow you wrote using the Windows Workflow Engine ... when you could have accomplished the same thing with a dozen lines of C# code without having to spin up a workflow process. Many of the other items here evolve around YAGNI.

Learn how to avoid these mistakes in my new book, Designing Silverlight Business Applications: Best Practices for Using Silverlight Effectively in the Enterprise (Microsoft .NET Development Series)

A good sign that YAGNI is being violated is when the team spends three months building the "application framework" without showing a single screen. It has to be built just right with a validation engine, a configurable business rules engine, an XSLT engine and your own data access adapter. The problem is that trying to reach too far ahead into the project is a recipe for disaster. Not only does it introduce a bulk of code that may not be used and adds unnecessary complexity, but many times as the project progresses you'll find you guessed wrong and now have to go back and rewrite the code. I had a boss once who would throw up his hands in exasperation and say, "No, don't ask me for another refactoring." Often users only think they know what they want, and building software too far into the future means disappointment when they figure out they want something different after testing the earlier versions of the code.

Well-written software follows the SOLID principles. Your software should be made of small, compact building blocks. You don't have to boil the ocean. Instead, assume you aren't going to need it. That doesn't mean the logger or rules engine will never come into play, it just means you defer that piece of the software puzzle until it is relevant and comes into focus. Often you will find the users weren't really sure of what they really wanted, and waiting to place the feature until the software has been proven will save you lots of cycles and unnecessary overhead. Instead of pulling in the Enterprise Library, just implement an ILogger interface. You can always put the Enterprise Library behind it or refactor it later, but you'll often find that simple implementation that writes to the debug window is all you'll ever need.

2. Sledgehammer Framework Syndrome

This syndrome is something I see quite a bit with the Prism framework. I see a lot of questions about how to scratch your left ear by reaching around your back with your right arm using five layers of indirection. Contrary to what some people have suggested, I am a huge fan of Prism and in fact give quite a bit of credit to Prism concepts in Jounce. The problem is that while Prism provides guidance for a lot of features, few people learn to choose what features are relevant and most simply suck in the entire framework and then go looking for excuses to use the features. You don't have to replace all of your method calls with an event aggregator message and an application with five menu items doesn't always have to be chopped into five separate modules. I can't tell you how many projects I've seen pull in the Enterprise Library to use the exception handling block only to find there are only two classes that actually implement it and the rest do the same old try ... catch ... throw routine. Understand the framework you are using, and use only the parts that are relevant and make sense. If the source is available, don't even compile the features you aren't going to need ... there it is, YAGNI again.

The problem with pulling in the whole framework is what many of you have experienced. You jump into a new code base and find out there are one million lines of code but it just seems weird when the application only has a dozen pages. You started to work on a feature and find entire project libraries that don't appear to be used. You ask someone on the team about it, and they shrug and say, "It's working now ... we're afraid if we pull out that project, something might be broken that we won't learn about until after it's been in production for 6 months." So the code stays ... which is Not A Good Thing™.

3. Everything is Dynamic

The first question I often get about Jounce is "how do I load a dynamic XAP" and then there is that stare like I've grown a third eye when I ask "Do you really need to load the XAP dynamically?" There are a few good reasons to load a XAP dynamically in a Silverlight application. One is plug-in extensibility — when you don't know what add-ons may be created in the future, handling the model through dynamic XAP files is a great way to code for what you don't know. Unfortunately, many developers know exactly what their system will need and still try to code everything dynamic. "Why?" I ask. "Because it is decoupled." "But why is that good?" "Because you told me to follow the SOLID principles." The SOLID principles say a lot about clean separation of concerns, but they certainly don't dictate the need to decouple an application so much that you can't even tell what it is supposed to load.

Following SOLID means you can build the application as a set of compiled projects first, and then refactor modules into separate XAP files if and when they are needed. I mentioned one reason being extensibility. The other is managing the memory footprint. Why have the claims module referenced in your XAP file if you aren't going to use it? The thing is, there isn't much of a difference between delaying the creation of the claim view and the claim view model versus adding the complexity of loading it from a separate XAP file. If you profile the memory and resources, you'll find that most satellite XAP files end up being about 1% of the total size of the application. The main application is loaded with resources like images and fonts and brushes and controls, while the satellite XAP files are lightweight views composed of the existing controls and view models. Instead of making something dynamic just because it's cool, why not build the application as an integrated piece and then tackle the dynamic XAP loading only if and when it's needed?

4. Must ... Have ... Cache

Caches are great, aren't they? They just automatically speed everything up and make the world a better place by reducing the load on the network. That sounds good, but it's a tough sell for someone who actually profiles their applications and is looking to improve performance. Many operations, even with seemingly large amounts of data, end up having a negligible impact on network traffic. What's worse, a cache layer adds a layer of complexity to the application and another level of indirection. In Silverlight, the main option for a cache is isolated storage. Writes to isolated storage are slower than slugs on ice due to the layer between the isolated storage abstraction and the local file system.. Often you will find that your application is taking more time to compute whether or not a cached item has expired and de-serializing it from isolated storage than it would have taken to simply request the object from the database over the network. Obviously, there are times when a cache is required such as when you want the application to work in offline mode. The key is to build the cache based on need, and sometimes you may find that you aren't going to need it. As always, run a performance analysis and measure a baseline with and without the cache and decide based on those results whether or not the cache is necessary — don't just add one because you assume it will speed things up.

5. Optimistic Pessimistic Bipolar Synchronization

Synchronization is a problem that has been solved. It's not rocket science and there are great examples of different scenarios that deal with concurrency. Many applications store data at a user scope, so the "concurrency" really happens between the user and, well, the user. If you are writing an application that works offline and synchronizes to the server when it comes online, be practical about the scenarios you address. I've seen models that tried to address "What if the user went offline on their phone and updated the record, then updated the same record on their other offline phone then they went to their desktop in offline mode and updated the same record but the time stamp on the machine is off, and now both go online - what do we do?!" The reality is that scenario has about a 1 in 1,000,000 likelihood. Most users simply aren't offline that much and when they are, it's an intermittent exception case. Field agents who work in rural areas will be offline more often, but chances are they are using your application on one offline device, not multiples. It simply doesn't make sense to create extremely complex code to solve the least likely problem in the system, especially when it's something that can be solved with some simple user interaction. Sometimes it makes more sense to simply ask the user, "You have multiple offline updates. Synch with your phone or your desktop?" rather than trying to produce a complex algorithm that analyzes all of the changes and magically constructs the target record.

6. 500 Projects

I'm a big fan of planning your projects carefully. For example, it often does not make sense to include your interfaces in the same project as your implementations. Why? Because it forces a dependency. If you keep your interfaces (contracts) in a separate project, it is possible to reference them across application layers, between test and production systems, and even experiment with different implementations. I've seen this taken to the extreme, however, with applications that contain hundreds of projects and every little item is separated out. This creates a convoluted mass of dependencies and building the project can take ages. Often the separation isn't even needed because groups of classes are often going to be updated and shipped together.

A better strategy is to keep a solid namespace convention in place. Make sure that your folder structure matches your namespaces and create a folder for models, contracts, data access, etc. Using this approach enables you to keep your types in separate containers based on namespaces, which in turn makes it easy to refactor them if you decide that you do need a project. If you have a project called MyProject with a folder called Model and a class called Widget, the class should live in the MyProject.Model namespace. If you find you need to move it to a separate project, you can create a project called MyProject.Model, move the class to it and update references, and you're done - just recompile the application and it will work just fine.

Designing Silverlight Business Applications: Best Practices for Using Silverlight Effectively in the Enterprise (Microsoft .NET Development Series)

7. No Code Behind!

This is one that amazes me sometimes. Developers will swear MVVM means "no code behind" and then go to elaborate lengths to avoid any code-behind at all. Let's break this down for a minute. XAML is simply declarative markup for object graphs - it allows you to instantiate types and classes, set properties and inject behaviors. Code-behind is simply an extension of those types and the host class that contains them. The idea of MVVM is to separate concerns - keep your presentation logic and view-specific behaviors separate from your application model so you can test components in isolation and reuse components across platforms (for example, Windows Phone 7 vs. the new WinRT on Windows 8). Having business logic in your code-behind is probably NOT the right idea because then you have to spin up a view just to engage that logic. What about something completely view-specific, however? For example, if you want to kick off a storyboard after a component in the view is loaded, does that really have to end up in a view model somewhere? Why? It's view-only logic and doesn't impact the rest of the application. I think it's fine to keep concerns separated, but if you find you are spending 2 hours scouring forums, writing code and adding odd behaviors just so you can take some UI code and shove it into a view model, you're probably doing it wrong. Code-behind is perfectly fine when it makes sense and contains code that is specific to the view and not business logic. A great example of this is navigation on Windows Phone. Because of the navigation hooks, some actions simply make sense to write in the code-behind for the view.

8. Coat of Many Colors

Have you ever worked on a system where your classes wear coats of many colors? For example, you have a data base table that is mapped to an Entity Framework class, which then gets shoved inside a "business class" with additional behaviors, that is then moved into a lightweight Data Transfer Object (DTO) to send over the wire, is received using the proxy version of the DTO generated by the service client, and then pushed into yet another Silverlight class? This is way too much work just to move bits over the wire. Modern versions of the Entity Framework allow you to create true POCO classes for your entities and simply map them to the underlying data model. Silverlight produces portable code that you can share between the client and server projects, so when you define a service you can specify that the service reuses the type and de-serializes to the original class instead of a proxy object. WCF RIA Services will handle all of the plumbing for sharing entities between the client and the server for you. You know you are a victim of this problem if you ask someone to add a new entity into the mix and they moan for 10 minutes because they know it's going to take forever to build the various incarnations of the object. When there is too much ritual and ceremony involved with moving a simple entity from the server to the Silverlight client, it's time to step back and re-evaluate. In some cases it might make sense to keep the entities but use code-generation techniques like T4 templates to simplify the repetive tasks, but in many cases you can probably get away with reusing the same class across your entire stack by separating your models into a lightweight project that you reference from both sides of the network pond.

9. Navigation Schizophrenia

Are you building a web site in Silverlight, or an application? The presence of the navigation framework has led many projects down the path of using URL-driven navigation for line of business applications., To me, this is a complete disconnect. Do I use URLs in Excel? What does the "back" button mean in Word? The point is that some applications are well-suited to a navigation paradigm similar to what exists on the web. There is a concept of moving forward and "going back." Many line of business applications are framed differently with nested menus, multiple areas to dock panels and complex graphs, grids, and other drill-downs. It just doesn't make sense to try to force a web-browser paradigm on an application just because it is delivered over the web. Sometimes you have no choice - for example, navigation is an intrinsic part of the Windows Phone experience, and that's fine. Just make sure you are writing navigation based on what your application needs, rather than forcing a style of navigation on your application simply because there is a template for it.

10. Everything is Aggregated

The final issue is one that I've seen a few times and is quite disturbing. If you are publishing an event using the event aggregator pattern, and receiving the same event on the same class that published it, there's something wrong. That's a lot of effort to talk to yourself. The event aggregator is a great pattern that solves a lot of problems, but it shouldn't be forced to solve every problem. I've always been a fan of allowing classes communicate with peers through interfaces. I don't see an issue with understanding there is a view model that handles the details for a query, so it's OK to expose an interface to that view model and send it information instead of using the event aggregator. I still expose events on objects as well. For example, if I have a repository that is going to raise a notification when the collection changes, I'll likely expose that as an event and not as a published message. Why? Because for that change to be interesting, the consumer needs to explicitly understand the repository and have an established relationship. The event aggregator pattern works great when you have messages to publish that may have multiple subscribers, impact parts of the system that may not be explicitly aware of the class publishing the message, and when you have a plug-in model that requires messages to cross application boundaries. Specific messages that are typically shared between two entities should be written with that explicit conversation in mind. In some cases you want the coupling to show the dependency because it is important enough that the application won't work well without it. There is nothing wrong with using the event aggregator, just understand the implications of the indirection you are introducing and determine when a message is really an API call, a local notification, or a global broadcast.

Conclusion

I love writing line of business software. I've been doing it for well over a decade across a variety of languages ranging from C++, Java, VB6, JavaScript and XSLT (yes, I called XSLT a language, if you've worked with systems driven by XSLT you know what I mean) ... and I've been guilty of most of the items I listed here. One thing I learned quickly was that most people equate "enterprise software" to "large, clumsy, complex and difficult to maintain software" and that doesn't have to be the case. The real breakthrough for me happened when I started to focus on the tenants of SOLID software design as well as DRY (don't repeat yourself) and YAGNI. I learned to focus on simple building-block elements and working with what I know and not spending too much time worrying about what I don't know. I think you'll find that keeping the solution simple and straightforward creates higher quality software in a shorter amount of time than over-engineering it and going with all of the "cool features" that might not really be needed. If there is nothing else you take away from this article, I hope you learn two things: first, don't code it unless you know you need it, and second, don't assume - measure, spike, and analyze, but never build a feature because you THINK it will benefit the system, only build it when you can PROVE that it will.

Want to avoid these mistakes? Read about lessons learned from over a decade of enterprise application experience coupled with hands-on development of dozens of line of business Silverlight applications in my new book, Designing Silverlight Business Applications: Best Practices for Using Silverlight Effectively in the Enterprise (Microsoft .NET Development Series).

Jeremy Likness

Thursday, September 15, 2011

If Silverlight is Dead...

Once again speculation and worry has developers around the world biting their fingers and lamenting the end of a new era. It almost seems developers want to stick a fork in their Silverlight development because so many are latching onto the hype wagon, calling .NET "legacy" and refusing to see the bigger picture. Microsoft announces a new run-time called "Metro" that is not based on .NET, and suddenly .NET is dead — even though anyone can download the bits for the new operating system, install it, and see for themselves that .NET is alive and well. There happen to be two modes for the application, one in a new "Metro" environment and one in a more "desktop" environment. Microsoft's own Visual Studio is NOT a Metro app so I don't buy the line that this is just a staged coup d'etat. Microsoft announces that there are going to be two version of Internet Explorer: a "Metro" version with no plug-ins, and a desktop version that supports them. I downloaded Silverlight, installed it, and even loaded our Silverlight tablet Rooms to Go Application. It installed fine, appeared on the start menu for Windows 8 and launched without an issue ... but the headlines are reading "Microsoft abandons plug-ins."

First, let me say that I believe Silverlight is alive and well. I'm not saying that because I'm writing a book. People who know me understand I don't get emotionally invested in projects and try to force something to happen when it's not meant to be. I'm not basing this on mere speculation. "What if" doesn't buy me anything. Don't get wrong: I know "what if" is real because it tumbles stocks and cancels contracts, so it does have an impact, but instead of adding to the hysteria I prefer to look at the facts. I know that Windows 8 is not going to be the de facto operating system over night. I know that even when it does, I will be able to build and deploy Silverlight applications to it. I know customers will still have applications to support. I also know I work on a lot of Silverlight applications that simply won't work with the new "Metro" interface and require a more immersive UI and model, and that the guidelines for Metro will probably force those to be written in a traditional stack anyway. I know that a new version of Silverlight is coming out at the end of the year if Microsoft makes their drop target, and I know companies have already begun developing applications that take advantage of its features. But just in case the world is really ending and .NET, Silverlight, and all of those other technologies are truly legacy as of today, what will really happen? I asked my followers on Twitter just what it is that would be missing, and here's what I found out:

Multi-platform and OSX Support

Let's be real here. The only "real" multi-platform support Silverlight has right now is between the Mac OSX and Windows. There is a fledgling presence on Linux but that's hasn't impacted any deals that I'm aware of. The cross-browser story is better because between the two platforms, there is solid compatibility across FireFox, Chrome, Internet Explorer, and Safari. I believe this is a very valid point, as I've done many projects where the customer was most interested in the fact that Silverlight could easily target both platforms with one maintained code base. Of course, the original dream was for this reach to be extended but those hopes were largely dashed by the surge in popularity of the iPad that refused to run the plug-in. While this is a very important aspect of Silverlight, I don't buy that Windows 8 impacts this at all. Windows 8 is an operating system that will run new applications and boasts a new version of a web browser. It also runs the traditional browser and we've confirmed it fully supports Silverlight. So what is missing? The changes to Windows 8 don't remove the ability to drop Silverlight applications on to Mac or existing Windows machines, let alone the next version. It seems the only thing that could negatively impact this point would be lack of features (i.e. I'm missing something that I was expecting to come in a future version) or simply self-fulfilling prophecy, i.e. developers complain so much about it going away that people believe them and pull the plug.

Deployment and web-based Xaml Delivery

This is another sweet spot for Silverlight. The deployment strategy is insanely simple, and many large corporations embrace the easy of installation. This is a double-edged sword however, because for every shop that enjoys the fact that users can navigate to a web page and download the latest version of their application, there is another shop with complicated security policies that must make significant changes to their infrastructure in order to allow the plugin and make Silverlight applications available to employees. This really gets back to the traditional decisions used to drive technology and I don't see how Silverlight is really the primary ingredient. If you want to reach Macs and Windows machines, you will still have that option. If you need a different type of reach or want to take advantage of new innovations, the decision is the same it has always been: either build specific to the platforms you are targeting, with the trade-off that you must now have several teams and versions of the product but it provides a seamless, native experience, or compromise by using a technology like HTML5. That same trade-off existed with the previous version of HTML, it's just that Silverlight development was superior in many cases. I still see cases where HTML5 development is too painful compared to Silverlight, but what it were actually easier to build and deploy HTML5 apps with the same featureset as the Silverlight version? Why on earth would you even want to stick with Silverlight in that scenario?

Community

When I was younger and programmed the Commodore 64, there was a great Commodore community in the St. Petersburg, Florida area. We'd meet up, show each other how to crack open the bread box and solder the little red RadioShack reset button, then swap assembly snippets and chat about the latest VIC chip register hack. When the Commodore began to wane in popularity, people moved onto other platforms and built community around those. Ironically, there is still a strong, growing Commodore 64 community. I'm pretty sure community is more about the individuals in the community than the technology that drives it. Silverlight has a great community. If Silverlight goes away, that community will evolve. (OK, so there are always one or two who can't move on and are still stuck on Information Society breaking up and refuse to program on anything other than an Amiga).

Income

This is like community. First, let me say I know the financial impact of decisions is very real. Speculation about technology causes contracts to get canceled and people to lose jobs. However, if you believe your income is based on the success of Silverlight you are making a very, very big mistake. I remember when I received my fitness and sports nutrition certifications so I could coach people to lose weight. Many of the other "graduates" felt they should research what the pay ranges for trainers were, start at the lowest rate and work their way up. I felt like I should get paid what I was worth, not what the average income was, and had some success working with people so I started at the high end of the range and built a practice around that. My income wasn't based on the latest diet fad or exercise scam, it was based on results. When people lost weight and kept it off, they told others, and my practice grew. It was the value of my service that determined my rates, not industry averages or trends. Software development is the same way. Skilled developers provide value, the customer perceives that value, and they continue to deliver the best possible solutions based on the right technology for the job. If that technology changes, they change with it. Of course, if you want to focus all of your energy on complaining about how horrible it is that Microsoft shifts their strategies and let everyone know how much time and money you invested in learning dead technologies, you're welcome to. Complain away. The people I know who are successful in this industry move on. I'm not saying it's a good thing when you find a contract canceled because of a shift in technology, I'm saying you can either focus on the one that got away or figure out how to make sure it doesn't happen with the next one. Your choice.

P/Invoke

Really? "I don't want Silverlight to go away because it makes sense to run an abstraction layer dependent on a browser so I can go through another abstraction layer to talk back to native code." I just don't get it — is p/Invoke a vaid reason to worry about Silverlight's future? There's no equivalent on Mac OSX so you aren't doing it for cross platform. I'm not sure why you're doing it, really. I like programming in Silverlight: it's fast and it's easy, and p/Invoke opens up options. With the new development platform I can skip the p/Invoke, call the WinRT layer directly and save myself the overhead of importing DLLs and creating obscure structures or learning about how to marshal. To me this one just says, "If you're going heavy p/Invoke maybe it makes sense to look at Visual Studio 2011 and native applications instead."

C# Web App

I don't agree with this one at all. If you are bulding a web site, I think going with the web technologies is key - if I want an application, I'll build it. If I want a rich web site, I'll build it — but different approaches and different tools. Rich web applications still have nuances like page navigation, browser back buttons, and compability that make them different than applications. When I write Silverlight, I'm not writing a web application. I'm writing an application that is easily delivered over the web. That's why I don't use the navigation framework, because I don't think customers are used to navigating desktop applications using URLs. So if it's a web site I want to build and I want to use C#, why not MVC instead? If it's an application, let me use C# by all means ... and as I mentioned above, I may just lose the ease of deploying it over the web. Oh, by the way, did you notice that MVC 4 preview was released? Weird: it's not written in Metro, doesn't create Metro applications, yet Microsoft is still developing it and I don't hear people crying that MVC is dead.

Line of Business Applications

One key thing I see most people missing is that Windows 8 is two separate, distinct systems. Just launch the Visual Studio 2011 to see what I mean. That is not a Metro application. I like Metro, it works great on my phone and think it is the right way to build tablet-based applications, but there are just some things like development environments that don't and won't make sense. If you build for Metro you MUST follow the rules of the sand box, and you are limited. If you jump outside of that, it's back to the traditional stack. So I don't see this shifting gears. Personally the reason why I like Silverlight for line of business applications is because of Xaml and C#. I don't see that changing. I've converted a few applications to Windows 8 as well as walked through the examples and the gap is not huge. It's there, but not huge.

Bottom Line

I see myself having a choice. If I want to develop line of business applications that run on Mac OSX and are delivered over the web, I can develop Silverlight 5 applications. Regardless of whether someone labels that "legacy" it will be supported through 2020 (when the HTML5 spec will finally get ratified) and it will run on my target environments. If I'm building a rich, interactive line of business application, I'm going to want it in that environment. If I'm looking for a user-friendly, touch-first tablet interface, Metro doesn't change things for me. Today without Windows 8 my options are HTML5 or writing native iOS, Java, and Silverlight for Windows. With Windows 8, those options simply shift to HTML or native iOs, Java, and XAML/C#/WinRT. For many years to come, most of my customers will still be on Windows 7 and even Windows XP so guess what: Silverlight and WPF will still be our best options.

Silverlight development will be alive and strong, with official support for at least a decade even if no new version is in the pipeline, and longer if there is one. Even if it is the last version, though, as I'm writing my book I see that 90% of the topics covered are going to be the relevant to developing in the new Windows 8 runtime. Here's something that won't come as a surprise to seasoned developers: even if it does go away, there is no way it will ever happen overnight. As long as there is speculation, it's still around. When there is no more speculation, i.e. we know for a fact there is no vNext, there will be plenty of time to transition.

What's my point? My point is this: there are always people who are going to shout that the sky is falling and the world is coming to an end and air all of their woes to the world. The reality is we all have the same hours in the day and we can do with them as we choose. While I've been accused of being a blind, passionate follower of Silverlight for my optimism and enthusaism, I think they've got it wrong. I'm just optimistic and enthusiastic in spite of Silverlight. If it goes away I will adapt and continue to provide value where I can because at the end of the day I'm a developer and Silverlight is a tool in my arsenal. To me, moaning, whining, and complaining is a waste of time. If something's broke, it isn't going to fix itself. I'd like to see more posts on solutions and options moving forward rather than "Hey, I've got a flat, so let's sit on the side of the road, point at it and talk about all of the things that went wrong with my day."

That's my opinion, and not necessarily the opinion of my employer, and I'm sticking to it. What are your thoughts? Please sound off with comments below.

Jeremy Likness

Wednesday, September 14, 2011

Windows 8: What you Need to Know

If you are trying to follow the hash tag for the //BUILD conference you are probably dizzy by now. I don't blame you for trying to sort through all the messages about standing in line for the toilet or what someone is having for breakfast. I thought it might be a good time to step back and pull together what you need to know.

Hopefully this helps you sort through the firehose of information. Happy Windows 8!

Jeremy Likness