<?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: Uzodufa Ebere</title>
    <description>The latest articles on DEV Community by Uzodufa Ebere (@ebereuzodufa).</description>
    <link>https://dev.to/ebereuzodufa</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%2F99888%2F84071d0f-bd5a-49f7-af6c-129b0120f68c.png</url>
      <title>DEV Community: Uzodufa Ebere</title>
      <link>https://dev.to/ebereuzodufa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ebereuzodufa"/>
    <language>en</language>
    <item>
      <title>Understanding the Unit of Work Pattern in NestJS</title>
      <dc:creator>Uzodufa Ebere</dc:creator>
      <pubDate>Fri, 17 Jan 2025 15:51:56 +0000</pubDate>
      <link>https://dev.to/ebereuzodufa/understanding-the-unit-of-work-pattern-in-nestjs-56m5</link>
      <guid>https://dev.to/ebereuzodufa/understanding-the-unit-of-work-pattern-in-nestjs-56m5</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Unit of Work&lt;/strong&gt; is a behavioral design pattern that helps manage complex transactions and maintain data consistency. It ensures that a set of changes to your data is treated as a single unit, and either all changes are successfully applied or none are. This is especially critical in enterprise applications, where multiple operations on different data sources need to be coordinated and committed atomically.&lt;/p&gt;

&lt;p&gt;Design patterns provide reusable solutions to common software design problems. They promote code organization, readability, and scalability, enabling developers to write maintainable and efficient systems.&lt;/p&gt;

&lt;p&gt;This article will guide you through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding the Unit of Work pattern.&lt;/li&gt;
&lt;li&gt;Implementing UoW in a NestJS application.&lt;/li&gt;
&lt;li&gt;Using a practical example to demonstrate the concept.&lt;/li&gt;
&lt;li&gt;Practical considerations and challenges for real-world usage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What is the Unit of Work Pattern?
&lt;/h3&gt;

&lt;p&gt;At its core, the Unit of Work pattern manages changes to your data as a single transaction. It helps track entities that need to be inserted, updated, or deleted and coordinates changes to ensure consistency and manage transactions efficiently.&lt;/p&gt;

&lt;p&gt;In simpler terms, we can think of a Unit of Work as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A "to-do list" for your database operations.&lt;/li&gt;
&lt;li&gt;A means to track all the actions (e.g., inserts, updates, deletes) you want to perform and ensure they are all applied together or none at all.&lt;/li&gt;
&lt;li&gt;A process to handle operation to the DB if something goes wrong during execution, the Unit of Work rolls back all changes to prevent partial updates and maintain data integrity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Imagine you’re booking a flight ticket for a travel. You first select the flight going to your destination from your current location. Then you pick a seat after which you make payment. These steps are interdependent. If the payment fails, you wouldn’t want the flight to be booked without incomplete details or payment confirmation.&lt;br&gt;
The Unit of Work ensures that all these steps are treated as one atomic operation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If all steps succeed, the booking is confirmed.&lt;/li&gt;
&lt;li&gt;If any step fails, the entire process is canceled.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Why Use the Unit of Work Pattern?
&lt;/h3&gt;

&lt;p&gt;The UoW pattern reduces complexity by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consolidating multiple database operations into a single transaction.&lt;/li&gt;
&lt;li&gt;Preventing partial updates that can lead to data corruption.&lt;/li&gt;
&lt;li&gt;Decoupling transaction management from business logic.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  When to Use the Unit of Work Pattern
&lt;/h3&gt;

&lt;p&gt;The UoW pattern is beneficial in scenarios where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple entities are updated as part of a single operation.&lt;/li&gt;
&lt;li&gt;Transaction consistency is critical.&lt;/li&gt;
&lt;li&gt;You want to centralize transaction management for better maintainability.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Practical Example: Flight Booking System
&lt;/h3&gt;

