Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

2 years ago I gave up on Silverlight

Almost two years ago, to the day, I completely gave up on Silverlight. How do I remember the day so clearly? Because every now and I again, I get an email notification that someone has replied to my following forum post: http://silverlight.net/forums/p/1334/216456.aspx. In it, I asked why the Shape classes are sealed. At the time I figured it might have just been a early-release kinda thing. However, since the issue continues to be raised I’ll assume the problem still hasn’t been fixed.

This whole thing reminds me of another common .NET problem – internal framework classes. This was a hot topic with the release of .NET 3.5 and the ExpressionVisitor code, so much so that a David Kean from Microsoft jumped in to explain the situation. For the most part though, all it did was highlight how inefficient and unwilling to change Microsoft was. Why are classes internal? Because the process to make them public involves 20 some people and a multi-layered review system. There’s no “how do you guys handle these problems?” or “where can we improve” – merely a statement of fact of how things are (and therefore must be).

Back to the sealed silverlight classes. This to is a pretty old topic – remember Java is virtual by default, C# is not. What annoys me though, is the approach Microsoft has taken. I asked Why are the classes sealed, and the official response was Why do you want them unsealed? If .NET is built on the basis that developers need to justify how they use the framework, we’re in deep shit. The default behavior of a framework developer should be to open components, and only close them off when necessary. Otherwise it limits what your customers can do with your product, places assumptions on how your framework will be used, and makes it clear that you think you know better than we do. Lets not forget that coming up with a use-case for inheriting Line isn’t particularly difficult – maybe I want to create my own DottedLine class?

The specific wording used by Nick Kramer (Silverlight’s Program Manager) was:

“We want to err on the side of less API surface area — if you’re
missing something important someone will tell you, but if you include a
feature that doesn’t get used you’ll never hear about it, and will pay
the download cost for it forever. We weren’t able to think of a
compelling reason for arbitrary subclassing, but maybe we weren’t
creative enough — what scenarios do you have in mind?”

It isn’t Nick Kramer & Team’s job to think of reasons for subclassing (its our job to do that). Nick Kramer and Team should only be concerned with reasons not to have an unsealed class. Nick did provide some of that reasoning, but I’m unconvinced. Essentially coming down to performance and wrapping unmanaged objects – issues simple enough to cover via documentation.

 

 

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

