About This E-Book

Transcription

About This E-BookEPUB is an open, industry-standard format for e-books. However, support forEPUB and its many features varies across reading devices and applications. Useyour device or app settings to customize the presentation to your liking. Settingsthat you can customize often include font, font size, single or double column,landscape or portrait mode, and figures that you can click or tap to enlarge. Foradditional information about the settings and features on your reading device orapp, visit the device manufacturer’s Web site.Many titles include programming code or configuration examples. To optimizethe presentation of these elements, view the e-book in single-column, landscapemode and adjust the font size to the smallest setting. In addition to presentingcode and configurations in the reflowable text format, we have included imagesof the code that mimic the presentation found in the print book; therefore, wherethe reflowable format may compromise the presentation of the code listing, youwill see a “Click here to view code image” link. Click the link to view the printfidelity code image. To return to the previous page viewed, click the Back buttonon your device or app.

Clean ArchitectureA CRAFTSMAN’S GUIDE TO SOFTWARE STRUCTUREAND DESIGNRobert C. MartinBoston Columbus Indianapolis New York San Francisco Amsterdam Cape Town Dubai London Madrid Milan Munich Paris Montreal Toronto Delhi Mexico City São Paulo Sydney Hong Kong Seoul Singapore Taipei Tokyo

Many of the designations used by manufacturers and sellers to distinguish theirproducts are claimed as trademarks. Where those designations appear in thisbook, and the publisher was aware of a trademark claim, the designations havebeen printed with initial capital letters or in all capitals.The author and publisher have taken care in the preparation of this book, butmake no expressed or implied warranty of any kind and assume no responsibilityfor errors or omissions. No liability is assumed for incidental or consequentialdamages in connection with or arising out of the use of the information orprograms contained herein.For information about buying this title in bulk quantities, or for special salesopportunities (which may include electronic versions; custom cover designs; andcontent particular to your business, training goals, marketing focus, or brandinginterests), please contact our corporate sales department atcorpsales@pearsoned.com or (800) 382-3419.For government sales inquiries, please contactgovernmentsales@pearsoned.com.For questions about sales outside the U.S., please contact intlcs@pearson.com.Visit us on the Web: informit.comLibrary of Congress Control Number: 2017945537Copyright 2018 Pearson Education, Inc.All rights reserved. Printed in the United States of America. This publication isprotected by copyright, and permission must be obtained from the publisherprior to any prohibited reproduction, storage in a retrieval system, ortransmission in any form or by any means, electronic, mechanical,photocopying, recording, or likewise. For information regarding permissions,request forms and the appropriate contacts within the Pearson Education GlobalRights & Permissions Department, please visitwww.pearsoned.com/permissions/.ISBN-13: 978-0-13-449416-6ISBN-10: 0-13-449416-4

1 17

This book is dedicated to my lovely wife, my four spectacular children, and theirfamilies, including my quiver full of five grandchildren—who are the dessert ofmy life.

CONTENTSForewordPrefaceAcknowledgmentsAbout the AuthorPART IIntroductionChapter 1What Is Design and Architecture?The Goal?Case StudyConclusionChapter 2A Tale of Two ValuesBehaviorArchitectureThe Greater ValueEisenhower’s MatrixFight for the ArchitecturePART IIStarting with the Bricks: Programming ParadigmsChapter 3Paradigm OverviewStructured ProgrammingObject-Oriented ProgrammingFunctional ProgrammingFood for Thought

ConclusionChapter 4Structured ProgrammingProofA Harmful ProclamationFunctional DecompositionNo Formal ProofsScience to the RescueTestsConclusionChapter 5Object-Oriented ConclusionChapter 6Functional ProgrammingSquares of IntegersImmutability and ArchitectureSegregation of MutabilityEvent SourcingConclusionPART IIIDesign PrinciplesChapter 7SRP: The Single Responsibility PrincipleSymptom 1: Accidental DuplicationSymptom 2: MergesSolutionsConclusionChapter 8OCP: The Open-Closed PrincipleA Thought ExperimentDirectional ControlInformation HidingConclusion

