Regular readers will already know about Structurizr — a set of open source libraries to create a software architecture model as code, plus a SaaS product to visualize those models. Having created and helped create a number of models with Structurizr now, I've noticed an interesting side-effect. In the absence of architectural information being present in the code, the power of using something like Structurizr to define a software architecture model using code is in extracting information algorithmically, by codifying the rules that you've ultimately used to structure your codebase.
Let me give you an example. Imagine you're building a web-MVC web application in Java, C#, etc. and you have a tens or hundreds of controller classes, each of which uses a number of other components to implement some functionality. Drawing a single diagram to visualize the static structure of the entire web application is a bad idea because it shows too much information. A better approach is to create one view per vertical slice, where there could be one vertical slice per web controller. This results in smaller, simpler diagrams like this.
So far, so good, and this is relatively easy to do using static analysis techniques. But you'll notice this diagram includes an "Authenticated User", which isn't part of the code itself. This raises the question of how the user ends up getting included on the diagram.
There are a number of options:
- Manually add the correct type of user on a case by case basis.
- Match the controller's URL routing to the permitted user role (this is likely specified in configuration somewhere) and use this information to choose the appropriate type of user for each controller.
- Add machine-readable metadata (e.g. Java Annotations, C# Attributes) to specify the user type (there are some Structurizr annotations I've created to help with this).
- Codify the rules you've used to organize the controllers in your codebase.
The ability to codify the rules you've used to organize the controllers in your codebase obviously depends on how much thought you've put into doing this. For example, did you dump all of these controller classes into a single package or namespace without giving it much thought at all? Or perhaps you took Martin Fowler's advice and modularised further, creating one package/namespace per functional area or aggregate root, for example. Another possibility is that you grouped controllers together based upon whether unauthenticated users, authenticated users or other software systems are using them. Organising your code well provides you with another angle to extract architectural information, because you can codify rules such as, "the Anonymous User uses all controllers in the com.mycompany.mywebapp.unsecured package/namespace".
With hindsight this is fairly obvious, but we often don't put enough thought into how we organize our code, possibly because we perceive that it doesn't actually matter that much and modern IDEs provide powerful ways to navigate large and/or complex codebases. Trying to codify the rules used to organize a codebase certainly gets you thinking, and often refactoring too.