ebook img

Get Your Hands Dirty on Clean Architecture PDF

108 Pages·2019·4.384 MB·English
Save to my drive
Quick download
Download
Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.

Preview Get Your Hands Dirty on Clean Architecture

Get Your Hands Dirty on Clean Architecture A Hands-on Guide to Creating Clean Web Applications with Code Examples in Java Tom Hombergs Thisbookisforsaleathttp://leanpub.com/get-your-hands-dirty-on-clean-architecture Thisversionwaspublishedon2019-09-30 ThisisaLeanpubbook.LeanpubempowersauthorsandpublisherswiththeLeanPublishing process.LeanPublishingistheactofpublishinganin-progressebookusinglightweighttoolsand manyiterationstogetreaderfeedback,pivotuntilyouhavetherightbookandbuildtractiononce youdo. ©2018-2019TomHombergs Tweet This Book! PleasehelpTomHombergsbyspreadingthewordaboutthisbookonTwitter! Thesuggestedtweetforthisbookis: InterestedinaHands-ondiscussiononbuildingaClean/HexagonalArchitecture?Havealookat thebook”GetYourHandsDirtyonCleanArchitecture”by@TomHombergs. Thesuggestedhashtagforthisbookis#get-your-hands-dirty. Findoutwhatotherpeoplearesayingaboutthebookbyclickingonthislinktosearchforthis hashtagonTwitter: #get-your-hands-dirty Contents Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 WhatIstheGoalofThisBook? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 WhoShouldReadThisBook? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 TheExampleApplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 ANoteonCodeExamples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Feedback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.What’sWrongWithLayers? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 ItPromotesDatabase-DrivenDesign . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 It’sPronetoShortcuts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 ItGrowsHardtoTest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 ItHidestheUseCases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 ItMakesParallelWorkDifficult . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 HowDoesThisHelpMeBuildMaintainableSoftware? . . . . . . . . . . . . . . . . . . . . . 10 2.InvertingDependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 TheSingleResponsibilityPrinciple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 ATaleaboutSideEffects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 TheDependencyInversionPrinciple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 CleanArchitecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 HexagonalArchitecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 HowDoesThisHelpMeBuildMaintainableSoftware? . . . . . . . . . . . . . . . . . . . . . 18 3.OrganizingCode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 OrganizingByLayer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 OrganizingByFeature. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 AnArchitecturallyExpressivePackageStructure . . . . . . . . . . . . . . . . . . . . . . . . . 21 TheRoleofDependencyInjection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 HowDoesThisHelpMeBuildMaintainableSoftware? . . . . . . . . . . . . . . . . . . . . . 25 4.ImplementingaUseCase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 ImplementingtheDomainModel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 AUseCaseinaNutshell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 ValidatingInput. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 ThePowerofConstructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 CONTENTS DifferentInputModelsforDifferentUseCases . . . . . . . . . . . . . . . . . . . . . . . . . . 33 ValidatingBusinessRules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Richvs.AnemicDomainModel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 DifferentOutputModelsforDifferentUseCases . . . . . . . . . . . . . . . . . . . . . . . . . 36 WhatAboutRead-OnlyUseCases?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 HowDoesThisHelpMeBuildMaintainableSoftware? . . . . . . . . . . . . . . . . . . . . . 38 5.ImplementingaWebAdapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 DependencyInversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 ResponsibilitiesofaWebAdapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 SlicingControllers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 HowDoesThisHelpMeBuildMaintainableSoftware? . . . . . . . . . . . . . . . . . . . . . 45 6.ImplementingaPersistenceAdapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 DependencyInversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 ResponsibilitiesofaPersistenceAdapter. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 SlicingPortInterfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 SlicingPersistenceAdapters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 ExamplewithSpringDataJPA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 WhataboutDatabaseTransactions? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 HowDoesThisHelpMeBuildMaintainableSoftware? . . . . . . . . . . . . . . . . . . . . . 57 7.TestingArchitectureElements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 TheTestPyramid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 TestingaDomainEntitywithUnitTests. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 TestingaUseCasewithUnitTests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 TestingaWebAdapterwithIntegrationTests . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 TestingaPersistence AdapterwithIntegrationTests . . . . . . . . . . . . . . . . . . . . . . . 63 TestingMainPathswithSystemTests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 HowMuchTestingisEnough?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 HowDoesThisHelpMeBuildMaintainableSoftware? . . . . . . . . . . . . . . . . . . . . . 68 8.MappingBetweenBoundaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 The“NoMapping”Strategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 The“Two-Way”MappingStrategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 The“Full”MappingStrategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 The“One-Way”MappingStrategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 WhentousewhichMappingStrategy? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 HowDoesThisHelpMeBuildMaintainableSoftware? . . . . . . . . . . . . . . . . . . . . . 76 9.AssemblingtheApplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 WhyEvenCareAboutAssembly? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 AssemblingviaPlainCode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 AssemblingviaSpring’sClasspathScanning . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 CONTENTS AssemblingviaSpring’sJavaConfig . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 HowDoesThisHelpMeBuildMaintainableSoftware? . . . . . . . . . . . . . . . . . . . . . 84 10.EnforcingArchitectureBoundaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 BoundariesandDependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 VisibilityModifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 Post-CompileChecks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 BuildArtifacts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 HowDoesThisHelpMeBuildMaintainableSoftware? . . . . . . . . . . . . . . . . . . . . . 92 11.TakingShortcutsConsciously. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 WhyShortcutsAreLikeBrokenWindows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 TheResponsibilityofStartingClean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 SharingModelsbetweenUseCases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 UsingDomainEntitiesasInputorOutputModel . . . . . . . . . . . . . . . . . . . . . . . . . 96 SkippingIncomingPorts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 SkippingApplicationServices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 HowDoesThisHelpMeBuildMaintainableSoftware? . . . . . . . . . . . . . . . . . . . . . 98 12.DecidingonanArchitectureStyle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 TheDomainisKing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 ExperienceisQueen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 ItDepends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 Changelog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Preface If you have picked up this book, you care about the architecture of the software you’re building. Youwantyoursoftwarenotonlytofulfillthecustomer’sexplicitrequirements,butalsothehidden requirementofmaintainabilityandyourownrequirementsconcerningstructureandaesthetics. It’s hard to fulfill these requirements because software projects (or projects in general, for that matter) usually don’t go as planned. Managers are drawing deadlines all around the project team¹, external partners build their APIs differently from what they had promised, and software products we’redependingonarenotworkingasexpected. And then there is our own software architecture. It was so nice in the beginning. Everything was clear and beautiful. But then the deadlines pressed us into taking shortcuts. Now, the shortcuts are allthat’sleftofthearchitectureandittakeslongerandlongertodelivernewfeatures. Ourshortcut-drivenarchitecturemakesithardtoreacttoanAPIthathadtobechangedbecausean external partner screwed up. It seems easier to just send our project manager into battle with that partnertotellthemtodelivertheAPIwehadagreedupon. Now we have given up all control over the situation. In all likelihood, one of the following things willhappen: • theprojectmanagerisnotstrongenoughtowinthebattleagainsttheexternalpartner, • theexternalpartnerfindsaloopholeintheAPIspecs,provingthemright,or • theexternalpartnerneedsanother<enternumberhere>monthstofixtheAPI. Allofwhichleadtothesameendresult:wehavetofixitonoursidebecausethedeadlineislooming. Weaddanothershortcut. Instead of letting external factors govern the state of our software architecture, this book takes the stance of taking control ourselves. We gain this control by creating an architecture that makes the softwaresoft,asin“flexible”,“extensible”and“adaptable”.Suchanarchitecturewillmakeiteasyto reacttoexternalfactorsandtakealotofpressurefromourbacks. What Is the Goal of This Book? I wrote this book because I was disappointed with the practicality of the resources available on domain-centric architecture styles like Robert C. Martin’s “Clean Architecture” and Alistair ¹Theword“deadline”probablyoriginatesfromthe19thcenturyanddescribedalinedrawnaroundaprisonoracampofprisoners.A prisonerthatcrossedthatlinewasshot.Thinkaboutthisdefinitionthenexttimesomeone“drawsadeadline”aroundyou…itwillcertainly openupnewperspectives. Preface 2 Cockburn’s “Hexagonal Architecture”. Many books or online resources explain valuable concepts butnothowwecanactuallyimplementthem. That’sprobablybecausethereismorethanonewayofimplementingsuchanarchitecture. Withthisbook,Iamtryingtofillthisvoidbyprovidingahands-on-codediscussionaboutcreating a web application in the Hexagonal Architecture style. In order to live up to that goal, the code examples and concepts discussed in this book provide one interpretation of how to implement a HexagonalArchitecture.Therearecertainlyotherinterpretationsoutthere,andIdonotclaimmine tobethesilverbulletforallsituations. I certainly hope, however, that you will find some of the concepts in this book helpful enough to includethemintoyourowntoolbox. Who Should Read This Book? This book is aimed at software developers of all experience levels involved in creating web applications. Asajuniordeveloperyou’lllearnabouthowtodesignsoftwaremodulesandcompleteapplications inacleanandmaintainablemanner.Youwillalsolearnsomeargumentsforwhentoapplyacertain technique.Youshould,however,haveparticipatedinbuildingawebapplicationinthepastinorder togetthemostoutofthisbook. If you’re an experienced developer, you’ll enjoy comparing the concepts from the book with your own way of doing things and incorporating bits and pieces into your own software development style. ThecodeexamplesinthisbookareinJavabutalldiscussionsareequallyapplicabletootherobject- oriented programming languages. If you’re not a Java programmer but can read object-oriented code in other languages, you’ll be fine nevertheless. In the few places where we need some Java or frameworkspecifics,theywillbeexplained. The Example Application To have a recurrent theme throughout the book, most of the code examples show code from an examplewebapplicationfortransferringmoneyonline.We’llcallit“BuckPal”². TheBuckPalapplicationallowsausertoregisteranaccount,transfermoneybetweenaccounts,and viewtheactivities(depositsandwithdrawals)ontheaccount. I’mnotabankingspecialistbyanymeans,sopleasedon’tjudgetheexamplecodebasedonlegalor functionalcorrectness.Ratherjudgeitonstructureandmaintainability. ²AquickonlinesearchhasrevealedthatacompanycalledPayPalhasstolenmyideaandevencopiedpartofthename.Shameonthem! Jokingaside:trytofindanamesimilarto“Paypal”thatisnotthenameofanexistingcompany.It’shilarious! Preface 3 The curse of example applications used in software engineering books and online resources is that they’re too simple to highlight the real world problems we’re struggling with every day. On the other hand, an example application must not be too complex, in order to be able to transport the discussedconcepts. I hope to have found a balance between “too simple” and “too complex” as we’re discussing use casesoftheBuckPalapplicationfortherestofthisbook. Thecodeoftheexampleapplicationcanbefoundongithub³. A Note on Code Examples The code examples in this book are in Java. Even as a Java fanboy, I’ll admit that Java is a very verbose programming language. Since I don’t want you to be distracted by boilerplate code within the code examples, I decided to just leave it away. In order for the code to still be valid, I included Lombok⁴annotationsinthecodethatwillauto-generatesomeboilerplatecode: • the@Getterannotationwillauto-generategettermethodsfortheannotatedfieldor,ifusedon aclass,onallprivatefieldsofthatclass, • the @RequiredArgsConstructor annotation will auto-generate a constructor with parameters toinitializeallprivate finalfieldsofaclass,and • the@NoArgsConstructorannotationwillauto-generateano-argument(default)constructor. Feedback If you have anything to say about this book, I’d love to hear it! Get in touch with me via mail to [email protected]⁵oronTwittervia@TomHombergs⁶. You can also use the Leanpub forum of this book to post errata and ask questions about this book. TheforumisavailableatthisURL:https://community.leanpub.com/c/get-your-hands⁷. Sincethisbookisself-published,IhavethefreedomtocreateasmanyreleasesasIwish,soIinvite youtotakepartbygivingfeedback. ³https://github.com/thombergs/buckpal ⁴https://projectlombok.org/ ⁵mailto:[email protected] ⁶https://twitter.com/TomHombergs ⁷https://community.leanpub.com/c/get-your-hands 1. What’s Wrong With Layers? Chances are that you have developed a layered (web) application in the past. You might even be doingitinyourcurrentprojectrightnow(actually,Iam). Thinking in layers has been drilled into us in computer science classes, tutorials and best practices. Ithasevenbeentaughtinbooks⁸. Figure1-Aconventionalwebapplicationarchitectureconsistsofaweblayer,adomainlayer,andapersistencelayer. Figure1showsahigh-levelviewoftheverycommonthree-layerarchitecture.Wehaveaweblayer that receives requests and routes them to a service in the domain or “business” layer. The service does some business magic and calls components from the persistence layer to query for or modify thecurrentstateofourdomainentities. You know what? Layers are a solid architecture pattern! If we get them right, we’re able to build domain logic that is independent of the web and persistence layers. We can switch the web or persistence technologies without affecting our domain logic if we feel like it. We can add new featureswithoutaffectingexistingfeatures. With a good layered architecture we’re keeping our options open and are able to quickly adapt to changing requirements and external factors. And if we believe Uncle Bob, this is exactly what architectureisallabout⁹. So,what’swrongwithlayers? Inmyexperiencealayeredarchitecturehastoomanyopenflanksthatallowbadhabitstocreepin and make the software increasingly harder to change over time. In the following sections, I’ll tell youwhy. ⁸SoftwareArchitecturePatternsbyMarkRichards,O’Reilly,2015 ⁹CleanArchitecturebyRobertC.Martin,PrenticeHall,2017,Chapter15

See more

The list of books you might like

Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.