Chapter 9LSP: The Liskov Substitution PrincipleGuiding the Use of InheritanceThe Square/Rectangle ProblemLSP and ArchitectureExample LSP ViolationConclusionChapter 10 ISP: The Interface Segregation PrincipleISP and LanguageISP and ArchitectureConclusionChapter 11 DIP: The Dependency Inversion PrincipleStable AbstractionsFactoriesConcrete ComponentsConclusionPART IVComponent PrinciplesChapter 12 ComponentsA Brief History of ComponentsRelocatabilityLinkersConclusionChapter 13 Component CohesionThe Reuse/Release Equivalence PrincipleThe Common Closure PrincipleThe Common Reuse PrincipleThe Tension Diagram for Component CohesionConclusionChapter 14 Component CouplingThe Acyclic Dependencies PrincipleTop-Down DesignThe Stable Dependencies Principle

The Stable Abstractions PrincipleConclusionPART VArchitectureChapter 15 What Is anceKeeping Options OpenDevice IndependenceJunk MailPhysical AddressingConclusionChapter 16 IndependenceUse CasesOperationDevelopmentDeploymentLeaving Options OpenDecoupling LayersDecoupling Use CasesDecoupling ModeIndependent Develop-abilityIndependent DeployabilityDuplicationDecoupling Modes (Again)ConclusionChapter 17 Boundaries: Drawing LinesA Couple of Sad StoriesFitNesseWhich Lines Do You Draw, and When Do You Draw Them?What About Input and Output?Plugin ArchitectureThe Plugin Argument

ConclusionChapter 18 Boundary AnatomyBoundary CrossingThe Dreaded MonolithDeployment ComponentsThreadsLocal ProcessesServicesConclusionChapter 19 Policy and LevelLevelConclusionChapter 20 Business RulesEntitiesUse CasesRequest and Response ModelsConclusionChapter 21 Screaming ArchitectureThe Theme of an ArchitectureThe Purpose of an ArchitectureBut What About the Web?Frameworks Are Tools, Not Ways of LifeTestable ArchitecturesConclusionChapter 22 The Clean ArchitectureThe Dependency RuleA Typical ScenarioConclusionChapter 23 Presenters and Humble ObjectsThe Humble Object PatternPresenters and Views

Testing and ArchitectureDatabase GatewaysData MappersService ListenersConclusionChapter 24 Partial BoundariesSkip the Last StepOne-Dimensional BoundariesFacadesConclusionChapter 25 Layers and BoundariesHunt the WumpusClean Architecture?Crossing the StreamsSplitting the StreamsConclusionChapter 26 The Main ComponentThe Ultimate DetailConclusionChapter 27 Services: Great and SmallService Architecture?Service Benefits?The Kitty ProblemObjects to the RescueComponent-Based ServicesCross-Cutting ConcernsConclusionChapter 28 The Test BoundaryTests as System ComponentsDesign for TestabilityThe Testing APIConclusion

Chapter 29 Clean Embedded ArchitectureApp-titude TestThe Target-Hardware BottleneckConclusionPART VIDetailsChapter 30 The Database Is a DetailRelational DatabasesWhy Are Database Systems So Prevalent?What If There Were No Disk?DetailsBut What about Performance?AnecdoteConclusionChapter 31 The Web Is a DetailThe Endless PendulumThe UpshotConclusionChapter 32 Frameworks Are DetailsFramework AuthorsAsymmetric MarriageThe RisksThe SolutionI Now Pronounce You ConclusionChapter 33 Case Study: Video SalesThe ProductUse Case AnalysisComponent ArchitectureDependency ManagementConclusionChapter 34 The Missing Chapter

Package by LayerPackage by FeaturePorts and AdaptersPackage by ComponentThe Devil Is in the Implementation DetailsOrganization versus EncapsulationOther Decoupling ModesConclusion: The Missing AdvicePART VIIAppendixAppendix A Architecture ArchaeologyIndex

