Wednesday, December 26, 2018

Improve Your Software Architecture with Ports and Adapters

Improve Your Software Architecture with Ports and Adapters

Software is often designed around modeling things in real life. The problem is, these designs do not translate well to clean software. The resulting architecture and code base are often coupled and difficult to maintain. A good example of coupling is interacting with a rails application with the intent of creating a new user record and accidentally triggering a welcome email to be sent. In this example, persistence is tightly coupled with domain logic. These tightly coupled applications violate one of the most important principles in software architecture, the single responsibility principle.

Single Responsibility Principle

The single responsibility principle can be defined in two ways:
  1. An object should do only one thing.
  2. An object should have only one reason to change.
The basics and understanding are simple; however, implementation is considerably more difficult. Drawing the dividing line through an object’s responsibilities can be difficult, and it is possible to split an object too many times.
There are also a few more things to keep in mind during when thinking about single responsibility. How often are things changing inside of the class, and how would I describe the object’s purpose to someone without any knowledge? When a class has pieces that are changing at different rates, the single responsibility principle is being probably being violated. Also, if you describe the object and use the words “and” or “or,” the class might be violating single responsibility.

Code Smells

There are also a number of code smells that can be indicators of single responsibility violation:
  • Methods that are too long. (Fewer than 5 lines is often a good number to aim for.)
  • Sawtooth code, which has many alternating levels of deep indentation.
  • Large values of cyclomatic complexity, which is a measure of how much decision logic is contained in a function.
As always, these principles are open to interpretation and should be applied pragmatically.

Problem: Single Responsibility in Traditional 3-Layer Architecture

3_tier_architectureIn a traditional 3-layered architecture, we split things into a presentation tier, a logic tier, and a data tier. This solves a few problems with single responsibilities, but it also creates a few, most prevalently within model–view–controller (MVC) projects with a complicated domain.
In MVC, views are kept logic-less and controllers are kept thin. Domain logic ends up getting shoveled into the data tier, resulting in objects that are a tangled mess of persistence and domain logic. The problem is that the SRP is not well represented in 3-layer architectures. We need a different way of looking at our software which promotes single responsibilities and decoupling.

Solution: Ports and Adapters

Ports and adapters, also known as hexagonal architecture, is an attempt to solve this problem of business logic becoming tightly coupled to other dependencies such as client frameworks and persistence. When implemented well, ports and adapters results in little classes with well-defined pieces of functionality. With these pieces of well-defined functionality, the classes are easy to name and the code base becomes comfortable for developers, resulting in reduced cost of maintenance and development. In addition, individual pieces can be mocked out, developed, and tested in isolation. Domain logic can be isolated from side-effect-inducing dependencies, specifically databases and web services.

Visualization

Ports and adapters presents a new way to view interactions between your objects, from a domain perspective. It can be visualized as an onion diagram, with the external entities on the outer most layer, adapters on the inner layer, and the domain logic at the core. I generally try to place the event-driving dependencies on the left and cooperative dependencies on the right.
ports_and_adapters_architecture

Ports

On the outermost layer lie the ports. These are pieces of dependent code or services that we do not have control over. These ports are anything external to our business logic such as user clients, persistence, and communication frameworks. I tend to split these up into two categories, event generating and collaborative.
The event-generating dependencies are ones that generate the events which drive our business logic. Our business logic will eventually be called on from these requests and eventually play a role in the formulation of a response. These can be any number of things such as users interacting with an MVC framework, other programs making calls against a web service, a developer manipulating objects in a REPL, subscribing to a message queue, and even automated tests.
The collaborative dependencies assist the domain with accomplishing a specific task. Examples of collaborative dependencies are databases, ORMs, external web APIs, and the producing side of a message queue.

Adapters

