<?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: Dinh Vo</title>
    <description>The latest articles on DEV Community by Dinh Vo (@dylanvo28).</description>
    <link>https://dev.to/dylanvo28</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%2F889850%2F4548d643-c56b-48de-92e1-3c2456228d57.png</url>
      <title>DEV Community: Dinh Vo</title>
      <link>https://dev.to/dylanvo28</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dylanvo28"/>
    <language>en</language>
    <item>
      <title>Horizontal and Vertical Scaling In Databases</title>
      <dc:creator>Dinh Vo</dc:creator>
      <pubDate>Tue, 06 Sep 2022 14:05:03 +0000</pubDate>
      <link>https://dev.to/dylanvo28/horizontal-and-vertical-scaling-in-databases-22on</link>
      <guid>https://dev.to/dylanvo28/horizontal-and-vertical-scaling-in-databases-22on</guid>
      <description>&lt;p&gt;Scaling alters size of a system. In the scaling process, I either compress or expand the system to meet the expected needs. The scaling operation can be achieved by adding resources to meet the smaller expectation in the current system, or by adding a new system in the existing one, or both. &lt;br&gt;
Types of Scaling: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RcoyfNSm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1cw69zvn9zq9e65p952d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RcoyfNSm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1cw69zvn9zq9e65p952d.png" alt="Image description" width="880" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scaling can be categorised into 2 types: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Vertical Scaling: When new resources are added in the existing system to meet the expectation, it is known as vertical scaling. &lt;br&gt;
Consider a rack of servers and resources that comprises of the existing system. (as shown in the figure). Now when the existing system fails to meet the expected needs, and the expected needs can be met by just adding resources, this is considered as vertical scaling. &lt;strong&gt;Vertical scaling is based on the idea of adding more power(CPU, RAM) to existing systems, basically adding more resources.&lt;/strong&gt; Vertical scaling is not only easy but also cheaper than Horizontal Scaling. It also requires less time to be fixed. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Horizontal Scaling: When new server racks are added in the existing system to meet the higher expectation, it is known as horizontal scaling. &lt;br&gt;
Consider a rack of servers and resources that comprises of the existing system. (as shown in the figure). &lt;strong&gt;Now when the existing system fails to meet the expected needs, and the expected needs cannot be met by just adding resources, we need to add completely new servers&lt;/strong&gt;. This is considered as horizontal scaling.&lt;br&gt;
Horizontal scaling is based on the idea of adding more machines into our pool of resources&lt;br&gt;
Horizontal scaling is difficult and also costlier than Vertical Scaling. It also requires more time to be fixed.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Difference between Horizontal and Vertical Scaling:&lt;/strong&gt; &lt;br&gt;
 &lt;strong&gt;Horizontal Scaling&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When new server racks are added in the existing system to meet the higher expectation, it is known as horizontal scaling.&lt;/li&gt;
&lt;li&gt;It expands the size of the existing system horizontally.&lt;/li&gt;
&lt;li&gt;It is easier to upgrade.&lt;/li&gt;
&lt;li&gt;It is difficult to implement&lt;/li&gt;
&lt;li&gt;It is costlier, as new server racks comprises of a lot of resources&lt;/li&gt;
&lt;li&gt;It takes more time to be done&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Vertical Scaling&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When new resources are added in the existing system to meet the expectation, it is known as vertical scaling&lt;/li&gt;
&lt;li&gt;It expands the size of the existing system vertically.&lt;/li&gt;
&lt;li&gt;It is harder to upgrade and may involve downtime.&lt;/li&gt;
&lt;li&gt;It is easy to implement&lt;/li&gt;
&lt;li&gt;It is cheaper as we need to just add new resources&lt;/li&gt;
&lt;li&gt;It takes less time to be done&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Design principles of Monolithic Architecture — KISS, YAGNI, DRY</title>
      <dc:creator>Dinh Vo</dc:creator>
      <pubDate>Tue, 06 Sep 2022 13:08:40 +0000</pubDate>
      <link>https://dev.to/dylanvo28/design-principles-of-monolithic-architecture-kiss-yagni-dry-1394</link>
      <guid>https://dev.to/dylanvo28/design-principles-of-monolithic-architecture-kiss-yagni-dry-1394</guid>
      <description>&lt;p&gt;In this part I'm going to see some example of Reference architectures for Monolithic Architectures.&lt;/p&gt;

