Decomposition Design Patterns Flashcards
Decompose by Business Capability
Summary:
Take your business architecture (e.g. Customers, Orders, etc) and use this as the base for your your objects/services model.
Detail:
Microservices is all about making services loosely coupled, applying the single responsibility principle. It decomposes by business capability. Define services corresponding to business capabilities. A business capability is a concept from business architecture modeling. It is something that a business does in order to generate value. A business capability often corresponds to a business object, e.g.
Order Management is responsible for orders
Customer Management is responsible for customers
https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-decomposing-monoliths/decompose-business-capability.html
Decompose by Subdomain
Summary:
Usually to avoid mini-monoliths or god classes when decomposing by business capability. Using DDD you can identify subdomains within larger domains. These are usually core and supporting (which are built in house) for example customer data and content. There is also generic which is not central to business and can be built using 3rd party off the shelf solutions (e.g. system monitoring, auth, system alerts, cloud infrastructure etc.)
Detail:
Decomposing an application using business capabilities might be a good start, but you will come across so-called “God Classes” which will not be easy to decompose. These classes will be common among multiple services. Define services corresponding to Domain-Driven Design (DDD) subdomains. DDD refers to the application’s problem space — the business — as the domain. A domain is consists of multiple subdomains. Each subdomain corresponds to a different part of the business.
Subdomains can be classified as follows:
Core — key differentiator for the business and the most valuable part of the application
Supporting — related to what the business does but not a differentiator. These can be implemented in-house or outsourced
Generic — not specific to the business and are ideally implemented using off the shelf software
The subdomains of an Order management include: Product catalog service Inventory management services Order management services Delivery management services
https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-decomposing-monoliths/decompose-subdomain.html
Decompose by Transaction Two Phase Commit (2pc) pattern
Summary:
Use sparingly. 2PC pattern can slow a system down. Designed to help break monoliths into smaller services that require distributed transactions. Involves all services “preparing” for change and then “committing” or “rolling back” change.
Detail:
You can decompose services over the transactions. Then there will be multiple transactions in the system. One of the important participants in a distributed transaction is the transaction coordinator
May have benefits when multiple microservices calls are needed to complete one business transaction (e.g. when decomposing a monolith).
https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-decomposing-monoliths/decompose-transactions.html
2PC Pattern NOT IDEAL FOR HIGH LOAD
Prepare phase — during this phase, all participants of the transaction prepare for commit and notify the coordinator that they are ready to complete the transaction
Commit or Rollback phase — during this phase, either a commit or a rollback command is issued by the transaction coordinator to all participants
The problem with 2PC is that it is quite slow compared to the time for operation of a single microservice. Coordinating the transaction between microservices, even if they are on the same network, can really slow the system down, so this approach isn’t usually used in a high load scenario.
Strangler Pattern
Summary:
Proxy services to route calls that initially may just forward calls to legacy services, later will replace legacy services with new functionality.
Detail:
The Strangler pattern creates two separate applications that live side by side in the same URI space. Over time, the newly refactored application “strangles” or replaces the original application until finally, you can shut off the monolithic application. The Strangler Application steps are transform, coexist, and eliminate.
Transform — Create a parallel new site with modern approaches.
Coexist — Leave the existing site where it is for a time. Redirect from the existing site to the new one so the functionality is implemented incrementally.
Eliminate — Remove the old functionality from the existing site.
The strangler fig pattern was introduced by Martin Fowler as a way to manage risk when modernizing or rewriting large, monolithic systems. The pattern is an analogy for a type of plant that begins life as a vine growing alongside an older, established tree. As the vine grows, it spreads to completely consume and ultimately replace the host tree, leaving a new, strangler fig tree in its place. In the context of modernizing ASP.NET web services, this pattern incrementally replaces system functionality by establishing proxies where other systems have dependencies on web services. Initially, you can consider these proxies as having pass-through behavior, because their implementation is fulfilled by the existing monolithic application service. In the natural analog, this is when the strangler fig initially sends a vine up the host tree’s trunk. Then, a new service, which is decoupled from the monolith, is created, and the proxy’s implementation is deferred to that new service. In the natural analog, this is when the strangler fig vine wraps around one of the tree’s branches and overtakes it. This pattern of proxying and then swapping out the proxy implementation with a new service continues until all the legacy system’s functions are migrated to new services. At this point, the strangler fig vine completely consumes the tree, and the legacy system can be decommissioned.
Follow these best practices when using the strangler fig pattern, so you can independently scale and deploy your application more smoothly:
Select a component that has good test coverage and less technical debt associated with it. Starting with this component can give teams a lot of confidence during the modernization process.
Select components that have scalability requirements, and start with one of these components.
Select a component that has frequent business requirement changes and frequent deployments.
To implement this pattern at scale on AWS, deploy the refactored ASMX services in a Windows container that is running in Amazon Elastic Container Service (Amazon ECS), and publish your modernized REST API by using Amazon API Gateway.
https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-aspnet-web-services/fig-pattern.html
Bulkhead Pattern
Summary:
Involves handling service failure via fail fast default value or error returns or leveraging async communications through queues/bus/etc. Intention is to provide mechanism for service to avoid overload (e.g. threadpool). Example, if a service has a threadpool limit of 300 and needs to make three service calls to complete transaction, you can partition the pool into 100 threads for each dependent service.
Detail:
Isolate elements of an application into pools so that if one fails, the others will continue to function. This pattern is named Bulkhead because it resembles the sectioned partitions of a ship’s hull. Partition service instances into different groups, based on consumer load and availability requirements. This design helps to isolate failures, and allows you to sustain service functionality for some consumers, even during a failure.
To implement the bulkhead pattern, we need to make sure that all our services work independently of each other and failure in one will not create a failure in another service. Techniques such as maintaining:
A single-responsibility pattern
An asynchronous-communication pattern
Fail-fast or other Failure-handling patterns.
Sidecar or Sidekick Pattern
Summary:
Useful when applications use heterogeneous components/technologies and a need for common functionality across services (e.g. logging, infrastructure access patterns, etc.). Use a container to provide isolation/encapsulation and attach to parent application. This was done for KDM System (Wailua was sidecar to Key Generation servers).
Detail:
Deploy components of an application into a separate processor container to provide isolation and encapsulation. This pattern can also enable applications to be composed of heterogeneous components and technologies. This pattern is named Sidecar because it resembles a sidecar attached to a motorcycle. In the pattern, the sidecar is attached to a parent application and provides supporting features for the application. The sidecar also shares the same lifecycle as the parent application, is created and retired alongside the parent. The sidecar pattern is sometimes referred to as the sidekick pattern and is the last decomposition pattern that we show in the post.
When to Use this Pattern
Your primary application uses a heterogeneous set of languages and frameworks. A component located in a sidecar service can be consumed by applications written in different languages using different frameworks.
A component is owned by a remote team or a different organization.
A component or feature must be co-located on the same host as the application
You need a service that shares the overall lifecycle of your main application, but can be independently updated.
You need fine-grained control over resource limits for a particular resource or component. For example, you may want to restrict the amount of memory a specific component uses. You can deploy the component as a sidecar and manage memory usage independently of the main application.
https://docs.microsoft.com/en-us/azure/architecture/patterns/sidecar
Anti Corruption Layer
Summary:
Used when migrating from legacy system, but new system still needs access to legacy data. This pattern isolates services that by their need to talk to the legacy system would “corrupt” the design (e.g. bloat, add support for old protocols, data models, APIs, etc.). Often paired with Strangler pattern.
Detail:
Implement a façade or adapter layer between different subsystems that don’t share the same semantics. This layer translates requests that one subsystem makes to the other subsystem. Use this pattern to ensure that an application’s design is not limited by dependencies on outside subsystems.
https://docs.microsoft.com/en-us/azure/architecture/patterns/anti-corruption-layer