In the middle layer lies adapters, a gang of four pattern also called a wrapper. The adapter’s job is to translate an interface from a framework or class into a compatible interface. In my opinion, this is the most critical piece of ports and adapters. It provides an anti-corruption layer and keeps the external dependencies from leaking into our domain logic. By keeping these external dependencies from leaking, dependencies can be quickly interchanged, as long as the same interface is kept. This results in the code base becoming agile and flexible.
If a persistence framework were to be changed, there are only a handful of objects that will need to change — compared to a leaky codebase, which will require touching almost all pieces of code. The fewer objects we have to change, the less chance that something will break and the less costly maintenance and development becomes. Repository objects, which wrap an ORM, usually reside at this layer. There is also an added benefit: if table access becomes slow, it is easy to look in one place and see all the queries that are being used, which can make tuning and performance analysis easier.
The adapters for event generating dependencies are a little bit different since the users of our application reside at the port layer. Adapters are the implementation of MVC views, MVC controllers, and REST interfaces. These adapters will call through to the core domain to trigger specific actions.
For more information about ports and adapters, I recommend reading Alistair Cockburn’s article on hexagonal architecture, as well as Growing Object-Oriented Software Guided by Tests.

The Clean Architecture

The Clean Architecture

13 August 2012

Clean Arch, Onion and Hexagonal, all in on figure.

Interface Adapterns are set of Intefaces by which different Deatial lik DB, Infrastructure, Persistence, CCCs are injected to the application. these interfaces make the all the details plugins.




Over the last several years we’ve seen a whole range of ideas regarding the architecture of systems. These include:
  • Screaming Architecture from a blog of mine last year
  • DCI from James Coplien, and Trygve Reenskaug.
  • BCE by Ivar Jacobson from his book Object Oriented Software Engineering: A Use-Case Driven Approach
Though these architectures all vary somewhat in their details, they are very similar. 

They all have the same objective, which is the separation of concerns. 

They all achieve this separation by dividing the software into layers. 

Each has at least one layer for business rules, and another for interfaces.
Each of these architectures produce systems that are:
  1. Independent of Frameworks. The architecture does not depend on the existence of some library of feature laden software. This allows you to use such frameworks as tools, rather than having to cram your system into their limited constraints. Frameworks, DB, ORM, UI Frameworks, CCCs, Infrastrucutre. All these things are details and replaceable and mock able
  2. Testable. The business rules can be tested without the UI, Database, Web Server, or any other external element.
  3. Independent of UI. The UI can change easily, without changing the rest of the system. A Web UI could be replaced with a console UI, for example, without changing the business rules.
  4. Independent of Database. You can swap out Oracle or SQL Server, for Mongo, BigTable, CouchDB, or something else. Your business rules are not bound to the database.
  5. Independent of any external agency. In fact your business rules simply don’t know anything at all about the outside world.
The diagram at the top of this article is an attempt at integrating all these architectures into a single actionable idea.

The Dependency Rule

The concentric circles represent different areas of software. In general, the further in you go, the higher level the software becomes. The outer circles are mechanisms. The inner circles are policies.
The overriding rule that makes this architecture work is The Dependency Rule. This rule says that source code dependencies can only point inwards

Nothing in an inner circle can know anything at all about something in an outer circle. 

In particular, the name of something declared in an outer circle must not be mentioned by the code in the an inner circle. That includes, functions, classes. variables, or any other named software entity.
By the same token, data formats used in an outer circle should not be used by an inner circle, especially if those formats are generate by a framework in an outer circle. We don’t want anything in an outer circle to impact the inner circles.

Method Call and Passing Parameters 

Outer Layer
{

  innterlayer.Method(Data Types defined in Inner Layer);

}

Application Service Layer
{
// AS include the ref to the Domain Layer
// Domain Layer know nothing about the AS Layer
// While dealing with Lower Layer, its Data Structures are used
//While dealing with Lower Layers, Data Structures of Upper //layer are not used. 
//Call Lower Layer in terms of its own Data Structures.
// Talk to Lower Layer in its own Language or Data Structures.


domainLayer.Method(Entities/VO);
Entities/VO = domainLayer.Method();
}

UI Layer
{

// UI Layer include the ref to the AS Layer
// AS Layer know nothing about the UI Layer
// While dealing with Lower Layer, its Data Structures are used
//While dealing with Lower Layers, Data Structures of Uppper //layer are not used. 
//Call Lower Layer in terms of its own Data Structures.
// Talk to Lower Layer in its own Language or Data Structures.
We need Auto Mapper here to map the Data Structures of Layers
//Request/Reponse are POCO data structures defined in AS Layer
applicationServiceLayer.Method(Request/ResponseModel);
Request/ResponseModel = applicationServiceLayer.Method();

}

