Show Me the Laws
By: Rodolfo Hansen
Tags: Software Engineering, Functional Programming, Software Architecture, Software Testing

Software Architecture is getting too complicated…

It is easy to look at all those design pattern books, and online articles about hexagonal architectures, or the cake pattern, or the onion architecture and get lost on how you are best able to design applications and services in a world driven by docker containers, edge computing and serverless architectures.

There must be a way to cut through all the noise and get to some core principles that have a more rigorous mathematical defense…

This article is the introduction in a three part series about algebra and software development.

Basic Algebra

Why don’t we just go back to basics for a minute and talk about algebra. The very same topic we all took in high-school where we were first presented with the notion of variables and factoring expressions out thanks to known properties on the operations we were doing.

I don’t want you to believe this is all just to sneak in Abstract Algebra or Category Theory for which there are more advanced articles or series on these subjects available; like: Algebird for Data Analysis, or Bartosz’ Category Theory for Programmers. Before worrying about how we can compose algebras, we need to refresh the basics of what we mean by a simple algebra…

An algebra are these three things working together:

Some values Some operations that can be done with those values Some laws or properties that hold for the above combination of values and operations.

That is it! Surely we must be able to leverage this idea into our day to day work; we already are dealing with data types, functions, and are asked to write tests that match expected outcomes to the actual result of our function calls. This is quite possibly something we are already doing without noticing, or being explicit about it.

What is interesting about this connection?

If we are already doing this, then what does it matter what title I give to my work; sure! but every developer already knows naming is important! When you realize we are working in Algebra then you can start looking at all three components from an algebraic perspective. What are the laws for the Cake algebra? or the hexagon algebra? What are the values it works with? All of a sudden you should start seeing all those crevices waiting to get filled with bugs.

By choosing to name what you do Algebra you will recognize so many of those common patterns you saw in school also are true for the properties your own operations are expected to hold. you might already know some of these properties from elsewhere:

Associativity: I don’t want the order I do two operations in to matter. Idempotency: I don’t want my operation to change anything if I mistakenly apply it twice. Traversability: I want my operation to be applicable to multiple values in some sequence of evaluation.

A very popular example where this has been extremely successful is in database systems where the ACID laws are expressly shared and allowed to be verified by DBMS users. It’s no accident it is so easy to integrate with one of these systems…

This urge to re-use and leverage your existing libraries should be enough motivation to go and take a quick look at one of those abstract algebra libraries already in your language like cats.

By writing algebras you are explicit in the ways your code is allowed to interact / compose; you are also able to provide tests for the different invariants your code is supposed to hold and guides on how your code’s clients are expected to use it.

Share those Laws!

Having an Algebra means you don’t just have your objects and methods (a.k.a data types and functions), you are also carrying around the properties / contracts / invariants that MUST hold in their usage.

This then also means you also get these things for little or no extra work:

A property based test suite that helps you exercise your operations with values from your domain, proving the laws you set out to define hold. There are a slew of benefits to property based testing above only doing unit tests. A domain specific language that is just a derivation from the operations and how your properties allow them to compose with each other. A self contained module or library, with a clear definition of what it can do, and how it is supposed to do it, you are free to link to and leverage in whatever form or protocol you want / need to wrap it in. A complete specification of what your code is expected to do and how it is expected to behave.

And when you ship your algebra, this also means shipping your laws. This way users of your code can run the properties and contracts around how their own code interacts with yours.

Conversely, you will naturally want to re-use tests and properties you have already written for one of your modules (algebras) your own code uses. This is possible! And you will see it in all the best functional programming libraries already; with projects like discipline where you can publish your own property specifications as test suites your modules clients can use to verify proper usage of your algebras.

Don’t fall for the hype!

As you will notice; the one thing that most architecture designs seem to be lacking is an executable specification about how they are supposed to interact. Without these specifications you start running into unexpected consequences and uses. For example the Cake Pattern was advertised as revolutionary in 2016 only later to be discarded and considered more trouble than it was worth by 2018.

System Design and Architecture is an exercise of distributing cognitive complexity; e.g. it is about organizing a system so we continue to reason about it as it evolves through time; and leveraging the taxonomy of structures studied by mathematicians over the past several thousand years seems like an easy choice; especially when you get to re-use all those objects, methods, and tests already studied.

By leveraging algebraic reasoning; you now have an extra axis with which to judge that shiny new upcoming design pattern / architecture for your next serious project: