<?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>Forem: Dang Quoc Khanh</title>
    <description>The latest articles on Forem by Dang Quoc Khanh (@khanhdangbmt).</description>
    <link>https://forem.com/khanhdangbmt</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%2F767985%2F43426cd6-947d-4f82-af75-f5becb04ef9e.jpg</url>
      <title>Forem: Dang Quoc Khanh</title>
      <link>https://forem.com/khanhdangbmt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/khanhdangbmt"/>
    <language>en</language>
    <item>
      <title>🏠 Stop guessing construction costs.</title>
      <dc:creator>Dang Quoc Khanh</dc:creator>
      <pubDate>Fri, 08 May 2026 02:28:18 +0000</pubDate>
      <link>https://forem.com/khanhdangbmt/stop-guessing-construction-costs-fck</link>
      <guid>https://forem.com/khanhdangbmt/stop-guessing-construction-costs-fck</guid>
      <description>&lt;p&gt;We built VatgiaTop to help homeowners, contractors, and architects quickly check material prices and estimate construction costs in Vietnam.&lt;/p&gt;

&lt;p&gt;With VatgiaTop, you can:&lt;br&gt;
• Check updated construction material prices&lt;br&gt;
• Estimate your dream house budget&lt;br&gt;
• Explore house construction cost references&lt;br&gt;
• Save time comparing quotations manually&lt;/p&gt;

&lt;p&gt;Building a house is already stressful enough — pricing shouldn’t be.&lt;/p&gt;

&lt;p&gt;Would love your feedback, support, and ideas for improving the platform.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://vatgia.top/" rel="noopener noreferrer"&gt;VatgiaTop&lt;/a&gt; — Checking prices &amp;amp; estimating your dream house costs smarter.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>What I Learned After Working with Real Construction Costs in Vietnam (And Why Most People Get It Wrong)</title>
      <dc:creator>Dang Quoc Khanh</dc:creator>
      <pubDate>Wed, 06 May 2026 01:30:26 +0000</pubDate>
      <link>https://forem.com/khanhdangbmt/what-i-learned-after-working-with-real-construction-costs-in-vietnam-and-why-most-people-get-it-5hf1</link>
      <guid>https://forem.com/khanhdangbmt/what-i-learned-after-working-with-real-construction-costs-in-vietnam-and-why-most-people-get-it-5hf1</guid>
      <description>&lt;p&gt;If you've never built a house in Vietnam, there's one thing you should know upfront:&lt;/p&gt;

&lt;p&gt;The biggest mistake isn't design, labor, or even contractors - it's misunderstanding material costs.&lt;/p&gt;

&lt;p&gt;After years working in construction and consulting homeowners, I've seen the same issue over and over again:&lt;br&gt;
People start building with a rough budget... And end up overspending by 20-30%.&lt;/p&gt;

&lt;p&gt;And honestly? It's not their fault.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Hidden Problem: "Estimated" Prices Are Often Fiction
&lt;/h1&gt;

&lt;p&gt;Most homeowners rely on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Old Excel sheets&lt;/li&gt;
&lt;li&gt;Rough quotes from contractors&lt;/li&gt;
&lt;li&gt;Or "market price" conversations&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  But here's the reality:
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Construction material prices change constantly - and vary by province.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, cement, steel, sand, and brick prices are updated monthly or quarterly by provincial Departments of Construction, and they can differ significantly between regions. ([Vt Gi Top][1])&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A price in Ho Chi Minh City isn't a price in Da Nang&lt;/li&gt;
&lt;li&gt;A quote from last month may already be outdated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So when you estimate based on "average numbers," you're already starting with inaccurate data.&lt;/p&gt;




&lt;h1&gt;
  
  
  Real Experience: Where Costs Actually Go Wrong
&lt;/h1&gt;

&lt;p&gt;From real projects I've worked on, cost overruns usually come from:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Material price mismatch
&lt;/h2&gt;

