No one likes to maintain diagrams.
We should turn this around somehow: the code should "be" architecture diagrams.
i.e. existing code should be analyzed to deduct the desired architecture diagram.
It's not like the dependencies aren't there. They just aren't made obvious.
Which maybe they should!
As an example: when I see an instance of a http-server being created with a port number and routes registered, I already know at least two boxes of my diagram :)
If I analyze package/namespaces dependencies, I have a bunch more boxes.
If I analyze this across repos with slight hints (i.e. repo A is front-end, talking to repo B, backend), I have many more boxes errr out of the box.
One could argue that if we can't deduct our architecture from looking at the code and configuration, something is smelling badly.
I'd push this idea further: this shouldn't be just architecture deduction to make diagramming be derived from code. This should be concept deduction to make programming itself work on higher conceptual level (which may involve automatically creating diagrams on the fly, too).
For example, imagine I have a bunch of classes that I know implement a state machine. I should be able to annotate them as such in code, and gain the ability to do things like:
- Render a state machine diagram from them
- View them in a UI (could be graphical, could be just a different textual representation) dedicated for state machines - one that emphasizes states, transitions, and associated conditions and side effects, while diminishing or hiding all other aspects.
- Edit them in that same UI. In there, "add state" or "rename state" or "add transition (with conditions)" are the atomic editing actions, matching the way I'm currently thinking about these classes.
Elsewhere, I may have another state machine, where states are just functions tail-calling each other, or actors sending each other blocking messages (both are a common pattern in Erlang). I should be able to use the same annotations on such code too, and get the same capabilities described above.
Furthermore, some of the classes in the class-based state machine example may be parts of other, lower or higher-level concepts. Or I might encounter pieces of the state machine while working on a cross-cutting concern like error propagation. I should be able to interact with those pieces through UIs dedicated to other concepts or concerns I'm focusing on.
Trying to force the base, raw plaintext form of the code to represent all relevant concepts, all the time, in an explicit and readable way, is a fool's errand (and a source of endless, unresolvable debates about "clean code" and software architecture). Instead, I believe programming languages should be optimized to allow us to write code using a bag of higher-level tools, each dedicated to a concept that's closer to how we think about our programs. We should rarely, if ever, touch the raw source form - and we definitely shouldn't expect the raw form to clearly represent every possible role it plays in the whole program.
There are tools that can analyze the code automatically. They are worthless because they have no way to capture what grouping is important. There are groups of boxes in my system that need to be together because they are a subsystem. Note that when I ask a different question I will want a different grouping of boxes.
i.e. existing code should be analyzed to deduct the desired architecture diagram. It's not like the dependencies aren't there. They just aren't made obvious. Which maybe they should!
As an example: when I see an instance of a http-server being created with a port number and routes registered, I already know at least two boxes of my diagram :)
If I analyze package/namespaces dependencies, I have a bunch more boxes. If I analyze this across repos with slight hints (i.e. repo A is front-end, talking to repo B, backend), I have many more boxes errr out of the box.
One could argue that if we can't deduct our architecture from looking at the code and configuration, something is smelling badly.