Monthly Archives: September 2011

The Skyscraper, the Great Wall, and the Tree

One World Trade Center will be a 105 story super-skyscraper when completed. It’s estimated total cost is $3.1 Billion.

When it’s complete, how much would it cost to add the 106th story? Would it be 105th of $3.1 Billion? No. The building was constructed from the ground up to be a certain height. The maximum height depends on the ground it’s sitting on, the foundation, the first floor, and so on. Each of those would need to be strengthened to add one more story.

It’s possible to engineer a building so that you can add more floors later, but that means over-engineering the foundation and the structure.

Contrast the building of a skyscraper with the building of the Great Wall in China. The Great Wall is infinitely scalable. It stretches for many thousands of kilometers, and each additional kilometer probably cost less than the one before because the builders became more skilled as they worked.

The difference between the skyscraper and the Great Wall is all about dependencies. In the case of the skyscraper, every story depends on everything below it. In the case of the Great Wall, each section of wall only depends on the ground underneath, and the sections of wall on either side. If one section is faulty, you can easily demolish it and rebuild it. If one section is in the wrong place, you only have to rebuild a copy of sections to go around the obstacle.

When you’re building the Great Wall, you can probably take an experienced stonemason and have him start laying stone on the first day, without much thought about the design. With a skyscraper, it’s the opposite. You spend years designing before you ever break ground.

When people first started to write software, they built it like the Great Wall. Just start writing code. The program gets longer and longer. Unfortunately, complex programs don’t have linear dependencies. Each part of the code tends to have dependencies on every other part. Out of this came two things: the Waterfall model, and Modular programming. While modular programming was a success at reducing dependencies, and eventually led to object-oriented (and message-oriented) programming, the Waterfall model was eventually supplanted by Agile methodologies.

The software developed by Agile methodologies is neither like the Great Wall (there are still many inter-dependencies) and yet nothing like the traditional skyscraper (because the many dependencies are loosely coupled).

Agile software grows organically, like a tree. You can cut off a limb that’s no longer useful, or grow in a new direction when you must.

Many programmers seem to think that Agile means you don’t have to design. This isn’t true. A tree still has an architecture. It’s just a more flexible architecture than a skyscraper. Instead of building each new layer on top of the layers beneath it, you build a scaffolding structure that supports each module independently.

The scaffolding is made up of the SOLID principles like the single responsibility principle, and dependency injection, but it also consists of external structures like automated unit tests. If Agile software is like a tree, you spend more time on the trunk than the branches and more time on the branches than the leaves. The advantage is that none of the leaves are directly connected, so you can move them. That’s what it means to be Agile.

What are the trade-offs? Agile enthusiasts seem to think that every other methodology is dead, but that’s not true. You can still go higher, faster, with a skyscraper, or get started sooner with the Great Wall.

Embedded control systems for automobiles are still built like a skyscraper. That’s because the requirements should be very well known, and future changes are unlikely. On the other hand, you’d be surprised how many businesses run significant portions of their businesses on top of Excel spreadsheets. That’s typical Great Wall methodology. It works as long as complexity stays low.

Use Agile when you need complexity and flexibility.

Editing Logic is Business Logic

If you’re writing an “n-tier” application then you typically split your application into layers, like the “GUI layer”, “business logic layer”, and “data layer”. Even within those layers we typically have more divisions.

One of the advantages of this architecture is that you can swap out your outer layers. You should be able to switch from SQL Server to MySQL and all your changes should be confined to the data layer. You should be able to run a web interface in parallel with your desktop GUI just by writing another set of modules in the GUI layer.

This all sounds great in principle, so you start building your application and you run into problems. Here’s the typical scenario:

Business rule: one salesperson can be associated with one or more regions.

Business rule: each salesperson has exactly one “home region”, which must be one of their associated regions.

Now you go and build your entity model, and it probably looks like a SalesPerson class that inherits from the Employee class. There’s a many-to-many association between SalesPerson and Region. The relationship class (SalesPersonRegion) might have a boolean property called HomeRegion (there are other ways to model it, but that’s a typical and simple way).

