Designing and maintaining a code architecture will always be a game of pro’s and con’s where in many cases there is no right answer. In some companies it is design by committee in others its who has been there the longest or can shout the loudest.
One topic which I have always found interesting and have never really come to a decision on is how many degrees of separation should exist within a code base. There are merits for and against each set-up which I will discuss further in this post. To define degrees of separation, I mean the layers of code that exist between top and the bottom of the application. An example of this is a service design I worked on for a service orientated architecture (SOA) where each services had the following layout.
Database - Foo.Database.Schema (Database Poco's) - Foo.Database.Repository (Implementation of database interfaces) - Foo.Database.IRepository (Interfaces to define database methods) Business - Foo.Business.Service (Implementation of business interfaces) - Foo.Business.IService (Interfaces to define business methods) Api - Foo.Api.Schema (Poco's to produce JSON mapping) - Foo.Api.Controller (Public interface methods) - Foo.Api.Validation (Validation methods for schema)
There was three degrees of separation in the design (Api > Business > Database) which meant that in some cases the business layer just dealt with the mapping of the api schema to the database schema, in other services there was a large amount of logic involved in the business layer. A decision was made to maintain the design across each service (~20) and for some was a complete overkill and in others was a good set-up.
The design could have easily been reduced to two degrees of separation in number of different ways.
Option 1 Business - Foo.Business.Schema (Database Poco's) - Foo.Business.Service (Implementation of business interfaces) - Foo.Business.IService (Interfaces to define business methods) Api - Foo.Api.Schema (Poco's to produce JSON mapping) - Foo.Api.Controller (Public interface methods) - Foo.Api.Validation (Validation methods for schema) Option 2 Database - Foo.Database.Schema (Database Poco's) - Foo.Database.Repository (Implementation of database interfaces) - Foo.Database.IRepository (Interfaces to define database methods) Api - Foo.Api.Schema (Poco's to produce JSON mapping) - Foo.Api.Controller (Public interface methods) - Foo.Api.Validation (Validation methods for schema)
In option one the database layer could have been merged into the business layer (Api > Business), as a good ORM significantly decreases the amount of code required. In some cases it would have also made running large database transactions a lot easier. There how ever would have still been a requirement to have a database schema for persistence using the attributes on the poco’s for the ORM. The problem with this option is that without developing against interfaces for your persistence layer it removes the possibilities to easier change the ORM provider or use mocking to run your unit tests.
Option two would have been to move the business layer into the API controllers (Api > Database). In a Model View Controller (MVC) set-up this would have made the solution change from large services layers to large controllers which again is decision about where you want your code to lie. The downside to this design is that it does significantly reduce the re-usability of the business layer in other applications. In a SOA architecture this is not a problem because other applications would be consuming the service but in a other architecture designs patterns this could lead to a large amount of code duplication.
In a more extreme way the persistence and the business layer could have been coded into the API controllers so there was only a single layer of code.
Option 1 Api - Foo.Api.Schema (Poco's to produce JSON mapping) - Foo.Api.Controller (Public interface methods) - Foo.Api.Validation (Validation methods for schema)
In a single layer application the api schema could be decorated with with the persistence attributes as well as the serialisation attributes. This would have significantly reduced the possibility of code duplication between the database layer and the JSON schema. This does introduce the possibility of not marking your attributes correctly and outputting sensitive information in your JSON data (e.g. hash and salt of a password). The possibility of reusing the code from a single layer application is very small but again in a SOA architecture it would not be a great issues.
As we have been through each of the examples it is evident there are trade off’s in each design in the following areas:
- Code duplication
- Possibilities for security issues
In many examples of building web applications there does seem to be a trend towards building single layer applications and reusing poco’s for multiple responsibilities by attributes. The design decision could be because they are much easier to demo and explain but speed of implementation of a single layer application is defiantly a plus.
I don’t think its possible to answer my own question. There is no real right or wrong answer when it comes to degrees of separation in an application, each has its trade off’s when considered as part of the architecture of a system. On the project I worked on we chose three degrees of separation in all of the services which took longer to implement but allowed each component of the application to grow over time and be fully tested using dependency injection. If I was to repeat the design exercise again I would consider the other levels of separation based on the requirements of the project.
Don’t jump straight in with the first idea that you see in a demo, spend time looking at the business requirements of the projects and the possible future direction of the code base. It is vital to document the design decisions that are made so every one working on a project can understand why a decision was made.
So what do you think? What’s your experience with different degrees of separation in your code?
Update 05/06/2015: Code examples for this can be found on https://github.com/ollietrex/degrees-of-separation-csharp