//We need Auto Mapper here to map the Data Structures of Layers

During Read Operations
RequestModel <== automapper <== Entities (in AS Layer)
ViewModel <== automapper <== RequestModel (in UI Layer)

During Write Operations
ViewModel ==> automapper ==> RequestModel (in UI Layer)

RequestModel ==> automapper ==> Entities (in AS Layer)

Entities in Domain Model or Domain Layer

Entities encapsulate Enterprise wide business rules.

An entity can be an object with methods, or it can be a set of data structures and functions.

It doesn’t matter so long as the entities could be used by many different applications in the enterprise.
If you don’t have an enterprise, and are just writing a single application, then these entities are the business objects of the application.

They encapsulate the most general and high-level rules. They are the least likely to change when something external changes.

For example, you would not expect these objects to be affected by a change to page navigation, or security. No operational change to any particular application should affect the entity layer.

Use Cases in Application Service Layer

The software in this layer contains application specific business rules.

It encapsulates and implements all of the use cases of the system.

These use cases orchestrate the flow of data to and from the entities, and direct those entities to use their enterprise wide business rules to achieve the goals of the use case.
We do not expect changes in this layer to affect the entities.

We also do not expect this layer to be affected by changes to externalities such as the database, the UI, or any of the common frameworks.

This layer is isolated from such concerns.
We do, however, expect that changes to the operation of the application will affect the use-cases and therefore the software in this layer.

If the details of a use-case change, then some code in this layer will certainly be affected.

Interface Adapters

Data Adapters/ Auto Mapper Components
Convert Data from type of Data Structure to Others

The software in this layer is a set of adapters that convert data from the format most convenient for the use cases and entities, to the format most convenient for some external agency such as the Database or the Web. 

It is this layer, for example, that will wholly contain the MVC architecture of a GUI. The Presenters, Views, and Controllers all belong in here. The models are likely just data structures that are passed from the controllers to the use cases, and then back from the use cases to the presenters and views.
Similarly, data is converted, in this layer, from the form most convenient for entities and use cases, into the form most convenient for whatever persistence framework is being used. i.e. The Database. No code inward of this circle should know anything at all about the database. If the database is a SQL database, then all the SQL should be restricted to this layer, and in particular to the parts of this layer that have to do with the database.
Also in this layer is any other adapter necessary to convert data from some external form, such as an external service, to the internal form used by the use cases and entities.

Frameworks and Drivers.

The outermost layer is generally composed of frameworks and tools such as the Database, the Web Framework, etc. Generally you don’t write much code in this layer other than glue code that communicates to the next circle inwards.
This layer is where all the details go. The Web is a detail. The database is a detail. We keep these things on the outside where they can do little harm.

Only Four Circles?

No, the circles are schematic. You may find that you need more than just these four. There’s no rule that says you must always have just these four. However, The Dependency Rule always applies. Source code dependencies always point inwards. As you move inwards the level of abstraction increases. The outermost circle is low level concrete detail. As you move inwards the software grows more abstract, and encapsulates higher level policies. The inner most circle is the most general.

Crossing boundaries.

At the lower right of the diagram is an example of how we cross the circle boundaries. It shows the Controllers and Presenters communicating with the Use Cases in the next layer. Note the flow of control. It begins in the controller, moves through the use case, and then winds up executing in the presenter. Note also the source code dependencies. Each one of them points inwards towards the use cases.
We usually resolve this apparent contradiction by using the Dependency Inversion Principle. In a language like Java, for example, we would arrange interfaces and inheritance relationships such that the source code dependencies oppose the flow of control at just the right points across the boundary.
For example, consider that the use case needs to call the presenter. However, this call must not be direct because that would violate The Dependency Rule: No name in an outer circle can be mentioned by an inner circle. So we have the use case call an interface (Shown here as Use Case Output Port) in the inner circle, and have the presenter in the outer circle implement it.
The same technique is used to cross all the boundaries in the architectures. We take advantage of dynamic polymorphism to create source code dependencies that oppose the flow of control so that we can conform to The Dependency Rule no matter what direction the flow of control is going in.

What data crosses the boundaries.

