Microservices or Monoliths – Fences and Neighbors

Photo of fence separating fields from a road

 

At the end of my last post, “What Makes a Monolith Monolithic?”, I stated that I didn’t consider the term “monolithic” to be inherently derogatory. It is, rather, a descriptive term relating to the style of organizing an application’s architecture. Depending on the context the system operates within, a monolithic architectural style could lie anywhere on the continuum between perfectly suited and perfectly disastrous. Placing it on that continuum requires a sense of what qualities are most needed or desired and which can be traded off in their stead. Everything comes with a cost, and attempting to ignore that fact merely sets us up for unpleasant future surprises.

After an initial period of unbridled enthusiasm, opinion seemed to gel around the idea that highly distributed application architectures (aka microservice architectures) were not suitable to all contexts. There are prerequisites for jumping into the microservices pool in terms of problem architecture, infrastructure, and organization. Attempting to shoehorn a microservice architecture into an environment that cannot support it will be overly expensive at best and a failure of apocalyptic proportions at worst.

There are many aspects of application design that are commonly recognized as beneficial: modularity, loose-coupling, high cohesion, and separation of concerns. It is critical to realize that these aspects can be found in systems with microservice architectures, monolithic systems, and everything in between. Distributed architectures are not necessary for modularity, nor any of those other aspects. In fact, one could easily create an application with a microservice architecture whose qualities are opposite to these desirable ones.

There are, however, situations where the benefit of a microservice architecture outweighs the costs and complexity. The ability to independently deploy and scale the various parts of an application is a major benefit, in my opinion. A well designed microservice architecture can even allow for the components of an application to be replaced on the fly. These features are not unique to microservice architectures, but are arguably easier to achieve than in other application architectures.

Real design, balancing both costs and benefits, is required. Sticking a bit of network in between the components is insufficient to ensure success. Deliberate design, especially as the boundaries multiply, is critical for an effective system. Identifying and providing for those boundaries at the conceptual level (i.e. before they become physical) is key. Good fences can either make for good neighbors, or they can create a maze of barriers.

What Makes a Monolith Monolithic?

Photo of Stonehenge, 1877

 

It seems like everybody throws around the term “monolith”, but what do we mean by that?

Sam Newman started the ball rolling yesterday with this tweet:

My first response was a (semi) joke:

I say semi joke because, in truth, semantics (i.e. meaning) is critical. The English language has a horrible tendency to overload terms as it is, and in our line of work we tend to make it even worse. Lack of specificity obscures, rather than enlightens. The problem with the term “monolith” is that, while it’s a powerfully evocative term, it isn’t a simple one to define. My second response was closer to an actual definition:

The purpose of this post is to expand on that a bit.

The “mono” portion of the term is, in my opinion, the crucial part. I believe that quality of oneness is what defines a monolithic system. As I noted in the second tweet, it’s a matter of meta-coupling, whether that coupling exists in the form of deployment, data architecture, or execution style (Jeppe Cramon‘s post “Microservices: It’s not (only) the size that matters, it’s (also) how you use them – part 3” shows how temporal coupling can turn a distributed system into a runtime monolith). The following tweets between Anne Currie and Sam illustrate the amorphous nature of what is and isn’t a monolith:

Modules that can be deployed to run in a single process need not be considered monolithic, if they’re not tightly coupled. Likewise, running distributed isn’t a guarantee against being monolithic if the components are tightly coupled in any way. The emphasis on “in any way” is due to the fact that any of the types of coupling I mentioned above can be a deal killer. If all the “microservices” must be deployed simultaneously for the system to work, it’s a distributed monolith. If the communication is both synchronous and fault intolerant, it’s a distributed monolith. If there’s a single data store backing the entire system, it’s a distributed monolith. It’s not the modularity that defines it (you can have a modular monolith), but the inability to separate the parts without damaging the whole system.

I would also point out that I don’t consider “monolithic” to be derogatory, in and of itself. There is a trade-off involved in terms of coupling and complexity (and cost). While I generally prefer more flexibility, there is always the danger of over-engineering. If we’re hand-carving marble gargoyles to stick on a tool shed, chances are the customer won’t be pleased. The solution should bear at least a passing resemblance to the problem context it’s supposed to address.