FOREWORDWhat do we talk about when we talk about architecture?As with any metaphor, describing software through the lens of architecture canhide as much as it can reveal. It can both promise more than it can deliver anddeliver more than it promises.The obvious appeal of architecture is structure, and structure is something thatdominates the paradigms and discussions of software development—components, classes, functions, modules, layers, and services, micro or macro.But the gross structure of so many software systems often defies either belief orunderstanding—Enterprise Soviet schemes destined for legacy, improbableJenga towers reaching toward the cloud, archaeological layers buried in a bigball-of-mud slide. It’s not obvious that software structure obeys our intuition theway building structure does.Buildings have an obvious physical structure, whether rooted in stone orconcrete, whether arching high or sprawling wide, whether large or small,whether magnificent or mundane. Their structures have little choice but torespect the physics of gravity and their materials. On the other hand—except inits sense of seriousness—software has little time for gravity. And what issoftware made of? Unlike buildings, which may be made of bricks, concrete,wood, steel, and glass, software is made of software. Large software constructsare made from smaller software components, which are in turn made of smallersoftware components still, and so on. It’s coding turtles all the way down.When we talk about software architecture, software is recursive and fractal innature, etched and sketched in code. Everything is details. Interlocking levels of

detail also contribute to a building’s architecture, but it doesn’t make sense totalk about physical scale in software. Software has structure—many structuresand many kinds of structures—but its variety eclipses the range of physicalstructure found in buildings. You can even argue quite convincingly that there ismore design activity and focus in software than in building architecture—in thissense, it’s not unreasonable to consider software architecture more architecturalthan building architecture!But physical scale is something humans understand and look for in the world.Although appealing and visually obvious, the boxes on a PowerPoint diagramare not a software system’s architecture. There’s no doubt they represent aparticular view of an architecture, but to mistake boxes for the big picture—forthe architecture—is to miss the big picture and the architecture: Softwarearchitecture doesn’t look like anything. A particular visualization is a choice, nota given. It is a choice founded on a further set of choices: what to include; whatto exclude; what to emphasize by shape or color; what to de-emphasize throughuniformity or omission. There is nothing natural or intrinsic about one view overanother.Although it might not make sense to talk about physics and physical scale insoftware architecture, we do appreciate and care about certain physicalconstraints. Processor speed and network bandwidth can deliver a harsh verdicton a system’s performance. Memory and storage can limit the ambitions of anycode base. Software may be such stuff as dreams are made on, but it runs in thephysical world.This is the monstrosity in love, lady, that the will is infinite, and the execution confined; that thedesire is boundless, and the act a slave to limit.—William ShakespeareThe physical world is where we and our companies and our economies live. Thisgives us another calibration we can understand software architecture by, otherless physical forces and quantities through which we can talk and reason.Architecture represents the significant design decisions that shape a system, where significant ismeasured by cost of change.—Grady BoochTime, money, and effort give us a sense of scale to sort between the large and thesmall, to distinguish the architectural stuff from the rest. This measure also tellsus how we can determine whether an architecture is good or not: Not only does agood architecture meet the needs of its users, developers, and owners at a given

point in time, but it also meets them over time.If you think good architecture is expensive, try bad architecture.—Brian Foote and Joseph YoderThe kinds of changes a system’s development typically experiences should notbe the changes that are costly, that are hard to make, that take managed projectsof their own rather than being folded into the daily and weekly flow of work.That point leads us to a not-so-small physics-related problem: time travel. Howdo we know what those typical changes will be so that we can shape thosesignificant decisions around them? How do we reduce future development effortand cost without crystal balls and time machines?Architecture is the decisions that you wish you could get right early in a project, but that you arenot necessarily more likely to get them right than any other.—Ralph JohnsonUnderstanding the past is hard enough as it is; our grasp of the present isslippery at best; predicting the future is nontrivial.This is where the road forks many ways.Down the darkest path comes the idea that strong and stable architecture comesfrom authority and rigidity. If change is expensive, change is eliminated—itscauses subdued or headed off into a bureaucratic ditch. The architect’s mandateis total and totalitarian, with the architecture becoming a dystopia for itsdevelopers and a constant source of frustration for all.Down another path comes a strong smell of speculative generality. A route filledwith hard-coded guesswork, countless parameters, tombs of dead code, and moreaccidental complexity than you can shake a maintenance budget at.The path we are most interested is the cleanest one. It recognizes the softness ofsoftware and aims to preserve it as a first-class property of the system. Itrecognizes that we operate with incomplete knowledge, but it also understandsthat, as humans, operating with incomplete knowledge is something we do,something we’re good at. It plays more to our strengths than to our weaknesses.We create things and we discover things. We ask questions and we runexperiments. A good architecture comes from understanding it more as a journeythan as a destination, more as an ongoing process of enquiry than as a frozenartifact.