Typically the data that crosses the boundaries is simple data structures. You can use basic structs or simple Data Transfer objects if you like. Or the data can simply be arguments in function calls. Or you can pack it into a hashmap, or construct it into an object. The important thing is that isolated, simple, data structures are passed across the boundaries. We don’t want to cheat and pass Entities or Database rows. We don’t want the data structures to have any kind of dependency that violates The Dependency Rule.
For example, many database frameworks return a convenient data format in response to a query. We might call this a RowStructure. We don’t want to pass that row structure inwards across a boundary. That would violate The Dependency Rulebecause it would force an inner circle to know something about an outer circle.
So when we pass data across a boundary, it is always in the form that is most convenient for the inner circle.

Conclusion

Conforming to these simple rules is not hard, and will save you a lot of headaches going forward. By separating the software into layers, and conforming to The Dependency Rule, you will create a system that is intrinsically testable, with all the benefits that implies. When any of the external parts of the system become obsolete, like the database, or the web framework, you can replace those obsolete elements with a minimum of fuss.

Screaming Architecture

30 September 2011



Imagine that you are looking at the blueprints of a building. This document, prepared by an architect, tells you the plans for the building. What do these plans tell you?
If the plans you are looking at are for a single family residence, then you’ll likely see a front entrance, a foyer leading to a living room and perhaps a dining room. There’ll likely be a kitchen a short distance away, close to the dining room. Perhaps a dinette area next to the kitchen, and probably a family room close to that. As you looked at those plans, there’d be no question that you were looking at a house. The architecture would screamhouse.
Or if you were looking at the architecture of a library, you’d likely see a grand entrance, an area for check-in-out clerks, reading areas, small conference rooms, and gallery after gallery capable of holding bookshelves for all the books in the library. That architecture would screamLibrary.
So what does the architecture of your application scream? When you look at the top level directory structure, and the source files in the highest level package; do they scream: Health Care System, or Accounting System, or Inventory Management System? Or do they scream: Rails, or Spring/Hibernate, or ASP?

The Theme of an Architecture

Go back and read Ivar Jacobson’s seminal work on software architecture: Object Oriented Software Engineering. Notice the subtitle of the book: A use case driven approach. In this book Ivar makes the point that software architectures are structures that support the use cases of the system. Just as the plans for a house or a library scream about the use cases of those buildings, so should the architecture of a software application scream about the use cases of the application.
Architectures are not (or should not) be about frameworks. Architectures should not be supplied by frameworks. Frameworks are tools to be used, not architectures to be conformed to. If your architecture is based on frameworks, then it cannot be based on your use cases.

The Purpose of an Architecture

The reason that good architectures are centered around use-cases is so that architects can safely describe the structures that support those use-cases without committing to frameworks, tools, and environment. Again, consider the plans for a house. The first concern of the architect is to make sure that the house is usable, it is not to ensure that the house is made of bricks. Indeed, the architect takes pains to ensure that the homeowner can decide about bricks, stone, or cedar later, after the plans ensure that the use cases are met.
A good software architecture allows decisions about frameworks, databases, web-servers, and other environmental issues and tools, to be deferred and delayed. A good architecture makes it unnecessary to decide on Rails, or Spring, or Hibernate, or Tomcat or MySql, until much later in the project. A good architecture makes it easy to change your mind about those decisions too. A good architecture emphasizes the use-cases and decouples them from peripheral concerns.

But what about the Web?

Is the web an architecture? Does the fact that your system is delivered on the web dictate the architecture of your system? Of course not! The Web is a delivery mechanism, and your application architecture should treat it as such. The fact that your application is delivered over the web is a detail and should not dominate your system structure. Indeed, the fact that your application is delivered over the web is something you should defer. Your system architecture should be as ignorant as possible about how it is to be delivered. You should be able to deliver it as a console app, or a web app, or a thick client app, or even a web service app, without undue complication or change to the fundamental architecture.

Frameworks are tools, not ways of life.

Frameworks can be very powerful and very useful. Framework authors often believein their frameworks. The examples they write for how to use their frameworks are told from the point of view of a true believer. Other authors who write about the framework also tend to be disciples of the true belief. They show you the way to use the framework. Often it is an all-encompassing, all-pervading, let-the-framework-do-everything position. This is not the position you want to take.
Look at each framework with a jaded eye. View it skeptically. Yes, it might help, but at what cost. How should I use it, and how should I protect myself from it. How can I preserve the use-case emphasis of my architecture? How can I prevent the framework from taking over that architecture.