&lt;p&gt;You can imagine that I'm building an e-commerce application that takes orders from customers, add to basket and checkout the order and so on.&lt;/p&gt;

&lt;p&gt;Lets see example Reference Monolithic Architectures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference Monolithic Architecture 1
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xo1Mfzh9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/azz76hg6dcyifzgqpjx7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xo1Mfzh9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/azz76hg6dcyifzgqpjx7.png" alt="Image description" width="875" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The application can include several components like GUI and business logics and database persistence layers. The application is deployed as a single monolithic application.  For example, a Java web application consists of a single WAR file that runs on a web container such as Tomcat. You can run multiple instances of the application behind a load balancer in order to scale and improve availability.&lt;br&gt;
As a result this solution has a number of benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple to develop — you develop in single code base&lt;/li&gt;
&lt;li&gt;Simple to deploy — you simply need to deploy only the WAR file&lt;/li&gt;
&lt;li&gt;Simple to scale — you can scale the application by running multiple copies of the application behind a load balancer&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reference Monolithic Architecture 2
&lt;/h2&gt;

&lt;p&gt;Here is, I can see different illustrations, again e-commerce application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JmA88ViM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5paqau225gdckq10t3l6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JmA88ViM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5paqau225gdckq10t3l6.png" alt="Image description" width="875" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Evolve Reference Monolithic Architectures**
&lt;/h2&gt;

&lt;p&gt;And the last one shows how to evolve monolithic architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uxZSsccS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8yxbf8611qttv6fksaea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uxZSsccS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8yxbf8611qttv6fksaea.png" alt="Image description" width="875" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see in this picture, the evolution of monolithic architecture. So its start with standalone 1 application server and database. After that I can split Client application, after that split the business logic and data access and last I split services components in monolithic application.&lt;/p&gt;

&lt;p&gt;So as you can see that I will also follow these example reference monolithic architectures and principles and design our own e-commerce application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design principles of Monolithic Architecture — KISS, YAGNI, DRY
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;DRY Principle&lt;/strong&gt;&lt;br&gt;
DRY is stands for “Don’t Repeat Yourself”&lt;br&gt;
&lt;em&gt;Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.&lt;/em&gt;&lt;br&gt;
This means that, you must try to maintain the behavior of a functionality of the system in a single piece of code, it should not have duplicated code or design item. It’s easier to maintain a code or system that is only in one place, because if you need to change something in the code or system, you just need to change in one place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;KISS Principle&lt;/strong&gt;&lt;br&gt;
KISS is stands for “Keep It Simple, Stupid”&lt;br&gt;
This principle says about to make your code or system simple. You should avoid unnecessary complexity. A simple code it’s easier to maintain and easier to understand. You can apply this principle in the design and in the implementation of the code. You should eliminate duplicated code, should remove unnecessary features, use names for apis and methods that makes sense and matches their responsibilities.&lt;/p&gt;

&lt;p&gt;You also should separate the responsibilities of your applications and the responsibilities from the layers of the systems. Most systems work best if they are kept simple rather than making them complex designs; therefore, simplicity should be a key goal in design and unnecessary complexity should be avoided.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;YAGNI Principle&lt;/strong&gt;&lt;br&gt;
YAGNI is stands for “You Ain’t Gonna Need It”.&lt;br&gt;
Sometimes, I try to think way ahead, into the future of the project, adding some extra features “just in case we need them”. This is Wrong! I don’t need it and in most of the case I can say YAGNI = “You Aren’t Gonna Need It”. This principle is similar to the KISS principle, both of them aim for a simpler solution. The difference between them is that YAGNI focus on removing unnecessary functionality and logic and KISS focus on the complexity.&lt;/p&gt;

&lt;p&gt;So with following these principles, I will start to design our e-commerce application architecture. Remember that a clean system, it’s easier to main, easier to understand and for sure it will save your time when you need to change or implement something.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design the Monolithic Architecture — E-Commerce App — KISS &amp;amp; YAGNI
&lt;/h2&gt;

&lt;p&gt;In this part I'm going to design our e-commerce application with the monolithic architecture step by step. I will iterate the architecture design one by one as per requirements.&lt;/p&gt;

&lt;p&gt;In every case, before we design the architecture, We should always start with writing down FRs and NFRs. So lets write down FRs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Functional Requirements&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;List products&lt;/li&gt;
&lt;li&gt;Filter products as per brand and categories&lt;/li&gt;
&lt;li&gt;Put products into the shopping cart&lt;/li&gt;
&lt;li&gt;Apply coupon for discounts and see the total cost all for all of the items in shopping cart&lt;/li&gt;
&lt;li&gt;Checkout the shopping cart and create an order&lt;/li&gt;
&lt;li&gt;List my old orders and order items history
Lets write down N-FR.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Non-Functional Requirements&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Availability&lt;/li&gt;
&lt;li&gt;Scalability
Its good to add principles in our picture in order to remember them always.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Principles&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DRY&lt;/li&gt;
&lt;li&gt;KISS&lt;/li&gt;
&lt;li&gt;YAGNI
We are going to consider these principles when design our architecture.
Now we can consider to Database and Components of e-commerce application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Database&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database will be single relational database — RDBMS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Components of E-Commerce&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shop UI&lt;/li&gt;
&lt;li&gt;Catalog Service&lt;/li&gt;
&lt;li&gt;SC Service&lt;/li&gt;
&lt;li&gt;Discount Service&lt;/li&gt;
&lt;li&gt;Order Service
With following all these considerations, we can design our E-Commerce Monolithic Architecture with applying tech stack as below image;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GJOCGsRS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/354sqk3jx6cugeactkmf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GJOCGsRS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/354sqk3jx6cugeactkmf.png" alt="Image description" width="880" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see that all modules of this traditional web application, such as Shop Front UI, Catalog Service, SC Service, Discount Service and Order Service, are single artifacts in the container.&lt;br&gt;
This monolithic application has a massive codebase that includes all modules. If you introduce new modules to this application, you have to make changes to the existing code and then deploy the artifact with a different code to the Tomcat server.  We can develop Java application and output to single WAR Artifact. We can use Oracle or PostgreSQL for our e-commerce monolithic database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Communication of Components — E-Commerce App — Monolithic Application — Inter-Process Communication&lt;/strong&gt;&lt;br&gt;
As you know that, monolithic application sitting in the same server with all modules.  So we don’t need to make any network call. So it is very easy and fast to communicate between modules of our E -Commerce Monolithic Application.&lt;br&gt;
The communication will be INTER-PROCESS COMMUNICATION.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6uteT6ws--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9stk41pvdtnx2o6dgnkj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6uteT6ws--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9stk41pvdtnx2o6dgnkj.png" alt="Image description" width="456" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inter-process communication is the mechanism provided by the operating system that allows processes to communicate with each other. So that means communication performs by method calls into the code.&lt;br&gt;
This communication could involve a process letting another process know that some event has occurred or transferring of data from one process to another. As you can see that we only use method calls for communication in monolithic architectures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transaction Management in Monolithic Architectures&lt;/strong&gt;&lt;br&gt;
Transaction management in Monolith architecture is quite easy compared to Microservice Architecture.  Many frameworks or languages contains some mechanism for transaction management. &lt;br&gt;
These mechanism have a single database of the whole application. They are developed for scenarios where all transactions are running on a single context. In other words, we can simply commit and rollback operations with these mechanism in monolith architectures.&lt;br&gt;
Lets think about our e-commerce domain, We have transactional use case when placing order.&lt;br&gt;
Lets see pseudo code fore place_order method&lt;br&gt;
&lt;code&gt;function place_order()&lt;br&gt;
 do_payment&lt;br&gt;
 decrease_stock&lt;br&gt;
 send_shipment&lt;br&gt;
 generate_bill&lt;br&gt;
 update_order&lt;/code&gt;&lt;br&gt;
As you can see that we can handle all operations into one method and surround operation in a transactional scope.&lt;br&gt;
By this way, Transactions operated in the transaction scope are kept in memory without writing to the database until they are committed, and if a Rollback is made at any time, all transactions that have been processed so far in the scope are deleted from memory and the transaction is canceled. Without rollback, when Commit is written to the database, the transaction is completed successfully.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Monolith and Microservices Architecture</title>
      <dc:creator>Dinh Vo</dc:creator>
      <pubDate>Mon, 05 Sep 2022 15:31:27 +0000</pubDate>
      <link>https://dev.to/dylanvo28/monolith-and-microservices-architecture-3gcj</link>
      <guid>https://dev.to/dylanvo28/monolith-and-microservices-architecture-3gcj</guid>
      <description>&lt;h2&gt;
  
  
  Monolithic architecture