Architecture is a hypothesis, that needs to be proven by implementation and measurement.—Tom GilbTo walk this path requires care and attention, thought and observation, practiceand principle. This might at first sound slow, but it’s all in the way that you walk.The only way to go fast, is to go well.—Robert C. MartinEnjoy the journey.—Kevlin HenneyMay 2017

PREFACEThe title of this book is Clean Architecture. That’s an audacious name. Somewould even call it arrogant. So why did I choose that title, and why did I writethis book?I wrote my very first line of code in 1964, at the age of 12. The year is now2016, so I have been writing code for more than half a century. In that time, Ihave learned a few things about how to structure software systems—things that Ibelieve others would likely find valuable.I learned these things by building many systems, both large and small. I havebuilt small embedded systems and large batch processing systems. I have builtreal-time systems and web systems. I have built console apps, GUI apps, processcontrol apps, games, accounting systems, telecommunications systems, designtools, drawing apps, and many, many others.I have built single-threaded apps, multithreaded apps, apps with few heavyweight processes, apps with many light-weight processes, multiprocessor apps,database apps, mathematical apps, computational geometry apps, and many,many others.I’ve built a lot of apps. I’ve built a lot of systems. And from them all, and bytaking them all into consideration, I’ve learned something startling.The architecture rules are the same!This is startling because the systems that I have built have all been so radicallydifferent. Why should such different systems all share similar rules ofarchitecture? My conclusion is that the rules of software architecture are

independent of every other variable.This is even more startling when you consider the change that has taken place inhardware over the same half-century. I started programming on machines thesize of kitchen refrigerators that had half-megahertz cycle times, 4K of corememory, 32K of disk memory, and a 10 character per second teletype interface. Iam writing this preface on a bus while touring in South Africa. I am using aMacBook with four i7 cores running at 2.8 gigahertz each. It has 16 gigabytes ofRAM, a terabyte of SSD, and a 2880 1800 retina display capable of showingextremely high-definition video. The difference in computational power isstaggering. Any reasonable analysis will show that this MacBook is at least 1022more powerful than those early computers that I started using half a century ago.Twenty-two orders of magnitude is a very large number. It is the number ofangstroms from Earth to Alpha-Centuri. It is the number of electrons in thechange in your pocket or purse. And yet that number—that number at least—isthe computational power increase that I have experienced in my own lifetime.And with all that vast change in computational power, what has been the effecton the software I write? It’s gotten bigger certainly. I used to think 2000 lineswas a big program. After all, it was a full box of cards that weighed 10 pounds.Now, however, a program isn’t really big until it exceeds 100,000 lines.The software has also gotten much more performant. We can do things todaythat we could scarcely dream about in the 1960s. The Forbin Project, The MoonIs a Harsh Mistress, and 2001: A Space Odyssey all tried to imagine our currentfuture, but missed the mark rather significantly. They all imagined hugemachines that gained sentience. What we have instead are impossibly smallmachines that are still just machines.{xx}And there is one thing more about the software we have now, compared to thesoftware from back then: It’s made of the same stuff. It’s made of if statements,assignment statements, and while loops.Oh, you might object and say that we’ve got much better languages and superiorparadigms. After all, we program in Java, or C#, or Ruby, and we use objectoriented design. True—and yet the code is still just an assemblage of sequence,selection, and iteration, just as it was back in the 1960s and 1950s.

When you really look closely at the practice of programming computers, yourealize that very little has changed in 50 years. The languages have gotten a littlebetter. The tools have gotten fantastically better. But the basic building blocks ofa computer program have not changed.If I took a computer programmer from 1966 forward in time to 2016 and puther1 in front of my MacBook running IntelliJ and showed her Java, she mightneed 24 hours to recover from the shock. But then she would be able to write thecode. Java just isn’t that different from C, or even from Fortran.And if I transported you back to 1966 and showed you how to write and editPDP-8 code by punching paper tape on a 10 character per second teletype, youmight need 24 hours to recover from the disappointment. But then you would beable to write the code. The code just hasn’t changed that much.That’s the secret: This changelessness of the code is the reason that the rules ofsoftware architecture are so consistent across system types. The rules of softwarearchitecture are the rules of ordering and assembling the building blocks ofprograms. And since those building blocks are universal and haven’t changed,the rules for ordering them are likewise universal and changeless.Younger programmers might think this is nonsense. They might insist thateverything is new and different nowadays, that the rules of the past are past andgone. If that is what they think, they are sadly mistaken. The rules have notchanged. Despite all the new languages, and all the new frameworks, and all theparadigms, the rules are the same now as they were when Alan Turing wrote thefirst machine code in 1946.But one thing has changed: Back then, we didn’t know what the rules were.Consequently, we broke them, over and over again. Now, with half a century ofexperience behind us, we have a grasp of those rules.And it is those rules—those timeless, changeless, rules—that this book is allabout.Register your copy of Clean Architecture on the InformIT site for convenientaccess to updates and/or corrections as they become available. To start theregistration process, go to informit.com/register and log in or create an

