Tuesday, October 23, 2007

Model View Presenter Data Binding Part 2: The Model

In my Model-View-Presenter application, the Model is fairly simple, but can be extended to be more complicated (I guess that's really true for just about anything). I won't go into details on persistence, I'm going to concentrate on how I do the data binding. For the Model, I follow the same pattern for properties that I did on the View:
int _nThingy;
public int Thingy
{
   get
   {
       return _nThingy;
   }
   set
   {
       bool bChanged = (this.Thingy != value);
       _nThingy = value;
       if (bChanged) FireDataChanged("Thingy");
   }
}
The FireDataChanged(string) method will fire a PropertyChanged event for the specified property. When I'm working with collections, I create a class that inherits from BindingListBase (my custom .NET 1.1 class that implements IBindingList) or from System.ComponentModel.BindingList (when using .NET 2.0). Both IBindingList implementations will look for changes to each of the elements in the list and translate them to ListChanged events. This will make life really easy when binding to grids and lists. Oh yea, I almost forgot, there's one more piece that needs to be in place. The data object needs to implement IEditableObject. The MSDN documentation has an example on how to implement it. While this is deceptively simple, it does have some interesting consequences. Now, I can make changes to properties (with sheer impunity) and I can notify everyone else of all the changes that happen on the data objects. Here's an example: I have a program that lets the user define a set of tubular equipment that is laid end to end. Each piece of equipment has the following properties: Inner Diameter, Outer Diameter, Top Depth, Bottom Depth, Length. For the sake of simplicity, lets say they are all integers. For each equipment, Bottom Depth = Top Depth + Length. The equipment has to enforce this rule all the time. Also, when making adjustments, it should favor keeping the Length property constant. Here's how the properties end up looking:
public int TopDepth
{
   get { return _nTopDepth; }
   set
   {
       bool bChanged = (this.TopDepth != value);
       _nTopDepth = value;
       if (bChanged)
       {
           this.BottomDepth = this.TopDepth + this.Length;
           FireDataChanged("TopDepth");
       }
   }
}

public int BottomDepth
{
   get { return _nBottomDepth; }
   set
   {
       bool bChanged = (this.BottomDepth != value);
       _nBottomDepth = value;
       if (bChanged)
       {
           this.Length = this.BottomDepth - this.TopDepth;
           FireDataChanged("BottomDepth");
       }
   }
}

public int Length
{
   get { return _nLength; }
   set
   {
       bool bChanged = (this.Length != value);
       _nLength = value;
       if (bChanged)
       {
           this.BottomLength = this.TopDepth + this.Length;
           FireDataChanged("Length");
       }
   }
}
If I set any of these three properties, the others will be synced up until the system stabilizes. Also, setting any one property will not only make adjustments to another property, it will fire both notifications automatically. This is OK for a single piece of equipment, but we need to have some more interaction between the equipment. When the BottomDepth of a piece of equipment changes, the next equipment's TopDepth needs to change. When the TopDepth of a piece of equipment changes, the previous equipment's BottomDepth needs to change. To make this work, we hook into the ListChanged event on the BindingList and look at the ListChangedEventArgs.PropertyDescriptor property. If the change was BottomDepth or TopDepth, we make a change to the appropriate item. We have to take care of all the different types of ListChanged events: ItemAdded, ItemChanged, ItemDeleted, ItemMoved, and Reset. In each case, we make sure the adjacent TopDepth/BottomDepth pairs match up on the changed equipment. Once all the pieces are in place, I just need to create a list, add some items to it, then set the DataSource property of a DataGridView, sit back, and watch the magic. If you edit the TopDepth, Length, or BottomDepth columns, then the model will make the adjustments and the DataGridView will be automatically updated. Also, you can assign the same list instance to another DataGridView, then the two grids will be synchronized automagically. This is the basis for the Model layer of the Model View Presenter architecture. Using these techniques, we can bind any collection of data fearlessly to any UI component as well as binding properties with each other.

Monday, October 08, 2007

ALT.NET Conference Sessions: Architecture

I rummaged Technorati and looks like a lot of people already put up their summaries / impressions of the sessions at the ALT.NET Conference in Austin, TX. Here's some more about some of the sessions that I'm not seeing much discussion about: Architecture (Trends and Observations) The architecture chat started off a little sparse, but fattened up nicely fairly quickly. Aaron Armstrong was driving the conversation to see what people were seeing in architectures. There were a lot of familiar terms on the whiteboard (I can't really remember them all, did anyone write this down?) I stood up and talked about the Model-View-Presenter architecture of the WinForms application I'm working on at work (picture 1, picture 2). I have a post about it that I'm planning to turn into a series of posts with some code and stuff. There was some interest in the data binding work I was doing, too. I'll talk more about that later. The main point that I was trying to make was that you can have multiple Models that don't know anything about the Views and are tied together using the Presenters. You can have multiple Models aggregated (in whole or partially) into one or more Views. Aaron asked how someone would handle the scenario where you have a composite View in a WinForms application. The approach I would use would be to expose the different sub-Views on the composite View as properties and use an Inversion of Control framework to tie it all together. In the application I'm working on, I'm using Spring.NET to tie everything together (coincidentally, Mark Pollack was in the back of the room). My property data binding would then keep everything in sync. The conversation then moved to more distributed architectures and web-related systems. There was some mention of the technique of using commodity hardware and/or software to create cheaply replaceable systems. On a similar note, Amazon released a white paper (papers?) on "Dynamo", their network architecture. It is designed with the simple fact that hardware will fail and needs to be easily (and cheaply) replaceable. We also talked about Service-Oriented Architecture and what to do about data. Some people feel compelled to integrate all the databases and data sources into one unified database. This leads to some friction as the different functions of the system move forward. When the data stores are properly separated, then the needs of the different applications (or services) can be met without affecting other applications (or services) that may be using the same data store. Everyone agreed that the database should not be used as an integration tool. Someone (I forget who) also explained the idea of thinking of the data flowing through the distributed system as a "document" instead of just messages going back and forth. We also talked a little about how to have a good architecture while still doing agile development. Agile development is against "Big Design Up Front", but sometimes you will need to have a vision and an architecture to scale properly. The main idea is to keep the architecture simple at first, get the project working, then make refinements as needed. Don't optimize too early, otherwise you may end up debugging strange issues that would not have risen from a simpler design. Also, you can more easily optimize when you start from a simple design and you can do small steps at a time to keep the system stable as you try to improve performance. That's all I can remember off the top of my head. I'm sure others will fill in the gaps and make corrections. All in all, it was a very interesting talk. Software Architecture is one of the subjects that I am very interested in and I found it very invigorating to hear from others and their thoughts on architecture.

ALT.NET Conference Sessions: DSL

I rummaged Technorati and looks like a lot of people already put up their summaries / impressions of the sessions at the ALT.NET Conference in Austin, TX. Here's some more about some of the sessions that I'm not seeing much discussion about: Domain-Specific Languages for Business Users / Developers The DSL talk started off a little rough (the organizer wasn't there), but Arafat Mohamed stepped up and started the conversation. Just about everyone in the room was there to learn about DSLs and were not really using them in their projects. We talked about what we thought a DSL really was. It seems that just about anything can be a DSL (depending on how specific you are to what domain). According to Martin Fowler, "a domain-specific language is a veneer over an API" (I think that's the verbage he used). He differentiates between an internal DSL (one that is consumed by developers) versus an external DSL (one that is consumed by the users). Martin Fowler has some more information on his website. There is also some information on Wikipedia. One of the primary applications for DSLs that I can think of is a business rules engine. For example, you have a cell phone provider who has complex billing semantics and wants to be able to add new rules easily. There are a lot of concerns with this, however. Developers may not want the analysts modifying the behavior of the system as they may not be as disciplined. On the flip side, managers want the analysts to do the work to keep the developer freed up. It is a delicate balance that can only really be helped by properly training the analysts so that they know the proper practices. You can also avoid problems by creating the proper tooling. Going to the more practical side... Scott Guthrie pointed out that IL had some pragmas that could be used to give the debugger hints on what the original source file was and what line of that source file corresponds to the generated code. He said that they used this mechanism for debugging the generated code from XAML, XOML and the other declarative constructs. You could also use Boo as a meta-language to construct your DSL. In theory, Visual Studio should be able to debug Boo since Boo compiled to IL and _should_ have the line numbers and source file information embedded in the PDB files. (in theory). Boo is also the source of Boobs (the build system with an oral fixation) and Binsor. Oren (Ayende) has a lot of posts regarding Boo. Also, if you want good IDE support for Boo, look at SharpDevelop. If you need to develop your own language from scratch, Antlr seems to be the way to go. The people in the room who had used it said it was better than the old-school lexx / yacc approach. There are a lot of concerns though in creating a DSL in that you would have to maintain it and train everyone how to use it. This reminds me of two things: 1) Wasabi, the language created by Joel Spolsky for FogBugz (linky) 2) The MUMPS System (linky) In both cases, developers will basically have a bunch of work that they can't really put on their resume because their expertise is in an in-house language. A DSL may create the same sort of situation. Also, whoever develops the DSL will be the authority on it and if he/she decides to leave the company without properly documenting it, the DSL will be useless. At the end of the session, I think everyone got a good feel for the positives and negatives of creating and using domain-specific languages. I learned that I would need to think long and hard before considering implementing a DSL and that there are a lot of solutions (Boo, Ruby, scripting) that would require a lot less work up front and would provide fellow developers with some take-aways. Another summary on the DSL session: David Woods

Sunday, October 07, 2007

Back from ALT.NET Conference

I just got back from ALT.NET Conference (http://www.altnetconf.com/) in Austin and it was a blast. I've only been to a few other "conferences" but this is the only one that I would actually consider a "conference" more than a one-way brain dump. I met a lot of interesting people who I've been reading about, but didn't really know. Everyone is really passionate about their work and they have strong opinions (that are not really set in stone). Everyone was very receptive to alternative techniques, theories and interpretations. I'm looking forward to participating more in this community. I would also like to thank everyone for being there and making my weekend spectacular! And also to thank the organizers for giving us such a unique and fulfilling opportunity. I think a few people were interested in the WinForms MVP data binding work I've been doing, I'll try to continue that series of posts as soon as possible (I started one a month ago, but haven't really continued it). I'll get some recreated code samples up too.