At OSCON in 2015 I gave a brief talk (14 min) on what architecture is and why it matters.
Software Architecture Guide
When people in the software industry talk about “architecture”, they refer to a hazily defined notion of the most important aspects of the internal design of a software system. A good architecture is important, otherwise it becomes slower and more expensive to add new capabilities in the future.
Like many in the software world, I’ve long been wary of the term “architecture” as it often suggests a separation from programming and an unhealthy dose of pomposity. But I resolve my concern by emphasizing that good architecture is something that supports its own evolution, and is deeply intertwined with programming. Most of my career has revolved about the questions of what good architecture looks like, how teams can create it, and how best to cultivate architectural thinking in our development organizations. This page outlines my view of software architecture and points you to more material about architecture on this site.
A guide to material on martinfowler.com about software architecture.
What is architecture?
People in the software world have long argued about a definition of architecture. For some it's something like the fundamental organization of a system, or the way the highest level components are wired together. My thinking on this was shaped by an email exchange with Ralph Johnson, who questioned this phrasing, arguing that there was no objective way to define what was fundamental, or high level and that a better view of architecture was the shared understanding that the expert developers have of the system design.
A second common style of definition for architecture is that it's “the design decisions that need to be made early in a project”, but Ralph complained about this too, saying that it was more like the decisions you wish you could get right early in a project.
His conclusion was that “Architecture is about the important stuff. Whatever that is”. On first blush, that sounds trite, but I find it carries a lot of richness. It means that the heart of thinking architecturally about software is to decide what is important, (i.e. what is architectural), and then expend energy on keeping those architectural elements in good condition. For a developer to become an architect, they need to be able to recognize what elements are important, recognizing what elements are likely to result in serious problems should they not be controlled.
Why does architecture matter?
Architecture is a tricky subject for the customers and users of software products - as it isn't something they immediately perceive. But a poor architecture is a major contributor to the growth of cruft - elements of the software that impede the ability of developers to understand the software. Software that contains a lot of cruft is much harder to modify, leading to features that arrive more slowly and with more defects.
This situation is counter to our usual experience. We are used to something that is “high quality” as something that costs more. For some aspects of software, such as the user-experience, this can be true. But when it comes to the architecture, and other aspects of internal quality, this relationship is reversed. High internal quality leads to faster delivery of new features, because there is less cruft to get in the way.
While it is true that we can sacrifice quality for faster delivery in the short term, before the build up of cruft has an impact, people underestimate how quickly the cruft leads to an overall slower delivery. While this isn't something that can be objectively measured, experienced developers reckon that attention to internal quality pays off in weeks not months.
Application Architecture
The important decisions in software development vary with the scale of the context that we're thinking about. A common scale is that of an application, hence “application architecture”.
The first problem with defining application architecture is that there's no clear definition of what an application is. My view is that applications are a social construction:
- A body of code that's seen by developers as a single unit
- A group of functionality that business customers see as a single unit
- An initiative that those with the money see as a single budget
Such a loose definition leads to many potential sizes of an application, varying from a few to a few hundred people on the development team. (You'll notice I look at size as the amount of people involved, which I feel is the most useful way of measuring such things.) The key difference between this and enterprise architecture is that there is a significant degree of unified purpose around the social construction.
Application Boundary
One of the undecided problems of software development is deciding what the boundaries of a piece of software is. (Is a browser part of an operating system or not?) Many proponents of Service Oriented Architecture believe that applications are going away - thus future enterprise software development will be about assembling services together.
I don't think applications are going away for the same reasons why application boundaries are so hard to draw. Essentially applications are social constructions:
Microservices Guide
The microservice architectural pattern is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies. While their advantages have made them very fashionable in the last few years, they come with the costs of increasing distribution, weakened consistency and require maturity in operational management.
Patterns of Legacy Displacement
When faced with the need to replace existing software systems, organizations often fall into a cycle of half-completed technology replacements. Our experiences have taught us a series of patterns that allow us to break this cycle, relying on: a deliberate recognition of the desired outcomes of displacing the legacy software, breaking this displacement in parts, incrementally delivering these parts, and changing the culture of the organization to recognize that change is the unvarying reality.
Micro Frontends
Good frontend development is hard. Scaling frontend development so that many teams can work simultaneously on a large and complex product is even harder. In this article we'll describe a recent trend of breaking up frontend monoliths into many smaller, more manageable pieces, and how this architecture can increase the effectiveness and efficiency of teams working on frontend code. As well as talking about the various benefits and costs, we'll cover some of the implementation options that are available, and we'll dive deep into a full example application that demonstrates the technique.
GUI Architectures
Graphical User Interfaces provide a rich interaction between the user and a software system. Such richness is complex to manage, so it's important to contain that complexity with a thoughtful architecture. The Forms and Controls pattern works well for systems with a simple flow, but as it breaks down under the weight of greater complexity, most people turn to “Model-View-Controller” (MVC). Sadly MVC is one of the most misunderstood architectural patterns around, and systems using that name display a range of important differences, sometimes described under names like Application Model, Model-View-Presenter, Presentation Model, MVVM, and the like. The best way to think of MVC is as set of principles including the separation of presentation from domain logic and synchronizing presentation state through events (the observer pattern).
Serverless Architectures
Serverless architectures are application designs that incorporate third-party “Backend as a Service” (BaaS) services, and/or that include custom code run in managed, ephemeral containers on a “Functions as a Service” (FaaS) platform. By using these ideas, and related ones like single-page applications, such architectures remove much of the need for a traditional always-on server component. Serverless architectures may benefit from significantly reduced operational cost, complexity, and engineering lead time, at a cost of increased reliance on vendor dependencies and comparatively immature supporting services.
Presentation Domain Data Layering
One of the most common ways to modularize an information-rich program is to separate it into three broad layers: presentation (UI), domain logic (aka business logic), and data access. So you often see web applications divided into a web layer that knows about handling HTTP requests and rendering HTML, a business logic layer that contains validations and calculations, and a data access layer that sorts out how to manage persistent data in a database or remote services.
Catalog of Patterns of Distributed Systems
Distributed systems provide a particular challenge to program. They often require us to have multiple copies of data, which need to keep synchronized. Yet we cannot rely on processing nodes working reliably, and network delays can easily lead to inconsistencies. Despite this, many organizations rely on a range of core distributed software handling data storage, messaging, system management, and compute capability. These systems face common problems which they solve with similar solutions. In 2020 Unmesh Joshi began collecting these solutions as patterns, publishing them on this site as he developed them. In 2023 these were published in the book Patterns of Distributed Systems. This page links to short summaries of each pattern, with deep links to the relevant chapters for the online eBook publication on oreilly.com
Feature Toggles (aka Feature Flags)
Feature Toggles (often also refered to as Feature Flags) are a powerful technique, allowing teams to modify system behavior without changing code. They fall into various usage categories, and it's important to take that categorization into account when implementing and managing toggles. Toggles introduce complexity. We can keep that complexity in check by using smart toggle implementation practices and appropriate tools to manage our toggle configuration, but we should also aim to constrain the number of toggles in our system.
Modularizing React Applications with Established UI Patterns
Established UI patterns are often underutilized in the frontend development world, despite their proven effectiveness in solving complex problems in UI design. This article explores the application of established UI building patterns to the React world, with a refactoring journey code example to showcase the benefits. The emphasis is placed on how layering architecture can help organize the React application for improved responsiveness and future changes.
Enterprise Architecture
While application architecture concentrates on the architecture within some form of notional application boundary, enterprise architecture looks architecture across a large enterprise. Such an organization is usually too large to group all its software in any kind of cohesive grouping, thus requiring coordination across teams with many codebases, that have developed in isolation from each other, with funding and users that operate independently of each other.
Much of enterprise architecture is about understanding what is worth the costs of central coordination, and what form that coordination should take. At one extreme is a central architecture group that must approve all architectural decision for every software system in the enterprise. Such groups slow down decision making and cannot truly understand the issues across such a wide portfolio of systems, leading to poor decision-making. But the other extreme is no coordination at all, leading to teams duplicating effort, inability for different system to inter-operate, and a lack of skills development and cross-learning between teams.
Like most people with an agile mindset, I prefer to err on the side of decentralization, so will head closer to the rocks of chaos rather than suffocating control. But being on that side of the channel still means we have to avoid the rocks, and a way to maximize local decision making in a way that minimizes the real costs involved.
Enterprise Architects Join the Team
Enterprise Architecture groups often get separated from day to day development. This can lead to their knowledge of development work getting out of date and development teams not taking a broad company-wide perspective. Having seen this happen frequently my colleague (Thoughtworks CTO) Rebecca argues that enterprise architects can be much more effective by joining development teams.
Creating an integrated business and technology strategy
To make fruitful use of technology, we need to align our technology thinking with underlying business plans. A technology strategy can drive this alignment, providing it properly integrates business and technology. We have developed a conceptual framework to help us with this strategic thinking, based on recognizing common aspects of strategic initiatives, leading us to identify eleven prevalent strategic directions. For each direction we outline the key business questions that they raise, and the investigations that we need to do to explore the technology implications. We've found that this framework leads not just to more effective technology strategies, but allows technology to inform business thinking, developing new revenue streams.
Products Over Projects
Software projects are a popular way of funding and organizing software development. They organize work into temporary, build-only teams and are funded with specific benefits projected in a business case. Product-mode instead uses durable, ideate-build-run teams working on a persistent business issue. Product-mode allows teams to reorient quickly, reduces their end-to-end cycle time, and allows validation of actual benefits by using short-cycle iterations while maintaining the architectural integrity of their software to preserve their long-term effectiveness.
The Architect Elevator — Visiting the upper floors
Many large organizations see their IT engine separated by many floors from the executive penthouse, which also separates business and digital strategy from the vital work of carrying it out. The primary role of an architect is to ride the elevators between the penthouse and engine room, stopping wherever is needed to support these digital efforts: automating software manufacturing, minimizing up-front decision making, and influencing the organization alongside technology evolution.
The Role of an Enterprise Architect in a Lean Enterprise
When an organization takes on an agile mindset, enterprise architecture doesn't go away, but the role of enterprise architects changes. Enterprise Architects no longer make choices, but help others make the right choice and then radiate that information. Enterprise Architects still need to form a vision, but then need to build bridges between teams to build communities of learning. These will allow teams to explore new approaches and learn from each other, with Enterprise Architects as partners in that growth.
Enterprise Integration Using REST
Most internal REST APIs are one-off APIs purpose built for a single integration point. In this article, I'll discuss the constraints and flexibility that you have with nonpublic APIs, and lessons learned from doing large scale RESTful integration across multiple teams.