&lt;p&gt;Let’s use a &lt;strong&gt;Flight Booking System&lt;/strong&gt; as an example. The system involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Booking flight details.&lt;/li&gt;
&lt;li&gt;Saving passenger information.&lt;/li&gt;
&lt;li&gt;Processing payments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these operations should either succeed together or fail together.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Note that the examples provided in this article are simplified to explain the design process and core concepts of the Unit of Work pattern. In real-life scenarios, the service and architecture would require further expansion and adjustments to handle edge cases, scalability, and maintainability in production environments.&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Without Unit of Work
&lt;/h3&gt;

&lt;p&gt;In this approach, each database operation is handled independently, without transaction management.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FlightBookingService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;InjectRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;FlightBookingRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;flightBookingRepository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FlightBookingRepository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;InjectRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PassengerRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;passengerRepository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PassengerRepository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;InjectRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PaymentRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;paymentRepository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PaymentRepository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;bookFlightWithoutUoW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;bookingData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FlightBooking&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;passengerData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Passenger&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;paymentData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FlightBooking&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Step 1: Reserve the flight&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;booking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;flightBookingRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bookingData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Step 2: Save passenger details&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;passenger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;passengerData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;booking&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;passengerRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;passenger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Step 3: Process payment&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;paymentData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;booking&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;booking&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error during booking:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Problems Without Unit of Work
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Atomicity:&lt;/strong&gt; If payment saving fails, the flight booking and passenger details are still saved, leaving the database in an inconsistent state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error Handling Complexity:&lt;/strong&gt; You would need to implement manual rollback logic for each step, which is error-prone and repetitive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scattered Transaction Logic:&lt;/strong&gt; Each repository call handles its operations separately, leading to duplication and harder maintainability.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  With Unit of Work
&lt;/h3&gt;

&lt;p&gt;Using the Unit of Work pattern, all operations are wrapped in a transaction, ensuring that they succeed or fail together.&lt;/p&gt;

&lt;p&gt;First, we implement our unit of work service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DataSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryRunner&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typeorm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UnitOfWork&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;queryRunner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;QueryRunner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;dataSource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DataSource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryRunner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createQueryRunner&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;startTransaction&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryRunner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryRunner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;commitTransaction&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryRunner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commitTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;rollbackTransaction&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryRunner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rollbackTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryRunner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getManager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryRunner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
Then, we apply it to the flight booking service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FlightBookingService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;unitOfWork&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UnitOfWork&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;bookFlightWithUoW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;bookingData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FlightBooking&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;passengerData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Passenger&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;paymentData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FlightBooking&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unitOfWork&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Step 1: Reserve the flight&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;booking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unitOfWork&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getManager&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;FlightBooking&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bookingData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Step 2: Save passenger details&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;passenger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;passengerData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;booking&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unitOfWork&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getManager&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Passenger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;passenger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Step 3: Process payment&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;paymentData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;booking&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unitOfWork&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getManager&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Commit the transaction&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unitOfWork&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commitTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;booking&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Rollback the transaction if anything fails&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unitOfWork&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rollbackTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Flight booking failed: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Release the transaction resources&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unitOfWork&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing the codes. Below are examples for both "without" and "with" Unit of Work approaches.&lt;/p&gt;

&lt;p&gt;Testing Without Unit of Work&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should book a flight without unit of work&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bookingData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;flightNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FL123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;departureDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;savedBooking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;bookingData&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;bookingRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;mockResolvedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;savedBooking&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bookFlightWithoutUoW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bookingData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;savedBooking&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bookingRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bookingData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing With Unit of Work&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should book a flight with unit of work&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bookingData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;flightNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FL123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;departureDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;savedBooking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;bookingData&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockSave&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;unitOfWork&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getManager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;mockReturnValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mockSave&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;mockSave&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockResolvedValueOnce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;savedBooking&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bookFlightWithUoW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bookingData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;savedBooking&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unitOfWork&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startTransaction&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unitOfWork&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;commitTransaction&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Benefits of Using Unit of Work
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Atomicity:&lt;/strong&gt; All operations are treated as a single unit. If any step fails, all previous changes are rolled back automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consistency:&lt;/strong&gt; The database remains in a consistent state, even in case of errors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplified Error Handling:&lt;/strong&gt; No need to manually undo changes; the Unit of Work ensures the rollback of all operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reusability:&lt;/strong&gt; The Unit of Work service can be reused across different parts of the application, reducing boilerplate code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Practical Considerations for Real-World Applications
&lt;/h3&gt;

