Wednesday, September 08, 2010

How I got out of spaghetti and in to a domain model

Refactor code to reveal a domain model

"Spaghetti Code" hides a domain model. In OOP a domain model refers to the conceptual model of a software system. A simple domain might be a model that represents a calculator. There will be classes that represent the buttons and their functions and a class that represents the display, etc...

Spaghetti code is often the product of rapid development. A first step to untangling your code is to begin refactoring a model from it. Try to find code that performs similar or duplicate functionality. This code is a candidate for refactoring. If it works on an object that appears to be fundamental to the character of your system then it should be reworked in to a domain model class.

Encapsulate at the module level

There is a boundary where objects that your code consumes should end and your domain objects begin. Sometimes this is called an anti-corruption layer. An anti-corruption layer is useful for minimizing your exposure to objects consumed from referenced modules. It provides a single point of failure and a convenient way to repair or extend the interface. You could merely build a "wrapper" class that provides a pass-through directly to the consumed object's properties and methods or you could be more creative.

If your model will be exposing classes to other consumers then make sure that the only classes you expose come from your domain. Exposing classes that are from a dependency of your model will give you what I call "dependency bleed-through". Not only is your model dependent on those classes but now any consumer of your model is dependent on the same module that your model is. Talk about untestable code...

Simplicity and Structure

In my opinion, a domain model should lack complexity. The interactions of the objects in the model should be direct. Using indirection, such as delegates and events, adds complexity and should be avoided unless necessary. This will help you and your team to understand your domain and will reduce the time it takes for new team members to come up to speed.

A glossary of terms used in the domain can be helpful, especially for interacting with non-technical personnel. Using the same terminology as someone that doesn't work directly with the code can increase the quality of your communication with them. There is no time wasted on trying to understand what one or the other is referring to in the system.

Unit test your model. Unit testing ought to be called unit building because Test Driven Development (TDD) leads to well defined components. Obviously you aren't doing pure TDD but writing tests for your new model gives you a good idea of the function/responsibility of each class.

At the end...

Once you've gotten your model out of your spaghetti you will have a system that is more maintainable than it ever was. You'll probably still have some spaghetti code leftover that needs to be refactored in to other parts of your architecure, maybe a Model and a View, but you're off to a good start.

No comments: