39,59 €
Spring 5 and its ecosystem can be used to build robust architectures effectively. Software architecture is the underlying piece that helps us accomplish our business goals whilst supporting the features that a product demands. This book explains in detail how to choose the right architecture and apply best practices during your software development cycle to avoid technical debt and support every business requirement. Choosing the right architecture model to support your business requirements is one of the key decisions you need to take when a new product is being created from scratch or is being refactored to support new business demands. This book gives you insights into the most common architectural models and guides you when and where they can be used. During this journey, you’ll see cutting-edge technologies surrounding the Spring products, and understand how to use agile techniques such as DevOps and continuous delivery to take your software to production effectively. By the end of this book, you’ll not only know the ins and outs of Spring, but also be able to make critical design decisions that surpass your clients’ expectations.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 356
Veröffentlichungsjahr: 2018
Copyright © 2018 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 authors, 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.
Commissioning Editor: Richa TripathiAcquisition Editor: Sandeep MishraContent Development Editor: Anugraha ArunagiriTechnical Editor: Subhalaxmi NadarCopy Editor: Safis EditingProject Coordinator: Ulhas KambaliProofreader: Safis EditingIndexer: Aishwarya GangawaneGraphics: Tom ScariaProduction Coordinator: Shraddha Falebhai
First published: August 2018
Production reference: 1310818
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-78899-299-2
www.packtpub.com
Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Mapt is fully searchable
Copy and paste, print, and bookmark content
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.
René Enríquez works as technical leader in a multinational company headquartered in Silicon Valley. He worked on different projects using Java Enterprise Edition and Spring Framework. He currently works with different Spring projects to maintain legacy code and write microservices applying best practices to deliver products using Agile techniques with a strong focus on testing at different levels. During the last years, he worked as a software consultant for private and government companies and as an instructor of courses to develop enterprise and mobile applications. He was also a speaker at the ScrumDay and JavaDay conferences in Quito-Ecuador.
Alberto Salazar is an entrepeneur, passionate Java consultant, JUG leader, Auth0 ambassador and founder of the Java User Group of Ecuador, an associate member of the Java community process and a Java evangelist/trainer. He founded a consulting company in Latin America 10 years ago, where he creates and offers technical solutions based on Java. He has been working for 2 decades creating higly scalable and transactional systems. He is a regular speaker at multiple Java conferences and meetings. He recently organized a Java Conference in Ecuador with Java Champions and co-organized a Java Hackdays event in Spanish that brought together 11 different cities from around the world and 9 Spanish-speaking countries.
Yogendra Sharma is a developer with experience in the architecture, design, and development of scalable and distributed applications. He was awarded a bachelor's degree from Rajasthan Technical University in computer science with a core interest in microservices and Spring. He also has hands-on experience in technologies such as AWS Cloud, Python, J2EE, NodeJS, Angular, MongoDB, and Docker. He is currently working as an IoT and cloud architect at Intelizign Engineering Services. He constantly explores technical novelties, and is open-minded and eager to learn about new technologies and frameworks. He has also technically reviewed books and video courses for Packt.
Roland Alden has been the founder as well as co-founder of three technology startups and has decades of experience managing software engineering teams distributed around the world (Armenia, China, India, Micronesia, Nigeria, Pakistan, UAE, Ukraine, and Zambia). His background includes large companies (Data General and AT&T) and venture capital backed startups (Forethought, Go, and Eo). Currently, he works at ioet Inc., a software outsourcing firm based in Silicon Valley and Ecuador. He is a co-author of the Working with Computers and Working with Microsoft Office series of textbooks published by Houghton Mifflin.
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Title Page
Copyright and Credits
Software Architecture with Spring 5.0
Packt Upsell
Why subscribe?
PacktPub.com
Contributors
About the authors
About the reviewer
Packt is searching for authors like you
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Download the color images
Conventions used
Get in touch
Reviews
Software Architecture Today
Defining software architecture
I know my land
I want to stay ahead
Predicting the future
Architecture and architects
Software architecture principles
Components
Low coupling
High cohesion
SOLID principles
The single responsibility principle (SRP)
The Open–Closed Principle (OCP)
The Liskov substitution principle 
The interface segregation principle (ISP)
The dependency inversion (DI) principle
Conway's law
Choosing the right technology for you
New trends 
Summary
Software Architecture Dimensions
Dimensions
The business dimension
Managing user requirements
Identifying and tracking business metrics
The data dimension
The technical dimension
The operations dimension
How to deploy an application
How interaction occurs among your components
Dealing with infrastructure
Understanding the infrastructure
Versioning
Testing
Cloud versus on-premise
Deploying your application
The C4 model
Context diagram
Container diagram
Components diagram
Class diagram
Summary
Spring Projects
Why Spring appeared
Spring projects
Spring Initializr
Spring Boot in a Nutshell
Servlet container integration
Autoconfiguration
Dependency management
mvnw and mvnw.cmd
pom.xml
DemoApplication.java
The application.properties file
DemoApplicationTests.java
Avoiding redeployment with developer tools
Spring Data
Supporting EIPs with Spring Integration
Spring Batch
The read step
The process step
The write step
Securing applications with Spring Security
Embracing (Spring) HATEOAS
Spring Cloud and the microservices world
Configuration server
Service registry
Edge services
Microproxy
API gateway
Circuit breaker
Reactive and Spring
Publisher
Subscriber
Subscription
Processor
Project reactor
Mono
Flux
Back pressure
Reactive Spring Data
Reactive REST services
Summary
Client-Server Architectures
Understanding client-server architectures
Server
Scaling 
Request
Client
Network
Where to apply client-server architectures
Implementing client-server architectures with Spring
The server
SOAP web services
RESTful web services
CORBA
Sockets
AMQP
Implementing the server
Banking-domain
Banking-api
Boundaries
Domain
Persistence
Service
Monitoring the server
Testing
Banking-client
Authentication endpoint client
Account balance endpoint client
The clients
JavaFX client
Android client
Thin client
Summary
Model-View-Controller Architectures
MVC
The Model (M)
The View (V)
The Controller (C)
Benefits of using MVC 
Common pitfalls
Implementing applications using MVC
Spring MVC
Testing
Test coverage
UI frameworks
Thymeleaf
Securing an MVC application
Basic authentication
Implementing basic authentication
Summary
Event-Driven Architectures
Underlying concepts and key aspects
Command
Event
Patterns of event-driven architectures
Event notification
Event-carried state transfer
Improving application performance
Reducing the load on the source application
Increasing the availability of the system
Event sourcing
CQRS
Complex domain models
Distinct paths to query and persist information
Independent scaling
Summary
Pipe-and-Filter Architectures
Introducing Pipe-and-Filter concepts
Filters
Pipes
Boarding Pipe-and-Filter architectures
Use cases for Pipe-and-Filter architecture
Spring Batch
Implementing pipes with Spring Batch
Summary
Microservices
Principles of microservices
Size
Autonomous
Working well together
Advantages
Alignment to the single responsibility principle
Continuous releases
Independent scalability
Increased adoption of new technologies
Drawbacks
Too many options
Slow at the beginning
Monitoring
Transactions and eventual consistency
Modeling microservices
Speeding up
Accelerating the development process
Embracing tests
Going to production
Implementing microservices
Dynamic configuration
Implementing a configuration server
Implementing a configuration client
Service discovery and registration
Introducing Eureka
Implementing a Netflix Eureka service registry
Implementing a service registry client
Netflix Ribbon
Edge services
Introducing Zuul
CAP theorem
Consistency
High availability
Partition tolerance
Circuit breaker
Hystrix
Summary
Serverless Architectures
An introduction to serverless architecture
Infrastructure and file storage
Benefits and pitfalls
Backend as a service
Function as a service
Concerns about serverless architectures
Vendor lock-in
Security
Framework support
Troubleshooting
Examples and common use cases
Adopting serverless architectures for SPA 
Implementing FaaS with Spring Cloud Functions
Functions with Spring
Coding the example
Adapters
AWS Lambda adapter
Azure adapter
Summary
Containerizing Your Applications
Containers
Basic concepts
Containers and images
Basic commands
Running containers
Working with containers
Working with images
Building your own images
FROM command
MAINTAINER command
RUN command
ENV command
EXPOSE command
CMD command
Containerizing applications
Docker Gradle plugin
Registries
Publishing images
Provisioning multiple-container environments
Docker Compose
Linking containers
links
depends_on
Container orchestration with Kubernetes
Pod
Labels
Replication controllers
Services
Summary
DevOps and Release Management
Silos
How to break silos
DevOps culture
Motivations
DevOps adoption
Embracing automation
Infrastructure as code
Spring application and DevOps practices
Supporting different environments
Selecting profiles
Vagrant
Working with Vagrant
Release management
pipelines
Continuous integration
Continuous delivery and continuous deployment
Automating pipelines
Jenkins
Summary
Monitoring
Monitoring
Monitoring Spring applications
Application Performance Management (APM) tools
New Relic
Summary
Security
Why security is important as a part of an application's architecture
Key security recommendations
Authentication and authorization
Cryptography
Data input validation
Sensitive data
Social engineering
OWASP Top 10
Penetration testing
Authentication and authorization as a service
Summary
High Performance
Why performance matters
Scalability
Horizontal scalability
Vertical scalability
High availability
Performance
The key recommendation to avoid performance issues
Identifying bottlenecks
Profiling applications 
Visual VM
SQL query optimizations
A load test example
Summary
Other Books You May Enjoy
Leave a review - let other readers know what you think
Today we count on different software architecture styles that can be applied in different scenarios. In this book, we will review the most common software architecture styles and how they can be implemented using Spring Framework, which is one of the most widely adopted frameworks within the Java ecosystem.
At the beginning, we'll review some key concepts inherent to software architecture in order to understand the fundamental theory before diving into technical details.
This book is aimed at experienced Spring developers who are aspiring to become architects of enterprise-grade applications and at software architects who would like to leverage Spring to create effective application blueprints.
Chapter 1, Software Architecture Today, provides an overview of how software architectures are managed today and why they are still important. It discusses how the most recent needs of the software industry are handled by the new emerging architecture models and how they can help you to solve these new challenges.
Chapter 2, Software Architecture Dimensions, reviews the dimensions associated with software architectures and how they influence the building process of your applications. We will also introduce the C4 model used to document software architectures.
Chapter 3, Spring Projects, speaks about some of the most useful Spring Projects. It's important to know which tools are inside your toolbox because Spring provides a wide variety of tools that fit your needs and can be used to boost your development process.
Chapter 4, Client-Server Architectures, covers how client-server architectures work and the most common scenarios where this style of architecture can be applied. We will go through various implementations, starting from simple clients such as desktop applications to modern and more complex usages such as devices connected to the internet.
Chapter 5, MVC Architectures, speaks about MVC, which is one of the most popular and widely known architecture styles. In this chapter, you will get an in-depth understanding of how MVC architectures work.
Chapter 6, Event-Driven Architectures, explains the underlying concepts related to event-driven architectures and which issues they handle using a hands-on approach.
Chapter 7, Pipe-and-Filter Architectures, focuses heavily on Spring Batch. It explains how to build pipelines, which encapsulate an independent chain of tasks aimed to filter and process big amount of data.
Chapter 8, Microservices, provides an overview about how to implement microservice architectures using the spring cloud stack. It details every component and how they interact with each other in order to provide a fully functional microservice architecture.
Chapter 9, Serverless Architectures, speaks about many services on the internet that are ready-to-use and can be used as part of software systems, allowing companies to just focus on their own business core concerns. This chapter shows a new way to think about building applications around a series of third-party services to solve common problems such as authentication, file storage, and infrastructure. We will also review what FaaS approach is and how to implement it using Spring.
Chapter 10, Containerizing Your Applications, explains that containers are one of the most handy technologies used in the last few years. They help us to get rid of manual server provisioning and allow us to forget the headaches related to building production environments and the maintenance tasks for servers. This chapter shows how to generate an artifact ready for production that can be easily replaced, upgraded, and interchanged eliminating the common provisioning issues. Through this chapter, we will also introduce container orchestration and how to deal with it using Kubernetes.
Chapter 11, DevOps and Release Management, explains that Agile is one of the most common approaches to organizing teams and making them work together to build products more quickly. DevOps is an inherent technique of these teams, and it helps them to break unnecessary silos and boring processes, giving teams the chance to be in charge of the whole software development process from writing code to deploy applications in production. This chapter shows how to achieve this goal by embracing automation to reduce manual tasks and deploy applications using automated pipelines in charge of validating the written code, provisioning the infrastructure, and deploying the required artifacts in a production environment.
Chapter 12, Monitoring, explains that once the application is published, unexpected behaviors are not uncommon and that it's essential to notice them so that they can be fixed as quickly as possible. This chapter gives some recommendations regarding techniques and tools that can be used to monitor the performance of an application bearing in mind technical and business metrics.
Chapter 13, Security, explains that often security is one of the fields that teams do not pay close attention to when they are working on developing their products. There are a few key considerations that developers should keep in mind when they are writing code. Most of them are pretty obvious, while others aren't, so we will discuss all of them here.
Chapter 14, High Performance, explains that there is nothing more disappointing in a job than dealing with issues in production when an application is behaving in an unexpected way. In this chapter, we'll discuss some simple techniques that can be applied to get rid of these annoying problems by applying simple recommendations on a daily basis.
A good understanding of Java, Git, and Spring Framework is necessary before reading this book. A deep knowledge of OOP is desired, although some key concepts are reviewed in the first two chapters.
You can download the example code files for this book from your account at www.packtpub.com. If you purchased this book elsewhere, you can visit www.packtpub.com/support and register to have the files emailed directly to you.
You can download the code files by following these steps:
Log in or register at
www.packtpub.com
.
Select the
SUPPORT
tab.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box and follow the onscreen instructions.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR/7-Zip for Windows
Zipeg/iZip/UnRarX for Mac
7-Zip/PeaZip for Linux
The code bundle for the book is also hosted on GitHub athttps://github.com/PacktPublishing/Software-Architecture-with-Spring-5.0. We also have other code bundles from our rich catalog of books and videos available athttps://github.com/PacktPublishing/. Check them out!
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://www.packtpub.com/sites/default/files/downloads/SoftwareArchitecturewithSpring5_ColorImages.pdf.
Feedback from our readers is always welcome.
General feedback: Email [email protected] and mention the book title in the subject of your message. If you have questions about any aspect of this book, please email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the Internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packtpub.com.
In this chapter, we will review what software architecture is and why it's still relevant today. We will also discuss the new business demands that have been guiding the world of software development in the last few years, and how they have affected the software industry as a whole.
Software and technology are evolving daily, introducing new demands that businesses must meet in order to remain relevant in a competitive market. Regardless of their core business, every competitive company has had to turn to technology. Online transactions and clients around the world are just some of the challenges that have to be mastered in order to stay ahead.
In order to support these new demands, we have been discovering new ways to do our work. Drastic changes have been made and adopted, directly affecting our software development life cycle (SDLC). Some examples of these changes are reflected in how we work on the following phases:
Gathering requirements
Organizing teams
Designing software architectures
Writing code
Deploying applications
In this chapter, we will start by revisiting the underlying concepts of software architecture, which have been present for a long time and are still relevant today.
This chapter will cover the following topics:
Defining software architecture
Common
mistakes that are made when creating architecture
s
Architecture and architects
Software architecture principles
Applying high cohesion and low coupling in order to create components
SOLID principles
Conway's law
Choosing the right technology for you
New technology tendencies
No matter whether or not someone holds the software architect role in a team, every application has an architecture that somebody needs to take care of. This is an important step as it helps us to avoid writing entangled code, which makes a software system impossible to evolve in the future.
First things first: In order to know why you need to remember software architecture, we first need to understand what it is and why it is important.
In software, the term architecture is hard to define. Authors often borrow the definition from the construction industry, which is wrong. Software architecture is not all about diagrams, such as plans for buildings or houses—it's more than that. It's about the shared knowledge that technical and even nontechnical people have about the application that the whole team is creating, how the modules are connected to shape it, and all the complicated and vital elements surrounding it. Good software architectures are heavily focused on business requirements rather than on frameworks, programming languages, diagrams, and programming paradigms. Of course, we need these because we create applications using them. However, they don't have to define the underlying principles that dictate how we conceive the software. Instead, this role should be played according to business requirements.
The long-term success of an application is mainly based on its architecture, which must be created to support a well-defined set of business requirements, as mentioned earlier. Since an application needs to resolve these specific requirements, they must guide the architecture of the application. However, there are two main scenarios in which we guide software architecture decisions based on technology instead of business requirements:
I know my land
I want to stay ahead
This scenario occurs when we create software architectures using frameworks and programming languages that we already know about, without paying close attention to business needs.
Let's say that the ABC company needs an application for manipulating text from large log files. If someone were to ask to work on this requirement, then they will choose a programming language that they are comfortable with during the development process, instead of looking for the best approach elsewhere.
Imagine that the person in charge of creating this application has already mastered JavaScript. In this case, do you think it's a good idea to write code using Node JS or another JavaScript framework running on the server in order to write an application to manipulate log files? I'm not saying that this is impossible—you can do it. However, do you think an application created using this approach will be able to perform and scale better than a system written in Perl, Python, or C, for example? This is not to say that JavaScript is terrible—it is simply important to know that this approach is not a good fit for JavaScript.
We all want to stay ahead with technology, using the latest trends in the programming world to have a better technological background and consequently land cool jobs. Some people tend to write applications, keeping this idea in mind. Let's explain this scenario using the application example for manipulating log files that we mentioned in the previous section.
Suppose you're asked to solve the problem that we mentioned in the I know my land section. In this scenario, your only concern is technology. For instance, let's say you want to try the newest features in the latest PHP release. In this case, you will build this application using PHP. While this programming language has been improving over the last few years since Facebook started to add new features to it, the idea behind writing an application to manipulate large log files using PHP is crazy. As you may know, this programming language is intended to create other kinds of applications—mainly those that have to be accessed using a web browser and without high transactional requirements.
Again, you can write an application using PHP to manipulate large log files, but what will happen when more features are needed? Do you think a software architecture created with this approach in mind will be able to respond quickly to new requirements and the inherent characteristics of the application used in this example?
While we can't predict each detail of an application when we are creating it, we can keep some apparent assumptions in mind to avoid glaring mistakes, like the ones exposed in the preceding sections. Even if you have created an application using the wrong approach, one part of the software architecture process is to evaluate the code base from time to time and take corrective actions based on this. This is important because the existing software architecture needs to evolve in order to avoid becoming useless. During the development process—and because we do not want to miss the established project deadlines—weoften use the FIXMEandTODOtags. However, we should pay close attention to these and take action as soon as we can, as they represent a technical debt that gets worse as time passes. Imagine how easy it is to get rid of a recently introduced debt in the next iteration. Now, imagine how hard it would be if the developer who added that debt is no longer working on the project or even within the same company.
The process of improving the existing software architecture sometimes tends to be even more interesting than creating a new one from scratch. This is because you now have more information about the business requirements and how the application was performing at the time that it was in production.
When you are adding new features to an existing application, you will figure out how good the initial idea was. If the process of adding new features is simple and requires only a few changes in its structure, then we can conclude that the software architecture is doing its job well. Otherwise, if we need to make substantial changes to the underlying parts of the original design, we can say that the initial idea and assumptions were all wrong. However, at this point, the team in charge of the product should be responsible enough to make it evolve instead of writing additional patches to support new features.
Even though patching something sounds similar to making it evolve, it isn't. This idea is explained clearly in the book Building Evolutionary Architectures, written by Neal Ford, Rebecca Parsons, and Patrick Kua.
Proactive teams continually apply changes that make it possible to better support preexisting and new features rather than simply sitting and waiting for chaos when things get out of control. There's nothing wrong with changing an initial design, and it's always worth doing this. The following diagram illustrates this process, as applied to a geometric shape:
Now that we know that business needs must guide the application architecture, we can conclude that if it is unable to support new features, then new business opportunities will be missed, making the application and its architecture useless.
Before the agile and DevOps approaches appeared, architects used to focus on creating standards and rules to write code. In the past, it was common to find architects who wrote code, but this approach is currently outdated with regards to programming. Over the last few years, the idea of architects has been disappearing, all thanks to the new emerging models for creating teams. Agile movements have been in the software industry for a while, helping us to rethink how we are building software and organizing teams.
Nowadays, it's almost impossible to find software teams that have an architect working with them. Moreover, the idea of having different groups of people as part of an organization that collaborates using a silo style (where one task has to be finished before starting a new one) is disappearing. A few years ago, we had well-defined roles and even specialized departments for the following roles:
Business analysts
Developers
QA engineers
Architects
DBAs
People working on infrastructure
Operations
Security
The following graphic shows how teams work using a silos style:
The preceding list also grows in specific cases. Teams working using a silo style used to work on producing defined artifacts, such as documentation, UML diagrams, and other things that are usually incomplete.
This approach is changing, and having small and multidisciplinary teams in charge of taking care of every single detail of an application is now more common. This approach has helped to create proactive teams with strong skills that allow us to ensure that software architecture is still happening all the time.
It's evident that not every team member has the full set of skills required to work on every stage, from gathering requirements to deploying the application in production, but the communication among all of them allows us to reduce the technical gaps and have a better understanding of the bigger picture of the application. This is one of the most important aspects of software architecture.
This shared knowledge helps the team to continue improving the existing software architecture, overcoming the most complex problems. All of the teams in charge of writing software can understand the details of the system under development instead of delegating this responsibility to only one person or even to a department. This approach can lead us to rely on people or teams that would be slightly out of the business context of why the application was being created. This is because people that worked on the project in the past but no longer participate actively due to working on more than one project can't fully understand all of the details of every system.
Software architecture should improve by following two simple principles that are often difficult to achieve:
Low coupling
High cohesion
No matter what programming language, paradigm, or tools you are using to architect your applications, these two principles should guide you when building your software architecture components.
In order to build the components that will shape your architecture, it's always worth following the guidelines. These are still relevant, even after many years of existence, and they should always be considered when components are being created. In this section, I'm talking about SOLID principles and Conway's law, which we will discuss in more detail later in this chapter. It is now time to look at what components are in more detail.
A component is a set of functions, data structures, and algorithms that solve one problem. This means that all the code and artifacts that are used to build the component have a high cohesion with each other; the rule here is that the classes or files that create a component should change at the same time and for the same reason.
Software architecture is built using many components, and you should not be worried about having an excessive quantity of these. The more components you write, the more freedom there is to assign them to different developers or even to different teams. Large software architectures can be created using many smaller components that can be developed and deployed independently of each other.
Once we connect these components to each other, they allow us to create the desired software architecture.
As shown in the following diagram, we can see the components as pieces of a puzzle that come together to form an application:
The connected components define application architectures, and their designs describe how each component has been created internally. It's here that pattern designs and SOLID principles must be used to create good designs.
The principle of high cohesion also has a pretty simple definition: one component should perform one and only one well-defined job. Although the description is pretty simple, we often tend to get confused and violate this principle.
In the previous example, we had NotificationService, which was in charge of sending notifications by email and fax. The word and can be helpful for us when it comes to identifying the violation of this principle. Now that we have two different classes (one per notification channel), it's fair to say that our classes only have one responsibility.
Again, the same is true for components, and another reason to keep the same idea with them is that you will likely have each component accomplishing only one specific requirement. For example, what would happen if all our customers just wanted to receive their bank statements by email; do you think it's okay to depend on a class that has the ability to send faxes too?
Although the previous question may seem unimportant, imagine that you solved an existing issue related to sending notifications using faxes as a notification mechanism, and a new issue was then introduced into the mechanism in order to send email notifications by mistake.
Remember that components shape your software architecture, and architects should design them in a way that maximizes team productivity. Aligning your components to the high-cohesion principle is an excellent way to separate them and allows teams to work independently on different parts of your application. This ability to create various components with clear responsibilities will make it easier when solving other issues and adding new features, and will also make you less prone to introducing bugs.
With regards to the previous example, you are probably wondering why the NotificationChannel class is apparently sending notifications with a BankStatement parameter.
Common sense leads us to believe that we need to replace this class with any other generic type. It can be helpful to allow the application to send different kinds of notifications, and not only bank statements: this may include drawbacks, or when a new deposit is received in the account. Even though the idea of supporting incoming requirements looks like something you might want to include in the program at this stage, the application doesn't currently need this ability. This is why it is not necessary for us to add this feature right now. Instead, this design should evolve when this becomes necessary; in this way, we are sticking to the KISS principle (https://www.techopedia.com/definition/20262/keep-it-simple-stupid-principle-kiss-principle) and following the directions of only building the most basic features to make the application work.
SOLID is an acronym that represents the five underlying principles that guide a good software design. The design is related to the creation of components that shape your software architecture.
In 2004, Michael Feathers suggested this acronym to Robert C. Martin, the author of these principles. The process for creating them took him around 20 years, and during this period, many of them were added, removed, and merged to achieve a robust set of principles named SOLID. Let's review each one of the principles and provide a brief and clear explanation that will be helpful for getting a precise idea of how we can use them.
We will use the term module in tandem with the idea of modules shaping components, and we will make reference to the object-oriented programming (OOP)world using terms such as classes and interfaces in order to provide a more precise explanation of modules.
The SRP is very closely related to the high cohesion that we reviewed earlier. The idea behind this principle is that a module should be changed for one reason only.
This definition leads us to conclude that a module should have only one responsibility. One way to verify whether this principle is achieved in your design is to answer the following questions:
Does the module's name represent its exposed functionality?