&lt;p&gt;When implementing the UoW pattern in real-world applications, keep these points in mind:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling:&lt;/strong&gt; Design robust error handling mechanisms to ensure transactions are rolled back properly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; Consider how transactions impact performance, especially in high-concurrency environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Framework-Specific Features:&lt;/strong&gt; Leverage features like TypeORM’s Transaction decorator for simple use cases.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Trade-Offs and Considerations
&lt;/h3&gt;

&lt;p&gt;While the Unit of Work pattern offers significant benefits, it’s not without challenges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Performance Overhead: Managing multiple entities in memory can impact performance.&lt;/li&gt;
&lt;li&gt;Scalability: Distributed transactions spanning multiple services require additional complexity.&lt;/li&gt;
&lt;li&gt;Error Handling: Designing robust error recovery mechanisms is essential for production systems.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;p&gt;Key Takeaways&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Unit of Work pattern simplifies transaction management and ensures consistency.&lt;/li&gt;
&lt;li&gt;It centralizes logic for committing or rolling back changes, reducing the risk of partial updates.&lt;/li&gt;
&lt;li&gt;Implementing the UoW pattern in NestJS can streamline database operations and improve maintainability.&lt;/li&gt;
&lt;li&gt;Real-world implementations require additional attention to scalability, error handling, and performance.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By adopting the Unit of Work pattern, you can build applications that are robust, maintainable, and resilient to failure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/EbereUzodufa/learn-book/tree/main/understanding-the-unit-of-work-pattern-in-nestjs" rel="noopener noreferrer"&gt;View the code on Github&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Creating Dynamic Review Rating Displays with Font Awesome and Class Attribute in Angular.</title>
      <dc:creator>Uzodufa Ebere</dc:creator>
      <pubDate>Sat, 29 Feb 2020 22:37:35 +0000</pubDate>
      <link>https://dev.to/ebereuzodufa/creating-dynamic-review-rating-displays-with-font-awesome-and-class-attribute-in-angular-32ac</link>
      <guid>https://dev.to/ebereuzodufa/creating-dynamic-review-rating-displays-with-font-awesome-and-class-attribute-in-angular-32ac</guid>
      <description>&lt;p&gt;This article shows a simple and efficient way to create review ratings for stores and products using font awesome icons, and class attribute in Angular.&lt;/p&gt;

&lt;p&gt;Font Awesome Icon provides us with amazing icons that are very performant for frontend development. The icons provide accessibility supports.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;p&gt;It is assumed that you have a basic understanding of Angular and how to place font awesome CDN link in a website - that is adding the link to the head of the HTML code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create an angular app using the &lt;a href="https://angular.io/guide/setup-local#step-1-install-the-angular-cli"&gt;Angular CLI&lt;/a&gt;. Run &lt;code&gt;ng new my-app-name&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the &lt;a href="https://fontawesome.com/how-to-use/on-the-web/referencing-icons/basic-use"&gt;Font-Awesome CDN link&lt;/a&gt; to the head of &lt;code&gt;index.html&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the &lt;code&gt;app.component.html&lt;/code&gt;, add the following code to add a div for the reviews&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"review"&lt;/span&gt; &lt;span class="na"&gt;*ngFor=&lt;/span&gt;&lt;span class="s"&gt;"let review of reviews"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"review-rating"&lt;/span&gt; &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"review.rating"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!--This is were we perform the magic--&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"review-summary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ review?.reviewSummary }}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"review-feedback"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ review?.reviewMessage }}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"reviewBy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"review-date"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ (review?.reviewDate ?  review?.reviewDate : 1581470956443) | date}}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    by
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"review-author"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ review?.name }}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, let you look at the logic - magic.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Logic
&lt;/h2&gt;

