Sunday, October 10, 2010

A brief history of Silverlight and a few cautions for the newbies...

This is a small history of Silverlight.  Based on my experience, it would have been nice to know what I was getting myself into before I embarked upon this technology.  Not that it's been a decision of regret.  However it wasn't nearly as smooth for me as it was implied it should have been.  Perhaps my expectations were too high or out of line, or perhaps my skills were just deficient.  At any rate, here's a brief overview and some words of wisdom for those of you new to the technology:

In the beginning... there was WPF...  
The origins of Silverlight rest on the coat-tails of a technology Microsoft invented on the Windows platform called WPF (which stands for Windows Presentation Foundation).  The basis of this technology is a mark-up language called XAML.  Basically, the idea here is that UI is expressed in an HTML/XML mashup.  The XAML reader within the WPF framework converts this tree of nodes into text, pictures, drop down lists, etc and renders them on screen as such. Basically this mark-up is a specification/recipe of how to render the visuals to your screen.  Microsoft has viewed this as a sort of Microsoft version of HTML (though some would argue it shares more resemblance to SVG).  And as such, there are strategies that allow this to exist on the web as well as in desktop applications.

The goal of this was to provide a GUI application platform alternative to the mess that is AJAX and the dinosaur that is Windows Forms.  With Apple having a very rich and friendly design environment in Cocoa, this was a huge step forward to creating a flexible platform for designing UI in Windows.  The key concept of WPF's flexibility is the notion of a "behavior" model or "non-graphic" implementation of various control elements.  From WPF's design philosophy, what a control does or can do is far more important than what it looks like.  For instance, a "Button" is basically defined as a group of behaviors and events associated with what a Button can do and how you interact with it.  You can click it, you label it with content in some form, you can hover over it, and so forth.  But whether the button is silver, round, or shaped like a cashew doesn't take away from the fact that it needs to carry one or more of those behaviors to be considered a "Button".

Microsoft provides default "skins" to the various controls (including the Button).  However, nearly every aspect of the controls beyond that can have their own custom skin provided by the developer.  Borrowing heavily from the concepts of cascading style sheets (CSS) in HTML markup, the re-skinning of the various elements can occur at various levels:  from the control's own definition, to the application (which affects every control) with similar rules of overriding the behavior.

