40 Would you code it that way?
It’s a common misconception that software architecture diagrams
It’s a common misconception that software architecture diagrams need to be stuck in need to be stuck in the clouds,the clouds, showing high-level concepts and abstractions that present the logical rather than the physical. showing high-level concepts and abstractions that present the logical rather than the physical. But it doesn’t have to be this way and bringing them back down to earth often makes diagrams But it doesn’t have to be this way and bringing them back down to earth often makes diagrams easier to explain and understand. It can also make diagrams easier to draw too.
easier to explain and understand. It can also make diagrams easier to draw too. T
To illustrate why thinking about the implementation can help the o illustrate why thinking about the implementation can help the diagramming process, here arediagramming process, here are a couple of scenarios that I regularly hear in my training classes.
a couple of scenarios that I regularly hear in my training classes.
Shared components
Shared components
Imagine that you’re designing a 3-tier software system that makes use of a web server, an Imagine that you’re designing a 3-tier software system that makes use of a web server, an application server and a database. While thinking about the high-level components that reside application server and a database. While thinking about the high-level components that reside in each of these containers, it’s not uncommon to hear a conversation like this:
in each of these containers, it’s not uncommon to hear a conversation like this:
•• Attendee Attendee: “Should we draw the logging component outside of the web server and the: “Should we draw the logging component outside of the web server and the application server, since it’s used by both?”
application server, since it’s used by both?”
•• MeMe: “Would you code it that way? Will the logging component be running outside of both: “Would you code it that way? Will the logging component be running outside of both the web server and application server? For example, will it really be a separate standalone the web server and application server? For example, will it really be a separate standalone process?”
process?”
•• Attendee Attendee: “Well … no, it would probably be a shared component in a [JAR file|DLL|etc]: “Well … no, it would probably be a shared component in a [JAR file|DLL|etc] that we would deploy to both servers.”
that we would deploy to both servers.”
•• MeMe: “Great, then let’s draw it like that too. Include the logging component inside of each: “Great, then let’s draw it like that too. Include the logging component inside of each server and label it as a shared component with an annotation, stereotype or symbol.” server and label it as a shared component with an annotation, stereotype or symbol.” If you’re going to implement something like a
If you’re going to implement something like a shared logging component that will be shared logging component that will be deployed todeployed to a number of different servers, make sure that your diagram reflects this rather than potentially a number of different servers, make sure that your diagram reflects this rather than potentially confusing people by including something that might be mistaken for a separate centralised confusing people by including something that might be mistaken for a separate centralised logging server. If in doubt, always ask yourself how you would code it.
logging server. If in doubt, always ask yourself how you would code it.
Layering strategies
Layering strategies
Imagine you’re designing a web application that is internally split up into a UI layer, a services Imagine you’re designing a web application that is internally split up into a UI layer, a services layer and a data access layer.
layer and a data access layer.
•• Attendee Attendee: “Should we show that all communication to the database from the UI goes: “Should we show that all communication to the database from the UI goes through the services layer?”
through the services layer?”
Would you code it that way?
Would you code it that way? 121121
•• Attendee Attendee: “We were thinking of perhaps adopting the: “We were thinking of perhaps adopting the CQRS¹ CQRS¹ pattern, so the UI could pattern, so the UI could bypass the services layer and use the data access layer directly.”
bypass the services layer and use the data access layer directly.”
•• MeMe: “In that case, draw the : “In that case, draw the diagram as you’ve just explained, with lines from the Udiagram as you’ve just explained, with lines from the UI to bothI to both the services
the services and data access and data access layers. Annotate the lines to layers. Annotate the lines to indicate the intent and rationale.indicate the intent and rationale.”” Again, the simple way to answer this type of question is to understand how you would code it. Again, the simple way to answer this type of question is to understand how you would code it.
Diagrams should reflect reality
Diagrams should reflect reality
If you’re drawing diagrams to retrospectively communicate a software system then the question If you’re drawing diagrams to retrospectively communicate a software system then the question becomes “is that
becomes “is that how how we coded it?”. The principle is the same though. Diagrams should present we coded it?”. The principle is the same though. Diagrams should present abstractions that reflect reality rather than provide conceptual representations that don’t exist. abstractions that reflect reality rather than provide conceptual representations that don’t exist. Y
You should be able to ou should be able to see how the diagram see how the diagram elements are reflected in the elements are reflected in the codebase and vice versa.codebase and vice versa. If you can understand how you would code it, you can understand how to visualise it.
If you can understand how you would code it, you can understand how to visualise it. ¹¹http://martinfowler.com/bliki/CQRS.htmlhttp://martinfowler.com/bliki/CQRS.html
41 Software architecture vs code
41 Software architecture vs code
Although many software teams find it tricky to
Although many software teams find it tricky to visualise the software architecture of their visualise the software architecture of their
software systems
software systems, let’s assume that this , let’s assume that this isn’t the case and that you’re isn’t the case and that you’re sketching some ideas relatedsketching some ideas related to the software architecture for a new system you’ve been tasked to build. An important aspect to the software architecture for a new system you’ve been tasked to build. An important aspect of
of just enough software architecture just enough software architecture is to understand how the significant elements of a software is to understand how the significant elements of a software system fit
system fit togethertogether..
Responsibility-driven design and decomposition into
Responsibility-driven design and decomposition into
components
components
For me, this means going down to the level of components, services or modules that each have For me, this means going down to the level of components, services or modules that each have a specific set of responsibilities. It’s worth stressing this isn’t about understanding low-level a specific set of responsibilities. It’s worth stressing this isn’t about understanding low-level implementation details, it’s about performing an initial level of decomposition. The Wikipedia implementation details, it’s about performing an initial level of decomposition. The Wikipedia page for
page for Component-based development¹ Component-based development¹ has a good summary and a “component” might be has a good summary and a “component” might be something like a risk calculator, audit logger, report generator, data importer, etc. The simplest something like a risk calculator, audit logger, report generator, data importer, etc. The simplest way to think about a component is that it’s a set of related behaviours behind an interface, way to think about a component is that it’s a set of related behaviours behind an interface, which may be implemented using one or more collaborating classes (assuming an OO language, which may be implemented using one or more collaborating classes (assuming an OO language, of course). Good components share a number of characteristics with good classes. They should of course). Good components share a number of characteristics with good classes. They should have high cohesion, low coupling, a well-defined public interface, good encapsulation, etc. have high cohesion, low coupling, a well-defined public interface, good encapsulation, etc. There are a number of benefits to thinking about a software system in terms of components, There are a number of benefits to thinking about a software system in terms of components, but essentially it allows us to think and talk about the software as a small number of high-level but essentially it allows us to think and talk about the software as a small number of high-level abstractions rather than the hundreds and thousands of individual classes that make up most abstractions rather than the hundreds and thousands of individual classes that make up most enterprise systems. The photo below shows a typical component diagram produced during the enterprise systems. The photo below shows a typical component diagram produced during the training classes we run. Groups are asked to design a simple
training classes we run. Groups are asked to design a simple financial risk system financial risk system that needs to that needs to pull in some data, perform some calculations and generate an Excel report as the output.
pull in some data, perform some calculations and generate an Excel report as the output. ¹¹http://en.wikipedia.org/wiki/Component-based_software_engineeringhttp://en.wikipedia.org/wiki/Component-based_software_engineering
Software architecture vs code
Software architecture vs code 123123
We often think in terms of components We often think in terms of components This
This sketsketchch incluincludes tdes thehe major major compocomponentnents yous you woulwouldd expeexpect to ct to seesee for a for a systesystemm that that is impois importingrting data, performing risk calculations and generating a report. These components provide us with data, performing risk calculations and generating a report. These components provide us with a framework for partitioning the behaviour within the boundary of our system and it should a framework for partitioning the behaviour within the boundary of our system and it should be relatively easy to trace the major use cases/user stories across them. This is a really useful be relatively easy to trace the major use cases/user stories across them. This is a really useful starting point for the software development process and can help to create a shared vision that starting point for the software development process and can help to create a shared vision that the team can work towards.
the team can work towards.
But it’s also very dangerous at the same time. Without technology choices (or options), this But it’s also very dangerous at the same time. Without technology choices (or options), this diagram looks like the sort of thing an ivory tower architect might produce and it can seem very diagram looks like the sort of thing an ivory tower architect might produce and it can seem very “conceptual” (or “fluffy”, depending on your point of view) for many people with a technical “conceptual” (or “fluffy”, depending on your point of view) for many people with a technical background.
background.
We talk about components but write classes
We talk about components but write classes
People generally understand the benefit of thinking about software as a small number of high- People generally understand the benefit of thinking about software as a small number of high- level building blocks. After all, it’s a great way to partition responsibilities across a software level building blocks. After all, it’s a great way to partition responsibilities across a software system and you’ll often hear people talking in terms of components when they’re having system and you’ll often hear people talking in terms of components when they’re having architecture discussions. This is what
architecture discussions. This is what component-based component-based developmentdevelopment²² is all about and although is all about and although many people
many people talk talk about their software systems in terms of components, that structure isn’t about their software systems in terms of components, that structure isn’t usually reflected in the code. This is one of the reasons why there is a disconnect between usually reflected in the code. This is one of the reasons why there is a disconnect between software architecture and coding as disciplines - the architecture diagrams on the wall say one software architecture and coding as disciplines - the architecture diagrams on the wall say one thing, but the code says another.
thing, but the code says another.
When you open up a codebase, it will often reflect some other structure due to the organisation When you open up a codebase, it will often reflect some other structure due to the organisation of the code. The mapping between the architectural view of a software system and the code are of the code. The mapping between the architectural view of a software system and the code are often very different. This is sometimes why you’ll see people ignore architecture diagrams (or often very different. This is sometimes why you’ll see people ignore architecture diagrams (or documentation) and say “the code is the only single point of truth”. George Fairbanks calls this documentation) and say “the code is the only single point of truth”. George Fairbanks calls this
Software architecture vs code 124 the “Model-code gap” in his book called Just Enough Software Architecture³. The organisation of the codebase can really help or hinder architectural understanding.
Packaging code by layer
Many software teams structure their code by layer. In other words, if you open up a codebase, you’ll see a package for domain classes, one for UI stuff, one for “business services”, one for data access, another for integration points and so on. I’m using the Java terminology of a “package” here, but the same is applicable to namespaces in C#, etc.
The reason for this is very simple. We know that architectural layering is generally “a good thing” and many of the tutorials out there teach this packaging style as a way to structure code. If you do a Google search for tutorials related to Spring or ASP.NET MVC, for example, you’ll see this in the sample code. I spent most of my career building software systems in Java and I too used the same packaging approach for the majority of the projects that I worked on.
Although there’s nothing particularly wrong with packaging code in this way, this code structure never quite reflects the abstractions that we think about when we view the system from an architecture perspective. If you’re using an OO programming language, do you talk about “objects” when you’re having architecture discussions? In my experience, the answer is no. I typically hear people referring to concepts like components and services instead. The result is that a “component” on an architecture diagram is actually implemented by a combination of classes across a number of different layers. For example, you may find part of the component in a “services” package and the rest of the component inside the “data access” package.
Software architecture vs code 125
Packaging by layer
In order to make this possible, the code in the lower layers (e.g. that “data access” package) often has public visibility, which means that it can be called directly from any other layer in the architecture too.
Packaging by feature
Packaging by layer isn’t the only answer though and Mark Needham has a great blog post called Coding: Packaging by vertical slice⁴ that talks about another approach to code organisation based upon vertical slices of functionality. A Google search for “package by feature vs package by layer”⁵ will throw up lots of other discussions on the same topic.
⁴http://www.markhneedham.com/blog/2012/02/20/coding-packaging-by-vertical-slice/
Software architecture vs code 126
Packaging by component
Organising a codebase by layer makes it easy to see the overall structure of the software but there are trade-offs. For example, you need to delve inside multiple layers (e.g. packages, namespaces, etc) in order to make a change to a feature or user story. Also, many codebases end up looking eerily similar given the fairly standard approach to layering within enterprise systems.
In Screaming Architecture⁶, Uncle Bob Martin says that if you’re looking at a codebase, it should scream something about the business domain. Organising your code by feature rather than by layer gives you this, but again there are trade-offs. A slight variation I like is organising code explicitly by component. For example, if you take a look at the je.techtribes.component.tweet package on GitHub⁷, you’ll see that it looks something like this.
Packaging by component
This is similar to packaging by feature, but it’s more akin to the “micro services” that Mark Needham talks about in his blog post⁸. Each sub-package of je.techtribes.component⁹ houses a separate component, complete with it’s own internal layering and configuration. As far as possible, all of the internals are package scoped. You could potentially pull each component out and put it in it’s own project or source code repository to be versioned separately. This approach will likely seem familiar to you if you’re building something that has a very explicit
⁶http://blog.8thlight.com/uncle-bob/2011/09/30/Screaming-Architecture.html
⁷https://github.com/techtribesje/techtribesje/tree/master/techtribes-core/src/je/techtribes/component/tweet
⁸http://www.markhneedham.com/blog/2012/02/20/coding-packaging-by-vertical-slice/
Software architecture vs code 127 loosely coupled architecture such as a distributed messaging system made up of loosely coupled components.
I’m fairly confident that most people are still building something more monolithic in nature though, despite thinking about their system in terms of components. I’ve certainly packaged
parts of monolithic codebases using a similar approach in the past but it’s tended to be fairly ad hoc. Let’s be honest, organising code into packages isn’t something that gets a lot of brain- time, particularly given the refactoring tools that we have at our disposal. Organising code by