&lt;p&gt;Font Awesome has a regular (&lt;code&gt;far&lt;/code&gt;) and solid (&lt;code&gt;fas&lt;/code&gt;) category of icons. The regular has outlines while the solid is completely filled. We want the solid star to represent a point and the regular star to represent zero points. We also want to represent half-point for points greater than zero but less than one. We can use solid half-star.&lt;/p&gt;

&lt;p&gt;We have 5 stars to represent each of the ratings - let us call these stars &lt;code&gt;Rep-Stars&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;First Rep-Star&lt;/strong&gt; - This is used to represent rating(&lt;code&gt;r&lt;/code&gt;) for &lt;code&gt;r = 0&lt;/code&gt;, &lt;code&gt;0 &amp;lt; r &amp;lt; 1&lt;/code&gt;, and &lt;code&gt;r &amp;gt;= 1&lt;/code&gt;. This means if the rating is 0, use a regular star icon. Else if the rating is greater than 0 but less than 1, use the solid half-star icon. Else, the rating is 1 or greater than 1, then use the solid star.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Second Rep-Star&lt;/strong&gt; - with rating still as &lt;code&gt;r&lt;/code&gt;, we represent &lt;code&gt;1 &amp;lt; r &amp;lt; 2&lt;/code&gt;, &lt;code&gt;r &amp;gt;= 2&lt;/code&gt; and &lt;code&gt;r &amp;lt;= 1&lt;/code&gt; - &lt;em&gt;which means &lt;code&gt;r&lt;/code&gt; was never greater than the previous rep-star maximum rating&lt;/em&gt;. This means if the rating is 1, use a regular star icon. Else if the rating is greater than 1 but less than 2, use the solid half-star icon. Else, the rating is 2 or greater than 2, then use the solid star.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Third Rep-Star&lt;/strong&gt; - with rating still as &lt;code&gt;r&lt;/code&gt;, we represent &lt;code&gt;2 &amp;lt; r &amp;lt; 3&lt;/code&gt;, &lt;code&gt;r &amp;gt;= 3&lt;/code&gt; and &lt;code&gt;r &amp;lt;= 2&lt;/code&gt;. Similar to the second rep-star, if the rating is 2, use a regular star icon. Else if the rating is greater than 2 but less than 3, use the solid half-star icon. Else, the rating is 3 or greater than 3, then use the solid star.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same process if applied for &lt;strong&gt;Four Rep-Star&lt;/strong&gt; and &lt;strong&gt;Five Rep-Star&lt;/strong&gt;. This logic can be applied to 10 and more stars.&lt;/p&gt;

