Architecture is About People: Sharing Models

In this follow-up to the previous post on Architecture let’s visit a problem that lots of project have and most face as an unavoidable thing.

I have seemed this a lot in the past years. Once I worked at a product company that develop a very complex and distributed system. We had three different groups among developers: the first group was responsible or the client application, a Java Swing system that would send JMS messages and display 3D reports; the second group developed the business rules, transforming mathematical expressions and algorithms developed by domain specialists into Java code; I was member of the third group, those who provided the technical framework that others used. Each group would be independent to do their tasks, which were related but different.

In a few weeks I realized that something was wrong. Every single change I made would break lots of different modules across the software and I had to walk around the office asking people if there were any problem with the change. The walk around the office was eventually replaced by an email message and later by a weekly meeting.

The application was a 2+ years Java EE system that was developed when the company was a startup, by its founder. In the first years the coupling between part was easy to manage but when the company grow into a global 40+ developers it became very painful.

I remember entering the system architect’s room with a suggestion that would help the groups work more independently. When I sketched the model and the proposed solution in the whiteboard he looked at me in that way only architects do and said: “Whatever. I’m here to think about the future and in the future this won’t be a problem.”

At that moment I realized that the project was doomed.

Last year I met the guys that used to work with me at that place. Those who are still there says that –obviously- the architect’s proposals were never implemented and that after a massive failure developing an important feature they merged the three teams into one single 40 people team. It is basically the same thing that we had before but at least developers have the same title on their business cards.

I think the bigger problem in that architecture was that it was yet another example of ignoring one of its most important stakeholders: the developers.

Software design is about managing complexity and in a world where a greenfield project is some really rare to find we have to design our systems so that the complexity is limited to a manageable amount.

I’ve faced many time two kinds of artificial complexity caused by architectures that won’t take developers in account. The first kind is when the software we are working on is a part of a bigger system, a module or logical component of something bigger.

In this case generally part of our domain models comes from a shared code base. Your billing module needs to use the Subscriber objects from the subscriber management module, for example. The problem I frequently see in projects is that even if different groups, with different priorities, develop the modules the architecture faces the domain as a single artifact shared among modules.

Eric Evans summarizes quite well the problems of having a huge model:

Multiple models are in play on any large project. Yet when code based on distinct models is combined, software becomes buggy, unreliable, and difficult to understand. Communication among team members becomes confused. It is often unclear in what context a model should not be applied.

And he also gives the general guidelines to solve this problem:

Explicitly define the context within which a model applies. Explicitly set boundaries in terms of team organization, usage within specific parts of the application, and physical manifestations such as code bases and database schemas. Keep the model strictly consistent within these bounds, but don’t be distracted or confused by issues outside.

While the obvious solution is to split the big model into a few little models this is not straightforward. Questions always rise about the owner of a given class or concept and what happens when the owner changes the concept implementation without alerting the whole team. It is not rare that the team each team decides to have its own version of the shared domain -creating lots of different implementations of the same concept- so a change in one development stream won’t affect others.

The concerns about isolated teams changing the shared domain are valid but I see two simple ways of facing this problem so that you can keep complexity manageable and still integrate work from all teams seamlessly.

First you have to agree on a Shared Kernel, one of the Domain-Driven Design Patterns. The Shared Kernel contains a set of objects that are shared among subsystems or modules. Changing these objects is something that affects more than one team and it have to be done with more caution than when changing something specific to your module.

Generally in a real world™ system you have some objects that are part of the Shared Kernel but are too tied to a module. In the example above the Subscriber object is more used in the subscriber management module than any other module. If we ask the developers from the subscriber management module to wait for an OK from all teams before changing anything their work would never be finished.

What we need in that case is to rely on abstractions, not in implementations. This is Uncle Bob’s Dependency Inversion Principle and in practice it means that you should define a general contract for a concept and depend on the contract, not how the contract is implemented.

In our billing module example we would rely on an interface (a contract) that defines the operations that we need to work. Having a contract means that a class must fulfil the pre and post conditions defined on it.

This allows our code to be sure that the Subscriber is exactly what we need it to be and lets the that actually writes the Subscriber class to use whatever implementation they want to, and change that frequently without much impact.

Discipline with the shared concepts is a great tool when integrating modules but sometimes it isn’t enough. In that 3-module system I talked before in this post we had lots of cases where sharing objects by itself wouldn’t solve the problem. I can remember a particular case between the guys developing the user interface and the business model developers.

The business model guys thought of a sale as an instance of a sales class. It had a defined set of attributes and those wouldn’t change. The guys developing the UI, in the other hand, had a different concept of sale. For them a sale was something that was editable by the user, he or she could add or remove attributes from it besides changing values. When the user added or removed attributes from a sale the business model faced that as a new version of the sale but for the UI the concept of versioned objects wasn’t relevant at all. Although the UI needs the information coming into the sale object from the business model it couldn’t simply use it without previous transformation of some kind.

In this case I can think of other Domain-Driven Design pattern, named Anti-Corruption Layer. The Anti-Corruption Layer translates between a model to other, in our example it would transform sales into ui-sales objects and vice-versa.

Generally the layer accomplishes this by using the old adapter and façade patterns. It would wrap the sale object into an adapter that allows the user interface to deal with it as it was a ui-sale object and will convert changes made to a ui-sale object to the business model’s sale concept.

Its main benefit is that it keeps all transformation into a single layer instead of mixed with business code. This means that if something changes in the sale class we can still keep our UI code and just change the transformation code into that specific layer.

Those strategies show the most important thing when having separate modules (even if they are developer by the same team): integration adds complexity, limit integration and handle it with discipline. Next post we will talk about the other kind of artificial complexity: when you have to use a framework developed by other team.

4 Responses to “Architecture is About People: Sharing Models”


  1. 1 Bruno Laturner Feb 17th, 2008 at 9:53 am

    Is that the same principle of using Proxy Classes to take care of the integration borders between the systems?

  2. 2 Phillip Calçado "Shoes" Feb 19th, 2008 at 10:22 pm

    Hi Bruno,

    I’m not sure of what the proxy in your case actually does but I’d say no. Proxies will intercept calls, integrating two subsystems you could make a remote call look like a local call if you use a proxy to encapsulate it, but it is different from what the text suggests.

    The text is talking abut how to integrate and manage dependencies among domains. It doesn’t really matter the technology used to make calls here, if they’re local or remote, in any scenario you’ll have problems trying to integrate different subdomains into the same system.

    cheers

  3. 3 Nicolas Jan 23rd, 2009 at 8:31 am

    Hi,

    A well known pattern in .NET world of WPF is Model-View-ViewModel, and your example on the difference between SaleUI and Sale, is the same thing that the difference between ViewModel and the model! I use this pattern even has a single developper because a SaleUI is coupled with UI concept (binding, property changed and so on…) whereas Sale is only a business concept. So even when you are a single developper you have to create two differente view of the same concept.

    And I think this pattern should be extended for the interaction between a business object in a database and your real business object.
    (Wow now we have 3 view on the same concept, but I think it’s OK)

  4. 4 Phillip Calçado "Shoes" Jan 23rd, 2009 at 3:38 pm

    Hi Nicolas,

    AFAIK, the Model-View-ViewModel is just a name for the application of Presentation Models in Smart Clients. The concept are similar but this text is about shared models, not just layering. You may want to check out this article:

    http://fragmental.tw/2008/12/22/internal-data-transfer-objects/

    It talks a bit about Layers and how not using the model properly can get one into a bad architecture.

Leave a Reply








Creative Commons License

This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.