I presented an "in the brain" session at Skills Matter on Monday night as a follow-up to my post called Mapping software architecture to code that discussed how the mapping between the abstractions we talk about as software architects (e.g. components and services) are often never reflected in the code. The slides are available to view online and there's also a video that you can watch, although this was an "in the brain" session so don't expect a polished conference presentation. :-)
Packaging code by layer
The basic premise of the session is that 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. The reason for this is very simple. We know that architectural layering is good 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 10+ years in London 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. 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.
The driver for having this discussion is that a good software architecture enables agility. For example, there's a growing trend for building software systems from loosely coupled micro-services, which are basically very small applications that do one thing and do one thing well. While the benefits are easy to see, in my experience, many (most?) teams are still building systems that are monolithic in nature. In my view, both architectural styles have their advantages and disadvantages, with the decision to build a monolithic system vs one composed of micro-systems coming back to the trade-offs that you are willing to make. A major disadvantage of building a monolithic system is that it requires some major architectural refactoring in order to reshape it so that parts of the system can be deployed and evolved separately.
As with all things in the IT industry, there's a middle ground between these extremes. There's nothing stopping you from building a monolithic system but structured in a way that allows you to migrate to a micro-service architecture more easily at a later date.
This is what component-based development is all about and although many people *talk* 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 software architecture and coding as disciplines - the architecture diagrams on the wall say one thing, but the code says another.
Here's an example of a codebase that I've built where much of the code has been packaged by component. I'll write a separate blog post on the details later but the architectural components and code structure have a one-to-one mapping. There are some trade-offs, but I do quite like it as an approach. Perhaps bringing the software architecture and coding worlds closer together would prevent teams getting nervous whenever somebody mentions the phrase "architectural refactoring"?
* I'm using the Java terminology of a "package" here, but the same is applicable to namespaces in C#, etc.