&lt;p&gt;Binding this logic to the &lt;code&gt;class attribute&lt;/code&gt;, we have&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"review-rating"&lt;/span&gt; &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"review.rating"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- 1 star  --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"(review.rating == 0) ? 'far fa-star' : (review.rating &amp;gt; 0 &amp;amp;&amp;amp; review.rating &amp;lt; 1) ? 'fas fa-star-half-alt' : 'fas fa-star'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- 2 star  --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"(review.rating &amp;gt; 1 &amp;amp;&amp;amp; review.rating &amp;lt; 2) ? 'fas fa-star-half-alt' : (review.rating &amp;gt;= 2) ? 'fas fa-star' : 'far fa-star'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- 3 star  --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"(review.rating &amp;gt; 2 &amp;amp;&amp;amp; review.rating &amp;lt; 3) ? 'fas fa-star-half-alt' : (review.rating &amp;gt;= 3) ? 'fas fa-star' : 'far fa-star'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- 4 star  --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"(review.rating &amp;gt; 3 &amp;amp;&amp;amp; review.rating &amp;lt; 4) ? 'fas fa-star-half-alt' : (review.rating &amp;gt;= 4) ? 'fas fa-star' : 'far fa-star'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- 5 star  --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"(review.rating &amp;gt; 4 &amp;amp;&amp;amp; review.rating &amp;lt; 5) ? 'fas fa-star-half-alt' : (review.rating &amp;gt;= 5) ? 'fas fa-star' : 'far fa-star'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt; 
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The complete code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"review"&lt;/span&gt; &lt;span class="na"&gt;*ngFor=&lt;/span&gt;&lt;span class="s"&gt;"let review of reviews"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"review-rating"&lt;/span&gt; &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"review.rating"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- 1 star  --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"(review.rating == 0) ? 'far fa-star' : (review.rating &amp;gt; 0 &amp;amp;&amp;amp; review.rating &amp;lt; 1) ? 'fas fa-star-half-alt' : 'fas fa-star'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- 2 star  --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"(review.rating &amp;gt; 1 &amp;amp;&amp;amp; review.rating &amp;lt; 2) ? 'fas fa-star-half-alt' : (review.rating &amp;gt;= 2) ? 'fas fa-star' : 'far fa-star'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- 3 star  --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"(review.rating &amp;gt; 2 &amp;amp;&amp;amp; review.rating &amp;lt; 3) ? 'fas fa-star-half-alt' : (review.rating &amp;gt;= 3) ? 'fas fa-star' : 'far fa-star'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- 4 star  --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"(review.rating &amp;gt; 3 &amp;amp;&amp;amp; review.rating &amp;lt; 4) ? 'fas fa-star-half-alt' : (review.rating &amp;gt;= 4) ? 'fas fa-star' : 'far fa-star'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- 5 star  --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"(review.rating &amp;gt; 4 &amp;amp;&amp;amp; review.rating &amp;lt; 5) ? 'fas fa-star-half-alt' : (review.rating &amp;gt;= 5) ? 'fas fa-star' : 'far fa-star'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt; 
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&lt;/span&gt;r = {{review.rating}}&lt;span class="nt"&gt;&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"review-summary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ review?.reviewSummary }}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"review-feedback"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ review?.reviewMessage }}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"reviewBy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"review-date"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ (review?.reviewDate ?  review?.reviewDate : 1581470956443) | date}}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    by
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"review-author"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ review?.name }}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://stackblitz.com/edit/angular-uyirkv"&gt;Click Here to See Code Repo&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m99kWTqv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/waq0x0koqajwk0tia01s.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m99kWTqv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/waq0x0koqajwk0tia01s.PNG" alt="Image of the dynamic review ratings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There are many fun and effective ways we can explore the power of frontend frameworks. In this example, we eliminated the need to use various images (about 10) or packages to represent the various review ratings. &lt;/p&gt;

</description>
      <category>angular</category>
      <category>fontawesome</category>
      <category>frontend</category>
    </item>
    <item>
      <title>8 Tips i Would Recommend to any Beginner Frontend Web Developer</title>
      <dc:creator>Uzodufa Ebere</dc:creator>
      <pubDate>Fri, 31 Jan 2020 18:55:24 +0000</pubDate>
      <link>https://dev.to/ebereuzodufa/8-tips-i-would-recommend-to-any-young-frontend-web-developer-3a04</link>
      <guid>https://dev.to/ebereuzodufa/8-tips-i-would-recommend-to-any-young-frontend-web-developer-3a04</guid>
      <description>&lt;p&gt;In my journey as a frontend web developer, I have come across some tools and techniques I hope I knew earlier. I wish to share them with you and hopefully, contribute to your web development knowledge and save you some resources.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Bootstrap has its importance
&lt;/h1&gt;

