<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alain-Michel Chomnoue Nghemning</title>
    <description>The latest articles on DEV Community by Alain-Michel Chomnoue Nghemning (@chomnoue).</description>
    <link>https://dev.to/chomnoue</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F318688%2Fa9c87337-a4de-4f0b-838c-f248a89c494b.jpeg</url>
      <title>DEV Community: Alain-Michel Chomnoue Nghemning</title>
      <link>https://dev.to/chomnoue</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chomnoue"/>
    <language>en</language>
    <item>
      <title>Domain Driven Design for Highly Scalable applications</title>
      <dc:creator>Alain-Michel Chomnoue Nghemning</dc:creator>
      <pubDate>Mon, 27 Apr 2020 10:19:46 +0000</pubDate>
      <link>https://dev.to/chomnoue/domain-driven-design-for-highly-scalable-applications-3jn6</link>
      <guid>https://dev.to/chomnoue/domain-driven-design-for-highly-scalable-applications-3jn6</guid>
      <description>&lt;h1&gt;
  
  
  Domain Driven Design for Highly Scalable applications
&lt;/h1&gt;

&lt;p&gt;Domain driven design (DDD),  is the perfect tool to reduce complexity for software development. Other advantages include a ubiquitous language across  business and technical people and a clear separation between business sub-domains. &lt;/p&gt;

&lt;p&gt;DDD  makes it easier for software to match the business needs and for developers to  collaborate closely with domain experts. &lt;/p&gt;

&lt;p&gt;As a result, the technical team will not feel like fighting against the features rejection and requirements changes from the stakeholders. Instead, speaking the same language, they will work together and make software a competitive advantage for the business. &lt;/p&gt;

&lt;p&gt;In this article, I am going to discuss DDD, focussing on the aspects that can be leveraged to achieve high scalability.&lt;/p&gt;

&lt;h1&gt;
  
  
  Example domain
&lt;/h1&gt;

&lt;p&gt;Let's use an auction sales application as an example for our business domain. &lt;/p&gt;

&lt;p&gt;In our domain, a user can, raise auctions for an item she wants to sell and define a deadline. She might also set a direct buy price.  The other users will then make their offers by increasing the auction until the countdown reaches zero, or someone makes the direct purchase. In order to be able to make an offer, the user must first fund his account with the required amount.&lt;/p&gt;

&lt;p&gt;To apply DDD we will do the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We will start by separating the example domain in bounded contexts. &lt;/li&gt;
&lt;li&gt;We will then focus on one of the contexts to design its aggregates, focussing on scalability without sacrificing business constraints and scalability. &lt;/li&gt;
&lt;li&gt;Finally, we will discuss domain events, as a way to keep everything that happens to our domain. &lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Bounded contexts
&lt;/h1&gt;

&lt;p&gt;The first step to an effective domain design is strategic design. It consists of simplifying the business model complexity by decomposing it into bounded contexts that can be handled separately. &lt;/p&gt;

&lt;p&gt;Bounded contexts are sets of highly related business activities, along with the concepts that they manipulate.&lt;/p&gt;

&lt;p&gt;One way to separate bounded contexts is to put unrelated activities in separate contexts. Our bounded contexts must be decoupled, as tightly coupled contexts will limit the ability of the team to build, deploy and scale the related software components separately.&lt;/p&gt;

&lt;p&gt;For example, the payment service focuses on user account funding and withdrawal, and doesn't care about how auctions are raised.&lt;/p&gt;

&lt;p&gt;The delivery service, on the other hand, only tracks the item delivery from the seller to the buyer, without knowledge of the selling process. &lt;/p&gt;

&lt;p&gt;Our core domain is the auctions, and we will focus on it in the rest of this paper, but also discuss the integration with the other contexts as necessary.&lt;/p&gt;

&lt;p&gt;So we can define three bounded contexts as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OpnKmVlX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/53bnmsh52yidct7tehpo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OpnKmVlX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/53bnmsh52yidct7tehpo.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most important thing to understand here is the separation of bounded contexts. &lt;/p&gt;

&lt;h1&gt;
  
  
  Aggregates
&lt;/h1&gt;

&lt;p&gt;Good aggregates design is the key for a highly scalable domain model. We can think of aggregates as individual actors in the system, handling atomic operations. By atomic I mean operations that either complete successfully with all induced state changes saved durably, or fails with no change applied to state.&lt;/p&gt;

&lt;p&gt;Aggregates should be addressed by their identifiers, that way they can be easily shared across many instances of the underlying database to achieve linear scalability.&lt;/p&gt;

