Jan 31, 2011

Stacking or Slicing?

How do you design a new system? What order do you develop things?

One common approach is using separate layers to define what the system should do. Let's try it!

A user interface layer at the top. Then the server side with a business model layer coordinated by a controller layer. At the bottom is the data access layer and the actual database itself. This "separation of concerns" makes it possible for each technical expert to work on their specific layer.

Next, we continue by fleshing out each layer. For each layer, a solution is designed according to customers demands. This means we plan for all known requirements and maybe a few extra, because, as we all know, the customer may change her mind in the future.

Great! Next up is building it. With the design completed, experts run off to implement their specific layer. They know their TDD and write automated tests all the time to ensure each layer works as expected.

Once all are completed, we just have to put them together like a stack of pancakes and deliver the whole system. Sirup's optional!

Can you spot any problems with this approach?

The most important principle when creating software is early releases of valuable software. Consider two projects creating the same system:

The first project makes just one release. The second project creates releases each month. The resultis a huge difference in ROI. This means get get more feedback, marketing, more users for each new increment. The project could even fund itself during development. The only difference is how the two projects have structured their releases, and yet the result is miles apart. I'll bet your customer will be more satisfied as well.

The problem with designing for layers is that the product cannot be shipped until all layers are completed. This naturally happens at the end of the project, when time is already scarce. This is a sure way to integration hell, so you might as well prepare yourself for spending lots and lots of time testing, rewriting and duct-taping the parts together. Needless to say, this is not fun.

Now you might say this is not a problem with layering, but rather delaying their integration. Well, yes, but for that to work all layers must be in the same state (synchronized) at the same time. The chance of that is slim at best. Any lagging layer will effectively thwart all integration attempts. The only reasonable occasion is at the end of the project or at a defined milestone. It's like trying to complete a puzzle when you have all pieces, but they are constantly changing.

Why "at the end of project" or "at a milestone"? That's the only time we have reached a known level of functionality. If it was possible to reach that point earlier, we could integrate and release much sooner and they way to do that is by switching focus from completing layers to completing features.

Pick the most important feature today and implement it. That is what our users are paying us for, after all. Create the feature and make it complete, from top to bottom. I like to call this the "thin-slices" approach. To visualize it, consider the system as an empty box, database at the bottom and user interface at the lid. Adding features is akin to inserting vertical slices of functionality until we are satisfied, box completely filled or not. The layered method, on the other hand, is like pouring code into the box, slowly filling it from the bottom up until it is 100% full and only then ready for release.

How much of the layers should we complete? Create only those parts of each layer that is needed to complete the current feature. As simple as possible, develop parts of the architecture only when a specific feature calls for it. This means the system at any given moment is extremely tight, only consisting of code that has proven itself as part of a feature.

One important point is to refactor the code so it doesn't get stale. This also involves extracting common elements into more generic constructs. The goal is to reduce code duplication and let layers and abstractions emerge when they are actually needed, and not before that!

With the feature-based approach, there is no specific order layers should be developed. Rather it depends on the current feature you are implementing and the prioritization of them. After each completed feature, you integrate it into a working, potentially releasable system. This has a few advantages:
  • It makes it possible to release after each feature, rather than having to wait for whole system to be completed.
  • You can start making money much earlier (as in the image).
  • It helps make sure the system is working and not just a nicely layered architecture.
  • The client can test the system and give feedback during development. Feedback which can be used to make adjustments to the project, maybe even into new areas not originally intended.
  • It's possible to finish the project earlier. When it's good enough.
Following up with the puzzle example: you are creating each piece you as need it until you have created the most interesting parts of the puzzle. You don't have the whole picture, but that may not even be needed.

No comments:

Post a Comment

What are your comments? I'd love to hear 'em, so don't be shy now :-)  If you want to get in touch with me directly just drop me a mail.