Monolithic (single structure) and polylithic (multi-structure) applications each offer advantages, depending on the stage of an organization’s life. Eventually, organizations will reach a point where monolithic application structures restrict productivity and limit scale. The solution is the exploration of polylithic application structures, commonly referred to as microservices.
When the complexity is high
Why do we use microservices? Microservices are used when the complexity of a system is too large to manage as a monolithic application. If the application can’t be reasonably managed as a single application, in most cases, polylithic architecture structures are the most efficient. In a recent blog post, Martin Fowler outlined three reasons microservices are the answer for organizations with rapid growth.
- Reduced baggage: For complex systems, the additional overhead of microservices decreases overall complexity.
- Improvements in productivity: The more complex the system, the more productivity is impacted.
- Reduced attenuation: Productivity variability is narrowed when monolithic applications are decoupled.
For complex systems, the reduced baggage required to manage microservices improves productivity. As the complexity of the base system increases, productivity falls quickly without using microservices. Also, as the demand for scale magnifies, the application becomes bloated with complexity. The explosive need for scale raises the urgency to realize productivity gains. These gains are accelerated by the decreased coupling of microservices, that limit productivity attenuation. As a result, the environment becomes more stable, and the release cadence improves.
In his book The Mythical Man-Month: Essays on Software Engineering, Fred Brooks popularized the phrase “Adding manpower to a late software project makes it later.” We all understand that adding substantial resources to make aggressive software development milestones when changing monolithic applications rarely works. If most large single applications do have a degree of modularity, then why do these applications still fail to scale? It could be it’s not about the application at all. Applications are built around organizational communication structures or business processes. If those processes are efficient, guess what? The application functions well. But if business processes are ineffective, software applications mimic the inefficient processes.
Brooks’ experience leading development for the OS/360 at IBM led to many of his observations. Another comment Brooks made was on a 1967 paper written by Melvin Conway, a computer scientist and hacker. The paper was rejected by the Harvard Business Review and later accepted by Datamation, a popular IT publication at the time. Conway’s thesis was that “any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization’s communication structure.” Brooks coined the term “Conway’s Law” in his book, and the name stuck.
Conway’s Law is this: “Organizations which design systems… are constrained to produce systems which are copies of the communication structures of these organizations.”
Monoliths are large blocks of stone used to build structures or monuments. These colossal stones were used by ancient civilizations with primitive technology. Cueva de Menga in Antequera, Spain, is a dolmen made of megaliths and weighed up to 180 tons, built in 2500 BC. The Kerloas menhir often called the “standing stone” is located in Brittany, France, with the latest structure weighing in at 150 tons.
Similarly, monolithic applications are single-tiered structures where the user interface and code are combined into a single program from a single platform. Monolithic applications are easier to debug and test. Easily accessible coarse-grained application security, managed as one application, makes authentication and authorization straightforward. Collectively, these benefits produce applications that are faster to plan and quicker to design. However, eventually monolithic applications that were once efficient and produced near-flawless releases become repositories of technical debt. As vendor-partner integration become a minimum requirement for growth, security modules don’t have the granularity needed to expose particulars of functionality. The all-or-nothing access model doesn’t have a long life span. At this point, we turn to polylithic application types or microservices.
There are benefits to managing independent sections of a core application as opposed maintaining all functionality as one large application. In his book The Art of UNIX Programming, Eric Raymond outlined the 17 Unix rules that align to polylithic application types. The design rules Raymond identifies also have applicability to the deployment of microservices.
The Rule of Modularity stresses that programs are built from simple parts, so problems are local. The Rule of Clarity asks developers to write for developers, not for computers, making code easier to read. The Rule of Composition encourages developers to divide monolithic applications into small, simple programs to aid with simplicity. The Rule of Separation instructs developers to divide the program from the policy (front-end interface and back-end interface). The Rule of Simplicity aims to discourage complete but beautify complexities, which in practice become bug-ridden programs. The Rule of Parsimony directly states, “don’t write big programs,” which limits final waste (products built but not used). The Rule of Transparency reduces redundancy by designing pieces that other developers can see and access. The Rule of Robustness ensures that programs can undergo stress and therefore output reliable products. The Rule of Presentation has developers when necessary make the data more complicated rather than injecting additional procedural logic into programs. The Rule of Least Surprise means to build on expected logic — e.g. the “+” sign should always mean addition in a calculator program. The Rule of Silence attempts to keep developer output limited to prevent unnecessary parsing through output. The Rule of Repair suggests that programs should “fail noisily” and therefore be easy to fix. The Rule of Economy has developers value a developer’s time, over machine time, ideally reducing project costs. The Rule of Generation focuses on building code from abstract high-level programs, to limit writing code by hand thereby reducing errors. The Rule of Optimization suggests designers should prototype before polishing any code, preventing excessive time spent pursuing marginal gains. The Rule of Diversity supports designing programs to be leveraged in ways other than those initially intended by the developers. The Rule of Extensibility requests developers to build programs where functionality can be extended, stretching the life span of programs and improving utility.
The design rules created for Unix have many similarities with the microservice layout. The evolution from monolithic kernel-based operating systems to microkernel-based operating systems provided the near-minimum amount of software that could provide mechanisms that when implement together form an operating system. Traits such as correctness, consistency and completeness were applied to Unix and microkernels, and today they apply to microservices.
The Reactive Manifesto
Organizations working in different domains were in search of patterns to build software that looked similar. The need for portability resulted in the Reactive Manifesto, which states that systems built as reactive systems are more flexible. Four principles govern reactive systems:
- Responsive: timely responses driving usability and utility.
- Resilient: responsiveness even during failure (replication, containment, isolation and delegation).
- Elastic: responsive under varying workloads (dynamic resource) achieving elasticity.
- Message-driven: explicit message-passing to enable load management, elasticity, and flow control.
Systems that are responsive, resilient, elastic and message-driven are reactive systems. Microservices is a particular approach for service-oriented architectures used to build flexible, independently deployable software systems. By applying the principles of reactive systems to microservices, we create reactive microservices. These easy-to-replace services, organized around capabilities, can be implemented in a range of programming languages, databases, hardware and software environments.
Is a microservice strategy on your road map? Evaluate when it’s the right time for your organization to move from a monolithic to a polylithic application structure. Enabling reactive healthcare microservices might be the answer. The business will thank you.