20 Responses to 2 years ago I gave up on Silverlight

  1. I don’t any developer who uses silverlight, its either flash or nothing.

  2. I think the performance issue is a red herring. A sealed class can always be unsealed someday, but the reverse is not true (for backwards compatibility).

    Framework Design Guidelines goes in depth into Microsoft’s reasoning behind this and other decisions. It’s well worth reading.

  3. Andrew says:

    Bill, I’m not saying it’s a bad idea, I’m just saying that if that’s the only reason anyone can come up with to unseal classes, that its not enough incentive to do so.

    Karl, agreed that Managed Code was once slow, I think the problem is in this scenario is that once they sealed the classes it might be difficult for Mircosoft to unseal them in future versions since they might view it as a solved problem. I imagine it’s like in government where it’s relatively easy to pass a law and a complete pain in the ass to repeal it. :)

  4. Bill Sithiro says:

    You’re right Andrew that would be a terrible idea. Actually, that’s just me trying real hard to think of a good reason to unseal Shapes. The only glasses I would wear are category 5’s! 😎 But I guess, I’m not convinced the… “loose lips sink ships” that is the Shapes sealed modifier cannot be done behind the scenes at the IL level. Besides, if it’s such an intricate part of the .NET platform maybe Anders can come up with a modifier that means sealed if no descendants exist, or seal it at the last descendant. The developer takes the responsibility for the horror of tapping into a constructor and perhaps maybe adding a few members to the class. :)

  5. karl says:

    @Andrew I do take ScottGu at his word. I completely believe him. I just think its unfortunate that the tradeoffs are so extreme. Given those constraints, I agree that the right choice was made. I don’t think that’s the end of the story though, I have to believe that we can have our cake and eat it to (remember when running managed code was too slow?)

    @Don: Nice troll. I already acknowledge that at the time my design might have been bad.

  6. Andrew says:

    But Bill, if the only reason we have to unseal certain classes is so we can program for 3D glasses, don’t you think we’re getting close to throwing out the baby with the bath water?

    We have to take ScottGu at his word here, but if he is saying that leaving classes unsealed so .1% of the developers out there can feel empowered, but at the same time practically 100% of users will be negatively effected by up to 20%, then I don’t see how anyone can not think that doing so is an impractical trade off.

    What other industry would radically harm 99.9% of it’s user base to appease .1%? Not many that want to stay solvent I know that’s for sure.

    I get that big, bad Microsoft makes horrible decisions on what seems like a daily basis, but this time (and again we have to take ScottGu at his word) doesn’t feel like one of them.

  7. Bill Sithiro says:

    @andrew:

    “…but tell me what you want to do and I’ll show you how”.

    Well, the direct response and all is greatly appreciated but in terms of the larger picture it does nothing. Also one could argue, I can reverse the role and tell Microsoft how to keep Silverlight performance high. Would that feedback be appreciated by Microsoft? I don’t think so. We all know you can do things one way or the other. In my opinion it’s important for a platform company like Microsoft to demonstrate their intentions that they’ll do anything in their powers to give them (developers) the power they need to achieve their goals. I guess it’s good PR or marketing, whatever…

  8. Andrew says:

    I’m a little confused on this one Karl.

    For one, you can’t even remember why you wanted the classes unsealed other than a general “all should be open” philosophy, so I’m guessing that individual thing you wanted to do wasn’t all that important.

    I do tend to agree with you in that sense, but when an authority on the matter says, “We’d love to unseal everything but if we do we’ll get a 5-20% hit in speed which to us is unacceptable, but tell me what you want to do and I’ll show you how”, shouldn’t that be good enough?

    I have hardly been thrilled with all the choices Microsoft has made lately, but this one seems to make sense. Degrading the performance of Silverlight for 99.9% of the developers and practically 100% of the users by up to 20% just to appease the .1% of developers that wants to do something incredibly specific with the product just isn’t a good business decision.

  9. Don says:

    @karl: are you paid to blame? Why don’t you write what’s wrong and how to handle it?
    In my experience, code smell usually because of poor inheritance handling.
    For example, I prefer OCP principle by composition instead of inheritance. Shall I blame at Java for virtual members by default, hence suggesting poor design to people? I can find a lot of examples how bad inheritance can be…

  10. Bill Sithiro says:

    I’m much in favour of performance over anything else, but here is a scenario for unsealed Shapes:

    3D glasses stereogram.

    I want to take your existing XAML and make it work with 3D glasses just by adding a namespace in the XAML. I will essentially take shape primitives, clone, change colour, apply blur and slightly offset them in relation to their original shape position.

    Why? Because I have video content for 3D glasses, why not have the player in 3D too.

    I can also think of code libraries that could do things with your XAML just by adding them to your project.

    But anyway, as I said earlier, two cents…

  11. Here’s the thing about that performance hit. It’s not a case of “If I subclass my class runs 50x slower.” It’s “if the class is unsealed every shape class, including the built in ones, will run 50x slower.” Some may find it offensive, but if that’s the tradeoff I’ll take the sealed classes and find another way around what I’m trying to do.

  12. Bill Sithiro says:

    Two cents:

    Firstly, wanting to subclass a Shape descendent doesn’t necessarily mean you want to draw your own shape. In fact it doesn’t even make sense to do so! E.g. Subclassing Rectangle for the purpose of creating what? A tangerine? Additionally, subclassing (or should I say at least wanting to) a shape descendant for the purpose of styling still isn’t an ok reason since we already have ways of doing that and should stick to them. This is all fine. But perhaps, let’s say I want to add an additional Z point for 3D calculations, perhaps I want to throw some metadata on the class, perhaps I want to alter its measuring values, and there are so many reasons why. It really should be left to the developer to decide.

    Secondly, the performance issue. Here’s the thing with composition. It makes you think of memory management deeper (sometimes successfully, sometimes not). So if you were making a high-performing application this issue would drive you nuts because things just aren’t getting released as they should. So at least in some cases, you haven’t solved anything.

    I love Silverlight but I’ll have to agree with the author of this post; this… what’s your case approach sounds extremely amateur and does nothing for innovation.

    Finally, I would like to say that I’m not just posting this for the sake of posting this, but I as well have received the “what’s your case?” treatment, not that it bothered me, but a pattern(shape) does appear to emerge. :)

  13. phat shantz says:

    A benevolent tyranny is still a tyranny.

    An admission of a mistake, “We weren’t able to think of a compelling reason for arbitrary subclassing, but maybe we weren’t creative enough…,” isn’t the same thing as correcting the mistake.

    But it sure was a nice bit of deflection. Or was that deception?

    Open your classes.

  14. I don’t know anythin about silverlight, but in the general case I agree with MS aproach of minimal API surface.

    Every square inch of API surface needs to get maintained possibly creating roadblocks for further improvements and limiting the options for internal changes.

    Therefore I’d say “What do you need it for?” is a extremely good question, one trying to find the core problem, instead of quickly fixing the symptom.

    Of course with open source you could quickly change the source code if you are willing to support that change for all future versions you are going to use. But that is a completely different story.

  15. The problem with Sealed Shapes (not advocating the general sealing problem across .NET) is that shapes aren’t rendered in managed code. Unlike WPF where shapes aren’t sealed, in Silverlight the rendering is in unmanaged code so creating a new Shape would not give you the ability to draw that shape in the machine code. Creating new shapes in WPF are easy because they can get to the “Render” event and draw directly on the surface, in Silverlight (for a myriad of good reasons) this doesn’t work.

  16. karl says:

    @Scott:
    I don’t remember why I wanted to subclass a shape. I do remember that we were evaluating the platform and by the time Nick answered (9 days later), this as well as other frustrations with Silverlight (hopefully we can all agree that 1.0 and even 1.1 was very raw) caused us to abandon the platform.

    Maybe 2 years ago I was designing things wrongly (favoring inheritances over composition), who knows.

    You guys made a decision and by doing so, took that decision out of our hands. Ideally, you’d leave this open and inform us of the risk and let us chose if the 5-50x performance penalty maters. From the sounds of it, you guys aren’t able to give us that choice, because once unsealed there’s no going back.

    Pragmatically I can understand that. I still think that, ideally (and if possible), giving us the choice would be better.

  17. ScottGu says:

    Nick’s question is the right one – what is the scenario that requires the Shape classes to be unsealed which can’t be handled in one of several other (more performance efficient) ways?

    I haven’t seen in this blog post or in the old thread you linked to a scenario that cannot be handled in one of several other ways. For example, it would be easy to create a Control (using sub-classing) and composite a new custom shape using the existing shape objects. This is how all standard controls are implemented in Silverlight. It is also now possible to use WriteableBitmap and have complete pixel level drawing support if a vector based compositing shape approach didn’t work for some reason. Is there a reason neither of these scenarios don’t work for your scenario? If so, please explain it (which is what Nick asked in the thread – and which I do not think you ever replied to).

    The reason we asked for a clear scenario is because there are a lot of good reasons why the Shape classes are sealed – performance being the main one. Shapes are the lowest level vector drawing primitives in Silverlight and are implemented as native objects used at the raster layer (the managed API is just a wrapper to the native object). Complex views often have thousands of shape instances (every button, datagrid, radiobutton etc is implemented using multiple shape instances). Rendering these efficiently is obviously super important, and by having the lowest level Shapes be sealed we can perform much more efficient rendering passes and optimizations, and have the option to render with both a software raster and a GPU raster. If Shapes were unsealed and members virtual we’d have to have a lot more chatty communication between the raster layer and each shape object, which would significantly impact performance. It would also impact the ability to push certain operations down to a GPU.

    As I mentioned earlier, the Silverlight control model supports full compositing of UI – which means you can sub-class Control and create a custom shape by compositing the existing vector objects. Or you can use WriteableBitmap and draw your own pixels. I can’t think of a scenario where this wouldn’t enable what you are after – and by doing it this way the render performance is probably 5-20x faster than what it would be if the Shape objects had virtual members.

    BTW – it is worth calling out that unlike other UI frameworks, every control in Silverlight can be templated and have its default UI replaced or tweaked (this is not true for HTML, Win32, or Cocoa btw). Controls like Button are implemented using a view/model separation pattern, where the view can be a declarative templated XAML file that has shapes, controls, animations and transforms and uses bindings to retrieve its values from the control model. This enables you to both override style settings, as well as override the structure and UI behavior of a control’s view without having to write any procedural code. Obviously you can subclass controls as well to override their logic – but the fact that you don’t need to subclass for a large class of cases is very powerful and pretty unique. Because our raster layer is heavily optimized, you can build super complex UIs this way and still have screaming performance.

    The ability to use a MVVM (model, view, view-model) pattern for clean view/model/behavior separation at the application layer in WPF and SL enables you to go one step further and have a clean model/view architecture not just for controls but also for your application. This enables easy unit testing (and a nice TDD workflow) and will also enable applications built with SL to be optimized for different device form factors (large screen, small screen, mobile, non-phone device, etc) without requiring any changes other than at the (mostly declarative) view layer. It also enables a good designer/developer workflow.

    Scott

    P.S. In re-reading your post I saw that you did mention a dotted line scenario. This actually doesn’t require creating a new shape, control or using templating. Just set the “StrokeDash” property on the line object.

  18. Jake Good says:

    That’s why I love Ruby… just open the class up and add/change what you need to. Just write some damn good tests and you’re off to the races, no waiting around for service packs…

  19. nick says:

    Is this a case of “damned if they do, damned if they don’t” It is difficult for them, with anvils such as vista to deal withn to do the right thing.while not always the case, some upside is that you get to be more creative, pulling out your design pattern tricks. I feel your post has too many Shoulds in it, and such a constructed view will always result in pain.

    Based on the vision, some of which we are not privvy too, we cannot know which framework development rules or principles apply. And true enough rules applicable to one scenario may not fit well with another.

    I can see from the points you focused on why you feel the way you do. Not sure if for me they are enough to walk away from the/a technology, but everyones different…hence the perenniual bind Microsoft finds itself in.