Design for Life

Soundview, Bronx, NY

 

The underlying theme of my last post, “Babies, Bathwater, and Software Architects”, was that it’s necessary to understand the role of a software architect in order to understand the need for that role. If our understanding of the role is flawed, not just missing aspects of what the role should be focusing on, but also largely consisting of things the role should not be concerned with, then we can’t really effectively determine whether the role is needed or not. If a person drowning is told that an anvil is a life-preserver, that doesn’t mean that they don’t need a life-preserver. It does mean they need a better definition of “life-preserver”.

Ruth Malan, answering the question “Do we still need architects?”, captures the essence of what is unique about the concerns of the software architect role:

There’s paying attention to the structural integrity of the code when that competes with the urge to deliver value and all we’ve been able to accomplish in terms of the responsiveness of continuous integration and deployment. We don’t intend to let the code devolve as we respond to unfolding demands, but we have to intend not to, and that takes time — possibly time away from the next increment of user-perceived value. There’s watching for architecturally impactful, structurally and strategically significant decisions, and making sure they get the attention, reflection, expertise they require. Even when the team periodically takes stock, and spends time reflecting learning back into the design/code, the architect’s role is to facilitate, to nurture, the design integrity of the system as a system – as something coherent. Where coherence is about not just fit and function, but system properties. Non-trivial, mutually interacting properties that entail tradeoffs. Moreover, this coherence must be achieved across (microservice, or whatever, focused) teams. This takes technical know-how and know-when, and know-who to work with, to bring needed expertise to bear.

These system properties are crucial, because without a cohesive set of system properties (aka quality of service requirements), the quality of the system suffers:

Even if the parts are perfectly implemented and fly in perfect formation, the quality is still lacking.

A tweet from Charles T. Betz points out the missing ingredient:

Now, even though Frederick Brooks was writing about the architecture of hardware, and the nature of users has drastically evolved over the last fifty-four years, his point remains: “Architecture must include engineering considerations, so that the design will be economica1 and feasible; but the emphasis in architecture is upon the needs of the user, whereas in engineering the emphasis is upon the needs of the fabricator.”

In other words, habitability, the quality of being “livable”, is a critical condition for an architecture. Two systems providing the exact same functionality may not be equivalent. The system providing the “better” (from the user’s perspective) quality of service will most likely be seen as the superior system. In some cases, quality of service concerns can even outweigh functional concerns.

Who, if not the software architect, is looking out for the livability of your system as a whole?

Form Follows Function on SPaMCast 331

SPaMCAST logo

I’m back for another appearance on Tom Cagley’s Software Process and Measurement (SPaMCast) podcast.

SPaMCast 331 features Tom on Agile Coaching, a discussion of my “Microservices vs SOA – Is there any real difference?” post and an installment of Jo Ann Sweeny’s column, “Explaining Communication”, dealing with communication channels.

Microservices vs SOA – Is there any real difference?

Microservice architecture has been the hot topic for 2014, so I suppose it’s appropriate that it be the subject for what I intend to be my last post until 2015. Last week, Kelly Sommers kicked off an active discussion of the nature of microservices vis-a-vis SOA:

This isn’t really a new observation. Before Lewis and Fowler published their final installment of the post that started the everyone talking, Steve Jones had already published “Microservices is SOA, for those who know what SOA is”. Even Adrian Cockcroft, in response to Sommers, noted:

And yet, they’re different. In a post written for Iasa, “Microservices – The Return of SOA?”, I quoted Anne Thomas Manes’ “SOA is Dead; Long Live Services”:

Successful SOA (i.e., application re-architecture) requires disruption to the status quo. SOA is not simply a matter of deploying new technology and building service interfaces to existing applications; it requires redesign of the application portfolio. And it requires a massive shift in the way IT operates. The small select group of organizations that has seen spectacular gains from SOA did so by treating it as an agent of transformation. In each of these success stories, SOA was just one aspect of the transformation effort. And here’s the secret to success: SOA needs to be part of something bigger. If it isn’t, then you need to ask yourself why you’ve been doing it.