&lt;p&gt;For some developers, bootstrap hinders developers knowing the basics of HTML, CSS and some Javascript because codes are literally handed out; little thinking, add this, maybe that and we are good to go. Simple? But that not always the case. Some designs require using bootstrap to save time or serve as the foundation for other designs.&lt;br&gt;
Here is an example of using the bootstrap carousel as the foundation for testimonial slider in angular.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8ou7bcnrquekbxwoohoe.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8ou7bcnrquekbxwoohoe.PNG" alt="Bootstrap Carousel"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Bootstrap Carousel &lt;a href="https://getbootstrap.com/docs/4.4/components/carousel/#slides-only" rel="noopener noreferrer"&gt;Code&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc6l13gq5uqpovnr26kan.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc6l13gq5uqpovnr26kan.PNG" title="Angular Code" alt="Slider in Angular"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Angular Code&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fccn7nu0e9vwc270zen42.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fccn7nu0e9vwc270zen42.gif" alt="Slider in Angular Video"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Result&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For me, it is highly required for every developer to know their onions when it comes to HTML, CSS, and Javascript and also know that bootstrap can effectively speed up development. I prefer to stick to the &lt;a href="http://getbem.com/introduction/" rel="noopener noreferrer"&gt;Block-Element-Modifier (BEM)&lt;/a&gt; as much as I can but sometimes, the codebase becomes difficult to maintain which is one of the main reasons why bootstrap was designed. Hence, I recommend understanding at least the basics of HTML, CSS, and Javascript (who knows, it might be an apt measure just in case of any bootstrap apocalypse) and then use bootstrap when necessary.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. SASS is beautiful and not difficult
&lt;/h1&gt;

&lt;p&gt;Getting started with SASS (Syntactically Awesome Style Sheets) is very easy and &lt;a href="https://www.youtube.com/watch?v=Zz6eOVaaelI" rel="noopener noreferrer"&gt;this tutorial shows why if you start SASS, you might hardly ever want to write plain CSS ever again&lt;/a&gt;. &lt;a href="https://sass-lang.com/documentation/at-rules/mixin" rel="noopener noreferrer"&gt;SASS Mixins&lt;/a&gt; are like return functions which you can design to accept variable and use default values if null. &lt;a href="https://sass-lang.com/" rel="noopener noreferrer"&gt;SASS documentation&lt;/a&gt; is simple to use and understand.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;P.S&lt;/em&gt;: I use SCSS (Sassy CSS) which used the same syntax as SASS but wraps codes in curly brackets like CSS. Both SCSS and SASS use the same &lt;a href="(https://sass-lang.com/)"&gt;documentation website&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  3. IDE Shortcuts and Extensions
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fahcg8juc4mhj8u4x0dew.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fahcg8juc4mhj8u4x0dew.gif" alt="Emmet Example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;IDE Shortcuts makes development a lot faster. To achieve this, you need &lt;a href="https://emmet.io/download/" rel="noopener noreferrer"&gt;Emmet&lt;/a&gt; for IDE. Here is the &lt;a href="https://docs.emmet.io/cheat-sheet/" rel="noopener noreferrer"&gt;Emmet cheat-sheet&lt;/a&gt; for faster development across IDE.&lt;br&gt;
Extensions like &lt;a href="https://marketplace.visualstudio.com/items?itemName=ritwickdey.live-sass" rel="noopener noreferrer"&gt;Live SASS Compiler&lt;/a&gt; help convert SASS, LESS or SCSS to CSS on each file save.&lt;br&gt;
There are extensions like &lt;a href="https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb?hl=en" rel="noopener noreferrer"&gt;Web Server for Chrome&lt;/a&gt; which can help you serve local folders over the network, using HTTP. It also runs offline.&lt;/p&gt;

&lt;h1&gt;
  
  
  4. Version Control is a Norm
&lt;/h1&gt;

&lt;p&gt;Yes, version control is a norm in software development and there will be many times it will be the savior. Version control is easy to not abide. It is eminent to stick to it for easier understand and control of software. There are standards for using version controls on bugs and features such as &lt;a href="https://github.com/andela/bestpractices/wiki/Git-naming-conventions-and-best-practices" rel="noopener noreferrer"&gt;Andela's git naming conventions and best practices&lt;/a&gt;. Udacity has an awesome course on &lt;a href="https://www.udacity.com/course/version-control-with-git--ud123" rel="noopener noreferrer"&gt;Version Control&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  5. Scaffolding really saves time.
&lt;/h1&gt;