&lt;p&gt;But how do we make sure the state of an aggregate is consistent with the rest of the system? For example, how do we make sure that the offer of a user matches his available balance? The answer to this questions is eventual consistency. That is, we will design our operations in such a way that they can be reverted if consequent transactions on other aggregates fail. This way, the system will not be consistent at the time an operation is applied to a given aggregate, but subsequent operations will move it, eventually, to a consistent state.&lt;/p&gt;

&lt;p&gt;The most common way of implementing the eventual consistency is by applying the Saga Pattern, that we will discuss in a subsequent article.&lt;/p&gt;

&lt;p&gt;An aggregate is a set of business entities, and the entry point of each aggregate is called the aggregate root. For example, we can consider the following as an aggregate:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nrwO6nk4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lndcqhcjfglbn714j2al.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nrwO6nk4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lndcqhcjfglbn714j2al.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aggregates should refer to other aggregates by their identifiers. In the above diagram, the seller is referenced using the “sellerId” attribute of the Auction while the buyer is referenced using the “buyerId”.&lt;/p&gt;

&lt;p&gt;One consideration to take into account when designing your aggregates is their side. Aggregates should bet small, they should not be allowed to grow indefinitely. Otherwise they might be heavy to load in memory, and thus seriously harm the performance of the operations.  \&lt;/p&gt;

&lt;p&gt;Coming back to our above example, if an auction receives millions of offers, then it will have a huge memory footprint. No matter which persistent solution you use, the storage and retrieval of your aggregate will perform worse as most users make bids.&lt;/p&gt;

&lt;p&gt;One way to fix this issue could be to limit the number of offers an auction can consider. But will the business accept this? I guess no. We should accept as many offers as possible.&lt;/p&gt;

&lt;p&gt;The other solution is to make a separate aggregate for the Bid. But the bids are immutatbles. Once created, they are not modified. The user can just make another offer. So it doesn’t make sense to consider a bid as an aggregate by itself.&lt;/p&gt;

&lt;p&gt;The third solution (and the best one for this case) is to keep only the best offer, as new bids are accepted only if they are better than the current best offer. So let us change the diagram (only the cardinality between Auction and Bid changes here)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V8WHIGo3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ifzevbvzv2492085ml3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V8WHIGo3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ifzevbvzv2492085ml3g.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Domain Events
&lt;/h1&gt;

&lt;p&gt;So you might be asking: Are we losing the older bids as we replace them with higher offers? What if we want to reason about all the offers to a given auction later? For example, we might want to report the total count of bids for a given auction.&lt;/p&gt;

&lt;p&gt;This is where domain events enter into play. We need only the current aggregate state to make a decision (whether we accept a bid for example), but we will keep everything that happened to the aggregate as domain events. That way, we could introduce any kind of reports or views of the data later, just by replaying the events.&lt;/p&gt;

&lt;p&gt;In our example domain model, we will store an “Auction Created” event every time a new auction is started, “Offer Placed” event for each bid and “Auction Closed” event at the end of the auction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--32CtuH50--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h5z64c32cu6mspjhqgxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--32CtuH50--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h5z64c32cu6mspjhqgxf.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Storing domain events can be cumbersome if you use a relational database schema. Fortunately, we have tools and techniques that can make this more easier for us. In an upcoming article, I will discuss Event Sourcing and how to leverage it to achieve high scalability.&lt;/p&gt;

&lt;p&gt;Domain events should also be used to create or update other aggregates. The other bounded contexts might be interested by the changes that happens to our aggregates, and we should notify them by publishing domain events.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZJ6xIive--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hweado5hwpgjb5xsinaz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZJ6xIive--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hweado5hwpgjb5xsinaz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, when an auction is closed, the Auctions Context should publish an “Auction Closed” event, that is consumed by the Delivery Context to initiate the item delivery process. &lt;/p&gt;

&lt;p&gt;In an upcoming article discussing event sourcing and CQRS, we will also cover how domain events can be used to update the read side database.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;In this article we discussed how to design an application targeting high scalability. We introduced important concepts of domain driven design, including Bounded Contexts, Aggregates and Domain Events, and explained how they should be applied to make our application scalable. We also introduced a practical example, an online auctions application.&lt;/p&gt;

