Who Needs Architects? Who’s Minding the Architecture?

shearing layers diagram

Shearing layers are an important concept in building architecture. Essentially, the idea is that a building is not a unary thing with a single lifecycle, but a composition of several layers comprising elements with different concerns (site, structure, skin, services, space plan, and contents stuff) and with varying lifecycles based on their amenability to change. This same concept can be applied to software systems. Between platform components and the fractal nature of systems and solutions, groupings of concerns with diverse lifecycles are readily apparent.

Richard Veryard, in his post “Agile and Wilful Blindness”, used the concept of shearing layers to help illustrate a weakness of development styles that stress emergence over deliberate design:

Some things are easier to change than others. The architect Frank Duffy proposed a theory of Shearing Layers, which was further developed and popularized by Stuart Brand. In this theory, the site and structure of a building are the most difficult to change, while skin and services are easier.

Let’s suppose Agile developers know how to optimize some of the aspects of a system, perhaps including skin and services. So it doesn’t matter if they get the skin and services wrong, because these can be changed later. This is the basic for @swardley’s point that you don’t need to know beforehand exactly what you are building.

But if they get the fundamentals wrong, such as site and structure, these are more difficult to change later. This is the basis for John Seddon’s point that Agile may simply build the wrong things faster.

And this is where @ruthmalan takes the argument to the next level. Because Agile developers are paying attention to the things they know how to change (skin, services), they may fail to pay attention to the things they don’t know how to change (site, structure). So they can throw themselves into refining and improving a system until it looks satisfactory (in their eyes), without ever seeing that it’s the wrong system in the wrong place.

Although I disagree that all agile developers fall into this category, Richard’s and Ruth Malan’s point is an important one. We must be aware of a need in order to attend to it. As Seth Godin noted in “I didn’t see it because I wasn’t looking”: “This is one reason we feel the need to yell ‘surprise’ at a surprise party.”

Even when we’re aware of something, failing to understand the true nature of it can hamper our ability to deal with it effectively. Too many consider the practice of architectural design to be just a matter of drawing pictures and creating documents. The important aspect, however, is the decisions and the rationales for those decisions that these artifacts should capture. As Ipek Ozkaya tweeted from Gregor Hohpe‘s SATURN 2015 keynote:

Architectural design is essentially about making (albeit collaboratively) and communicating decisions. The decisions that are architecturally significant are the decisions that affect the longer-lived, harder to change aspects of a system. Intentionally addressing these concerns is a better strategy than hoping that something coherent just “emerges”.

Form Follows Function on SPaMCast 339

SPaMCAST logo

This week’s episode of Tom Cagley’s Software Process and Measurement (SPaMCast) podcast features Tom’s essay on demonstrations and a Form Follows Function installment on microservices, SOA, and Enterprise IT Architecture.

For SPaMCast 339, Tom and I discuss my “Microservices, SOA, and EITA: Where To Draw the Line? Why to Draw the Line?” post.

Laziness as a Virtue in Software Architecture

Laziness may be one of the Seven Deadly Sins, but it can be a virtue in software development. As Matt Osbun observed:

Robert Heinlein noted the benefits of laziness:

Even in the military, laziness carries potential greatness (emphasis mine):

I divide my officers into four groups. There are clever, diligent, stupid, and lazy officers. Usually two characteristics are combined. Some are clever and diligent — their place is the General Staff. The next lot are stupid and lazy — they make up 90 percent of every army and are suited to routine duties. Anyone who is both clever and lazy is qualified for the highest leadership duties, because he possesses the intellectual clarity and the composure necessary for difficult decisions. One must beware of anyone who is stupid and diligent — he must not be entrusted with any responsibility because he will always cause only mischief.

Generaloberst Kurt von Hammerstein-Equord

The lazy architect will ignore slogans like YAGNI and the Rule of Three when experience and/or information tells them that it’s far more likely that the need will arise than not. As Matt stated in “Foreseeable and Imaginary Design”, architects must ask “What changes are possible and which of those changes are foreseeable”. The slogans point out that engineering costs but the reality is that so does re-work resulting from decisions deferred. Avoiding that extra work (laziness) avoids the cost associated with it (frugality).

Likewise, lazy architects are less likely cave when confronted with the sayings of some notable person. Rather than resign themselves to the extra work, they’re more likely to examine the statement as Kevlin Henney did:

It’s far cheaper to design and build a system according to its context than re-build a system to fix issues that were foreseeable. The re-work born of being too focused on the tactical to the detriment of the strategic is as much a form of technical debt as cutting corners. The lazy architect knows that time spent identifying and reconciling contexts can allow them to avoid the extra work caused by blind incremental design.

Institutional Amnesia, Cargo Cults and Software Development

When George Santayana stated that “Those who cannot remember the past are condemned to repeat it.”, he wasn’t talking about technology. When Brenda Michelson and Ed Featherston said much the same thing recently, they were:

It’s a sad fact of life that today’s silver bullet is likely to be yesterday’s junk which was probably the day before yesterday’s silver bullet.

Poor design choices are made for a variety of reasons. Sometimes it’s a matter of ego. Sometimes inadequate analysis is the culprit. Focusing on technology rather than problem-solving can be another pitfall. Even attempts at post-hoc justification of a prior bad decision can drive new mistakes.

An uncritical acceptance of tradition is a significant source of problem designs. Eberhard Wolff recently took a swipe at one old standard:

The stock reason for a tiered/distributed design is scalability. However, it’s not a given that distributing X horizontal layers across Y machines (yielding X/Y instances) will yield better results than Y machines, each with all three layers deployed on the same machine. The context in which this sort of distribution makes sense is far from universal. Even when the costs of distribution are outweighed by the benefits, traditional monolithic horizontal layers will likely be less efficient than vertical slices. One of the purported benefits of microservices is the ability to independently scale according to business concerns (vertical slices organized around bounded contexts) rather technology concerns (horizontal layers).

