Atrocities of Software Architecture

Five years ago I’ve written my definition of a software architecture and have compared two alternative architectural designs: Monolyth vs SOA. For each design, I gave its advantages and disadvantages.

Now, five years later, I’ve learned a little more and want to amend this topic.

It has turned out, that in the organizations in the Enterprise Autumn phase, many decisions are made not out of best fit for the situation, but purely due to political reasons. Besides, due to Murphy’s Law, some implementors of the architecture have achieved their level of incompetency.

This can lead to a situation when additional disadvantages (for the enterprise) can emerge, which are not intinsic to the chosen architecture, but are just results of a wrong practical implementation strategy or political processes. Therefore, when describing and comparing possible advantages and disadvantages of some architectural design, for a proper decision, you also have to take into account its possible atrocities.

Atrocities of a Monolyth

  1. One usual atrocity of a monolytic application is the insisting on full re-test of the whole application on each and every release. Even though it is possible to retrieve the list of changed files and therefore exclude large parts of the application unaffacted by the change from retesting, people could reject that idea, thereby forcing many parallel developments to wait for a long time to be released,  as well as wasting the time of testers.
    To be able to decide about skipping some parts of the app from retesting, you need a) to know exactly what code is reused where, that is, you need to be able to know the source code of the whole app and be able to read code diffs quickly – not a skill that is completely impossible to learn (look at Linus Torvalds as an example) and b) want to take some minor risks (below 1% of chance) in order to facilitate more product lauches per year – something that people are told not to do, especially in the Enterprise Autumn phase, where the fear of the founders to damage the flywheel overweights their need to innovate.
  2. Another atrocity of the Monolyth is reusing it for any other software made by the company. You want to develop a new product, quite different from the first one, to become a second flywheel? No problem, we will put it inside of the existing Monolyth, because well, we can reuse some unimportant code from there (like the “about us” page and the ORM framework). Thus, a chance is missed to create a completely new project, which is not dependent on the first one and therefore that can be deployed independently.

A properly implemented Monolyth tends to be eagerly and on every suitable occasion splitted into several interdependent Monolyths. Creating a copy of the app in another language? New Monolyth. Creating a new area of the app not tightly interconnected with the other parts? New Monolyth. Besides, a properly implemented Monolyth would aggresively defend all opinions asking for full re-test on each update.

Atrocities of SOA

  1. M. Conway has stated the following law in 1967: “organizations which design systems … are constrained to produce designs which are copies of the communication structures of these organizations.” In case of the microservices, people would assign sub-teams to own one or several services. Because services are usually designed to be very small, as a result, changing one simple thing on the web site, requiring changing of several services, would make from it a huge project including very slow and expensive coordination of 3 teams (eg. 15 developers).
    This atrocity alone would lead to even longer time-to-market cycles compared to the monolyth. In a properly implemented SOA, every developer can develop any (or most) of the microservices, therefore, it is normal, for one team to change several services in just one week.
  2. Another atrocity is the wish to make everything to be a RESTful microservice. Some reusable modules, cloud services and databases have other interfaces, be it RPC, Protobuf, AMPQ or proprietary protocols. These communication protocols are carefuly designed, sometimes in the course of several decades, to provide imporant run-time properties (eg. automatic failover and cluster management, reduced overhead on serialization and connection establishing, coonection pooling etc). There is not so many reasons to implement a REST wrapper around them.
    In a properly implemented SOA, RESTful services are usually introduced only due to these two reasons: a) we want to communicate to “fat clients” (eg. mobile apps, modern HTML5/jQuery apps) over the public Internet, or b) we have some important business logic, which cannot or should not be encapsulated in the database (eg. using stored procedures or views), so that we need to develop and host a separate service process anyway.
  3. Yet another atrocity is that some teams would consider a microservice to be a deliverable (a completed piece of work, even a product), whereas a service is similar to one OOP class or package / module / assembly, that is a technical module, just a part of a product. You will never start creating a product with a service. In a properly implemented SOA, you will conceive and develop the UI and UX first, derive the API for the service according to the calls the frontend needs to made, and then use or develop the corresponding service or services.

Common atrocities

  1. Over-Engineering. If you imagine quality to be a number from 0 to 100%, some people are unable or unwilling to deliver any given quality level. They can just give the level 0% or the level 100%. What real world business situation usually requires is the level of 60%, sometimes being dropped to 30%. A properly run software development organization can deliver any required level of quality.
  2. Death by Security. If you imagine security to be number from 0 to 100%,… see above.
  3. Checklist-oriented development. Some people do things described in the checklists, formal quality criterias or common conventions, without checking first whether these things matter in the particular situation, do they add up to some desired property of the software, or maybe even counter-productive?
  4. Mandated Architecture. In the year 2018, it is impossible to mandate software architecture by a HiPPO, nor enforce it using architectural nazis running around with whips. If tried to do so, the architecture will invariably mutate to some of the atrocities described above, when implemented by the people who either a) don’t agree with it or b) don’t understand how exactly this architecture is going to solve their pains. A proper architecture is always something everybody unanimously (100%) agree to be The Good Thing to do, and usually it can only evolve from the trenches, not mandated from above.

Summary

In the year 1975 when I was just born, Frederick P. Brooks has already learned about software development enough to write his essay “There is no silver bullet”. Applying this principle to the architectures, one could say, any theoretical advantage of any architecture can be missed by a poor execution. Or, like Derek Sievers uses to say, idea is nothing, execution is everything.

Leave a comment