Matt’s first law of software complexity

The first law of thermodynamics states something like this: the total energy of the system plus the surroundings is constant. Or basically energy is conserved; it cannot be created or destroyed, just moved around. This first law is an important realization for chemists/physicists, and underpins the way they look at problems.

I think there is a similar realization that can be made regarding the complexity of software systems, and that it can change the way you look at and design software. It would go something like this:

Matt’s first law of software complexity:

The underlying complexity of a given problem is constant. It can be hidden, but it does not go away.
Or:
Complexity is conserved by abstractions. In fact, apparent complexity can be increased by abstractions, but the underlying complexity can never be reduced.

Complex problems remain complex, now matter how much good design and architecture you heap on top. Abstractions hide the complexity. But this is a good thing! A good abstraction divides a problem in two, putting part of the complexity on either side. A good abstraction puts most of the complexity where it can be solved by an existing solution to that subproblem.

But complex problems remain complex, and abstractions leak. If you come up with a good design that lets you hide the complexity of a problem, and then you forget about that complexity, rest assured that it will eventually come back to bite you. Hide complexity, but don’t ignore it.

You may have easily implemented a huge, performant web application because you used off-the-shelf components for presentation, persistence, messaging, clustering and fail-over. You applied well known abstractions like J2EE, RDBMSes, Web Services, MVC… the list goes on. But abstractions leak. Clustering and fail-over is inherently hard no matter what the vendors tell you, and the complexity often leaks through under load. HTTP and TCP do a great job of getting bytes from one place to another, until a bug feature in the OS or router shows itself (like MTU size or sockets closing on DHCP lease re-acquisition).

Use abstractions to move complexity to where it is more easily dealt with. But don’t forget that it is still there.

Mathematicians know a great trick that can be used to sidestep my first law of complexity: redefine the problem. The underlying complexity of a given problem is constant, so change the problem. This can be the single most useful outcome of a requirements gathering exercise. Someone may come up and ask you to solve this problem: “we need an enterprise-bus messaging system”. But if you dig a little bit, you may find out they would be happy with occasional automated emails, a .forward script and a CGI.

Use abstractions to move complexity to where it is more easily dealt with. But remember complexity is conserved by abstractions; and abstractions leak.

  • http://blog.manageability.org Carlos E. Perez

    Wait a minute here. You started out quoting law of energy conservation however not mentioning the equally important 2nd law of thermodynamics.

    2nd law of course as applied to information is that a closed system tends towards entropy, that is maximum disorder. If disorder implies complexity, then maximum complexity.

    So, to avoid this you’ve got to be constantly adding energy, and in information terms organized knowledge. So you keep on refactoring, reducing disorganization into organization.

    Of course the big law you’ve got to quote is "the only thing unavoidable in software is change".

  • http://blog.manageability.org Carlos E. Perez

    Sorry, a bit to quick.

    Good insight on the first law.

    That is if you don’t make any radical changes in abstractions, a complex system remains equally complex.

  • http://madbean.com/blog/ Matt Quail

    Carlos,
    I agree that the 2nd law is a whole other bag if fish! I have some thoughts on a "2nd law of software complexity" but I’m not sure how far I can stretch the analogy.

    I like the idea that to avoid entropy you have to keep on refactoring :D

  • Pete

    Good post, Matt.

    It highlights one of the classis issues in software development – Are we providing a solution to the right problem? Solving the wrong question, as you show, always adds unnecessary complexity.

    The other issue that clouds things pretty well is to recognise the complexity in a solution (as opposed to the constant complexity in a problem). Any given solution’s complexity can be far in excess of that mandated by the problem. In this case abstractions can assist greatly in reducing complexity. Often in the process of pulling out useful abstractions the developer can come to the realisation that much of what they are doing is superfluous and doesn’t actually assist in solving the problem. This kind of activity can remove the extraneous parts and lead to the replacement of core pieces of the system that were mis-designed (if that’s a word).

    Cheers,
    Pete.

  • http://frank.spieleck.de Frank Nestel

    Well, interesting thoughs, I just wonder how this well known facet fills in:
    "Every piece software will be maintained so long until its complexity is beyond scope for everyone maintaining it."
    Concerning real world settings. The question is whether the main purpose of abstractions is to help the gurus to prepare building bricks the mortals can handle. Every now and then the abstraction leaks and you have to call for the guru cause you do not understand what is going on, but in generall you have a nice simple black box labeled "miracle". For a simple example, I’ve found das many young programmers do not know the hashing algorithm. While an efficient assoziative storage is beyond their own design expertise they can use Perl assosciative arrays or Java Hashtables/Maps without harm. Most of the time they have no problem.

    As a trained mathematician I know mankind can build abstractions on which the next generation can move very safely. Software of course is all very young. No much time to mature…

  • Rajesh Vasa

    A very interesting observation. I am a researcher in the field of Software Evolution, and I have collected a large amout of data from a very many number of systems (All Java, Open Source). The most interesting find is that my data supports your First Law. Complexity does not change at all once a Software system has stabilised. And the even more interesting thing is that this near constant complexity distribution holds at all levels, i.e Method/Class/Package/System.

  • David G. Miller

    I’ve always referred to this phenomenon as “the law of conservation of difficulty.” You might also look at RFC 1925 (which really isn’t a joke even if it was posted on 1 April 1996). In particular:

    (6) It is easier to move a problem around (for example, by moving
    the problem to a different part of the overall network
    architecture) than it is to solve it.

        (6a) (corollary). It is always possible to add another level of
             indirection.
    

    Cheers,
    Dave