account. Enter the product ISBN (9780134494166) and click Submit. Lookon the Registered Products tab for an Access Bonus Content link next to thisproduct, and follow that link to access the bonus materials.1. And she very likely would be female since, back then, women made up a large fraction of programmers.

ACKNOWLEDGMENTSThe people who played a part in the creation of this book—in no particularorder:{xxiii}Chris GuzikowskiChris ZahnMatt HeuserJeff OverbeyMicah MartinJustin MartinCarl HickmanJames GrenningSimon BrownKevlin HenneyJason GormanDoug BradburyColin JonesGrady BoochKent BeckMartin FowlerAlistair Cockburn

James O. CoplienTim ConradRichard LloydKen FinderKris Iyer (CK)Mike CarewJerry FitzpatrickJim NewkirkEd ThelenJoe MabelBill DegnanAnd many others too numerous to name.In my final review of this book, as I was reading the chapter on ScreamingArchitecture, Jim Weirich’s bright-eyed smile and melodic laugh echoed throughmy mind. Godspeed, Jim!

ABOUT THE AUTHORRobert C. Martin (Uncle Bob) has been a programmer since 1970. He is the cofounder of cleancoders.com, which offers online video training for softwaredevelopers, and is the founder of Uncle Bob Consulting LLC, which offerssoftware consulting, training, and skill development services to majorcorporations worldwide. He served as the Master Craftsman at 8th Light, Inc., aChicago-based software consulting firm. He has published dozens of articles invarious trade journals and is a regular speaker at international conferences andtrade shows. He served three years as the editor-in-chief of the C Report andserved as the first chairman of the Agile Alliance.Martin has authored and edited many books, including The Clean Coder, CleanCode, UML for Java Programmers, Agile Software Development, ExtremeProgramming in Practice, More C Gems, Pattern Languages of ProgramDesign 3, and Designing Object Oriented C Applications Using the Booch

Method.

IINTRODUCTIONIt doesn’t take a huge amount of knowledge and skill to get a program working.Kids in high school do it all the time. Young men and women in college startbillion-dollar businesses based on scrabbling together a few lines of PHP orRuby. Hoards of junior programmers in cube farms around the world slogthrough massive requirements documents held in huge issue tracking systems toget their systems to “work” by the sheer brute force of will. The code theyproduce may not be pretty; but it works. It works because getting something towork—once—just isn’t that hard.Getting it right is another matter entirely. Getting software right is hard. It takesknowledge and skills that most young programmers haven’t yet acquired. Itrequires thought and insight that most programmers don’t take the time todevelop. It requires a level of discipline and dedication that most programmersnever dreamed they’d need. Mostly, it takes a passion for the craft and the desireto be a professional.And when you get software right, something magical happens: You don’t needhordes of programmers to keep it working. You don’t need massive requirementsdocuments and huge issue tracking systems. You don’t need global cube farmsand 24/7 programming.When software is done right, it requires a fraction of the human resources tocreate and maintain. Changes are simple and rapid. Defects are few and farbetween. Effort is minimized, and functionality and flexibility are maximized.

