In this article I’ll compare the Silverlight technology with it’s modern equivalent and explain why used correctly they should make life easy, not difficult.
XAML stands for Extensible Application Markup Language. It was born in the .NET world for WPF and Silverlight but lives on with a managed WinRT implementation in Windows 8.1 and later. It is often mistaken for a “UI language” because that what it was great at doing: declaratively defining your user interface. I say “mistaken” because XAML does not have to be tied to anything visual. It is really just a simple way to create rich object graphs in a declarative fashion. For example, I could something like this imperatively through code:
Or take advantage of XAML to declaratively create it like this:
The declarative method is very well suited for defining rich object graphs which is how we design most user interfaces. It is not as well suited for logic and flow control. It turns out that non-programmers can learn declarative syntax far more readily than the imperative rules of most programming languages. I assume this is why website designers outnumber web developers by a long shot, but I’m more interested in the fact that I can work with my designer and they can edit the code and understand the markup.
HTML5 is the “XAML” for Angular apps and the concepts are very similar.
Any programmer worth their salt is going to cringe when they have to write the same block of code more than a few times. The principal has been ratified as Don’t Repeat Yourself or DRY and when it comes to the UI this is done through controls, templates, and even control templates. In Silverlight you could create different types of templates, such as control templates to define the structure and look and feel for a reusable component (in Angular we do that with HTML and CSS), but you could also create data templates that showed how to transform data into a visual representation. A typical Silverlight data template might look like:
The same scenario played out in an Angular app uses directive and “mustaches” to define a template like this:
Dependency Properties and Data-Binding
Thank goodness the Angular team took a different approach!
It was precisely the amount of overhead to take an ordinary property and make it “observable” that drove most Silverlight developers nuts. We even went to great lengths to build highly custom solutions that taught the static C# language how to have some dynamic fun.
A neat flavor of the dependency property system in Silverlight was attached properties. These are properties you can project onto other entities. For example, a grid might want to keep track of what cell a piece of text is in. The text doesn’t know it’s in a grid, but the grid will project a column and row number any way to keep track of it. In C# this was like magic. The attached properties made it possible, and the logical extension of that was behaviors. These were reusable snippets that you could attach. For example, maybe one behavior would automatically detect a size change and crop the geometry of an object. Another behavior might force data-bindings to update as a user typed input in a text box.
In Silverlight, value converters help transform data into information. You won’t believe how many Silverlight developers would break into fisticuffs at conferences over whether it was acceptable to format a date in a view model or if it should be done in a reusable value converter that is declaratively attached in XAML. I tended to like the converters because I could write and test them independently and easily remove or add them when designers changed their mind (I know it doesn’t happen, of course, just being hypothetical).
Angular makes it extremely easy to create the same thing in what is called a “filter”. The syntax is incredibly less verbose. Here’s the sample with both approaches – again, we’re on the same page. Can you start to envision how your Silverlight XAML will translate to Angular yet?
Behind all of this data-binding is the construct known as the view model. In Silverlight, there were massive debates that raged over precisely what each “leg” of the MVVM stool was and meant. There were the “no code-behind” purists and the “getter vs. value converter” camps and the “model is data” vs. “model is behavior.” I tend to like to keep things simple. When I speak of MVVM, I’m referring to the model which is most of your app: it’s how you are dealing with and solving the problem your app addresses. It includes services, validation logic, business rules, etc. You can choose to pass a “data model” to simplify things but you have to have something that supports the rest of the app. The next piece is the view which is the UI, pure and simple. Finally, you have the view model that serves to synchronize the state of the view. It does this through data-binding, whether there are bound properties or events.
Angular keeps these aspects fairly distinct. The reason you want this separated is not to make building a page more complicated. If that happens, you’ve failed. It should get easier and part of that is because you can build pieces like the view and the view model in parallel. Part of it is because you can test the view model without the view, so you don’t have to spin up XAML (Silverlight) or a phantom browser (Angular) just to make it work. In Angular, you can either use a controller with $scope and that two together make a view model, or more recently you can use the “controller as” convention to make a true thing that we call a controller but really acts as a view model in the browser.
In Silverlight view models could implement IDataErrorInfo and other versions of the same interface (depending on whether you wanted synchronous or asynchronous validation). The implementation would hold a dictionary of grievances by property that controls then recognized and rendered. A chunk of XAML that supported validations might look like this:
This would result in highlighting the input field and showing the validation exception to the side. Angular uses a combination of built-in HTML attributes and directives to facilitate declarative validations:
Of course an app is only as good as it does, and a lot of what apps do is communicate with servers. Fortunately I’ve found that a well constructed Silverlight app is also mostly ready to be a well-constructed Angular app. I’ve found sometimes the disconnect when talking about patterns comes when one person is used to working on a team of one on a product over a period of time, versus talking to developers who are used to working with larger teams and separate design teams in parallel. The former often bemoan the complexity of “those patterns” and want to know why I’d ruin the perfect thing they have going with jQuery. For their situation, they may be right.
The instant you start building a larger team and trying to scale out work, however, things change. I have several examples of this from my Silverlight days. On one project, the design was built in parallel to the development effort – 6 months each. On another project, the services weren’t stood up yet and were being built in parallel. In both cases, the structure of separating the design (view) from the presentation logic (view model) and business logic (services, app model) paid off.
For the former, we were able to agree that the design might change how something is represented but we agreed on what would be represented. That meant I could build view models (controllers, $scope) and test them fully, as well as stand up the API for “doing stuff” independent of the design. As the design clicked in place, it was tweaks to XAML (HTML5) and we were out the door.
For the second, I abstracted the idea of the service call from the view model (controllers, $scope). I knew I would need to get a list of widgets, or display a given widget, so our team built those facets and just mocked the service layer. Once the services were stood up, we adapted the façade to make real-time calls and cut over the project quickly. What’s nice about this architecture is that this type of app is fairly easy to port over to Angular. No, I don’t have some magic HTML5 generator that runs over the XAML, but we could analyze the app and see what filters (value converters) and validations were needed, what view models (controllers, $scope) looked like, and start to build out the UI without having to touch the back end. The same services were there (granted, if you are using something like WCF with SOAP or OData this is more complicated because Angular speaks best with REST out of the box, but there are plenty of client libraries for bridging those gaps as well).
What’s really cool is if you follow TDD, your specs are already written. You can take the same spec you wrote for your view model (given user when email is invalid then prevents submission) and write the same specs for your Angular controller as you start to port code over, and how satisfying is it when you see two sets of identical green specs, one from the Silverlight Unit Testing Framework and the other from Jasmine?