Поделиться через


Silverlight: the art of subsetting

I am an architect of WPF, both the full desktop version and the subset that provides the UI framework for Silverlight.  This subsetting exercise raises challenges I've not run into before when designing software.  Simply put, how do we keep the framework small without completely changing the programming model?  Keeping it small is relatively easy:  just take out classes and APIs.  You of course lose functionality in the process, but almost always when designing software you start out with many features and then must prune back in order to ship.  Subsetting also makes it hard for users to move substantial bodies of code from the big system to the small system.  Not only features, but individual APIs that we decided to cut "because they weren't critical" are naturally called all the time in the application code, and there is no replacement.  Worse, it is easy to get confused reading books about desktop .NET or looking at blog articles about XAML and not be able to tell what is in Silverlight and what isn't.  There was a simple question in the Silverlight forums this morning about how to set the Name of a Framework element.  The user had seen code that simply said fe.Name="foo" and it wasn't working for him.  Well, that code works on desktop WPF and it is highly unlikely the place he saw the example noted that this wasn't available in Silverlight.

To keep somewhat sane, we choose to design around making it possible to port code *from* Silverlight *to* the desktop.  As long as the Silverlight APIs are a subset (with expected differences for application model) of the desktop ones, code should all just compile and run when moved over.  But this is where it gets trickier than we originally imagined.

 With the full desktop frameworks there are usually several ways of doing the same thing.  In Silverlight we eliminate many of these variations in the search for the smallest possible code and surface area.  However, what happens when we eliminate a path that is a best practice for a particular scenario?  For example, there are a number of complex APIs in desktop WPF that are only used if you want the best possible performance...usually with some tradeoff in flexibility.  The System.Windows.Media.Drawing class and its descendents are examples.  These allow you draw shapes into a single visual and render more efficiently.  Not strictly necessary, but they make for much better performance in some scenarios.  These scenarios are still possible in Silverlight, but if you now port your code to desktop, you will be well served to rewrite a big chunk of code. 

The above example is a bit of a special case, and I don't feel bad about it at all.  A much greater struggle that hits a very large number of users is how we do Control templating.  All of the APIs we use in Silverlight's Beta1 control templating model exist in desktop WPF, and yet the templates are completely different.  By subsetting the APIs we ended up changing not just the best practices, but the essential model. 

