Where you might want to start reading ...

Is there something wrong with software architecture - or with us?

I am a software architect (one of a few) for a 20-million LOC business software, with currently a few thousand installations, developed and ...

Saturday, June 17, 2017

A first example of rules - introducing Archichect

It's high time for a few examples. I'll draw them from two programs:
  • First, the medium-sized "Archichect" tool that I wrote for checking and exploration purposes (with substantial input some years ago from Thomas Freudenberg; and requests and ideas by colleagues at Pharmatechnik in Germany, my employer). Archichect is right now a proof-of-concept software, which means, among other things, that I change anything quite freely on a daily basis (if you nevertheless want to take a look, you can search it on GitHub and look into it).
  • Second, the large flagship IXOS product of our company, which I will use later to demonstrate large-scale architectural aspects.
Let me start with a small example from the prescriptive architecture of Archichect. Here is a rough sketch of some part of its intended (therefore, prescriptive) architecture:


Obviously, this is a "type 1 sketch": It is a mixture of definitive information ("there are three subpackages called Reading, Transforming, and Rendering") and illustrative, but incomplete information ("There is a class called DependencyChecker implementing interface ITransformer, but probably there are more implementors of this interface"). There is nothing at all wrong with such diagrams—except that one must be extremely careful to draw conclusions from them: The "existential assumption" is usually ok ("All the things in the diagram will be there in reality"), but even this is sometimes risky ("oh, I just meant that as an example").

So let us write some rules for this part of Archichect that lift the information from the diagram to a "type 3 declaration". Here they are, in Archichect syntax:
$ DOTNETITEM ---> DOTNETITEM

(**)                    ---> ::\1
Archichect.Reading      ---> ::Archichect
Archichect.Transforming ---> ::Archichect
Archichect.Rendering    ---> ::Archichect
(You are not happy with the notation?—you would like to express this in code? Well, as I said, I am not too stubborn about notation, so I will show how to write the same rules with code in one of the next postings).

One can actually run these rules over Archichect itself and get a nice and very long result telling us that Archichect (in its current version) has 35505 dependencies, 26690 of which violate the rules above: "Sad", as some well-known guy would tweet. Obviously, transferring an architectural diagram to strict rules requires a little more work than just more or less faithfully copy it to text—but it's only a little more, I promise (and will show you).

Before that, however, let me explain the rules above, and the assumptions behind them, a little more.

First of all, the diagram did not spell out how the concept of a UML package is mapped to the language. Most modern languages have at least one concept of nestable groups for naming things; for example, Java has packages, and the .Net languages have namespaces. In addition to these logical nestable constructs, the physical units of runtime environments, e.g. JAR files or .NET assemblies, are typically named with filenames, which can again use a hierarchical naming concept. For example, in .Net, there are assemblies named System.dll, System.Threading.dll, System.Threading.Tasks.dll, System.Threading.Tasks.Dataflow and System.Threading.Tasks.Parallel.dll etc.

In Archichect, I chose the standard approach of mapping packages to the naming concept of the implementation language, i.e., to .Net's (and C#'s) namespaces. Thus, I would put
  • Program, Item, Dependency as well as the three base interfaces into namespace Archichect;
  • DotNetAssemblyReader in namespace Archichect.Reading,
  • DependencyChecker in namespace Archichect.Transforming, and
  • ViolationsWriter in namespace Archichect.Rendering.
The type DOTNETITEM defined by Archichect's DotNetAssemblyReader nicely defines the fields Namespace, Class, Assembly.Name, Assembly.Version, Assembly.Culture, and Member.Name, and therefore the rules above refer to the Namespace field without any further syntactical ado.

Still, an alternative architecture decision could be to distribute the classes and interfaces into multiple assemblies, and then, the rules would have to be written differently, e.g. (there are more possibilities) as follows:
$ DOTNETITEM ---> DOTNETITEM

::(**)                    ---> ::\1
::Archichect.Reading      ---> ::Archichect
::Archichect.Transforming ---> ::Archichect
::Archichect.Rendering    ---> ::Archichect
The two colons indicate that the strings are assumed to refer to the third field of DOTNETITEM, i.e., the Assembly.Name field. Assembly rules collect, at least in .Net, also important architectural information and should therefore be part of the "rule set"; but I will ignore them for the moment and continue with namespace-based rules.

Secondly, regarding the diagram, it does not say anything about any dependency restrictions inside each package. A typical implicit assumption is that, on this level of granularity, each item inside a package may use any other item in the same package. To allow such dependencies, the rule
(**) ---> \1
is added. The \1 notation here is borrowed from regular expressions (and actually, internally, the rule checking is mostly done by creating regexes from the rules and then matching the read-in dependencies against them).
This Archichect rule says that items from some namespace can use items from exactly the same namespace, but not from a child or parent namespace. We will see in a later posting that this would, in some cases, prevent the useful organization of namespaces, and therefore the actual architecture rules of Archichect are somewhat different. For the moment, we leave it at that.

Still, we should understand why our apparently so useful rules gave us so many invalid dependencies, shouldn't we? That's some stuff for another posting.

No comments:

Post a Comment