Testable Architectures.

If you system architecture is all about the use cases, and if you have kept your frameworks at arms-length. Then you should be able to unit-test all those use cases without any of the frameworks in place. You shouldn’t need the web server running in order to run your tests. You shouldn’t need the database connected in order to run your tests. Your business objects should be plain old objects that have no dependencies on frameworks or databases or other complications. Your use case objects should coordinate your business objects. And all of them together should be testable in-situ, without any of the complications of frameworks.

Conclusion

Your architectures should tell readers about the system, not about the frameworks you used in your system. If you are building a health-care system, then when new programmers look at the source repository, their first impression should be: “Oh, this is a heath-care system”. Those new programmers should be able to learn all the use cases of the system, and still not know how the system is delivered. They may come to you and say: “We see some things that look sorta like models, but where are the views and controllers”, and you should say: “Oh, those are details that needn’t concern you at the moment, we’ll show them to you later.”

For more on this topic, see Episode VII - Architecture, Use-cases, and High Level Design, at cleancoders.com.

Chop Onions Instead of Layers in Software Architecture

Chop Onions Instead of Layers in Software Architecture
Chopping onions usually makes you cry. This is not the case in software architecture. On the contrary! The onion architecture, introduced by Jeffrey Palermo, puts the widely known layered architecture onto its head. Get to know the onion architecture and its merits with simple and practical examples. Combined with code structuring by feature your software is easy to understand, changeable and extendable. Turn your tears of sorrow into tears of delight. For a very long time the standard answer to the question how components and classes should be organized in the software architecture was layers. Before we explore the promised benefits of layers and how they represent themselves in software architecture, we need to get rid of a common misconception regarding layers vs. tiers.
Layers vs. Tiers
When we talk about layers, we mean the logical separation or division of components and functionality and not the physical location of components in different servers or places. The term "tiers" refers to the physical distribution of components and functionality in separate servers, including the network topology and remote locations. Tiers are usually used to refer to physical distribution patterns such as "2 Tier", "3 Tier" and "N Tier". Unfortunately, both layers and tiers often use similar names. In this article, we talk about layers and not tiers! Nevertheless, what is a layer besides a logical separation and when was it introduced?
In the year 1996 Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad and Michael Stal analyzed different software systems. They asked themselves what patterns make software systems successful and allow us to evolve systems without developing a big ball of mud. Their knowledge was published in a book called Pattern-oriented Software Architecture – A System of Patterns. [12]
In that book they came to the conclusion that large systems need to be decomposed in order to keep structural sanity. The so-called Layer pattern should help to structure applications that can be decomposed into groups of subtasks in which each group of subtasks is at a particular level of abstraction. The initial inspiration came from the OSI 7-layer Model defined by the International Standardization Organization. This inspired the original N-Layer model.
N-Layer model
The layer higher in the hierarchy (Layer N+ 1) only uses services of a layer N. No further, direct dependencies are allowed between layers. Therefore, each individual layer shields all lower layers from directly being access by higher layers (information hiding). It is essential that within an individual layer all components work at the same level of abstraction. This approach is also called strict layering. The relaxed or flexible layering is less restrictive about the relationships between layers. Each layer may use the services of all layers below it. The advantage of this approach is usually more flexibility and performance (less mappings between layers) but this is paid for by a loss of maintainability.
In order to be able to define layers and put component into layers you have to define the abstraction criterion. For example, the lower levels can be defined by the distance from the hardware on the upper levels by the conceptual complexity. Possible layering could be chosen (top to bottom):
  • User-visible elements
  • Specific application modules
  • Common services level
  • Operating system interface level
  • Operation System
  • Hardware