&lt;p&gt;Scaffolding frequently refers to a quick set up skeleton for an application. In most cases, Scaffolding is referred to as a backend process. An example of scaffolding is typing &lt;code&gt;html&lt;/code&gt; on the sublime text IDE  or &lt;code&gt;!&lt;/code&gt; in Visual studio code IDE and hitting &lt;code&gt;tab&lt;/code&gt;. Both will result in the basic boilerplate for most HTML pages. One basic challenge for most beginner frontend developers is auto-refresh of browser contents on saving file change without having to click the refresh button on the browser. I discovered &lt;a href="https://yeoman.io/" rel="noopener noreferrer"&gt;Yeoman&lt;/a&gt; solves this challenge and at the same time providing you with basic scaffolds for HTML, CSS and JS, test files and task runner. On installing yeoman, you ask to choose &lt;code&gt;SCSS&lt;/code&gt;, &lt;code&gt;Bootstrap&lt;/code&gt; or &lt;code&gt;CSS&lt;/code&gt;, &lt;code&gt;Behavior-Driven Development (BDD)&lt;/code&gt; or &lt;code&gt;Test-Driven Development (TDD)&lt;/code&gt; and pull out package manager dependencies. This saves you time need to setup browser-sync, write basic boilerplates, and create important task runners that help make development faster, better and stick close to standards.&lt;br&gt;
&lt;a href="https://github.com/yeoman/yo" rel="noopener noreferrer"&gt;Using Yeoman GitHub repo instructions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fudzqp43uvt5hhyc0x3qy.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fudzqp43uvt5hhyc0x3qy.PNG" alt="Running  raw `yo webapp` endraw "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgrxntorsxhd2iptpknw4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgrxntorsxhd2iptpknw4.PNG" alt="After Running yeoman"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  6. Task Runners
&lt;/h1&gt;

&lt;p&gt;Task runners are scripts that help automate numerous development process for web development. These processes can be converting SASS to CSS, spin up servers or serving the latest code files in the IDE on the browser during development, serving CSS on save without refreshing the browser, minify and uglify code, and compress (&lt;a href="https://en.wikipedia.org/wiki/Gzip" rel="noopener noreferrer"&gt;gzipping&lt;/a&gt;) codes. Task Runners help optimize codes and improve performance on the web. Major task runners are &lt;a href="https://gruntjs.com/" rel="noopener noreferrer"&gt;Grunt&lt;/a&gt; and &lt;a href="https://gulpjs.com/" rel="noopener noreferrer"&gt;Gulp&lt;/a&gt;.&lt;br&gt;
I mainly use Gulp which is an open-source task runner that uses javascript syntax to perform web automation and tooling. Gulp is very easy to start with and has a detailed &lt;a href="https://gulpjs.com/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;. It requires Node and npm to work. Gulp uses command in gulpfile.js for tooling which is written in javascript. In the file, you can specify which process to run when developing and that for production. Fortunately, Yeoman can help scaffold web apps that have gulp scripts for important task runners like minifying, uglifying, compressing images, and gzip on production as well as other tasks like browser-sync for development. This article does justice to &lt;a href="https://www.smashingmagazine.com/2016/06/harness-machines-productive-task-runners/" rel="noopener noreferrer"&gt;how to harness the power of task runner&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  7. There are easier ways to host your work for the world to see
&lt;/h1&gt;

&lt;p&gt;I use services like &lt;a href="https://netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; to showcase my works. Projects files or folder can be drag and dropped to deploy or lined to an online repository like Github and which updates automatically for nay change on the project. Netlify allows one to run the production script from deploy terminal if task runners like gulp where used in the project.&lt;/p&gt;

&lt;h1&gt;
  
  
  8. Web auditing and Checking Performance
&lt;/h1&gt;