&lt;/h2&gt;

&lt;p&gt;In software engineering, a monolithic pattern refers to a single indivisible unit. The concept of monolithic software lies in different components of an application being combined into a single program on a single platform. Usually, a monolithic app consists of a database, client-side user interface, and server-side application. All the software’s parts are unified and all its functions are managed in one place. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BrwKea3i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/779bfyxcdi9txlu4w31j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BrwKea3i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/779bfyxcdi9txlu4w31j.png" alt="Image description" width="701" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Сomponents of monolithic software are interconnected and interdependent, which helps the software be self-contained. I believe that a monolithic architecture is a perfect solution in some circumstances.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pros of a monolithic architecture
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Simpler development and deployment&lt;/strong&gt;&lt;br&gt;
 In addition, all actions are performed with one directory, which provides for easier deployment. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fewer cross-cutting concerns&lt;/strong&gt;&lt;br&gt;
It’s easier to hook up components to these concerns when everything runs in the same app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better performance&lt;/strong&gt;&lt;br&gt;
If built properly, monolithic apps are usually more performant than microservice-based apps. An app with a microservices architecture might need to make 40 API calls to 40 different microservices to load each screen, for example, which obviously results in slower performance.  Monolithic apps, in turn, allow faster communication between software components due to shared code and memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cons of a monolithic architecture
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Codebase gets cumbersome over time&lt;/strong&gt;&lt;br&gt;
In the course of time, most products develop and increase in scope, and their structure becomes blurred. The code base starts to look really massive and becomes difficult to understand and modify, especially for new developers.  It also gets harder to find side effects and dependencies. With a growing code base quality declines and the integrated development environment (IDE) gets overloaded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Difficult to adopt new technologies&lt;/strong&gt;&lt;br&gt;
Adding new technology means rewriting the whole application, which is costly and time-consuming.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limited agility&lt;/strong&gt;&lt;br&gt;
In monolithic apps, every small update requires a full redeployment. Thus, all developers have to wait until it’s done.  When several teams are working on the same project, agility can be reduced greatly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;Monolithic software architecture can be beneficial if your team is at the founding stage, you’re building an unproven product, and you have no experience with microservices. Monolithic is perfect for startups that need to get a product up and running as soon as possible. However, certain issues mentioned above come with the monolithic package.&lt;/p&gt;

&lt;h2&gt;
  
  
  Microservice architecture
&lt;/h2&gt;

&lt;p&gt;Microservice is a type of service-oriented software architecture that focuses on building a series of autonomous components that make up an app. Unlike monolithic apps built as a single indivisible unit, microservice apps consist of multiple independent components that are glued together with APIs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--82id0GQL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/za7c31041xvimddadi8d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--82id0GQL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/za7c31041xvimddadi8d.png" alt="Image description" width="701" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Microservices are important simply because they add unique value in a way of simplification of complexity in systems. By breaking apart your system or application into many smaller parts, you show ways of reducing duplication, increasing cohesion and lowering your coupling between parts, thus making your overall system parts easier to understand, more scalable, and easier to change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pros of microservices
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Easy to develop, test, and deploy&lt;/strong&gt;&lt;br&gt;
The biggest advantage of microservices over other architectures is that small single services can be built, tested, and deployed independently. Since a deployment unit is small, it facilitates and speeds up development and release. The last plus here is that the risks of deployment are reduced as developers deploy parts of the software, not the whole app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Increased agility&lt;/strong&gt;&lt;br&gt;
With microservices, several teams can work on their services independently and quickly. Each individual part of an application can be built independently due to the decoupling of microservice components. For example, you may have a team of 100 people working on the whole app (like in the monolithic approach), or you can have 10 teams of 10 people developing different services for the app. Let’s imagine this visually.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AfypU0mv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t72zca5gy55911abv1wb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AfypU0mv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t72zca5gy55911abv1wb.png" alt="Image description" width="701" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Increased agility allows developers to update system components without bringing down the application. Moreover, agility provides a safer deployment process and improved uptime. New features can be added as needed without waiting for the entire app to launch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ability to scale horizontally&lt;/strong&gt;&lt;br&gt;
Vertical scaling (running the same software but on bigger machines) can be limited by the capacity of each service. But horizontal scaling (creating more services in the same pool) isn’t limited and can run dynamically with microservices. Furthermore, horizontal scaling can be completely automated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cons of microservices
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Complexity&lt;/strong&gt;&lt;br&gt;
Splitting an application into independent microservices entails more artifacts to manage. This type of architecture requires careful planning, enormous effort, team resources, and skills. The reasons for high complexity are the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increased demand for automation, as every service should be tested and monitored&lt;/li&gt;
&lt;li&gt;Available tools don’t work with service dependencies&lt;/li&gt;
&lt;li&gt;Data consistency and transaction management becomes harder as each service has a database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security concerns&lt;/strong&gt;&lt;br&gt;
In a microservices application, each functionality that communicates externally via an API increases the chance of attacks.  These attacks can happen only if proper security measurements aren’t implemented when building an app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Different programming languages&lt;/strong&gt;&lt;br&gt;
The ability to choose different programming languages is two sides of the same coin. Using different languages make deployment more difficult.  In addition, it’s harder to switch programmers between development phases when each service is written in a different language.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;Microservices are good, but not for all types of apps. This pattern works great for evolving applications and complex systems.  Consider choosing a microservices architecture when you have multiple experienced teams and when the app is complex enough to break it into services. When an application is large and needs to be flexible and scalable, microservices are beneficial.&lt;/p&gt;