The common layers they defined were
Other books or articles may name it differently but we will stick to that definition. We have the presentation or client layer, the process or service layer, the domain or business logic layer, the data access or infrastructure layer. Sometimes you see the layers above extended with another layer sitting on the left side spawning all layers. This layer is often called crosscutting layer which handles tracing, logging and more.
The advantages of this approach are:
Layer reuse
If an individual layer embodies a well-defined abstraction and has a well-defined and documented interface, the layer can be reused in multiple contexts. Naturally the data access seems a nice fit for layer reuse.
Supports standards
Clearly defined and commonly accepted levels of abstraction enable the development of standardized tasks and interfaces. After many years of layered architecture a lot of tools and helpers have been invented to automatically map from one layer to another for example.
Local dependencies
Standardized interfaces between layers usually confine the effect of code changes to the layer that is changed.
Layer exchange
Individual layer implementations can be replaced by semantically equivalent implementations without too great of an effort.
Upon first sight the layer model seems straightforward and easy to adopt. Unfortunately developers often take the layering literally. Sometime later, this happens…
Instead of getting the best out of the benefits of the layered architecture style, we end up with several layers dependent on the layers below it. For example giving the previous layering structure the presentation layer depends on the application layer and then on the domain layer and finally on the database layer. This means that each layer is coupled to the layers below it and often those layers end up being coupled to various infrastructure concerns. It is clear that coupling is necessary in order for an application to be able to do anything meaningful but this architecture pattern creates unnecessary coupling.
The biggest offender is the coupling of the UI and business logic to the data access. Wait a moment. Did I just say that the UI is coupled to the data access? Yes indeed. Transitive dependencies are still dependencies. No matter how anyone else tries to formulate it. The UI cannot function if the business logic is not available. The business logic in return cannot function if the data access is not available. We gracefully ignore the infrastructure because typically it varies from system to system. When we analyze the architecture above in retrospective, we detect that the database layer is becoming the core foundation of the whole application structure. It is becoming the critical layer. Any change on the data access / infrastructure layer will affect all other layer of the application and therefore changes ripple through from the bottom to the top of the application.
This architecture pattern is heavily leaning on the infrastructure. The business code fills in the gaps left by the infrastructural bits and pieces. If a process or domain layer couples itself with infrastructure concerns, it is doing too much and becomes difficult to test. Especially this layer should know close to nothing about infrastructure. Infrastructure is only a plumbing support to the business layer, not the other way around. Development efforts should start from designing the domain-code and not the data-access, the necessary plumbing should be an implementation detail.
Layer.Factory sample
To illustrate the layer architecture, we will analyze a Layer.Factory code sample that is available on github [13]. The Layer.Factory sample is a very simple Domain Driven Design sample application which follows the layered architecture pattern. The idea is that the domain model behind it represents a factory which produces layers (what a coincidence). In order to be able to create layers a factory responsible for creating layers must be created first. In order to analyze our sample application, we use a tool called Structure101 Studio. Structure101 Studio is a commercial tool which helps to visualize and organize large code bases in various programming languages. When we analyze the sample application with Structure101 Studio we see that the application is well structured. It contains no namespace or class tangles and no fat namespaces or classes. From a structural complexity perspective our application is in good shape. The dependencies are only going down from layer to layer. Therefore the sample adheres the strict layering principles.
In order to see how the application structures itself internally we need to drill down deeper.
The presentation layer entry point is the LayerProductionPresenter. The LayerProductionPresenter uses the ILayerProductionApplicationService to open a factory and produces layers by using the previously opened factory. Because the application follows the strict layering pattern, the process layer has to translate domain objects into data transfer objects residing in the process layer (FactoryInfo and LayerInfo). The presentation layer can only use these data transfer objects to present information on the views. Data held by the domain objects has to be translated from layer to layer.
Drilling down deeper into the domain layer makes this issue more apparent. The LayerProductionApplicationService uses a set of Domain Services. These Domain Services implement the core business logic of the application and directly expose the domain model’s aggregates, entities and value objects (i.e. FactoryFactoryIdFactoryNameLayerLayerQuantity).
As we can see, there is a bunch of translation from top to bottom and from bottom to top going on. Input information floating down from the presentation to the domain layer has to be translated from the presentation data transfer objects to the process data transfer objects and ultimately to the domain objects. Output information going up from the domain to the process layer has to be translated from the domain objects to the process data transfer objects and ultimately to the presentation data transfer objects. As long as only data is transferred the mapping process is tedious but manageable. As soon as the presentation layer would like to reuse business rules from the core domain model this approach’s drawbacks outweigh its benefits.
How do we get around the drawbacks of the layered architecture? With onions! What else?
Onion Architecture
We simply move all infrastructure and data access concerns to the external of the application and not into the center. Jeffrey Palermo proposed this approach called Onion Architecture on his blog 2008. The approach is nothing new. However, Jeffrey liked to have an easy to remember name, which allows communicating the architecture pattern more effectively. Similar approaches have been mentioned in Ports & Adapters (Cockburn), Screaming Architecture (Robert C. Martin), DCI (Data Context Interaction) from James Coplien, and Trygve Reenskaug and BCE (A Use Case Driven Approach) by Ivar Jacobson. Let us depict the onion architecture.
The main premise is that it controls coupling. The fundamental rule is that all code can depend on layers more central, but code cannot depend on layers further out from the core. In other words, all coupling is toward the center. This architecture is unashamedly biased toward object-oriented programming, and it puts objects before all others.
Furthermore the Onion Architecture is based on the principles of Domain Driven Design. Applying those principles makes only sense if the application has a certain size and complexity. Be sure to reflect properly on that point before jumping blindly into the Onion Architecture. Let us see what Onions combined with Domain Driven Design produces.
In the very center, we see the Domain Model, which represents the state and behavior combination that models truth for the organization (everything unique to the business: Domain model, validation rules, business workflows). The number of layers in the application core will vary, but remember that the Domain Model is the very center, and since all coupling is toward the center, the Domain Model is only coupled to itself.
The first ring around the Domain Model is typically where we would find interfaces that provide object saving and retrieving behavior, called repository interfaces. The object saving behavior is not in the application core, however, because it typically involves a database. Only the interface is in the application core.
Out on the edges we see UI, Infrastructure, and Tests. The outer rings are reserved for things that change often. This approach to application architecture ensures that the application core doesn't have to change as: the UI changes, data access changes, web service and messaging infrastructure changes, I/O techniques change.
The Onion Architecture relies heavily on the Dependency Inversion principle. The application core needs implementation of core interfaces, and if those implementing classes reside at the edges of the application, we need some mechanism for injecting that code at runtime so the application can do something useful. So tools like Guice, Ninject etc. are very helpful for those kinds of architectures but not a necessity.
The application is built around an independent object model. The whole application core is independent because it cannot reference any external libraries and therefore has no technology specific code. The inner rings define interfaces. These interfaces should be focusing on the business meaning of that interface and not on the technical aspects. So the shape of the interface is directly related to the scenario it is used in the business logic. The core takes ownership of these interfaces. Outer rings implement interfaces, meaning all technology related code remains in the outer rings. The outermost ring can reference external libraries to provide implementations because it contains only technology specific code. This allows pushing the complexity of the infrastructure (which has nothing to do with the business logic) as far outwards as possible and therefore, the direction of coupling is toward the center.
That approach makes us independent of several infrastructure and crosscutting concerns:
  • Database: The business rules do not depend upon the database (so storage can be swapped out)
  • UI: The UI can change without changing the rest of the system
  • Frameworks: The architecture does not depend on the existence of some library. This allows you to use frameworks as tools rather than having to cram your system into their limited constraints
  • External agency: Business rules do not know anything about the outside world.
