Share E-Book

Designing Hexagonal Architecture with Java An architects guide to building maintainable and change-tolerant applications with… (Davi Vieira)(Z-Library)

Author

Rating 3.5 AI initial rating

Log in to rate

Java
Language English

A practical guide for software architects and Java developers to build cloud-native hexagonal applications using Java and Quarkus to create systems that are easier to refactor, scale, and maintain Key Features: Learn techniques to decouple business and technology code in an application Apply hexagonal architecture principles to produce more organized, coherent, and maintainable software Minimize technical debts and tackle complexities derived from multiple teams dealing with the same code base Book Description: Hexagonal architecture enhances developers' productivity by decoupling business code from technology code, making the software more change-tolerant, and allowing it to evolve and incorporate new technologies without the need for significant refactoring. By adhering to hexagonal principles, you can structure your software in a way that reduces the effort required to understand and maintain the code. This book starts with an in-depth analysis of hexagonal architecture's building blocks, such as entities, use cases, ports, and adapters. You'll learn how to assemble business code in the Domain hexagon, create features by using ports and use cases in the Application hexagon, and make your software compatible with different technologies by employing adapters in the Framework hexagon. Moving on, you'll get your hands dirty developing a system based on a real-world scenario applying all the hexagonal architecture's building blocks. By creating a hexagonal system, you'll also understand how you can use Java modules to reinforce dependency inversion and ensure the isolation of each hexagon in the architecture. Finally, you'll get to grips with using Quarkus to turn your hexagonal application into a cloud-native system. By the end of this hexagonal architecture book, you'll be able to bring order and sanity to the development of complex and long-lasting applications.

Format PDF
Size 6.8 MB
9
Views
(First 20 pages)

Registered users can read the full content for free

Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.