&lt;p&gt;Monolithic apps consist of interdependent, indivisible units and feature very low development speed. Microservices are very small, loosely coupled independent services and feature rapid continuous development.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Binary search tree (BST) - Insertion</title>
      <dc:creator>Dinh Vo</dc:creator>
      <pubDate>Tue, 09 Aug 2022 15:20:00 +0000</pubDate>
      <link>https://dev.to/dylanvo28/binary-search-tree-bst--2hp8</link>
      <guid>https://dev.to/dylanvo28/binary-search-tree-bst--2hp8</guid>
      <description>&lt;p&gt;&lt;strong&gt;Để insert một node vào BST, chúng ta cần tuân thủ 4 quy tắc sau:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Các node mới luôn được chèn vào leaf node.&lt;/li&gt;
&lt;li&gt;Bắt đầu từ node root và gọi đệ quy cho đến khi pointer left, hoặc right == null.&lt;/li&gt;
&lt;li&gt;Nếu value của node hiện tại nhỏ hơn value của node mới, thì chuyển sang node bên phải của node hiện tại, còn lại chuyển sang node bên trái.&lt;/li&gt;
&lt;li&gt;Nếu node hiện tại là null, hãy insert node mới đó bằng cách gán node hiện tại = node mới
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script&amp;gt;

// javascript program to demonstrate insert 
// operation in binary search tree
// BST node
class Node
{
    constructor()
    {
        this.key = 0;
        this.left = null;
        this.right = null;
    }
};

// Utility function to create a new node
function newNode(data)
{
    var temp = new Node();
    temp.key = data;
    temp.left = null;
    temp.right = null;
    return temp;
}

// A utility function to insert a new
// Node with given key in BST
function insert(root, key)
{

    // Create a new Node containing
    // the new element
    var newnode = newNode(key);

    // Pointer to start traversing from root and
    // traverses downward path to search
    // where the new node to be inserted
    var x = root;

    // Pointer y maintains the trailing
    // pointer of x
    var y = null;

    while (x != null)
    {
        y = x;
        if (key &amp;lt; x.key)
            x = x.left;
        else
            x = x.right;
    }

    // If the root is null i.e the tree is empty
    // The new node is the root node
    if (y == null)
        y = newnode;

    // If the new key is less than the leaf node key
    // Assign the new node to be its left child
    else if (key &amp;lt; y.key)
        y.left = newnode;

    // else assign the new node its right child
    else
        y.right = newnode;

    // Returns the pointer where the
    // new node is inserted
    return y;
}

// A utility function to do inorder
// traversal of BST
function Inorder(root)
{
    if (root == null)
        return;
    else
    {
        Inorder(root.left);
        document.write( root.key +" ");
        Inorder(root.right);
    }
}

// Driver code
/* Let us create following BST
        50
    / \
    30 70
    / \ / \
20 40 60 80 */
var root = null;
root = insert(root, 50);
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 80);
// Print inorder traversal of the BST
Inorder(root);