Which leads us to the ultimate benefit of this architecture. The application core is 100% testable.
Onion.Factory sample
To illustrate the onion architecture, we will analyze an Onion.Factory code sample that is available on github [14]
The Onion.Factory sample is a very simple Domain Driven Design application which follows the onion architecture pattern. The idea is that the domain model behind it represents a factory which produces onions (what a coincidence). In order to be able to create onion, a factory responsible for creating onions must be created first. When we analyze the sample application with Structure101 Studio we see that the application is well structured. It contains no namespace or class tangles and no fat namespaces or classes.
All classes which have dependencies to concrete things like the database, the file system, the view and more reside in the outer rings. All dependencies are floating towards the core. No dependency points from the core into the outer rings.
In order to see how the application structures itself internally we need to drill into the core. The core is shown isolated without the outer rings.
The core itself is pure domain driven design and contains only what is near and dear to the heart of the business: the business domain and rules! When we reflect again about the layered architecture we remember that we needed to map from data transfer object to data transfer object over all layers. How does the presenter and its dependencies look like with the onion architecture?
The OnionProductionPresenter uses the IOnionProductionApplicationService. This is exactly the same dependency we’ve previously seen in the layered architecture. The real difference becomes apparent in the area where the presenter directly uses the domain model. The presenter uses and display information available on the domain model and can reuse business rules implemented in the domain model behind aggregates, entities and value objects. We don’t need to reinvent the wheel!
Layers vs. Onions
If we apply the principles of the Onion Architecture to the layered architecture, we need to turn the layer diagram upside down.
The key difference is that the Data Access, the presentation and the cross-cutting layer along with anything I/O related is at the top of the diagram and not at the bottom. Another key difference is that the layers above can use any layer beneath them, not just the layer immediately beneath. At least this approach could be achieved by using relaxed layering.
If we put the traditional layered architecture in concentric circles we clearly see the application is built around data access and other infrastructure. Because the application has this coupling, when data access, web services, etc. change, the business logic layer will have to change. The world view difference is how to handle infrastructure. Traditional layered architecture couples directly to it. Onion Architecture pushes it off to the side and defines abstractions (interfaces) to depend on. Then the infrastructure code also depends on these abstractions (interfaces). Depending on abstractions is an old principle, but the Onion Architecture puts that concepts right up front.
Refactoring from Layers towards Onions
Now that we know the difference between layers and onions, let us try to refactor the Layer.Factory sample towards an onion architecture. The first refactoring approach we’ll take will try to leave as many of the original namespaces intact, remember they are used in the sample to simulate layers. After applying the following steps
  • Introduce Core namespace
  • Move Process and Domain namespace into Core
  • Move FactoryRepository and LayerRepository into Data namespace