The mention of microservices brings to mind the problem of jumping on bandwagons. How many applications currently under development are being designed using this architectural style because it’s the “next big thing” rather than because the style fits the problem? Sam Newman, author of O’Reilly’s Building Microservices, in “Microservices for Greenfield?”, even states that he considers the style to be more suitable for evolving an existing system rather than building from scratch:

I remain convinced that it is much easier to partition an existing, “brownfield” system than to do so up front with a new, greenfield system. You have more to work with. You have code you can examine, you can speak to people who use and maintain the system. You also know what ‘good’ looks like – you have a working system to change, making it easier for you to know when you may have got something wrong or been too aggressive in your decision making process.

You also have a system that is actually running. You understand how it operates, how it behaves in production. Decomposition into microservices can cause some nasty performance issues for example, but with a brownfield system you have a chance to establish a healthy baseline before making potentially performance-impacting changes.

I’m certainly not saying ‘never do microservices for greenfield’, but I am saying that the factors above lead me to conclude that you should be cautious. Only split around those boundaries that are very clear at the beginning, and keep the rest on the more monolithic side. This will also give you time to assess how how mature you are from an operational point of view – if you struggle to manage two services, managing 10 is going to be difficult.

This same over-eagerness is present in front-end development as much as back-end development. Stefan Tilkow recently tweeted regarding the trend of jumping straight into complex Javascript framework applications rather than evolving into them based on need:

In my opinion, the key to effective design is being able to give a good answer when asked “why”. Being able to articulate the reasons behind the choices made is critical to justifying them. By reasons, I mean a logical explanations of how the techniques chosen contribute to the desired ends. Neither “X recommends this” nor “This is what everybody’s doing” count. Designing, developing, and evolving software systems is not a game of following a recipe. In the words of Grady Booch:

Are Microservices the Next Big Thing?

Bandwagon

The question popped up in a LinkedIn discussion of my last post:

“A question for you, are microservices the next big thing?”

It was a refreshing change of pace to actually be asked about my opinion rather than be told what it is. The backlash against microservices is such that, anything less that outright condemnation is seen as “touting” the latest fad (this in spite of having authored posts such as “Microservice Architectures aren’t for Everyone”, “Microservice Mistakes – Complexity as a Service”, and “Microservices – The Too Good to be True Parts”). Reflex reactions like this will most likely be so simplistic as to be useless, regardless of whether pro or con.

Architectural design is about making decisions. Good design, in my opinion, is about making decisions justified by the context at hand rather than following a recipe. It’s about understanding the situation and applying principles rather than blindly replicating a pattern. No one cares about how cutting edge the technology is, they care that the solution solves the problem without bankrupting them.

So, to return to the question of whether I think microservices are “the next big thing”:

They shouldn’t be, but they might be. Shouldn’t, because a full-blown microservice architecture app, while perfectly appropriate for Netflix, isn’t likely to be appropriate for most in-house corporate applications. They won’t get a benefit because of the additional operational and development complexity. That being said, lots of inappropriate SOA initiatives sucked up a lot of money not that long ago – if software development had a mascot it would be an immortal lemming with amnesia.

The principles behind MSA, however, have some value IMHO. When a monolithic architecture begins to get in the way, those principles can provide some guidance on how to carve it up. The wonderful thing about SRP is its fractal nature, so you split out responsibilities at a level of granularity that’s appropriate for your application’s situation when it makes sense. There’s no rule that you have to carve up everything at once or that you have to slice it as thin as they do at Netflix.

That’s why my posts on the subject tend to sway back and forth. It’s not a recipe for the “right way” (as if there could be one right way) to design applications, it’s merely another set of ideas that, depending on the context, could help or hurt.

It’s not the technique itself that makes or breaks a design, it’s how applicable the technique is to problem at hand.

What Makes a Microservice “Micro”?

People really like to be able to use numbers. We see this in management; we see it in requirements gathering. Numbers, after all, are objective. Objective is better than subjective, right?

The answer, of course, is “it depends”. If one can defend the proposition that a given number equates to a given level of quality, then an objective measure should be preferable. If, however, the number is arbitrarily selected, the fact that it’s a number doesn’t change the fact that it was subjectively chosen.

Take, for example, the size metric that “defines” a microservice. According to James Hughes (who considers the definition “atrocious”), “…there seems to be a consensus that a micro service is a simple application that sits around the 10-100 LOC mark”. Does this mean that when the codebase hits 101 lines of code, the result ceases to be a microservice? Does this mean that higher-level languages are required to create microservices because lower-level ones would exceed the LOC limit before expressing something useful?

Clearly a quantitative metric that is irrelevant to what we really want to measure won’t work. This leaves us to choose a valid way to make a qualitative judgement about what makes a microservice “micro”.

There’s the cynical approach:

and there’s the pragmatic approach:

In my opinion, the defining characteristic of a microservice is that it’s an application (in terms of having an independent codebase that is independently deployed) that exists as a component of what an end-user would be more likely to consider the actual application. A microservice is part of the internals of what is the perceived application. It is important to remember that the microservice architectural style is an application architecture style.

I believe that Ben Morris’s suggestion that “…a single deployable service should be no bigger than a bounded context, but no smaller than an aggregate” is a good heuristic for identifying the service boundary. It puts the emphasis on cohesiveness rather than size. It is the single responsibility principle at the application/component level of abstraction.

In my opinion, a microservice is a component of an application that is independently scalable and independently deployable, possess an independent lifecycle, codebase, and data. It is “micro” in the sense of “microcosm” rather than “micro” in terms of some arbitrary unit of size.