Wednesday, February 15, 2006

Let's talk about skinning

No, not the "it puts the lotion in the basket" kind: the "my UI and business are loosely coupled" kind. In this post we are going to discuss a good way to break the user interface out of your system: Skinning. When you make your application "skinnable," you allow users to load new looks-and-feels at run-time. There is a Skin Pattern out there. Unfortunately, there is no definitive authority on what, exactly, the Skin Pattern is. There don't really seem to be any good authorities on what any pattern is, for that matter. I am going to talk about a way of implementing Skinning, not the way.

Skinning is little more than a fancy name wrapped around the Model-View-Controller pattern. Why that's not called the "Model-Controller-View" pattern is lost on me. Really quickly: Let's not get true skinning confused with ASP.NET Themse or Skins, which solve the problems that css should have. If you are one of those people who is in to service-oriented architecture, think of the skin as just another service: the "interface with foreign actor" service. If you are into MVC, think of a skin as a loadable view with a few extra restrictions. If you are someone who doesn't need fancy-pants terminology wrappped around everything you do then, well, good for you... we could probably be friends.

Consider the leftward class system. There are a number of business objects which represent the "Model." If you are an SOA guy, then they are your various data and business intelligence services. There is a controller that coordinates between the business objects and the skin. Finally, there are skins which compose the "View." For SOA people, the skin is just another service that allows foreign actors to communicate with a system.

There are slight differences between making an application "skinnable" and using the MVC pattern. For one, in the MVC pattern, the view is allowed to access the model. In the implementation of skinning proposed here (and in any instantiation of the Skin Pattern worth its salt, really), the Skin (the View) is not allowed to talk with the business objects (the Model). Also, while skins cannot provide new functionality, they are able to hide existing functionality. Additionally, there is a difference of intent. Most often, I have seen MVC used to create modularity between the presentation, the business intelligence, and the data; the ultimate goal being maintainability. Skinning, on the other hand, generally takes advantage of modularity to allow run-time selection and/or customization of the UI; the ultimate goal being flexibility.

In the diagram above, you should see an ISkin interface. This interface should serve as a contract between the controller and the skin. The contract defines three means of interaction:

  • Messages from the Controller to the Skin
  • Messages from the Skin to the Controller
  • Shared data

Messages from the Controller should be passed to the skin via method calls. Messages from the skin should be posted via an event. Shared data should be referenced by properties. Once you have defined the contract between your controller and its skin, you may then implement the skin and controller in whatever order and manner you choose. The end result is that you have a modular system in which new user interfaces can be deployed independantly of the application itself.

A code example of how this might be implemented will be posted in the near future.