Let me be clear.  If you write your own custom control in Silverlight, using the Silverlight model, you can create a template for it and take your custom control and its template and run them on desktop WPF.  The problem is, we do not provide Triggers in Silverlight and many of the properties (IsMouseOver, IsPressed) that Triggers depend on to work.  There are technical reasons Triggers were hard to add in Silverlight 2 (though we will add them in the future), but even greater was the test and development cost of adding all the additional properties necessary to make them work.  So, we decided to make the controls have to "trigger" the state changes themselves in code.  All this code works on desktop WPF.  But existing controls, written for the desktop, don't contain the code to "trigger" the state changes, so the control templates don't do anything when applied (they create their children, but don't react to events).

I should add at this point, that we also think there are some advantages for designers and tools of the Silverlight templating model.  The Parts and States model (which is just a pattern using existing APIs) adds structure to a template that makes it easier to understand.  And in the future, when we add Triggers into Silverlight they are completely compatible with the Parts and States model...providing the best of the two models.  Finally, the Beta1 Parts and States model is going to be considerably enhanced in the near future in ways that really show off the advantages and simplify the coding. 

Sorry for the tease about future stuff (watch this space), but this posting is about the essential subsetting problem, and the control templating model has been our greatest struggle in this area.  I hope this helps provide insights into the Silverlight programming model and some of the decisions we've made, which may seem arbitrary and patternless otherwise.

Comments

  • Anonymous
    May 01, 2008
    PingBack from http://dogs-pets.info/dog-breeding/?p=929

  • Anonymous
    May 01, 2008
    Appreciate the post.  I agree it is a difficult problem. I don't understand the issue with testing though.  Surely if you used the existing WPF code for templating then that would result in less testing - it already works in WPF !  at the moment you support two code bases - which doubles the work.   Didn't the same apply to getting the framework working initially?  A few scattered conditional compliation directives? Could you take the same approach for Silverlight?  Cross compile the code from WPF.  To prevent it from getting too big mark large chunks should be modular and optional.  You mention Media.Drawing - make this a separate assembly that can be brought into the application install.  If the user doesn't want to rewrite part of their app then they can just include the assembly and keep it as it is.  Triggers and other core functionality should be in the core DLL, and bring back the visual/logical tree split. I would like to see this apply to other parts of SL2 that are already in the core build to reduce the size.  Like DeepZoom and some of the controls that are rarely used.  Make it all optional on demand download.   Is it too late for this now?  Are we really talking about SL3 requirements?

  • Anonymous
    May 01, 2008
    Hi John, Great post. Thanks for the informative tease. You stated: "And in the future, when we add Triggers into Silverlight they are completely compatible with the Parts and States model...providing the best of the two models." I question whether having the best of both models results in something superior to "merely" having the best of one.  By the way you described it, the Parts and States model seems like a stopgap until triggers are properly implemented in Silverlight.  Despite any advantages it might have, once a stopgap solution goes live, it must be supported and continue to exist thereafter.  It's a shame to force oneself into a position where one must maintain backward compatibility with a stopgap solution. It's exciting to watch this process unfold.  All eyes are on you...keep up the awesome work (please)! :) Josh

  • Anonymous
    May 01, 2008
    To Josh: The Parts and States model is not a stop-gap...as I said, I believe it adds structure to the Template that is useful.  When we add Triggers, I'm not suggesting just adding Triggers with Setters, I'm also suggesting a "GoToState" custom Action, so we can pull the code that triggers the State transitions out of the controls and into the Template, but keep the structure available.   To really see the power though, you'll have to see the next iteration.

  • Anonymous
    May 01, 2008
    The comment has been removed

  • Anonymous
    May 01, 2008
    The comment has been removed

  • Anonymous
    May 02, 2008
    Oran, There will be times when we add something to Silverlight first, but the desktop Client is a long ways ahead of the web client in functionality and we'll be continuing to add stuff there too.   Deployment concerns are always going to limit how much we add to Silverlight...so I don't see it "overtaking" the desktop version for at least a decade.

  • Anonymous
    May 02, 2008
    John I know I'm simplifying things, but you said that WPF was written as a desktop platform with no size limitations - but couldn't the same be said of .NET.  You managed to pull it off for that.  It just seems a shame that you couldn't go the last mile and do it the same for the UI portion too. Sure there are OS specific parts in WPF - but this also applies to the core framework.  Just conditionally compile them out. The problem is that this becomes a long term concern.  There will always be differences in these two platforms and those differences are going to cause a big headache for developers.  What you're seeing now is the tip of the iceberg.   I've tried porting some of my WPF code already to SL2 B1 and frankly gave up.  So much code needed to change it was basically becoming a rewrite.  

  • Anonymous
    May 02, 2008
    Joe, believe me, we very, very much wanted to use the same code for WPF on desktop and web...but it was impractical.  Many other parts of .NET are much less platform dependent.  

  • Anonymous
    May 02, 2008
    I should add, we fixed a large number of incompatibilties between desktop WPF and Silverlight between Beta1 and Beta2 (stay tuned).

  • Anonymous
    May 02, 2008
    Thanks John I'm looking forward to beta 2. Maybe somebody from the team could provide some best practices of maintaining a WPF and SL tree in parallel.  I mean sharing source code, including resources that are common etc... Once you also freeze your feature list I would like to see a categorical list of differences - just to save time when porting and trying to track down something that just doesn't seem to work, on either side. Forgive the ranting, you are producing some great technology - it's just a little frustrating on the edges.

  • Anonymous
    May 02, 2008
    John Thanks so much for this post.  I have read lots of posts which describe the "what" about Silverlight but none of them describe the "why"! I feel much more comfortable knowing that you are aware of some of the issues and actively working on them for beta 2 - your comment saying you already fixed a large number of incompatibilties between desktop WPF and Silverlight between Beta1 and Beta2 made my mouth water in anticipation! Any idea of a rough date? ;-) Regards Neil

  • Anonymous
    May 03, 2008
    Wouldn't some kind of a tool like a WPF 'lint' be very useful in the scenarios that you described?

  • Anonymous
    May 03, 2008
    We have already dropped a couple Silverlight applications we had originally proposed into contracts for future applications. There are quite a few reasons for this. A lot of the developers we have already know WPF which cost our company money to get them up to speed. Seeing as how Silverlight is deciding to require different coding techniques specifically with the control templates and how that impacts both our developers and designers, it's too much a financial liability on the company now to keep retraining people on like technologies which require specifically different skill sets. I am also a developer and i must say that after using the new control templating/parts model, its awful. It takes far too long to accomplish what was easily done in WPF. It requires the designer to jump into the code which is not somewhere they should be. I keep hearing about how "tools" will be easier to write with the new control template/parts model and frankly, I don't care about the tools. I care about the way the technology works, and to me, the parts model is cumbersome and I hope that it is fixed/changed back to the way it works in WPF.

  • Anonymous
    May 08, 2008
    John, Its really nice to hear from somebody making the decisions about the tradeoffs involved in bringin Silverlight out.  Your explanation on the Template Model and some of the background involved is really helpful. However, there is one pain point that I wonder if you could go into: Why does SL not have an ICommand interface. I understand the complexity of RoutedEvents and the debate about event propagation through a visual tree verses the application logic as you mention in http://blogs.msdn.com/johngossman/archive/2008/02/06/more-on-mvc-and-m-v-vm.aspx  however, as you also indicate in that post you actually do like the ICommand interface itself. Why isn't the interface itself defined.  That would let me implement my own ICommand approach or more easily integrate with things like Prism.  With the core interface missing however, it leaves one of the fundement building blocks missing and from what you said its not the ICommand interface that you have issues with but the implementation.   I also understand the space and testing constraints but how much space and testing time would be consumed by including an ICommand interface with ZERO implementing code just to permit easy duplication of the programming pattern.  If it's the programming pattern itself that you want to prevent, can you perhaps explain a little about why that is? Thanks!

  • Anonymous
    May 08, 2008
    Mark, Good question about ICommand.  We definitely want to promote, not prevent, the programming pattern.  That said, commanding was on the bubble for Silverlight in favor of staffing must-have, user cannot duplicate features.  You can of course implement your own ICommand interface and use it.  I intend to prototype this and blog it, including use the Attached Behavior pattern to hook controls to Commands even though the built-in controls do not support them. Stay tuned.

  • Anonymous
    May 08, 2008
    WPF Controls Emphess.Net: A MenuKiller Control - this article is a work in progress detailing how to

  • Anonymous
    August 08, 2008
    As I’ve described before , we introduced the new VisualStateManager concept into Silverlight WPF before