Lecture4Notes (2)
Lecture4Notes (2)
Monolithic Architecture
Monolithic Architecture
• A monolithic architecture is the traditional unified
model for the design of a software program.
• Monolithic, in this context, means "composed all in
one piece."
• In a monolithic architecture, each component and its
associated components must all be present for code to
be executed or compiled and for the software to run.
• When all functionality in a system had to be deployed
together, we consider it a monolith.
Context
• You are developing a business-critical enterprise
application.
• You need to deliver changes rapidly, frequently and
reliably in order for your business to thrive in today’s
volatile, uncertain, complex and ambiguous world.
• Consequently, your engineering organization is
organized into small, loosely coupled, cross-functional
teams.
• The team delivers a stream of small, frequent changes
that are tested by an automated deployment pipeline
and deployed into production.
Context A team is responsible for one or more
subdomains.
Easy debugging – With all code located in one place, it’s easier
to follow a request and find an issue.
Resulting context:Disadvantages
• Slower development speed – A large, monolithic application
makes development more complex and slower.
• Scalability – You can’t scale individual components.
• Reliability – If there’s an error in any module, it could affect the
entire application’s availability.
• Barrier to technology adoption – Any changes in the framework
or language affects the entire application, making changes often
expensive and time-consuming.
• Lack of flexibility – A monolith is constrained by the technologies
already used in the monolith.
• Deployment – A small change to a monolithic application requires
the redeployment of the entire monolith.
Single Monolith
The most common example that comes to mind
when discussing monoliths is a system in which all of
the code is deployed as a single process.
Here we see a synchronous HTTP call made from our Warehouse service to a
downstream Order service to fetch required information about an order. To satisfy the
request, the Order service in turn has to fetch information from the Customer
service, again via a synchronous HTTP call. For this overall operation to complete,
the Warehouse, Order, and Customer services all needed to be up, and contactable.
They are temporally coupled.
Solution to Temporal Coupling
• We could reduce this problem in various ways:
1. We could consider the use of caching—if the Order
service cached the information it needed from the
Customer service, then the Order service would be
able to avoid temporal coupling on the downstream
service in some cases.
2. We could also consider the use of an asynchronous
transport to send the requests, perhaps using
something like a message broker. This would allow a
message to be sent to a downstream service, and for
that message to be handled after the downstream
service is available.
Deployment Coupling
• Consider a single process, which consists of multiple
statically linked modules.
• A change is made to a single line of code in one of the
modules, and we want to deploy that change.
• In order to do that, we have to deploy the entire
monolith—even including those modules that are
unchanged.
• Everything must be deployed together, so we
have deployment coupling.
Deploying something carries risk.
• There are lots of ways to reduce the risk of deployment, and one
of those ways is to change only what needs to be changed.
• If we can reduce deployment coupling, perhaps through
decomposing larger processes into independently deployable
microservices, we can reduce the risk of each deployment by
reducing the scope of deployment.
• Reducing deployment coupling doesn’t require microservices,
of course.
• Runtimes like Erlang allow for the hot-deployment of new versions
of modules into a running process. Eventually, perhaps more of us
may have access to such capabilities in the technology stacks we
use day to day
Domain Coupling
• Fundamentally, in a system that consists of multiple
independent services, there has to be some interaction
between the participants.
• For instance, If you want to place an order, you need to
know what items were in a customer’s shopping basket.
If you want to ship a product, you need to know where
you ship it.
Example Case: Music Corp.
• We have a warehouse that stores goods.
• When customers place orders for CDs, the folks working
in the warehouse need to understand what items need
to be picked and packaged, and where the package
needs to be sent.
• So, information about the order needs to be shared with
the people working in the warehouse.
Music Corp.
• An Order Processing service sends
all the details of the order to the
Warehouse service, which then
triggers the item to be packaged up.
• As part of this operation, the
Warehouse service uses the
customer ID to fetch information
about the customer from the
separate Customer service so that
we know how to notify them when
the order is sent out.
What is the problem with given
scenario?
• In this situation, we are sharing the entire order with the
warehouse, which may not make sense—the warehouse needs
only information about what to package and where to send it.
• They don’t need to know how much the item cost (if they need to
include an invoice with the package, this could be passed along
as a pre-rendered PDF).
• We’d also have problems with information that we have to
control access to being too widely shared—if we shared the full
order, we could end up exposing credit card details to services
that don’t need it, for example.
How can I reduce the risk?
• So instead, we might
come up with a
new domain
concept of a Pick
Instruction
containing just the
information the
Warehouse service
needs.
• This is another
example of
information
Further Improvement????
• We could further reduce coupling by removing the need for the
Warehouse service to even need to know about a customer if we
wanted to—we could instead provide all appropriate details via the
Pick Instruction