// This code is contributed by itsok.
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;20 30 40 50 60 70 80&lt;/code&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Cách sử dụng useMemo()</title>
      <dc:creator>Dinh Vo</dc:creator>
      <pubDate>Wed, 03 Aug 2022 13:32:00 +0000</pubDate>
      <link>https://dev.to/dylanvo28/cach-su-dung-usememo-276l</link>
      <guid>https://dev.to/dylanvo28/cach-su-dung-usememo-276l</guid>
      <description>&lt;p&gt;useMemo() được build bởi React hook và chấp nhận 2 argument- một function và mảng dependencies.&lt;br&gt;
&lt;code&gt;const memoizedResult = useMemo(compute, dependencies);&lt;/code&gt;&lt;br&gt;
Trong quá trình render lần đầu, &lt;code&gt;useMemo(compute,dependencies)&lt;/code&gt; ngay lập tức gọi &lt;code&gt;compute&lt;/code&gt;, ghi nhớ value đã return cho vào memorizes, và trả về component.&lt;br&gt;
Nếu trong suốt quá trình renderings, các dependencies không thay đổi, &lt;code&gt;useMemo()&lt;/code&gt; không gọi &lt;code&gt;compute&lt;/code&gt; mà return memorized value.&lt;br&gt;
Nhưng nếu các dependencies thay đổi trong quá trình re-rendering, &lt;code&gt;useMemo()&lt;/code&gt; sẽ gọi &lt;code&gt;compute&lt;/code&gt;, nó sẽ update một value mới vào memorizes, và trả về value đó.&lt;br&gt;
&lt;strong&gt;Ví dụ useMemo()&lt;/strong&gt;&lt;br&gt;
Một component  nhằm tính giai thừa của một số.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react';
export function CalculateFactorial() {
  const [number, setNumber] = useState(1);
  const [inc, setInc] = useState(0);
  const factorial = factorialOf(number);
  const onChange = event =&amp;gt; {
    setNumber(Number(event.target.value));
  };
  const onClick = () =&amp;gt; setInc(i =&amp;gt; i + 1);

  return (
    &amp;lt;div&amp;gt;
      Factorial of 
      &amp;lt;input type="number" value={number} onChange={onChange} /&amp;gt;
      is {factorial}
      &amp;lt;button onClick={onClick}&amp;gt;Re-render&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
function factorialOf(n) {
  console.log('factorialOf(n) called!');
  return n &amp;lt;= 0 ? 1 : n * factorialOf(n - 1);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mỗi khi bạn thay đổi giá trị input, &lt;code&gt;factorialOf(n)&lt;/code&gt; và &lt;code&gt;factorialOf(n)&lt;/code&gt; được gọi.&lt;br&gt;
Ben cạnh đó, mỗi lần bạn nhấn re-render, set state &lt;code&gt;inc&lt;/code&gt; sẽ được update và component &lt;code&gt;&amp;lt;CalculateFactorial/&amp;gt;&lt;/code&gt; sẽ được re-rendering. Nhưng, trong lần render thứ 2, &lt;code&gt;factorialOf(n)&lt;/code&gt; được gọi lại lần nữa.&lt;br&gt;
Vậy làm thế nào có thể ghi nhớ &lt;code&gt;factorial&lt;/code&gt; khi componnent re-renders? &lt;br&gt;
Bằng cách sử dụng &lt;code&gt;useMemo(()=&amp;gt;factorialOf(number),[number])&lt;/code&gt; thay vì đơn giản &lt;code&gt;factorialOf(number)&lt;/code&gt;, React sẽ ghi nhớ &lt;code&gt;factorial&lt;/code&gt;&lt;br&gt;
Ví dụ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useMemo } from 'react';
export function CalculateFactorial() {
  const [number, setNumber] = useState(1);
  const [inc, setInc] = useState(0);
  const factorial = useMemo(() =&amp;gt; factorialOf(number), [number]);
  const onChange = event =&amp;gt; {
    setNumber(Number(event.target.value));
  };
  const onClick = () =&amp;gt; setInc(i =&amp;gt; i + 1);

  return (
    &amp;lt;div&amp;gt;
      Factorial of 
      &amp;lt;input type="number" value={number} onChange={onChange} /&amp;gt;
      is {factorial}
      &amp;lt;button onClick={onClick}&amp;gt;Re-render&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
function factorialOf(n) {
  console.log('factorialOf(n) called!');
  return n &amp;lt;= 0 ? 1 : n * factorialOf(n - 1);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mỗi lần ấn button &lt;code&gt;Re-render&lt;/code&gt;,  &lt;code&gt;factorial(n)&lt;/code&gt; không được in ra màn hình console bởi vì &lt;code&gt;useMemo&lt;/code&gt; returns memorized của &lt;code&gt;factorial&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Kết luận&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;useMemo(()=&amp;gt;computation(a,b),[a,b])&lt;/code&gt; cho phép bạn ghi nhớ các phép tính lưu vào vùng nhớ memorize. Với các dependencies [a,b] giống nhau, hook sẽ trả về memorized value mà không cần gọi computation(a,b)&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Proxy Pattern trong Javascript</title>
      <dc:creator>Dinh Vo</dc:creator>
      <pubDate>Sat, 30 Jul 2022 17:38:14 +0000</pubDate>
      <link>https://dev.to/dylanvo28/proxy-pattern-trong-javascript-135l</link>
      <guid>https://dev.to/dylanvo28/proxy-pattern-trong-javascript-135l</guid>
      <description>&lt;p&gt;Với một Proxy object, chúng ta có quyền kiểm soát các tương tác với một object nhất định, ví dụ: getting một value hoặc setting một value.&lt;/p&gt;

&lt;p&gt;Hãy tạo một object &lt;code&gt;person&lt;/code&gt;, đại diện là John Doe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thay vì tương tác trực tiếp với object này, tôi muốn tương tác với một &lt;code&gt;proxy object&lt;/code&gt;. Trong javascript, tôi có thể tạo một proxy bằng cách sử dụng từ khóa &lt;code&gt;new Proxy&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

const personProxy = new Proxy(person, {});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Argument thứ 2 của proxy là một object đại diện được gọi là &lt;code&gt;handler&lt;/code&gt;. Trong handler object, tôi có thể xác định các hành vi cụ thể dựa trên loại tương tác. Mặc dù có nhiều methods mà tôi có thể thêm vào Proxy handler, 2 method phổ biến nhất là &lt;code&gt;get&lt;/code&gt; và &lt;code&gt;set&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;get&lt;/code&gt;: được gọi khi cố gắng access một property&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;set&lt;/code&gt; được gọi khi muốn modify một property
Quy trình sẽ xảy ra như xau:
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1cQQPcNX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qa83j4abxlrkm66ci1x4.png" alt="Image description" width="880" height="370"&gt;
Thay vì tương tác trực tiếp với object person, tôi sẽ tương tác với &lt;code&gt;personProxy&lt;/code&gt;.
Hãy thêm các handlers vào proxyHandler. Khi muốn modify một property, do đó gọi method &lt;code&gt;set&lt;/code&gt;  trên proxy, tôi muốn proxy in value cũ và value mới, sau đó thực hiện ghi đè value của property.
Khi cố gắng access một property, hãy gọi method &lt;code&gt;get&lt;/code&gt; trên Proxy, tôi muốn proxy ghi lại một  contains chứa key và value của property.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const personProxy = new Proxy(person, {
  get: (obj, prop) =&amp;gt; {
    console.log(`The value of ${prop} is ${obj[prop]}`);
  },
  set: (obj, prop, value) =&amp;gt; {
    console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
    obj[prop] = value;
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tuyệt hãy xem đoạn code dưới dây, điều gì sẽ xảy ra?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

const personProxy = new Proxy(person, {
  get: (obj, prop) =&amp;gt; {
    console.log(`The value of ${prop} is ${obj[prop]}`);
  },
  set: (obj, prop, value) =&amp;gt; {
    console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
    obj[prop] = value;
    return true;
  }
});

personProxy.name; //The value of name is John Doe 
personProxy.age = 43; //Changed age from 42 to 43 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Khi access &lt;code&gt;name&lt;/code&gt;, proxy trả về một câu: &lt;code&gt;The value of name is John Doe&lt;/code&gt;&lt;br&gt;
khi modify &lt;code&gt;age&lt;/code&gt;, proxy in &lt;code&gt;Changed age from 42 to 43&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Ngoài ra có thể bắt các validation của method proxy&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const personProxy = new Proxy(person, {
  get: (obj, prop) =&amp;gt; {
    if (!obj[prop]) {
      console.log(
        `Hmm.. this property doesn't seem to exist on the target object`
      );
    } else {
      console.log(`The value of ${prop} is ${obj[prop]}`);
    }
  },
  set: (obj, prop, value) =&amp;gt; {
    if (prop === "age" &amp;amp;&amp;amp; typeof value !== "number") {
      console.log(`Sorry, you can only pass numeric values for age.`);
    } else if (prop === "name" &amp;amp;&amp;amp; value.length &amp;lt; 2) {
      console.log(`You need to provide a valid name.`);
    } else {
      console.log(`Changed ${prop} from ${obj[prop]} to ${value}.`);
      obj[prop] = value;
    }
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hãy xem đoạn code dưới dây, điều gì sẽ xảy ra?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

const personProxy = new Proxy(person, {
  get: (obj, prop) =&amp;gt; {
    if (!obj[prop]) {
      console.log(`Hmm.. this property doesn't seem to exist`);
    } else {
      console.log(`The value of ${prop} is ${obj[prop]}`);
    }
  },
  set: (obj, prop, value) =&amp;gt; {
    if (prop === "age" &amp;amp;&amp;amp; typeof value !== "number") {
      console.log(`Sorry, you can only pass numeric values for age.`);
    } else if (prop === "name" &amp;amp;&amp;amp; value.length &amp;lt; 2) {
      console.log(`You need to provide a valid name.`);
    } else {
      console.log(`Changed ${prop} from ${obj[prop]} to ${value}.`);
      obj[prop] = value;
    }
    return true;
  }
});

personProxy.nonExistentProperty; //Hmm.. this property doesn't seem to exist
personProxy.age = "44"; //Sorry, you can only pass numeric values for age. 
personProxy.name = ""; //You need to provide a valid name. 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Proxy made sure tôi không sủa đổi object person với các value không hợp lệ, điều này giúp tôi giữ cho dữ liệu của tôi tinh khiết(data pure)&lt;br&gt;
&lt;strong&gt;Reflect&lt;/strong&gt;&lt;br&gt;
Js cung cấp một object gọi là &lt;code&gt;Reflect&lt;/code&gt;, giúp tôi thao tác với đối tượng đích dễ dàng hơn khi làm việc với proxy.&lt;br&gt;
Trước đây, tôi muốn modify và acces property trên một object bên trong proxy thông qua &lt;code&gt;get&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt; bằng ky hiệu {}. Thay vào đó, tôi có thể sử dụng Reflect. Methods trên Reflect có cùng tên với các methods trên object đang xử lý.&lt;br&gt;
Thay vì access property thông qua &lt;code&gt;obj[prop]&lt;/code&gt;, tôi có thể access hoặc modify property thông qua &lt;code&gt;Reflect.get()&lt;/code&gt; và &lt;code&gt;Reflect.set()&lt;/code&gt;. Các methods nhận các arguments dưới dạng methods trên handle obejct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const personProxy = new Proxy(person, {
  get: (obj, prop) =&amp;gt; {
    console.log(`The value of ${prop} is ${Reflect.get(obj, prop)}`);
  },
  set: (obj, prop, value) =&amp;gt; {
    console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
    Reflect.set(obj, prop, value);
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hãy xem đoạn code dưới dây:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

const personProxy = new Proxy(person, {
  get: (obj, prop) =&amp;gt; {
    console.log(`The value of ${prop} is ${Reflect.get(obj, prop)}`);
  },
  set: (obj, prop, value) =&amp;gt; {
    console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
    return Reflect.set(obj, prop, value);
  }
});

personProxy.name; //The value of name is John Doe 
personProxy.age = 43; //The value of name is John Doe 
personProxy.name = "Jane Doe"; //The value of name is John Doe 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Proxy là một cách hiệu quả để control các behavior của một object. Một proxy có thể có nhiều use-cases: nó giúp validation, formatting, notifications, hoặc debugging.&lt;br&gt;
Việc lạm dụng proxy hoặc thực hiện các thao tác nặng trên mỗi handler method có thể ảnh hưởng đến performance của app. &lt;strong&gt;Tốt nhất cũng không nên sử dụng proxy cho các đoạn code quan trọng về hiệu suất.&lt;/strong&gt;&lt;/p&gt;

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