&lt;p&gt;Modern browsers provide tools for analysis codes and show ways to improve on them for the web. There are also online tools like &lt;a href="https://developers.google.com/speed/pagespeed/insights/" rel="noopener noreferrer"&gt;Google Pagespeed Insights&lt;/a&gt;. &lt;br&gt;
On modern browsers, &lt;code&gt;Ctrl&lt;/code&gt; + &lt;code&gt;Shift&lt;/code&gt; + &lt;code&gt;i&lt;/code&gt; exposes the developer tool. Here you can check the performance of any website by going to the &lt;code&gt;performance tab&lt;/code&gt; and then, click the &lt;code&gt;start recording performance&lt;/code&gt;, &lt;code&gt;record&lt;/code&gt; or &lt;code&gt;profile&lt;/code&gt; button (the text is dependent on the browser). The result shows chart(s) on how long it takes the website to render, paint, etc. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flfvc0em935vj89clzuhu.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flfvc0em935vj89clzuhu.PNG" alt="Checking Performance of a website on Mozilla Filefox."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For Google Chrome, you can use the audit tab to run analysis and get feedback on what to improve on the website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8f0f8knymz0ghhirakuf.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8f0f8knymz0ghhirakuf.PNG" alt="Setting up Audit on Google Chrome"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft653ot3dj90zvl48jl0z.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft653ot3dj90zvl48jl0z.PNG" alt="Result from Audit on Google Chrome"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Udacity has two amazing courses - &lt;a href="https://www.udacity.com/course/browser-rendering-optimization--ud860" rel="noopener noreferrer"&gt;Browswe Rendering Optimization&lt;/a&gt; and &lt;a href="https://www.udacity.com/course/website-performance-optimization--ud884" rel="noopener noreferrer"&gt;Website Performance Optimization&lt;/a&gt; to help improve web application performance.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;As developers grow, we tend to use front-end frameworks for web development. These frameworks may use CLIs and scripts for web automation and tooling. This can be seen with the Angular CLI which has commands to help scaffold components, etc. This article is a solution for developers who are yet to start using frameworks or seeking fast and effective ways to scaffold web applications to be built on plain HTML, CSS, and JavaScript. Furthermore, there are quality documents, videos, and tutorials on how to set up processes to make our applications better such as &lt;a href="https://developers.google.com/web/progressive-web-apps" rel="noopener noreferrer"&gt;Progressive Web Application&lt;/a&gt;, &lt;a href="https://developers.google.com/web/fundamentals/design-and-ux/input/forms" rel="noopener noreferrer"&gt;efficient web forms&lt;/a&gt;, etc. This makes these processes easy to learn and apply.&lt;br&gt;
Finally, we all at some points in our career, look back at previous challenges and laugh at how hard it took us to figure it out. Every aspect of life learning is like that, including front-end web development. Consistent learning, discipline, keeping to standards, and refusing to stay on the ground when we fail makes us better.&lt;/p&gt;

&lt;p&gt;I will appreciate it if you can share the techniques you learned in your career that you would love to have known earlier.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/a/235027/5765188" rel="noopener noreferrer"&gt;https://stackoverflow.com/a/235027/5765188&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.smashingmagazine.com/2016/06/harness-machines-productive-task-runners/" rel="noopener noreferrer"&gt;https://www.smashingmagazine.com/2016/06/harness-machines-productive-task-runners/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://yeoman.io/" rel="noopener noreferrer"&gt;https://yeoman.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.udacity.com/course/web-tooling-automation--ud892" rel="noopener noreferrer"&gt;https://www.udacity.com/course/web-tooling-automation--ud892&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.udacity.com/course/version-control-with-git--ud123" rel="noopener noreferrer"&gt;https://www.udacity.com/course/version-control-with-git--ud123&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/andela/bestpractices/wiki/Git-naming-conventions-and-best-practices" rel="noopener noreferrer"&gt;https://github.com/andela/bestpractices/wiki/Git-naming-conventions-and-best-practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.udacity.com/course/website-performance-optimization--ud884" rel="noopener noreferrer"&gt;https://www.udacity.com/course/website-performance-optimization--ud884&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.udacity.com/course/browser-rendering-optimization--ud860" rel="noopener noreferrer"&gt;https://www.udacity.com/course/browser-rendering-optimization--ud860&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.vojtechruzicka.com/chrome-audit-lighthouse/" rel="noopener noreferrer"&gt;https://www.vojtechruzicka.com/chrome-audit-lighthouse/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>discuss</category>
      <category>newbie</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