Page 1
Designing Hexagonal Architecture with Java An architect's guide to building maintainable and change-tolerant applications with Java and Quarkus Davi Vieira D esigning H exagonal A rchitecture w ith Java D avi Vieira Hexagonal architecture enhances developers' productivity by decoupling business code from technology code, making the software more change-tolerant, and allowing it to evolve and incorporate new technologies without the need for signifi cant refactoring. By adhering to hexagonal principles, you can structure your software in a way that reduces the eff ort required to understand and maintain the code. This book starts with an in-depth analysis of hexagonal architecture's building blocks, such as entities, use cases, ports, and adapters. You'll learn how to assemble business code in the Domain hexagon, create features by using ports and use cases in the Application hexagon, and make your software compatible with diff erent technologies by employing adapters in the Framework hexagon. Moving on, you'll get your hands dirty developing a system based on a real-world scenario applying all the hexagonal architecture's building blocks. By creating a hexagonal system, you'll also understand how you can use Java modules to reinforce dependency inversion and ensure the isolation of each hexagon in the architecture. Finally, you'll get to grips with using Quarkus to turn your hexagonal application into a cloud-native system. By the end of this hexagonal architecture book, you'll be able to bring order and sanity to the development of complex and long-lasting applications. Designing Hexagonal Architecture with Java Things you will learn: • Find out how to assemble business rules algorithms using the specifi cation design pattern • Combine domain-driven design techniques with hexagonal principles to create powerful domain models • Employ adapters to make the system support diff erent protocols such as REST, gRPC, and WebSocket • Create a module and package structure based on hexagonal principles • Use Java modules to enforce dependency inversion and ensure isolation between software components • Implement Quarkus DI to manage the life cycle of input and output ports
Page 2
Designing Hexagonal Architecture with Java An architect's guide to building maintainable and change-tolerant applications with Java and Quarkus Davi Vieira BIRMINGHAM—MUMBAI
Page 3
Designing Hexagonal Architecture with Java Copyright © 2021 Packt Publishing All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews. Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book. Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information. Group Product Manager: Aaron Lazar Publishing Product Manager: Alok Dhuri Senior Editor: Rohit Singh Content Development Editor: Rosal Colaco Technical Editor: Pradeep Sahu Copy Editor: Safis Editing Project Coordinator: Deeksha Thakkar Proofreader: Safis Editing Indexer: Manju Arasan Production Designer: Aparna Bhagat First published: December 2021 Production reference: 1291121 Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK. ISBN 978-1-80181-648-9 www.packt.com
Page 4
To the memory of my mother, Rosimar Pinheiro, who instilled in me the desire to learn. To my father, Davi, for teaching me the value of persistence. To my brother, Bruno Pinheiro, for his influence on my character and career. To my wife, Eloise, for being my loving partner throughout our joint life journey. – Davi Vieira
Page 5
Contributors About the author Davi Vieira is a software craftsman with a vested interest in the challenges faced by large enterprises in software design, development, and architecture. He has more than 10 years of experience constructing and maintaining complex, long-lasting, and mission-critical systems using object-oriented languages. He values the good lessons and the software development tradition left by others who came before him. Inspired by this software tradition, he develops and evolves his ideas. I want to thank Fagner Silva for introducing me to hexagonal architecture. I'm also grateful to Paulo Lagranha, who gave me precious life lessons and believed in my ideas. A special thanks to Alok Dhuri, Rohit Singh, Rosal Colaco, Deeksha Thakkar, and all the Packt team. I cannot express in words how grateful I am for their patience, guidance, and support through the whole book development process. Finally, I'd like to thank the technical reviewer, Antonino Rau, who profoundly and positively influenced my ideas in the book.
Page 6
About the reviewer Antonino Rau has a background in the philosophy of language and computer science, with over 20 years of experience as a technical leader specialized in architecting distributed systems, mainly using Domain Driven Design strategic and tactical patterns to tackle complex projects. He has worked for several Italian and American companies (including Expert.ai, Condé Nast, and recently Compass), mainly operating in the area of content management, workflow, and recommendation systems, developing expertise in applied machine learning, distributed systems, and multiple architectural styles. Antonino moved from Rome, Italy, to New York 10 years ago, where he now lives with his beautiful wife, three children, and two cute cats.
Page 7
(This page has no text content)
Page 8
Table of Contents Preface Section 1: Architecture Fundamentals 1 Why Hexagonal Architecture? Technical requirements 4 Reviewing software architecture 4 The invisible things 5 Vicious cycle 6 It's not for everyone 7 Monolithic or distributed 8 Making decisions 10 Understanding the hexagonal architecture 11 Domain hexagon 13 Application hexagon 17 Framework hexagon 19 Advantages of the hexagonal approach 23 Summary 25 Questions 25 Further reading 26 2 Wrapping Business Rules inside Domain Hexagon Technical requirements 28 Modeling a problem domain with entities 28 The purity of domain entities 29 Relevant entities 29 Using UUIDs to define identity 32 Enhancing descriptiveness with value objects 34 Assuring consistency with aggregates 36 Working with domain services 43 Using policy and specification to deal with business rules 46
Page 9
viii Table of Contents Defining business rules as POJOs 56 Summary 57 Questions 58 Further reading 58 3 Handling Behavior with Ports and Use Cases Technical requirements 60 Expressing software behavior with use cases 60 How to create a use case 61 Implementing use cases with input ports 66 Using output ports to deal with external data 70 It's not only about repositories 70 Where to use output ports 73 Automating behavior with the Application hexagon 74 Summary 75 Questions 75 Further reading 76 4 Creating Adapters to Interact with the Outside World Technical requirements 78 Understanding adapters 78 Using input adapters to allow driving operations 80 Creating input adapters 81 Using output adapters to speak with different data sources 90 Creating output adapters 91 Summary 114 Questions 114 Further reading 115 5 Exploring the Nature of Driving and Driven Operations Technical requirements 118 Reaching the hexagonal application with driving operations 119 Integrating web applications with the hexagonal system 120 Running test agents 130 Calling the hexagonal system from other applications 134 Handling external resources with driven operations 136 Data persistence 137
Page 10
Table of Contents ix Messaging and events 137 Mock servers 149 Summary 150 Questions 150 Section 2: Using Hexagons to Create a Solid Foundation 6 Building the Domain Hexagon Technical requirements 154 Bootstrapping the Domain hexagon 154 Understanding the problem domain 158 Defining value objects 160 Defining entities and specifications 167 The Equipment and Router abstract entities 167 Core router entity and its specifications 169 Edge router entity and its specifications 174 Switch entity and its specifications 176 Defining domain services 179 Router service 179 Switch service 180 Network service 181 Testing the Domain hexagon 183 Summary 194 Questions 194 7 Building the Application Hexagon Technical requirements 196 Bootstrapping the Application hexagon 196 Defining use cases 199 Creating written descriptions for router management use cases 200 Defining the use case interface for router management 201 Creating written descriptions for switch management use cases 202 Defining the use case interface for switch management 203 Creating written descriptions for network management use cases 205 Defining the use case interface for network management 206 Implementing use cases with input ports 207 Testing the Application hexagon 215 Summary 223 Questions 224
Page 11
x Table of Contents 8 Building the Framework Hexagon Technical requirements 226 Bootstrapping the Framework hexagon 226 Implementing output adapters 229 Router management output adapter 229 Switch management output adapter 232 Implementing input adapters 233 Router management input adapter 234 Switch management input adapter 237 Network management input adapter 241 Testing the Framework hexagon 243 Summary 247 Questions 248 9 Applying Dependency Inversion with Java Modules Technical requirements 250 Introducing JPMS 250 Inverting dependencies on a hexagonal application 252 Providing services with use cases and input ports 253 Providing services with output ports and output adapters 257 Making the input adapters dependent on abstractions 259 Using the Java platform's ServiceLoader class to retrieve JPMS provider implementations 262 Initializing RouterManagementGenericAdapter 263 Initializing SwitchManagementGenericAdapter 265 Initializing NetworkManagementGenericAdapter 266 Summary 267 Questions 268 Further reading 268 Section 3: Becoming Cloud-Native 10 Adding Quarkus to a Modularized Hexagonal Application Technical requirements 272 Revisiting the JVM 272 Speeding up runtime performance with JIT compilation 275
Page 12
Table of Contents xi Improving startup time with AOT compilation 276 Introducing Quarkus 277 Creating REST endpoints with JAX-RS 277 Employing dependency injection with Quarkus DI 278 Validating objects 280 Configuring a data source and using Hibernate ORM 283 Adding Quarkus to a modularized hexagonal application 288 Summary 294 Questions 294 11 Leveraging CDI Beans to Manage Ports and Use Cases Technical requirements 296 Learning about Quarkus DI 296 Working with beans 297 Transforming ports, use cases, and adapters into CDI beans 301 Implementing CDI for router management objects 301 Implementing CDI for switch management objects 304 Implementing CDI for network management classes and interfaces 307 Testing use cases with Quarkus and Cucumber 310 Summary 315 Questions 316 Answers 316 12 Using RESTEasy Reactive to Implement Input Adapters Technical requirements 318 Exploring the approaches to handling server's requests 318 Imperative 319 Reactive 320 Implementing input adapters with RESTEasy Reactive 322 Implementing the Reactive input adapter for router management 323 Implementing the Reactive input adapter for switch management 327 Implementing the Reactive input adapter for network management 330 Adding OpenAPI and Swagger UI 333 Testing Reactive input adapters 337 Summary 341 Questions 341
Page 13
xii Table of Contents 13 Persisting Data with Output Adapters and Hibernate Reactive Technical requirements 344 Introducing Hibernate Reactive and Panache 344 Hibernate Reactive features 345 Panache features 347 Enabling reactive behavior on output adapters 351 Configuring reactive data sources 351 Configuring entities 353 Implementing reactive repository classes 357 Implementing reactive output adapters 359 Reactive router management of the MySQL output adapter 359 Reactive switch management of the MySQL output adapter 361 Testing the reactive output adapters 363 Summary 366 Questions 366 14 Setting Up Dockerfile and Kubernetes Objects for Cloud Deployment Technical requirements 368 Preparing the Docker image 368 Creating a Docker image with an Uber .jar artifact 369 Creating a Docker image with a native executable 371 Creating Kubernetes objects 374 Reviewing Kubernetes main objects 375 Configuring Kubernetes objects for the hexagonal system 376 Deploying on Minikube 381 Summary 384 Questions 384 15 Good Design Practices for Your Hexagonal Application Technical requirements 386 Using Domain Driven Design to shape the Domain hexagon 386 Understanding the business we are in 387 Promoting collaboration to increase knowledge 391 Applying DDD techniques to build the Domain hexagon 391 Implementing bounded contexts and subdomains in a hexagonal system 394
Page 14
Table of Contents xiii The need to create ports and use cases 401 Dealing with multiple adapter categories 402 Conclusion – the hexagonal journey 403 Summary 404 Questions 405 Assessments Other Books You May Enjoy Index
Page 15
(This page has no text content)
Page 16
Preface Since I started to work in software development, I have always felt overwhelmed by the recurring challenge of untangling and learning complex code. For me, part of that complexity derived from tight schedules, speed for speed's sake, feature quantity over code quality, and management pressure to deliver working software no matter the consequences. Under such circumstances, I always find it hard to find enough time for refactoring and other software quality concerns. And I also considered it unfair to blame people who had to write poorly structured code because they had no other choice. For those interested in economics, there is an axiom that says we're always in a state of scarcity. Nothing is unlimited in this world. Certain people may experience abundance, but the harsh reality is that all resources are scarce: water, food, electricity, money. They all are served in a limited amount. Wise, and very often richer, are those who know how to use their resources intelligently to produce good results. This scarcity condition cascades to all human activities. Software development is one of them. Every software project is given a limited number of resources to be carried out. We call successful the software project that knows how to use its resources intelligently. Working software is the most important output of a successful project. Unfortunately, this is not the only success criteria. If we deliver working software that is hard to maintain and expect to change that software in the future, then we're not using our resources intelligently. So, in my view, a successful software project delivers working and maintainable software. But how can we create working and maintainable software with scarce resources? I think this question has existed and has remained partially answered since the first line of code was written. I say partially answered because the circumstances of every software project may be so peculiar that it's hard to find an answer that encompasses all possibilities. Software architecture is one of the efforts to organize ideas supporting the creation of well-structured and maintainable software.
Page 17
xvi Preface One notable software architecture effort came from a guy called Alistair Cockburn. He was aware that a software system might contain code that exists only to solve business problems. On the other hand, he noted that there is also code that exists only to allow the software system to integrate with external systems and technologies. He then conceived an approach to organize the code and avoid the problems that arise when we mix code that solves business problems with code that integrates technologies. He gave that approach the name hexagonal architecture. It's the goal of this book to explore and extend hexagonal architecture ideas. More than that, we aim to frame hexagonal architecture in the context of a recent trend in the technology industry: cloud-native development. We live in the cloud era. It's hard to talk about any software development topic and ignore how it relates to the cloud's contemporary software practices. To help us in such an undertaking, we chose Quarkus as the cloud-native framework to guide us in this fascinating cloud-native development world. You can expect a hybrid approach where theory and practice are blended to improve the learning experience. We'll spend some time discussing concepts, but we'll also have fun by dirtying our hands while putting these concepts into practice. You may have reached a dead-end in your software project where things are so hard that new features are too complex to add and existent ones are equally difficult to maintain. Maybe you're an enthusiast searching for new ideas to improve your code base. No matter your reasons, I invite you to be my guest on this enlightening learning journey. Who this book is for This book is for software architects and Java developers who want to improve code maintainability and enhance productivity with an architecture that allows changes in technology without compromising business logic, which is precisely what hexagonal architecture does. Intermediate knowledge of the Java programming language and familiarity with Jakarta EE will help you to get the most out of this book. What this book covers Chapter 1, Why Hexagonal Architecture?, starts by saying that software that is not well organized and lacks sound architecture principles may work fine but will present a high risk of developing technical debt. As new features are added, the software tends to become more complex to maintain because there is no common ground to guide the addition or change of features. Based on this problem, this chapter explains why hexagonal architecture helps tackle technical debt by establishing an approach where business code is decoupled from technology code, allowing the former to evolve without dependency on the latter.
Page 18
Preface xvii Chapter 2, Wrapping Business Rules inside Domain Hexagon, follows a domain-driven approach and describes what Domain Entities are, what role they play within hexagonal architecture, and how they wrap business rules and data in simple Java POJOs. It explains why Domain Entities are the most important part of code and why they should not depend on anything other than other Domain Entities. Finally, it explains how business rules inside a domain entity can be implemented using the Specification design pattern. Chapter 3, Handling Behavior with Ports and Uses Cases, covers what use cases are, explaining that they are used to define software intent with interfaces describing things the software can do. Then, it explains what input ports are, classes that implement use case interfaces, and specifies in concrete ways how the software intent should be accomplished. It talks about output ports and their role in abstractly defining the behavior of operations that need to get data from outside the software. And finally, this chapter explains how use cases and ports are grouped together in what's called the Application hexagon. Chapter 4, Creating Adapters to Interact with the Outside World, shows how adapters allow the software to integrate with different technologies. It explains that the same port can have multiple adapters: input adapters, bound to input ports, enable the application to expose its functionalities through different communication protocols, such as REST, gRPC, or WebSocket. Output adapters, bound to output ports, allow the application to communicate with varying data sources, whether it be databases or even brokers or other applications. Finally, it shows how all adapters are grouped together in the Framework hexagon. Chapter 5, Exploring the Nature of Driving and Driven Operations, explains that driver operations drive the software behavior by starting one of its exposed functions. It details the Driver operations life cycle showing how a request is captured on Framework hexagon through an input adapter, then handed down to an input port on the application framework until it reaches Domain Entities on the Domain hexagon. It shows that a use case starts driven operations from the Application hexagon when the software needs to get data from outside, going from an output port to an output adapter to fulfill the use case needs. Chapter 6, Building the Domain Hexagon, shows how to start developing a telco's network and topology inventory application by first creating the Domain hexagon as a Java module. Then, this chapter shows how business rules and data are mapped to Domain Entities' classes and methods. The business rules are arranged in different algorithms with the aim of the Specification design pattern. Finally, it shows how to unit test the Domain hexagon.
Page 19
xviii Preface Chapter 7, Building the Application Hexagon, starts by adding the Application hexagon as the second Java module on the application. It then explains how to create the use case interface that describes the software's operations to manage the network and topology inventory. It shows how to implement the use case with an input port, giving a detailed description of how the code should be arranged. It details the creation of an output port interface and its role in obtaining data from external sources. Finally, it explains how to test the Application hexagon. Chapter 8, Building the Framework Hexagon, starts by adding the Framework hexagon as the third Java module on the application. Then it teaches how to create an input adapter and how it will carry its operation through an input port. After that, an output adapter will be created through the implementation of an output port. The output adapter will show how data can be fetched from external sources and converted to be dealt with in Domain terms. Finally, it explains how to test the Framework hexagon. Chapter 9, Applying Dependency Inversion with Java Modules, talks a little bit about Java modules, explaining why they are important to enforce the hexagonal architecture principles related to dependency inversion. It explains that Java modules don't allow cyclic dependencies and because of that there is no way to make two modules depend on each other at the same time. You will learn how to configure the module descriptor in this hexagonal application. Chapter 10, Adding Quarkus to a Modularized Hexagonal Application, briefly explains the Quarkus framework and its main features, then it advances to show how to add Quarkus to the hexagonal application that has been developed in the previous chapters. It introduces the creation of a fourth module, called bootstrap, that serves to get the application started and is used to group together the Domain, Application, and Framework modules. Chapter 11, Leveraging CDI Beans to Manage Ports and Use Cases, explains how to transform the already developed ports and use cases into CDI Beans, leveraging Enterprise Java's power in the hexagonal architecture. It starts by explaining what CDI Beans are, then shows how to implement them on input ports and output ports. Finally, it describes how to adjust the Application framework tests to use Quarkus CDI bean test features. Chapter 12, Using RESTEasy Reactive to Implement Input Adapters, starts by comparing reactive and imperative approaches for REST endpoints, detailing why the reactive approach performs better. It explains how to implement input adapters with Quarkus RESTEasy Reactive capabilities by explaining how to add the correct annotations and inject the proper dependencies to call input ports. In order to expose the hexagonal application APIs, this chapter explains how to add OpenAPI and SwaggerUI. Finally, it shows how to test the reactive input port with Quarkus test tools.
Page 20
Preface xix Chapter 13, Persisting Data with Output Adapters and Hibernate Reactive, talks about Hibernate Reactive and how it helps Quarkus to provide reactive capabilities for data persistence. It explains how to create a reactive output adapter to persist data on a MySQL database. Finally, it shows how to test the reactive output adapter with Quarkus test tools. Chapter 14, Setting Up Dockerfile and Kubernetes Objects for Cloud Deployment, explains how to create a Dockerfile for the hexagonal application based on Quarkus. It explains in detail how to package all the modules and dependencies in one single Docker image. It then shows how to create Kubernetes objects such as Deployment and Service for the hexagonal application and test them in a minikube local Kubernetes cluster. Chapter 15, Good Design Practices for Your Hexagonal Application, talks about some good practices you can adopt while creating each hexagon for your application. Starting with the Domain hexagon, we focus on Domain Driven Design aspects to clarify the business problems the application is supposed to solve. Then we move on to a discussion about the alternative ways to set up use cases and ports in the Application hexagon. And finally, we discuss the consequences of having to maintain multiple adapters. Assessments contains all the answers to the questions from all the chapters in this book. To get the most out of this book If you are using the digital version of this book, we advise you to type the code yourself or access the code from the book's GitHub repository (a link is available in the next section). Doing so will help you avoid any potential errors related to the copying and pasting of code. Download the example code files You can download the example code files for this book from GitHub at https:// github.com/PacktPublishing/Designing-Hexagonal-Architecture- with-Java. If there's an update to the code, it will be updated in the GitHub repository. We have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
The above is a preview of the first 20 pages. Register to read the complete e-book.

Recommended for You

Loading recommended books...
Failed to load, please try again later

Tip the Site

Scan the WeChat Pay or Alipay code to tip. No login required.

WeChat Pay
Alipay
← Back to List