Now, you can enforce these constraints on your entity model by making sure that you provide at least one Region in your SalesPerson constructor, and you make that the home region by default. You provide a SetHomeRegion method that throws an exception if you pass in a non-associated region, and you throw an exception if you try to dissociate the home region. If you do all this well, then your model is always consistent, and you can reason about your model knowing certain “invariant” conditions (as they’re called) are always true.

All of that, by the way, lives in the Domain Model, which is part of your Business Logic Layer.

Now let’s build our GUI where we can edit a SalesPerson. Obviously the GUI stuff goes in the GUI layer. Depending on your architecture, you might split up your GUI layer into “View” and “ViewModel” layers (if you use WPF) or “View” and “Controller” layers (if you’re using ASP.NET MVC).

Now unless you really don’t care about your users, this edit screen is going to have a Save and a Cancel button. The user is typically free to manipulate data on the screen in ways that don’t necessarily make sense to our business rules, but that’s OK as long as we don’t let them save until they get it right. Plus, they can just cancel and throw away all their edits.

My first mistake when I ran into this situation was assuming that I could just use the entities as my “scratch-pad” objects, letting the user manipulate them. In fact the powerful data binding features of WPF makes you think you can get away with this. Everyone wants to just bind their WPF controls directly to their entity model. It doesn’t work. Ok, let me be a little more specific… It works great for readonly screens, but it doesn’t work for editing screens.

To do this right, you need another model of the data during the editing process. This other model has slightly different business rules than the entity model you already wrote. For instance, in our example above about editing a SalesPerson, maybe you want to displays a list of possible regions on the right, let the user drag associated regions into a list on the left, drag out regions to dissociate them, and perhaps each region on the left has a radio button next to it allowing you to select the home region. During the editing process it might be perfectly legitimate to have no associated regions, or no home region selected. Unfortunately if you try to use your existing entity model to hold your data structure in the background, you can’t model this accurately.

There’s more than one way to solve this. Some programmers move the business rules out of the entity model and into a Validation service. Therefore your entity model allows you to build an invalid model, but you can’t commit those changes into the model unless it passes the validation. This approach has two problems: one, your entity model no longer enforces the “invariant” conditions that make it a little easier to work with (you have to test for validity every time someone hands you an entity), and two, certain data access layers, like NHibernate, automatically default to a mode where all entity changes are immediately candidates for flushing to the database. Using an entity you loaded from the database as a scratch pad for edits gets complicated. Technically you can disconnect it from the database, but then it gets confusing… is this entity real or a scratchpad?

Some other programmers move this logic into the ViewModel or Controller (both of which are in the GUI layer). This is where it gets ugly, for me. It’s true that the “edit model” is better separated from the “entity model”, but somewhere there has to be logic that maps from one to the other. When we load up our screen for editing a SalesPerson, we need to map the SalesPerson entity and relationships into the edit model, and when the user clicks Save, first we have to validate that the edit model can be successfully mapped into the entity model, and if it can’t then give the user a friendly hint about what needs to be fixed. If it can be mapped, then we do it. Do you see the problem? The sticky point is the Validation step. Validation logic is business logic. Most MVVM implementations I’ve seen essentially make the ViewModel the de-facto edit model, and they stuff the validation logic into the ViewModel as well. I think this is wrong. Business logic doesn’t belong in the GUI layer.

All of the following belongs in the business logic layer: the entity model, the edit model, the mapping logic from one to the other and back, and the validation logic.

If you follow this method, then WPF’s data binding starts to make sense again. You can map directly to the entity model if you have a read-only screen, and you can map to the edit model for your editing screens. (In my opinion, many situations call for both an “add model” and an “edit model” because the allowable actions when you’re adding something might be different than when you’re editing one that already exists… but that’s not a big deal.)

I apologize if this is all obvious to you, but I really wish someone would have explained this to me sooner. 🙂