Software architecture: Invariant things should be apparent

published Jul 29, 2015 02:55   by admin ( last modified Jul 29, 2015 03:07 )

I'm trying to figure out how to make the source code of a system readable, readable meaning that you can understand the system on a high level, and also its constituent parts, from the source code.

It seems to me, and I am just starting thinking about this, that there things (patterns, frameworks, data schemas) that are invariant, that is they don't change over time as the system runs.  I'm sure the word invariant has other definitions, but for this text that was invariant means. These invariant things are the things you can communicate to the developer/maintainer.

So it would seem that you should be upfront with your invariant stuff. Like in a central file or as imports to it. And if you have stuff that is changing and amorphous, can it be abstracted into, or at least abstractly described, as something invariant? Then do that.

It seems to me that the more of these invariant stuff you can get into your system and systems description, the easier it the system will be to understand.

However the invariants, such as e.g. a framework's modus operandi, should not lead to convoluted solutions.

So the rule might be:

Use as many invariants as you can in your system, but not to the point of convoluted constructs.

Could be a two step process: Find and describe the invariants you already have, and see if you can refactor code into invariants.

The invariants can work on many levels: Using a language that discourages TIMTOWDI, using frameworks (iff they fit the problem) and taking time to create well defined abstractions for as many parts of the code as possible. Abstractions here means in the direction of readability and understandability.

Another question then arises, what abstractions are easy to undertstand? In user interface design one measure of the complexity of a GUI is the number of objects on the screen and how many alignment lines there are. Fewer objects and aligned objects lead to lower complexity. I wonder how could one measure the complexity of abstractions in source code? Metrics could include

  • how many inputs
  • if there is mutable state in there somewhere
  • if there are side effects
  • how many other files the code interacts with
  • the cyclomatic complexity

Abstractions already familiar to the developer are easier for him to use, and re-using known abstractions with some magical twist may work too. it also means it may be a good idea to have a toolbox of powerful abstractios that covers most of the things needed to be done.

Sometimes there is a like precipice when interactions between even simple components get too complex to understand. In which case the sub system needs to be "black-boxed" and not leak into the environment.