Yes, this vision sounds a bit utopian. But I’ve been there; I’ve seen it happen.I’ve worked in projects where the design and architecture of the system made iteasy to write and easy to maintain. I’ve experienced projects that required afraction of the anticipated human resources. I’ve worked on systems that hadextremely low defect rates. I’ve seen the extraordinary effect that good softwarearchitecture can have on a system, a project, and a team. I’ve been to thepromised land.But don’t take my word for it. Look at your own experience. Have youexperienced the opposite? Have you worked on systems that are sointerconnected and intricately coupled that every change, regardless of howtrivial, takes weeks and involves huge risks? Have you experienced theimpedance of bad code and rotten design? Has the design of the systems you’veworked on had a huge negative effect on the morale of the team, the trust of thecustomers, and the patience of the managers? Have you seen teams, departments,and even companies that have been brought down by the rotten structure of theirsoftware? Have you been to programming hell?I have—and to some extent, most of the rest of us have, too. It is far morecommon to fight your way through terrible software designs than it is to enjoythe pleasure of working with a good one.

1WHAT IS DESIGN ANDARCHITECTURE?There has been a lot of confusion about design and architecture over the years.What is design? What is architecture? What are the differences between the two?One of the goals of this book is to cut through all that confusion and to define,once and for all, what design and architecture are. For starters, I’ll assert thatthere is no difference between them. None at all.The word “architecture” is often used in the context of something at a high levelthat is divorced from the lower-level details, whereas “design” more often seemsto imply structures and decisions at a lower level. But this usage is nonsensical

when you look at what a real architect does.Consider the architect who designed my new home. Does this home have anarchitecture? Of course it does. And what is that architecture? Well, it is theshape of the home, the outward appearance, the elevations, and the layout of thespaces and rooms. But as I look through the diagrams that my architectproduced, I see an immense number of low-level details. I see where everyoutlet, light switch, and light will be placed. I see which switches control whichlights. I see where the furnace is placed, and the size and placement of the waterheater and the sump pump. I see detailed depictions of how the walls, roofs, andfoundations will be constructed.In short, I see all the little details that support all the high-level decisions. I alsosee that those low-level details and high-level decisions are part of the wholedesign of the house.And so it is with software design. The low-level details and the high-levelstructure are all part of the same whole. They form a continuous fabric thatdefines the shape of the system. You can’t have one without the other; indeed, noclear dividing line separates them. There is simply a continuum of decisionsfrom the highest to the lowest levels.THE GOAL?And the goal of those decisions? The goal of good software design? That goal isnothing less than my utopian description:The goal of software architecture is to minimize the human resources required to build andmaintain the required system.The measure of design quality is simply the measure of the effort required tomeet the needs of the customer. If that effort is low, and stays low throughout thelifetime of the system, the design is good. If that effort grows with each newrelease, the design is bad. It’s as simple as that.CASE STUDYAs an example, consider the following case study. It includes real data from a

real company that wishes to remain anonymous.First, let’s look at the growth of the engineering staff. I’m sure you’ll agree thatthis trend is very encouraging. Growth like that shown in Figure 1.1 must be anindication of significant success!Figure 1.1 Growth of the engineering staffReproduced with permission from a slide presentation by Jason GormanNow let’s look at the company’s productivity over the same time period, asmeasured by simple lines of code (Figure 1.2).

Figure 1.2 Productivity over the same period of timeClearly something is going wrong here. Even though every release is supportedby an ever-increasing number of developers, the growth of the code looks like itis approaching an asymptote.Now here’s the really scary graph: Figure 1.3 shows how the cost per line ofcode has changed over time.These trends aren’t sustainable. It doesn’t matter how profitable the companymight be at the moment: Those curves will catastrophically drain the profit fromthe business model and drive the company into a stall, if not into a downrightcollapse.What caused this remarkable change in productivity? Why was the code 40times more expensive to produce in release 8 as opposed to release 1?

Figure 1.3 Cost per line of code over timeTHE SIGNATURE OF A MESSWhat you are looking at is the signature of a mess. When systems are throwntogether in a hurry, when the sheer number of programmers is the sole driver ofoutput, and when little or no thought is given to the cleanliness of the code or thestructure of the design, then you can bank on riding this curve to its ugly end.Figure 1.4 shows what this curve looks like to the developers. They started out atnearly 100% productivity, but with each release their productivity declined. Bythe fourth release, it was clear that their productivity was going to bottom out inan asymptotic approach to zero.

Figure 1.4 Productivity by releaseFrom the developers’ point of view, this is tremendously frustrating, becauseeveryone is working ha

code and configurations in the reflowable text format, we have included images of the code that mimic the presentation found in the print book; therefore, where the reflowable format may compromise the presentation of the code listing, you will see a “Click here to view code image” link. Click the lin