&lt;p&gt;In upcoming an article, I will introduce event sourcing and CQRS, and how we can use them to implement our domain model.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.amazon.fr/Domain-Driven-Design-Distilled-Vaughn-Vernon/dp/0134434420"&gt;Domain-Driven Design Distilled by Vaughn Vernon&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://academy.lightbend.com/courses/course-v1:lightbend+LRA-DomainDrivenDesign+v1/about"&gt;Lightbend Reactive Architecture(2): Domain Driven Design&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ddd</category>
      <category>architecture</category>
      <category>microservices</category>
      <category>cloudnative</category>
    </item>
    <item>
      <title>Three things I learned about fast and scalable software while watching software development teams</title>
      <dc:creator>Alain-Michel Chomnoue Nghemning</dc:creator>
      <pubDate>Thu, 27 Feb 2020 12:12:44 +0000</pubDate>
      <link>https://dev.to/chomnoue/three-things-i-learned-about-fast-and-scalable-software-while-watching-software-development-teams-414h</link>
      <guid>https://dev.to/chomnoue/three-things-i-learned-about-fast-and-scalable-software-while-watching-software-development-teams-414h</guid>
      <description>&lt;p&gt;There are  similarities between the way a team grows and how you can write scalable software. Lets apply those lessons to change our software architecture.&lt;/p&gt;

&lt;p&gt;A software company can start with a single fullstack engineer doing everything (frontend, backend, test, build ...) but for the company to grow, it needs to add more people and to have them work together as a team to deliver quality feature at a fast pace. &lt;/p&gt;

&lt;h1&gt;
  
  
  Specialization
&lt;/h1&gt;

&lt;p&gt;First of all, teams scale effectively by adding people with different skills (front-end engineers, backend engineers, test engineers, SRE, ...), who work on specific tasks and coordinate to produce fast. Specialized people are usually faster at what they do, and produce features with better quality. Also, you will have less conflicts as your team members will work on separate code bases, or modify specific parts of a shared code base.&lt;/p&gt;

&lt;p&gt;In the same way, &lt;strong&gt;for your software to scale effectively, you have to decompose in specialized pieces&lt;/strong&gt;. For example, separate microservices. Each microservice can, for example, use a specific database technology or a programming language that is well suited for the features it provides. Also, different micro services will not concurrently read and write to the same database, thus avoiding locks. &lt;/p&gt;

&lt;p&gt;Applying &lt;a href="https://dddcommunity.org/learning-ddd/what_is_ddd/"&gt;domain driven design techniques&lt;/a&gt; can help you separate your software in microservices.&lt;/p&gt;

&lt;h1&gt;
  
  
  Asynchronous Communication
&lt;/h1&gt;

&lt;p&gt;Secondly, the most effective communication is asynchronous, people send messages to colleagues and continue doing other things. They can then take decisions about how to proceed once they receive an answer. &lt;br&gt;
For example, using an issue tracker a frontend engineer can ask to the backend team to make a modification in the API. He will not wait for them to produce it before he can continue his work. He will instead have some progress on another feature while waiting for the modification. &lt;/p&gt;

&lt;p&gt;This is similar to the asynchronous communication in &lt;strong&gt;reactive software&lt;/strong&gt;. Different components communicate through asynchronous messages, using the computer resources to progress on other requests while waiting for replies.&lt;/p&gt;

&lt;p&gt;To learn more about reactive systems, have a look the the &lt;a href="https://www.reactivemanifesto.org/"&gt;reactive manifesto&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Disposability
&lt;/h1&gt;

&lt;p&gt;Finally different people can complete any given task if it doesn't depend on some knowledge or skill owned by a unique team member, but instead relies on information that is available to any qualified person. &lt;br&gt;
For instance, the front-end engineer can leave the team before the backend implementation he requested is ready, or he could be busy on other tasks. Because we have the documentation in the issue tracker, any other frontend team member should be able to progress with the given feature. &lt;/p&gt;

&lt;p&gt;This also applies to scalable software. When an instance of microservice requests data from another component to complete a task, the given task doesn't have to be completed by the same instance issuing the request. Software that runs in the cloud, or in containers managed by orchestrators like Kubernetes, should be aware of the volatility of the machines they are deployed to. New machines can be added to or removed from the cluster to reach the actual demand at any time. &lt;/p&gt;

&lt;p&gt;Making your software &lt;a href="https://pivotal.io/cloud-native"&gt;cloud native&lt;/a&gt; will enable it to easily scale in your chosen runtime infrastructure.&lt;/p&gt;

&lt;p&gt;We can learn how to scale our software by learning the many similarities between effective team work and software scalability. Have you noticed some more resemblance that you want to share with us? Please just enter a comment below and let us know any suggestion you have.&lt;/p&gt;

</description>
      <category>microservices</category>
    </item>
  </channel>
</rss>