&lt;p&gt;You planned with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Steel: X price&lt;/li&gt;
&lt;li&gt;Cement: Y price&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But when buying:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prices increased&lt;/li&gt;
&lt;li&gt;Or suppliers quoted higher&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Result: Budget breaks immediately.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. No quantity calculation
&lt;/h2&gt;

&lt;p&gt;Many people don't calculate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How much steel per m&lt;/li&gt;
&lt;li&gt;How many bricks per wall&lt;/li&gt;
&lt;li&gt;How much concrete per floor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So they:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Buy too much waste, estimate over the reality&lt;/li&gt;
&lt;li&gt;Or buy too little delays + higher cost later, cost change every day but we normaly didn't realize it&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Contractor opacity
&lt;/h2&gt;

&lt;p&gt;A common issue in Vietnam:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contractors buy materials without transparency&lt;/li&gt;
&lt;li&gt;Homeowners don't see real invoices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why experienced builders always insist on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear material price lists&lt;/li&gt;
&lt;li&gt;Stage-by-stage payments&lt;/li&gt;
&lt;li&gt;Independent verification when possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(If you skip this, you're basically handing over control of your budget.)&lt;/p&gt;




&lt;h1&gt;
  
  
  What Actually Works (From Practice)
&lt;/h1&gt;

&lt;p&gt;After dealing with multiple projects, I simplified everything into 3 rules:&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule #1: Always use real, local price data
&lt;/h2&gt;

&lt;p&gt;Not averages. Not guesses. You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Province-specific prices&lt;/li&gt;
&lt;li&gt;Updated regularly&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Rule #2: Estimate based on area + coefficients
&lt;/h2&gt;

&lt;p&gt;Instead of guessing totals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calculate cost per m&lt;/li&gt;
&lt;li&gt;Multiply by real material prices&lt;/li&gt;
&lt;li&gt;Adjust based on house type (townhouse, villa, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how professionals estimate quickly - and much more accurately.&lt;/p&gt;




&lt;h2&gt;
  
  
  Rule #3: Break everything into components
&lt;/h2&gt;

&lt;p&gt;A house is not one cost.&lt;/p&gt;

&lt;p&gt;It's:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Foundation&lt;/li&gt;
&lt;li&gt;Structure&lt;/li&gt;
&lt;li&gt;Finishing&lt;/li&gt;
&lt;li&gt;Interior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you break it down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You see where money goes&lt;/li&gt;
&lt;li&gt;You control cost much better&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Why I Built This Tool
&lt;/h1&gt;

&lt;p&gt;After seeing the same problems repeatedly, I wanted something simpler:&lt;/p&gt;

&lt;p&gt;A place where you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check real construction material prices&lt;/li&gt;
&lt;li&gt;Estimate house costs based on actual data&lt;/li&gt;
&lt;li&gt;Avoid "guess-based budgeting"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I built:&lt;br&gt;
 &lt;a href="https://vatgia.top/" rel="noopener noreferrer"&gt;https://vatgia.top/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What it does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provides construction material prices across 34 provinces in Vietnam&lt;/li&gt;
&lt;li&gt;Aggregates data from official sources&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Includes tools like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;House cost estimator&lt;/li&gt;
&lt;li&gt;Material calculator&lt;/li&gt;
&lt;li&gt;Quick price lookup&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Instead of guessing, you can base your decisions on real numbers.&lt;/p&gt;




&lt;h1&gt;
  
  
  A Practical Example
&lt;/h1&gt;

&lt;p&gt;Let's say you're building a 100m house.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I think it costs around $X..."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select your province&lt;/li&gt;
&lt;li&gt;Get actual material prices&lt;/li&gt;
&lt;li&gt;Estimate cost based on structure + materials&lt;/li&gt;
&lt;li&gt;Imagine how you use their house after its done (this is a important way to thinking about how to use it and reduce the gap between thinking and using)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Even with normal variance, the error is usually around 10-20% instead of 30-50% when guessing. ([Vt Gi Top][1])&lt;/p&gt;

&lt;p&gt;That difference alone can save you thousands.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;Building a house is not just about design or aesthetics.&lt;/p&gt;

&lt;p&gt;It's a data problem.&lt;/p&gt;

&lt;p&gt;If your inputs (material prices, quantities) are wrong:&lt;br&gt;
 Your entire budget will be wrong.&lt;/p&gt;

&lt;p&gt;But if your inputs are accurate:&lt;br&gt;
 Everything becomes predictable.&lt;/p&gt;




&lt;p&gt;If you're planning to build (or just curious about construction economics in Vietnam), feel free to explore:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vatgia.top/" rel="noopener noreferrer"&gt;https://vatgia.top/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I built it to solve a real problem I kept seeing in the field -&lt;br&gt;
and hopefully, it saves you from the same mistakes.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>learning</category>
      <category>management</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Writing (unit) tests action, event in Moleculer with Jest</title>
      <dc:creator>Dang Quoc Khanh</dc:creator>
      <pubDate>Wed, 15 Feb 2023 16:22:50 +0000</pubDate>
      <link>https://forem.com/khanhdangbmt/writing-unit-tests-action-event-in-moleculer-with-jest-5e0c</link>
      <guid>https://forem.com/khanhdangbmt/writing-unit-tests-action-event-in-moleculer-with-jest-5e0c</guid>
      <description>&lt;h2&gt;
  
  
  1. Preface ⛄
&lt;/h2&gt;

&lt;p&gt;Moleculer is a powerful microservice framework for NodeJs. Because of designed by a microservice architect, we have more than one service responsible for its duty. In order to communicate with other nodes, we can configure transporter like TCP, NATS, Redis transporter, MQTT, AMQP, and Kafka,.. or customize them to be suitable for your business.&lt;/p&gt;

&lt;p&gt;Beside design feature to interact with other node, we need to writing unitest for each feature, function inside to it. An aspect of it, we also need to write unitest for action call each other. In this post, I will present a few of my ways to write unitest in this case.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Please reading about Broker, Transporter, Action, Events concept before reading this post.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5s0zn1uesynh7533dzme.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5s0zn1uesynh7533dzme.png" alt="Moleculer" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Understand about action, event in Moleculer
&lt;/h2&gt;

&lt;p&gt;In the real world, if each of us represents a service so the actions look like the request you need from the other. But we have two cases to request something. First, we request something from others and want the result. Second, we request from others and we do not need or care about their response. &lt;br&gt;
I have two easy-to-understand examples of these concepts: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bob goes to the market and tells to the cashier, "I want to buy an apple". the cashier checks their stock and sells it to Bob or tells him it's out of stock. Bob will get the response from the cashier. This is the mechanism of actions in moleculer.&lt;/li&gt;
&lt;li&gt;Bob's garbage was full so he leave them in the trash can and he doesn't need to know when they take it out or how to process the rubbish. He just leaves it and goes back to his work. This is the mecahnism of events in moleculer framework.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7n6nnmsn6mci6b5oos5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7n6nnmsn6mci6b5oos5.jpg" alt="Simulation image for communicate" width="668" height="324"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. How to test action, event
&lt;/h2&gt;

&lt;p&gt;Let's join the main content. Different from testing on the monolithic architecture, each service can be located on a different server and called to another service via the transporter.&lt;/p&gt;

&lt;p&gt;In the original document, the example already tests the event called by the action. Based on the moleculer testing document, I have the basic implement test action which calls another action with 3 steps: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mock service broker.&lt;/li&gt;
&lt;li&gt;Create two services (we can load/create/import or create a new service and set test action to this service).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Okay, let's take an overview of the code...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Testing calling actions&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Mock service broker&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;broker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ServiceBroker&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// set start and stop service &lt;/span&gt;
    &lt;span class="nf"&gt;beforeAll&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;broker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nf"&gt;afterAll&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;broker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="c1"&gt;// create bob service&lt;/span&gt;
    &lt;span class="nx"&gt;broker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createService&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bob-service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;goToMarket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&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;buyAppleResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cashier-service.sellApple&lt;/span&gt;&lt;span class="dl"&gt;"&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;buyAppleResponse&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;span class="c1"&gt;// create cashier service&lt;/span&gt;
    &lt;span class="nx"&gt;broker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createService&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cashier-service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;sellApple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&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;isAvailableApple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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;isAvailableApple&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;span class="c1"&gt;// process test&lt;/span&gt;
    &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Test bob buy apple&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&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="s2"&gt;should calling to another action&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;viewBobGoToMarket&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;broker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bob-service.goToMarket&lt;/span&gt;&lt;span class="dl"&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;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;viewBobGoToMarket&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;Logic: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First I want to mock a service broker to create an individual environment to run our test.&lt;/li&gt;
&lt;li&gt;Next, I re-build two services corresponding to Bob and Cashier and also create action for each service.&lt;/li&gt;
&lt;li&gt;Process call service via Service Broker to make sure it works.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can imagine the communication above like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft2lnu7hvi0re0hojeumk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft2lnu7hvi0re0hojeumk.png" alt="communication simulation" width="662" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we replace the actions called with the events, we will not have the response because we don't care about the result or whether the call event lose.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxh49asyvswpy7nnvhhny.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxh49asyvswpy7nnvhhny.png" alt="Event simulation" width="662" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another way to test an action is to get only the action that we need to test and mock all actions, events, calling to the database,.. inside this test action. The solution depends on your style, business logic, or use context.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Conclusion
&lt;/h2&gt;

&lt;p&gt;Here is an unitest example when I'm trying to test action with mock action. It's similar when we replace action by event. I think it is simple and hope it easy to understand. I'm new bie in microservice and moleculer framwork, give me an comment if I have any shortcoming. &lt;/p&gt;

&lt;p&gt;Follow me and give me your heart if you're interesting ❤️&lt;br&gt;
Thanks for reading 😍&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://moleculer.services/docs/0.14/testing.html" rel="noopener noreferrer"&gt;https://moleculer.services/docs/0.14/testing.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>codenewbie</category>
      <category>discuss</category>
      <category>community</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>Logging levels</title>
      <dc:creator>Dang Quoc Khanh</dc:creator>
      <pubDate>Tue, 14 Feb 2023 15:10:03 +0000</pubDate>
      <link>https://forem.com/khanhdangbmt/logging-levels-2bpc</link>
      <guid>https://forem.com/khanhdangbmt/logging-levels-2bpc</guid>
      <description>&lt;h2&gt;
  
  
  Logging levels?
&lt;/h2&gt;

&lt;p&gt;Log is a piece of information that was shown when the application runs through that code. Its information serves for troubleshooting and monitoring. It can be saved in a log file and supervised by any monitoring tool. When something happens with your application, I think the first thing you want to do is check the log to check what happens with your code. It's really important when we write logging in the right way and have enough information to serve that case.&lt;/p&gt;

&lt;p&gt;Another case we can think about is that maybe in your sleep, the application caused some error for a specific case, it's a critical bug but not popular in our system. If you put in some logs in your code, the next morning will be very easy for you. Just check the log and find the reason why it happens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Log Level Hierarchy
&lt;/h2&gt;

&lt;p&gt;In most logging frameworks you will encounter some of the following log levels:&lt;br&gt;
Severity affecting the system is arranged in order from top to bottom&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Log type&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OFF&lt;/td&gt;
&lt;td&gt;This log levels does not log anything. We will get no logging in our application&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FATAL&lt;/td&gt;
&lt;td&gt;This log usually use to show critical errors which can break down the server or the business logic is no longer working. A FATAL log level may be used when the system is not able to connect to a crucial data store like a database or payment system are not available or any executing function &lt;code&gt;breaks down&lt;/code&gt; the system, &lt;code&gt;sys_error&lt;/code&gt;,...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ERROR&lt;/td&gt;
&lt;td&gt;The log level I'm using is very popular. This log is used when we &lt;code&gt;throw errors&lt;/code&gt; in functions that we can catch or prevent at that time. This error can prevent one or more functionality next. Imagine that this log can use in your try-catch function and it affects the user experience.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WARN&lt;/td&gt;
&lt;td&gt;The log level indicates that something &lt;code&gt;unexpected happened&lt;/code&gt; in the application. The problems or issues that might disturb the process of the functionality. The application does not fail in this case. For example, passing the error occurred that the send notice function like webhook to partner.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;INFO&lt;/td&gt;
&lt;td&gt;The standard log level that &lt;code&gt;something happened&lt;/code&gt;, the application entered to the specific state or just log to easily check again to make sure that steps working right. For example in this log, we can use the INFO of the request payment of the user, request authorization, and the result after calling from 3rd parties. Noted that the information in this log might not include the error.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DEBUG&lt;/td&gt;
&lt;td&gt;The log usually use for developers to &lt;code&gt;debug&lt;/code&gt; on the local / dev environment. It will be disabled in the production environment because it might be large. In specific cases, we also use this log on production. Less granular compared to the TRACE level but the developer use it every day. This log includes the information for &lt;code&gt;diagnosing issues&lt;/code&gt; and &lt;code&gt;troubleshooting&lt;/code&gt; or running on the test environment for the purpose of making sure everything is running correctly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TRACE&lt;/td&gt;
&lt;td&gt;The most rarity case when we want to know what happening in your application and in side the third-party libraries that we use in our application. We can use this log to check the steps inside the algorithm in the library or you want to check what query calling to our database.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ALL&lt;/td&gt;
&lt;td&gt;It is the combination of all other loggin levels. This log will log any logging levels that are defined.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Follow IBM documentations for logging levels, each level has an associated integer value usable by rules that monitor system mesages. View the detail values of each levels at &lt;a href="https://www.ibm.com/docs/en/cognos-analytics/10.2.2?topic=SSEP7J_10.2.2/com.ibm.swg.ba.cognos.ug_rtm_wb.10.2.2.doc/c_n30e74.htm"&gt;IBM - Understanding logging levels&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Logging levels format
&lt;/h2&gt;

&lt;p&gt;We need to identify what is the suitable format for our system. I prefer some of these parameter in our log format (make sure it consistent in our application): &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Timestamp: it will provide you with the order of the dozen of log (date or interger format).&lt;/li&gt;
&lt;li&gt;Log levels name: look like INFO, ERROR, TRACE,... to make sure you can classify these log.&lt;/li&gt;
&lt;li&gt;Message: the message you need to show. Make sure it use English language and friendly and it unique for each logs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RmezuX1Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/adjysxc1svqt61tc6k9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RmezuX1Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/adjysxc1svqt61tc6k9j.png" alt="Example for logging levels" width="728" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do not write this code in our application if the outside does not have the try catch function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// do something&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;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The log action is very important in our application. I don't want you to commit and push the code just to show the log because the error has been swallow. &lt;/p&gt;

&lt;p&gt;Log can inform you not only how healthy your website is, but also how to calculate critical metrics like the error rate. Logs assist you in location the issue more quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://sematext.com/blog/logging-levels/"&gt;https://sematext.com/blog/logging-levels/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codelearn.io/sharing/logging-python-system-talk-module"&gt;https://codelearn.io/sharing/logging-python-system-talk-module&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.section.io/engineering-education/how-to-choose-levels-of-logging/"&gt;https://www.section.io/engineering-education/how-to-choose-levels-of-logging/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.atatus.com/blog/9-best-practice-for-application-logging-that-you-must-know/#Use-English-Language-and-Friendly-Log-Messages"&gt;https://www.atatus.com/blog/9-best-practice-for-application-logging-that-you-must-know/#Use-English-Language-and-Friendly-Log-Messages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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