As I stated in that post

Part of the problem may be that both SOA and microservices have aspects that transcend boundaries. Manes quote above makes it clear that SOA is concerned with enterprise IT architecture. Microservices are primarily an application architecture pattern.

Microservices can be reused by multiple applications, but need not be. SOA’s emphasis was at a higher level of abstraction. While the two share a great many principles, they apply them at different scales (application and solution architecture versus enterprise IT architecture).

Last weeks Twitter stream did produce some examples of principles that are, if not unique, then at least more heavily emphasized in the microservice style. From Marco Vermeulen:

https://twitter.com/jetpack/status/543688544204898304

Eugene Kalenkovich‘s post, “Can I Haz Name?”, captures the essence (in my opinion) of this style: “Independent Scalability, Independent Lifecycle and Independent Data”. It’s not about the lines of code, but about the separation of concerns within the context of the application. These same “independences” are important to SOA, but define a microservice architecture.

Accidental Architecture

Hillside Slum

I’m not sure if it’s ironic or fitting that my very first post on Form Follows Function, “Like it or not, you have an architecture (in fact, you may have several)”, dealt with the concept of accidental architecture. A blog dedicated to software and solution architecture starts off by discussing the fact that architecture exists even in the absence of intentional design? It is, however, a theme that seems to recur.

The latest recurrence was a Twitter exchange with Ruth Malan, in which she stated:

Design is the act and the outcome. We design a system. The system has a design.

This prompted Arnon Rotem-Gal-Oz to observe that architecture need not be intentional and “…even areas you neglect well [sic] have design and then you’d have to deal with its implications”. To this I added “accidental architecture is still architecture – whether it’s good architecture or not is another thing”.

Ruth closed with a reference to a passage by Grady Booch:

Every software-intensive system has an architecture. In some cases that architecture is intentional, while in others it is accidental. Most of the time it is both, born of the consequences of a myriad of design decisions made by its architects and its developers over the lifetime of a system, from its inception through its evolution.

The idea that an architecture can “emerge” out of skillful construction rather than as a result of purposeful design, is trivially true. The “Big Ball of Mud”, an ad hoc arrangement of code that grows organically, remains a popular design pattern (yes, it’s a pattern rather than an anti-pattern – see the Introduction of “Big Ball of Mud” for an explanation of why). What remains in question is how effective is an architecture that largely or even entirely “emerges”.

Even the current architectural style of the day, microservices, can fall prey to the Big Ball of Mud syndrome. A plethora of small service applications developed without a unifying vision of how they will make up a coherent whole can easily turn muddy (if not already born muddy). The tagline of Simon Brown’s “Distributed big balls of mud” sums it up: “If you can’t build a monolith, what makes you think microservices are the answer?”.

Someone building a house using this theory might purchase the finest of building materials and fixtures. They might construct and finish each room with the greatest of care. If, however, the bathroom is built opening into the dining room and kitchen, some might question the design. Software, solution, and even enterprise IT architectures exist as systems of systems. The execution of a system’s components is extremely important, but you cannot ignore the context of the larger ecosystem in which those components will exist.

Too much design up front, architects attempting to make decisions below the level of granularity for which they have sufficient information, is obviously wrong. It’s like attempting to drive while blindfolded using only a GPS. By the same token, jumping in the car and driving without any idea of a destination beyond what’s at the end of your hood is unlikely to be successful either. Finding a workable balance between the two seems to be the optimal solution.

[Shanty Town Image by Otsogey via Wikimedia Commons.]

What do we mean by “architecture”?

Some things last longer than others

Every systematic development of any subject ought to begin with a definition, so that everyone may understand what the discussion is about.

Marcus Tullius Cicero (196BC ‒ 16BC), De Officiis, Book 1, Moral Goodness (h/t to Glen Alleman, October 8, 2013 Quote of the Day)