The code structures itself like the following:
We can see in that simple example that refactoring from a layered architecture to an onion architecture is not enough in order to get a true onion architecture. We actually need to redesign the software. The newly introduced Core still has a dependency outgoing. In order to get rid of this dependency we would need to introduce a small abstraction (interface) defined by the needs of the Core. The introduced interface needs then to be implemented by the outer rings (in the sample above by the SystemClock. Furthermore we need to get rid of the unnecessary abstractions introduced by the layered architecture in example by removing the unwanted data transfer objects.
Summary
Let us summarize what we learned. As easy as it may sound in the beginning, strictly following the layered architecture approach can lead to a big dependency tangle. Using the onion architecture approach makes you think about getting the dependencies right from the start. Combined with the introduction of necessary abstractions you achieve an independent application core which is fully testable. This allows you to maintain, protect and evolve what matters the most to your business: your domain logic! Chop onions instead of layers and turn your tears of sorrow into tears of delight.
References
  1. Alistair Cockburn Hexagonal Architecture
    http://alistair.cockburn.us/Hexagonal+architecture
  2. The Clean Architecture Uncle Bob
    http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html
  3. Screaming architecture Uncle Bob
    http://blog.8thlight.com/uncle-bob/2011/09/30/Screaming-Architecture.html
  4. Growing Object Oriented Software Guided by Tests, Steve Freeman & Nat Pryce, Addison-Wesley - Designing for Maintainability Page 47-49
  5. Ports and Adapters With No Domain Model http://www.natpryce.com/articles/000786.html
  6. Improve Your Software Architecture with Ports and Adapters
    http://spin.atomicobject.com/2013/02/23/ports-adapters-software-architecture/
  7. Implementing Domain Driven Design by Vaughn Vernon published by Addison-Wesley Professional - Chapter 4 Hexagonal or Ports and Adapters
  8. The Onion Architecture : part 1 to part 4
    http://jeffreypalermo.com/blog/the-onion-architecture-part-1/
  9. Creating N-Tier Applications in C# by Pluralsight
    http://pluralsight.com/training/courses/TableOfContents?courseName=n-tier-apps-part1
    http://pluralsight.com/training/courses/TableOfContents?courseName=n-tier-apps-part2
  10. The Onion Architecture by Matt Hidinger http://matthidinger.com
  11. Software development fundamentals part 2 Layered architecture by Hendry Luk
    http://hendryluk.wordpress.com/2009/08/17/software-development-fundamentals-part-2-layered-architecture/
  12. Pattern-oriented Software Architecture – A System of Patterns Volume 1 by Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad and Michael Stal published by Wiley Series
  13. The Layer.Factory example https://github.com/danielmarbach/Layer.Factory
  14. The Onion.Factory example https://github.com/danielmarbach/Onion.Factory