Layered Architecture and Ownership Inversion


Most of you know the Dependency Inversion Principle (DIP) and use abstractions when designing modular, flexible and maintainable systems. But do you have your abstractions defined in the correct layers?

Dependency Inversion and Layered Architecture

A few weeks ago, I took part on an agile programming meetup, which was held by one of the senior developers of the company I am currently working for. I expected usual talk about extreme programming (pair programming, TDD, refactoring, etc.). But this meetup started quite differently. The speaker drew a typical modular scheme of enterprise application as below.


As you can see, this is completely common example of structured object-oriented architecture. In this diagram, the high level Web App layer uses/references a lower-level Business layer, which in turn uses DAL and Web services layers.

The developer turned to us and said, "I expect that architecture of applications most of you is working on, looks like this. Do you think it's okay?'" We started looking at each other aware of fact, that our apps looked exactly like that (except the different layers). "Well, I think this approach is wrong", declared he, "why do you let the business layer to be dependent on all the other layers, when the business is the core of your application? All the other layers could be replaced/modified in the future..."
I must admit, he was right. After the meeting I dug in and read something about this topic. I wanted to know what are the benefits of this inversed approach and how should we implement it correctly.

I found the most relevant information in the book Agile Principles, Patterns, and Practices in C#, where is a whole chapter dedicated to DIP and its implementation in modular architecture. The following statement explains it quite well.

"The dependency structure of a well-designed object-oriented program is "inverted" with respect to the dependency structure that normally results from traditional procedural methods. It is the high-level modules that contain the important policy decisions and business models of an application. These modules contain the identity of the application. Yet when these modules depend on the lower-level modules, changes to the lower-level modules can have direct effects on the higher-level modules and can force them to change in turn. High-level modules simply should not depend on low-level modules in any way."

Agile Principles, Patterns, and Practices in C#
(ch. 11)

Ownership Inversion

I was sold. The question was, how we can invert the dependencies in our application. Luckily, the solution was quite simple. Our problem was that the abstract interfaces used in the business layer (e.g. repository interface) were declared in the lower-level layers. This way we had to reference DAL and Web Services layer from our Business layer. To invert the references, we moved the affected abstract interfaces to the Business layer. This way, the upper layers do not depend on the lower layers anymore. Instead, the lower layers depend on abstract interfaces declared in the Business layer.


As you can see, interfaces required by the Business layer are declared within it's package now and not in the libraries that implement them. In the mentioned Agile Principles book, Robert C. Martin calls this phenomenon Ownership Inversion.

"We often think of utility libraries as owning their own interfaces. But when DIP is applied, we find that the clients tend to own the abstract interfaces and that their servers derive from them."

Agile Principles, Patterns, and Practices in C#
(ch. 11)

Benefits of this approach

  • Separation of concerns.
  • The business module is not affected by changes in lower-level modules (it don't even reference them). For example, you can switch the database implementation without redeploying the business library.
  • The business module can be tested in isolation, without references to low-level layers.
  • The high-level modules can be reused quite simply in different contexts.

Viktor Borza

Freelance .NET developer with passion for software architecture and cutting-edge trends in programming.


Comments


Latest Posts

Browse

Archive All posts