One of the joys of the English language is the overloading of words with multiple meanings. While it’s not hard to start an argument over technical issues under normal circumstances, having multiple definitions to conflate makes it that much easier. Take, for example, the word “architecture”. While different dictionaries give slightly different definitions (e.g. Merriam-Webster Dictionary.com and Wiktionary), the common set of definitions boil down to:

While there is a relationship between these concepts, a person practicing architecture might create an architectural design using one or more architectural styles, there is enough differentiation to cause trouble if we don’t clarify our terms. Far from being an academic exercise, paying attention to semantics can actually save time and frustration when there is ambiguity present.

Architecture versus Design

There was interesting debate on what is an architect, the difference between design and architecture (no one really knows…
(Ilan Kirschenbaum, discussing a meeting of the Software Craftsmanship in Israel group)

All architecture is design but not all design is architecture. Architecture represents the significant design decisions that shape a system, where significant is measured by cost of change.
(Grady Booch, as quoted by nearly everyone)

In the inaugural post of Form Follows Function, I noted the definition of architecture that I felt best applied across the realms of Application, Solution, and Enterprise Architecture. While researching the post “What’s driving your architecture?”, I found considerable discussion of the difference between architecture and design (in the sense of design decisions that are architecturally significant versus those that are not). Although the distinction might seem to be academic at first glance, it cuts to the heart of questions around the value of architecture and architects, particularly under Agile processes. This makes the confusion alluded to above by Ilan Kirschenbaum doubly worrisome.

Simon Brown, building on Booch’s comment above, provides important insights on the concept of design in “Disambiguating architecture”. Design “…exists to resolve a force on the system”, where force represents “…cost, scope, resources, timescales, requirements – anything you wish to take into consideration as part of your design selection”. He also notes that “…a design is one of a number of possible choices for resolving a particular force on the system”. Thus design, architectural or not, can be defined as making the optimal choice to satisfy the various forces impacting the matter at hand.

Rick Kazmon and Amnon Eden, writing for the Carnegie Mellon Software Engineering Institute, identified locality as the defining characteristic of architectural design in their article “Defining the Terms Architecture, Design, and Implementation”. Non-local specifications, applying to the system as a whole, constitute architecture in their opinion. According to Kazmon and Eden, “More generally, for each specification we should be able to determine whether it is a design statement, describing a purely local phenomenon (and hence of secondary interest in architectural documentation, discussion, or analysis), or whether it is an instance of an underlying, more general rule”.

Eden and Kazman, joined by Yoram Hirshfeld, further expanded on this definition in “Abstraction Classes In Software Design”, published in IEE Software Vol. 153, No. 4 (Aug. 2006). The authors identify global design decisions as strategic and local design decisions as tactical:

Strategic design statements [11] articulate design decisions that determine the primary behavioural and structural properties of a program (software system). Strategic decisions address global, system-wide concerns and carry the most consequential implications. Strategic decisions include the choice of programming paradigm [36] (‘object-oriented programming’), architectural style [17] (‘pipes and filters’), application framework [24] (‘Microsoft Foundation Classes’), component-based software engineering standards [40] (‘Enterprise JavaBeans’), and design principles (‘universal base class’), as well as assumptions that may lead to architectural mismatch [18] (‘The Softbench Broadcast Message Server expected all of the components to have a graphical user interface’) and law governed regularities [28] (‘every class in the system inherits from class C’). Because of the consequences they carry, Strategic decisions must be made early in the software development process and should be established explicitly before any detailed design is carried out.

In contrast, Tactical design [11] statements articulate design decisions that are concerned with a specific module. Tactical decisions often describe a pattern of correlations between one collection of modules (objects, procedures, classes etc.) and another. Intuitively speaking, Tactical statements are ‘local’ in the sense that their scope is limited to some part of the program and not outside it. Tactical decisions include the choice of design patterns [16] (‘Factory Method’), refactorings [15] (‘Replace Conditional With Polymorphism’), and programming idioms [5] (‘counted pointer’), and usually are taken much later than strategic design decisions in the software development process.

Although I broadly agree with the general rule of global = strategic and local = tactical, it should not be considered an absolute. It is possible for one segment of a system to have aspects that strongly influence the overall architecture (justifying Booch’s criteria for significance). This is the reason that I do not hold the opinion that functional requirements are design and non-functional are architecture.

Arnon Rotem-Gal-Oz, architecture manager at Nice Systems, identifies several aspects of architecture in his presentation “Software Architecture”. Architecture comprises the major components of a system; their relationships and interactions. Data and behavior of these major components is only relevant to architecture from the point of view of the interactions between these components. Like Booch, Rotem-Gal-Oz characterizes the architecture as being the most difficult parts of the system to change. Like Eden, Kazman, and Hirshfeld, he defines architecture as the design decisions that must be made earliest in the process.

The value of strategic, foundational design decisions should be obvious. Since these aspects of the system are both difficult and costly to change, there should be considerable incentive to make optimal choices. As noted by Kevlin Henney in “What is Software Architecture?” on developerFusion:

The issue is not whether or not a system has architecture, but whether its architecture is good or not. All systems have architecture, whether intentional or accidental, explicit or implicit, good or bad – even “no architecture” systems have architecture!

Having related architecture to cost of change, we have a simple way of evaluating architectural quality. It is not that a good architecture makes a system cheap to create; it is that it is also cheap to evolve. In other words, a good architecture is one in which the significance of design decisions is minimised. You are free to change many aspects of a system without the fear that such changes are challenging, costly or create a cascade of bugs. A good architecture is therefore a sustainable one.

Given the criticality of these design decisions, it makes little sense to leave them to chance. Sustainable, flexible architecture is unlikely to emerge organically. Sufficient planning and coordination will be needed from someone in the architect role (regardless of whether the role is full or part-time). Localized design decisions can then be made within that framework in a decentralized manner.

Occasionally I hear people still raising the agile mantra against Big Design/Requirements Up Front. The thing is that Agile Manifesto never said to intentionally bury your head in the sand with regards to the purpose of the system. It was a push-back against spending months in analysis without anything but documents coming out, but the goal was to reach a middle ground. Nobody ever said “no design up-front” or “no requirements up front”.
(Udi Dahan from “A CQRS Journey – with and without Microsoft”)

Like it or not, you have an architecture (in fact, you may have several)

What better way to inaugurate the blog than by defining what is meant by architecture and why you should care?

Wikipedia’s definition: “Architecture is both the process and product of planning, designing and construction” is both concise and comprehensive (which is commendable from an architectural standpoint). It applies to all the various types of architecture, both physical and virtual. Regardless of the size of your organization, you will have multiple “products of planning, designing and construction”.

If you have a laptop, a cable modem and a wireless router, then you have a network architecture. Add in Office, QuickBooks and Gmail and you now have a solutions architecture (with a cloud component, no less). Of course, the data from those applications provides you with an information architecture. Combining those elements with the structure of your business: defining your current state, assessing how well you the technology/data/applications align with the business, mapping out where you want to be etc. and you have an enterprise architecture.

Does this mean that all enterprises, regardless of size, need formal architecture programs and, of course, the architects to run them? Obviously, the answer is “no”. There are far too many successful businesses without such programs for that to be the case. Even if the answer were “yes”, those too small to afford the expense would have to choose between making do and giving up (and I doubt the latter is really an option).

The important thing to take away is that “architect” is the name of a role, not necessarily a position. Not everyone “doing architecture” is a full time architect. Many small business owners perform the functions without thinking of themselves as enterprise architects. What is necessary is that some care is directed toward architectural concerns, because there is a critical omission in the definition above: Architecture should be both the process and product of planning, designing and construction, although it may just be the product of construction.

With one notable exception, most do not intentionally create architectural nightmares. They just evolve that way. You start simple, with an add-on here and an enhancement there; suddenly what was once simple is now rambling and incoherent. In such a situation, maintaining normal function may well consume more and more precious time and attention. This is where an up front focus on architecture pays dividends. Managed growth and change is far easier to deal with (not to mention cheaper) than the organic variety.