Also like HTML, the notion of event handling is accomplished through code.  While HTML/AJAX accomplishes this with Javascript, WPF accomplishes this with code from syntaxes compatible with .Net (such as C# or VB.Net)

By the nature of using an abstract mark-up language like XAML, the implementation is very portable between the desktop and web versions.  However,  WPF has a complete dependency on the .Net framework.  Which (unless you count the Mono project) is a technology exclusive to the Windows OS.  Consequently, WPF has just been viewed as a fancier version of ActiveX by most.  And just like ActiveX, you're not going to see WPF content on a Mac or Linux.

Enter WPF/E Silverlight
With the proof of concept for deploying WPF content to a browser essentially proven, the next step was to see if this could be forked off into a solution that was not only cross-browser compatible, but cross-platform. So, the first prototype of this was called WPF/E (WPF/Everywhere).  "Everywhere" at the time was considered the Mac and Windows platform.

Basically the concepts are and were the same as WPF.  UI is expressed in XAML mark-up (with WPF XAML mark-up nearly 100% compatible with WPF/E's version).  It was given it's own version/runtime of the .Net framework (which eliminated a lot of implementation redundancy and Windows specific APIs).  And as a result, given it's own development environment and deployment strategy in the form of a browser plug-in not too dissimilar to Adobe's Flash.

At release, WPF/E was dropped in favor of the term coined today:  "Silverlight".  Through a collaborative effort between Novell and Microsoft, an open source free software foundation-ish implementation has been created called Moonlight.  This is intended to target the Linux platforms.

Development Gotcha's...
This is where all the marketing and hype get put into perspective.  Before you get working on Silverlight, there are some things and certain mindsets you need to get accustomed to.  I know that if I had this knowledge, it would have made things a whole lot less painful.

  1. Silverlight is it's own thing.
    One of the most common misconceptions about Silverlight is that it is part of the standard .Net ecosystem.  This is simply not true. (Or not entirely true) While it certainly shares the same design and development philosophies and IDE, the only thing it really has in common is the syntax's supported by it.  Assemblies (DLLs) compiled in the standard .Net framework are not designed to be compatible in Silverlight, nor are Silverlight assemblies designed for compatibility with standard .Net.  Outside of certain unit test hacks, Visual Studio will generally forbid you from attempting to cross pollinate like this.

    Remember that Silverlight's .Net runtime is a much smaller subset of the "real" .Net framework, with pattern redundancies reduced and Windows-specific APIs removed or abstracted to fit a context suitable for cross-platform implementations.  As of this writing, both Windows/.Net and Silverlight contain APIs specific to their deployment platforms, which makes forcing this compatibility even more of a challenge.

    As long as you remember that you're basically targeting another framework that simply has C# in common with it and a few libraries that just happen to look like standard .Net libraries, you're on the right track.

    I should note that Silverlight 4.0 has tried to address some of this weirdness by allowing some .Net class libraries to exist in Silverlight 4.  However, this only works if your .Net class library's external library references are limited to a few common references between .Net and Silverlight's equivalent library sets.  Basically, the purpose of sharing assemblies here are for lightweight value objects and common algorithms that aren't doing a whole lot and don't require a lot of dependencies on a lot of .Net libraries on either side of the coin.

  2. Silverlight is designed for the browser first and foremost.
    Since version 3 of Silverlight, the concept of an "out of browser" application has been introduced.  However, it should be noted that (at least on the desktop versions of Silverlight), even out of browser applications need to originate from a web-page.  In these scenarios, your webpage acts as the "setup.exe" boot strapper to the installation process.  Users can right click and choose to install the application from the Silverlight plug-in directly.  Or, if you want to build a mandatory or custom install experience, there are APIs built into the Silverlight-specific libraries to handle that.  In that scenario, your application contains the installer logic in addition to it's primary functions.  This is significantly different than the installer deployment packages created with the .Net framework such as msi's or ClickOnce.

    As Silverlight is designed for the browser, communications with the hosting server (or any other web service) are only allowed asynchronously.  This is intended to prevent a Silverlight application from locking up a browser while it waits for results.  Remember that Silverlight's access to the outside world rests on what the browser allows and provides.  This interface is a published standard, and how it's implemented from browser to browser is largely up to the browser's development team.  This asynchronous way of doing things is to ensure a consistent experience for service calls.  It should also be noted that this communication occurs only when Silverlight's engine has control.

    A side effect of this is that you generally
     want UI elements to change based on what you get back from a service call.  You have to do this in the call-back event handler you specify on the web service call.  This essentially makes you split your UI logic up amongst one or more methods that have little knowledge of one another.  For example, a click event on a button could trigger a web service call.  But you can't fill in text boxes based on the results of that event until the web service's asynchronous callback has been fired.

  3. Rendering occurs as RETAINED (or once per frame)
    When dealing with graphics, and especially when targetting OpenGL or DirectX, it's important to understand the difference between rendering modes.  There are basically two main flavors:  Immediate Mode and Retained Mode.

    Immediate mode rendering is similar to the way you're doing in Windows Forms.  Basically, every instruction you give that modifies the display in some way occurs IMMEDIATELY.  Traditionally, what this has meant in the Windows Forms realm is that you introduce an inefficient effect called "over draw".  Basically what this means is, your program can end up triggering events and processes that force the display to repeated update and display portions of the screen.  Sometimes this is desirable.  In other cases you end up re-painting over the same part of the screen over and over again until it resembles the final state that the user see's.  Often times this generates artifacts on the screen, or simply introduces lag time and unresponsiveness until all of those unnecessary draw operations have completed.

    In Silverlight, nothing is rendered until control is given back to the Silverlight engine.  This is called "Retained" mode.  The concept here is that the screen's display element hierarchy is scanned once for changes and rendered once to reflect those changes.  

    What this means is that setting a checkbox control to checked in an event handler will not actually perform anything on the visual until your call stack has emptied out and control returns to the Silverlight engine.  Setting properties that affect visuals at this point are merely providing a specification to the renderer when it scans through the objects that make up your display.  This makes for efficient rendering, but it doesn't give you accurate access to any properties that are changed as the result of a render.

    So in a way, Silverlight has a rendering lifecycle closer to ASP.Net than Windows Forms.  Except the lifecycle completes several times a second and doesn't require any communication back to the server to figure out what the page looks like.

  4. Silverlight IS the application.  Your program is merely a parameter passed to it.
    Okay.. I know that sounds a little harsh.  But consider that none of the heavy system level lifting ever occurs until the Silverlight runtime retains control (i.e. your program's call-stack empties itself out).  This is true of rendering, and also true of any service calls out to the internet or hosting server.  

    With very few exceptions (pardon the pun as that's one of the cases), methods, classes and properties that interact directly with the Silverlight runtime act like a checklist for the engine to follow rather than performing any particular action directly.  Calling methods to perform a web service simply queues up the request.  That's right. It's true!  If you call a web service that only takes a second and then force a wait delay in your code for five seconds, you will find that the request never even fires until your method returns control back to Silverlight.  So if you prefer synchronous calls, you're out of luck.  As I just mentioned, you can't even add delays to block code while you're waiting for the call back.

    Also, as mentioned above in #3, the UI renders in a retained rendering pattern, and basically follows this same process for the visuals.
So if you are embarking on Silverlight for the first time, beware of these items. Peripheral understanding of how the runtime operates helps quite a bit before you waste time trying to implement patterns or APIs that fight the way Silverlight processes things.  Silverlight will always win in those fights, so it's good to know how to develop around the way the runtime prefers to execute.

No comments:

Post a Comment