<?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: Wichai Sawangpongkasame</title>
    <description>The latest articles on DEV Community by Wichai Sawangpongkasame (@kradasa4).</description>
    <link>https://dev.to/kradasa4</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%2F285570%2F26f27e75-6de6-44f4-9aba-3a8f603e1e37.jpg</url>
      <title>DEV Community: Wichai Sawangpongkasame</title>
      <link>https://dev.to/kradasa4</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kradasa4"/>
    <language>en</language>
    <item>
      <title>A Brief Introduction to Functor for Busy TypeScript Devs</title>
      <dc:creator>Wichai Sawangpongkasame</dc:creator>
      <pubDate>Sun, 28 Sep 2025 15:56:31 +0000</pubDate>
      <link>https://dev.to/kradasa4/a-brief-introduction-to-functor-for-busy-typescript-devs-52ai</link>
      <guid>https://dev.to/kradasa4/a-brief-introduction-to-functor-for-busy-typescript-devs-52ai</guid>
      <description>&lt;p&gt;In this article, we won't be diving deep into functional programming. Instead, we'll get familiar with functors, a concept you might already be using without realizing it, and how to apply this technique to your general coding practice.&lt;/p&gt;

&lt;p&gt;Before explaining what a Functor is, let's look at an example to see it in action and understand the benefits.&lt;/p&gt;

&lt;p&gt;Assuming that you have an array of numbers and you want to map over it to calculate something for every member. You might write it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const arr = [1, 2, 3];
arr.map((num) =&amp;gt; num + 1); // [2, 3, 4]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what if you wanted to perform two different calculations?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const arr = [1, 2, 3];
arr.map((num) =&amp;gt; num + 1).map((num) =&amp;gt; num ** 2); // [4, 9, 16]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we refactor this by extracting the calculation logic into separate callback functions, we get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const arr = [1, 2, 3];
const add1 = (num: number) =&amp;gt; num + 1;
const square = (num: number) =&amp;gt; num ** 2;
arr.map(add1).map(square); // [4, 9, 16]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should be easy to read. By using .map, we apply add1 to each element, then apply square to each element respectively.&lt;/p&gt;

&lt;p&gt;This is a functor in action! It allows us to read the operations performed on the data sequentially and makes it simple to chain operations together. This is a common pattern in functional programming.&lt;/p&gt;

&lt;p&gt;However, if we were being honest with ourselves, when we're accustomed to an imperative way of thinking and coding, we often don't write code as straightforwardly as the chained .map calls. We might end up with something more like this instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;arr.map(x =&amp;gt; {
    const addResult = add1(x);
    const squareResult = square(addResult);
    return squareResult;
})

// Or simplified:
arr.map(num =&amp;gt; square(add1(num))); // [4, 9, 16]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not too hard to read yet, right? But what if we want to add one more operation?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const times2 = (num: number) =&amp;gt; num * 2;

// 1st approach (Functor chaining)
arr.map(add1).map(square).map(times2); // [8, 18, 32]

// 2nd approach (Imperative with intermediate variables)
arr.map(x =&amp;gt; {
    const addResult = add1(x);
    const squareResult = square(addResult);
    const times2Result = times2(squareResult);
    return times2Result;
})

// 2nd approach (Nested functions)
arr.map(num =&amp;gt; times2(square(add1(num)))); // [8, 18, 32]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that using a functor keeps the code easy to read. We can simply read it from left to right! It takes the value from the array, add1 to it, square it, and then times by 2.&lt;/p&gt;

&lt;p&gt;In contrast, as we start nesting functions deeper in the second approach, we have to start chasing down variables, check if we're passing the right values, or mentally keep track that the outermost function is called with the result of the innermost one, all while counting parentheses.&lt;/p&gt;

&lt;p&gt;In terms of performance, the two approaches are negligibly different. The chained .map() runs three separate loops, while the nested approach runs all three operations in a single loop. However, since the Big O time complexity is still O(n) for both, the overhead is minimal compared to the significant gain in readability.&lt;/p&gt;

&lt;p&gt;The fact that both writing styles yield the same result is the &lt;em&gt;Composition Law&lt;/em&gt; of functors. We've just seen that the JavaScript Array is a type of functor, and we leverage its map property to structure our code for better readability.&lt;/p&gt;

&lt;p&gt;We've seen the practical benefit of this pattern. So, what exactly is a Functor?&lt;/p&gt;

&lt;h2&gt;
  
  
  What Exactly is a Functor?
&lt;/h2&gt;

&lt;p&gt;At its core, the concept of a functor is rooted in Category Theory, a branch of mathematics dealing with the transformation of objects from one category to another.&lt;/p&gt;

&lt;p&gt;In programming terms, a Functor is a data type (or container) that we can map over to apply a function to its contents. This changes the value inside but keeps the structure the same, which makes it remains a functor that you can continue mapping.&lt;/p&gt;

&lt;p&gt;A functor must obey two fundamental laws:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Identity Law
&lt;/h3&gt;

&lt;p&gt;If you pass the identity function (a function that simply returns its input) to the map method, you must get a functor that is equivalent to the original one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const arr = [1, 2, 3];
const identityFunction = (x: number) =&amp;gt; x;
arr.map(identityFunction); // [1, 2, 3]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use the word "equivalent" because while the value is the same ([1, 2, 3]), .map() actually creates a new array instance. For any functor type, map returns a new functor instance.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Composition Law
&lt;/h3&gt;

&lt;p&gt;As shown in the initial examples, both writing styles below are merely rearrangements of the same logic but produce identical results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const arr = [1, 2, 3];
const add1 = (num: number) =&amp;gt; num + 1;
const square = (num: number) =&amp;gt; num ** 2;
const times2 = (num: number) =&amp;gt; num * 2;

// Nested approach
arr.map(num =&amp;gt; times2(square(add1(num)))); // [8, 18, 32]

// Chained approach
arr.map(add1).map(square).map(times2); // [8, 18, 32]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can abstract this into a formal rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;F.map(x⇒f(g(x)))≡F.map(g).map(f)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where F is the functor (in our example, the array). Both forms of structuring the operations yield the same outcome.&lt;/p&gt;

&lt;p&gt;Following this rule, you can see that several other things in JavaScript are functors, such as Promises, which you can chain with repeated .then() calls.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const promise = Promise.resolve(2)
  .then(add1)
  .then(square)
  .then(times2)
  .then(val =&amp;gt; console.log(val)); // 18
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to Create Your Own Functor
&lt;/h2&gt;

&lt;p&gt;Based on this knowledge, we can define a few steps to build our own functor.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a data type (a container).&lt;/li&gt;
&lt;li&gt;Implement a map method that takes a callback function and applies it to our data's value.&lt;/li&gt;
&lt;li&gt;Wrap the result back in a new instance of our functor, according to the definition that the structure must be preserved.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For simplicity, before moving on to the TypeScript example, let's look at the basic JavaScript function implementation first to grasp the concept:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const functor = (value) =&amp;gt; ({
    map: (callback) =&amp;gt; functor(callback(value)),
    get: () =&amp;gt; value
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function is a constructor that takes a value and creates a data structure with a map method. The .map receives a callback function, applies it to the internal value, and then uses the result of callback(value) to create a new functor instance.&lt;/p&gt;

&lt;p&gt;We can define a simple TypeScript interface with generics to make our functor type-safe and flexible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface IFunctor&amp;lt;T&amp;gt; {
  map: &amp;lt;U&amp;gt;(callback: (val: T) =&amp;gt; U) =&amp;gt; IFunctor&amp;lt;U&amp;gt;;
  get(): T;
}

const functor = &amp;lt;T&amp;gt;(value: T): IFunctor&amp;lt;T&amp;gt; =&amp;gt; ({
  map: &amp;lt;U&amp;gt;(callback: (val: T) =&amp;gt; U): IFunctor&amp;lt;U&amp;gt; =&amp;gt; functor(callback(value)),
  get: () =&amp;gt; value,
});

const exclaim = (word: string) =&amp;gt; word + '!';
const capitalize = (word: string) =&amp;gt; word.charAt(0).toUpperCase() + word.slice(1);
const words = functor("i'm on a boat");

words.map(exclaim).map(capitalize); // {map: ƒ, get: ƒ} - The Functor itself
words.map(exclaim).map(capitalize).get(); // "I'm on a boat!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Method Chaining without the Functional Functor
&lt;/h2&gt;

&lt;p&gt;For those who are more comfortable with Object-Oriented Programming (OOP), you might recognize that you can achieve method chaining by having a class method simply return this keyword, which is equivalent to maintaining the same interface structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Functor&amp;lt;T&amp;gt; implements IFunctor&amp;lt;T&amp;gt; {
  constructor(private value: T) {}

  map&amp;lt;U&amp;gt;(callback: (val: T) =&amp;gt; U): IFunctor&amp;lt;U&amp;gt; {
    // Note: We mutate the internal state and cast to the new type
    this.value = callback(this.value) as unknown as T; 
    return this as unknown as IFunctor&amp;lt;U&amp;gt;;
  }

  get(): T {
    return this.value;
  }
}

// Using the same exclaim and capitalize functions
const exclaim = (word: string) =&amp;gt; word + '!';
const capitalize = (word: string) =&amp;gt; word.charAt(0).toUpperCase() + word.slice(1);
const words = new Functor("i'm on a boat");

words.map(exclaim).map(capitalize); // Functor {value: "I'm on a boat!"}
words.map(exclaim).map(capitalize).get(); // "I'm on a boat!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we get the same result whether we create the Functor using a functional approach or an OOP class. They are basically just a mean, from different paradigms, to the same end.&lt;/p&gt;

&lt;p&gt;However, a key difference (especially when thinking about functional programming) is side effects. The class-based Functor keeps its state (value) and mutates it within the map method. If not encapsulated strictly, this state could be modified unexpectedly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Even with TypeScript's private keyword, state can be modified at runtime
words["value"] = "random words"; 
words.map(exclaim).map(capitalize).get(); // 'Random words!'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While we can use # in modern JavaScript or rely on TypeScript's private keyword (which offers compile-time protection) to avert this OOP's state pitfall, the functional functor implementation avoids this concern altogether because it creates a new functor on every map call, ensuring &lt;em&gt;immutability&lt;/em&gt; from the start.&lt;/p&gt;

&lt;p&gt;There is more to it, but I hope this serve as a starting point for those who are more accustomed to OOP. I just want to demonstrate that a simple functional programming concept can get rid of the complexity overhead you have never thought of. I'm not a FP expert myself but reading SICP has shed some light on complexities I am too used to that I hadn't noticed before. More on that next time.&lt;/p&gt;

</description>
      <category>functional</category>
      <category>typescript</category>
      <category>complexity</category>
    </item>
    <item>
      <title>The Reasons I Format Dates on the API Server</title>
      <dc:creator>Wichai Sawangpongkasame</dc:creator>
      <pubDate>Sun, 21 Sep 2025 15:12:16 +0000</pubDate>
      <link>https://dev.to/kradasa4/the-reasons-i-format-dates-on-the-api-server-1eab</link>
      <guid>https://dev.to/kradasa4/the-reasons-i-format-dates-on-the-api-server-1eab</guid>
      <description>&lt;p&gt;As an engineer, I always have "solutions" which I thoroughly understand the pros and cons of. However, after working long enough, some things come to you intuitively, and you may want to revisit your thought process again. So here is a bit of my self-reflection.&lt;/p&gt;

&lt;p&gt;I have a MongoDB database that stores data with the date in UTC. I have a small aggregation pipeline that is used to quickly pull reports for customers, and the time the customers see is in Thai time (GMT+7).&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%2Fw00sjx3sld904792tqp9.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%2Fw00sjx3sld904792tqp9.png" alt=" " width="720" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One day, we decided to let customers generate this report themselves from the front-end. The question is, do we still want to format the date in the same place?&lt;/p&gt;

&lt;p&gt;My first thought was to move the logic to the API server, but the question is, why did I come up with that decision? So, I tried to list other choices.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Front-end: we can format it for a specific display. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API Server: The front-end sends the time zone to the API server -&amp;gt; the API server fetches the data from the DB, loops through it to format it into Thai time, and then sends the response.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Database: The front-end sends the time zone to the API server -&amp;gt; the API server sends the time zone to the database to format it within the aggregation pipeline.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Formatting the Date on the Front-end&lt;/strong&gt;&lt;br&gt;
Frameworks like Angular have pipe operators that are easy to use for data transformation just for display without mutating the original data. This is an approach that we would have to use anyway if we didn't control the API server ourselves. Also, it might seem proper if we use a common BFF and our frontends use different date formats.&lt;/p&gt;

&lt;p&gt;However, testing on the front-end is quite a bit harder, and if we set the date in a state before rendering, the rendering lifecycle can have an effect, making debugging more difficult.&lt;/p&gt;

&lt;p&gt;Furthermore, if there's a bug, a new deployment is required. If the front-end is a mobile app, there might be the additional cost of waiting for Apple/Google to approve the update.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Formatting the Date on the API Server&lt;/strong&gt;&lt;br&gt;
Formatting at this point has several advantages, such as easier testing. It might require an additional loop to iterate and format the data, but if the data isn't very large or complex, this cost is insignificant. &lt;/p&gt;

&lt;p&gt;In return, we get a clear separation of concerns. The front-end is only responsible for displaying the data, and the database is only for providing data. They don't have to concern about how we handle the date. If there is a problem, we know the business logic is right here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Formatting the Date in the Database&lt;/strong&gt;&lt;br&gt;
If we choose this approach, we can use the same existing query/pipeline to pull the data. But testing the formatting logic at this level might only be possible by writing a unit test in the API server to verify that the projection pipeline is formatted correctly or by doing smoke/integration tests. We lose the separation of concerns by adding extra logic to the database.&lt;/p&gt;

&lt;p&gt;The most important thing that makes this a bad approach, even though it seems, at first glance, to allow us to format the data directly from the query without an extra loop, is that while we might pay a lower performance cost when looking at it in isolation, we pay this cost at the database. &lt;/p&gt;

&lt;p&gt;The crucial issue is that the system's bottleneck, especially in microservices, is usually the database, which is much harder to scale than the API server. We can't improve performance at a single point without considering the relationships across the entire system. Otherwise, improving performance in one area might increase the throughput and just shift the bottleneck to the next part.&lt;/p&gt;

&lt;p&gt;However, there is one frightening advantage that I've encountered from using the third approach in a different context.&lt;/p&gt;

&lt;p&gt;I once worked somewhere a long time ago that used MSSQL as a database. At that company, they favored using stored procedures, which were used to store complex queries. The backend just had to send arguments and the name of the stored procedure to use. The mentioned advantage was that it allowed us to modify the data retrieval logic without a new deployment, which meant no downtime on the production system.&lt;/p&gt;

&lt;p&gt;Personally, I think there are many scary things about this. Even if we can test with SSDT, it scatters the business logic. Some parts are on the backend, and many data-related parts are in the database. A change to a stored procedure could also affect the backend tests, unless it's just unit tests. Additionally, versioning is hard to track. You wouldn't know who changed the query and when it started going wrong.&lt;/p&gt;

&lt;p&gt;Thinking about it, every decision comes from prioritizing different things, whether it's convenience, availability, maintainability, performance, or integrity. Each has its pros and cons. The problem is that we often don't have a comprehensive enough view to realize the downsides of our choices, which we might not be ready to pay for when the time comes.&lt;/p&gt;

&lt;p&gt;If anyone sees more disadvantages to the second option, please feel free to share it with me.&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>backend</category>
      <category>designsystem</category>
    </item>
    <item>
      <title>How to Prepare for the ITPEC FE Exam</title>
      <dc:creator>Wichai Sawangpongkasame</dc:creator>
      <pubDate>Sun, 21 Sep 2025 15:11:52 +0000</pubDate>
      <link>https://dev.to/kradasa4/how-to-prepare-for-the-itpec-fe-exam-4jbi</link>
      <guid>https://dev.to/kradasa4/how-to-prepare-for-the-itpec-fe-exam-4jbi</guid>
      <description>&lt;p&gt;As a developer who graduated from non-CS major, you might consider taking the ITPE with the same reason as I did. Therefore, I won't dig into that aspect too much and will get straight to the point (Btw, Thailand also holds the exam and provides the test in English. You can learn how to register for it in Thailand here, &lt;a href="https://medium.com/@wichai.sw19/how-to-register-itpe-exam-in-thailand-3b999e7a07f8" rel="noopener noreferrer"&gt;https://medium.com/@wichai.sw19/how-to-register-itpe-exam-in-thailand-3b999e7a07f8&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The FE exam consists of two parts, the morning session and the afternoon session. the first part covers a wide range of fundamental knowledges about computer engineering while the second half assesses pragmatic skills such as coding and designing diagrams. The questions are in multiple choices format.&lt;/p&gt;

&lt;h2&gt;
  
  
  At first glance, you might think that the second half is worrisome, but if you are a non-CS graduate, I assure you that the troublesome part is the first half. So, I will go with the easy one first.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  The Afternoon Part: your day-to-day job
&lt;/h2&gt;

&lt;p&gt;For the second half, while it takes some time to arrive with the answer, they're mostly your day-to-day job. If you have already gained experience for at least a year, it should be a walk in a park.&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%2Fe70vdkvjlxzld14kzyg7.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%2Fe70vdkvjlxzld14kzyg7.png" alt="The second part exam's example questions." width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The questions mostly come with pseudo code. If you can code, it's just a reading comprehension to you. However, some basic concept might come in handy. Here're what I would suggest you prepare for:&lt;br&gt;
SQL commands.&lt;br&gt;
data structures: hash map, graph, tree, queue, stack, etc.&lt;br&gt;
diagram designing: UML, use case diagram, ER diagram, flow chart.&lt;br&gt;
bitwise operation (optional).&lt;br&gt;
networking (optional): if you know about CIDR, subnet mask, and network switch, you should be more than fine, and it will also benefit some of the morning half questions. It's not that important for this part though.&lt;br&gt;
Java/C#/C++/etc. (optional): they're not needed for the current version of the exam, but knowing languages that expose you to many programming concepts does help for pseudo code part. If your main language is JavaScript, you might consider learning how static array, dynamic array, list, hash map, thread, etc. works in other languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  As I mentioned, if you have some working experience, this part should not be too crazy for you.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  The Morning Part: A Cramming Hell
&lt;/h2&gt;

&lt;p&gt;That's what I'd like to call this part.&lt;br&gt;
While the questions are straight forward and have almost none that you have to adapt your knowledge, the scope of contents are excessively wide. It spans from hardware, networks, security, to business strategy and financial report. It even asks about corporate hierarchy your country doesn't adopt.&lt;br&gt;
The questions are simple, but it's the kind of exam that if you know you know, but if you don't, there's no helping it. The challenge is that the exam really touches every topic a bit here and there. I can guarantee that.&lt;br&gt;
Here are all the topics:&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%2Ffeonjcxkvj7nbpzc42bm.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%2Ffeonjcxkvj7nbpzc42bm.png" alt="FE Exam's content category" width="706" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Tackle It
&lt;/h2&gt;

&lt;p&gt;I'll provide you with the learning materials later, but before you're over-intimidated, I'd like to offer some help by sharing the approach I use to prepare for this exam.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practice with the Past Exam&lt;/strong&gt;&lt;br&gt;
The problematic part has almost a thousand pages of learning materials and I had skimmed thought it with no avail. I find the best way to cram it is practice doing the past exam questions.&lt;br&gt;
The answers they provide only include the correct choice without explanation, so you should try coming up with the explanation yourself. During this step, treat it like an open-book exam. Write down the explanations or calculation steps while noting the topics that are required to solve the problem. This will help you figure out that lacking knowledge of which topics make you unable to answer it correctly.&lt;br&gt;
Proceed to the next past exam. Rinse and repeat. Your scores will get gradually higher with each round. Trust me.&lt;br&gt;
After you've done around 3 exams you will find some patterns on how the questions on each topic will play out. Some topics like logic gates and binary conversion tends to show up more often than others.&lt;br&gt;
This will drastically narrow down the content you might want to focus.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Knowing Which Calculations Need to be Learned&lt;/strong&gt;&lt;br&gt;
You'll find that there will be numerous formulas in the learning materials, but you surely don't need all of them.&lt;br&gt;
If you know the Rule of Three you will find that questions on some topics such as system throughput, production capacity, and financial calculations only require basic math. You could just treat them as algebra problems, apply some math operations with the given numbers that makes the most sense in the context and you will arrive at the correct choice most of the time.&lt;br&gt;
On the other hand, topics like finding out hamming distance, turnaround time &amp;amp; response time, binary conversion, CIDR (subnet mask calculation), and so on, require specific formulas or prerequisite knowledge about the topic.&lt;br&gt;
After you had done the past exam, you will begin to notice that some topics relate to others. For example, you need to be able to convert decimal to binary and back to be able to solve CIDR or subnet mask problems, and you need to understand stack data structure to understand reverse polish notation. You might want to work a little harder on those topics since lacking the requisite knowledge will prevent you from solving the related problems too.&lt;br&gt;
However, I recommend skipping some topics that require too much effort since you might have better chances at other topics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Split Your Time into Chunks&lt;/strong&gt;&lt;br&gt;
Some questions may take you longer to answer because they require calculations, while others simply depend on whether you have seen the information before.&lt;br&gt;
Since the exam require you to finish 60 questions in 90 minutes, completing 20 questions in 30 minutes will ensure that you'll be on time. Checking this every half an hour will remind you whether you're on the right pace or not.&lt;br&gt;
I wish I could be of more help, but I think there's no real trick to it. The exam covers a bit of here and there from the reading material that you need to remember.&lt;br&gt;
The mentioned approach just helps you find out what needs to be remembered for you, since everybody comes from different backgrounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Learning Materials
&lt;/h2&gt;

&lt;p&gt;For the resources I was talking about, there are the textbooks and old exam questions which you could find on the ITPEC site itself, but I'll guide you through that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The FE Textbooks&lt;/strong&gt;&lt;br&gt;
This consists of 2 books, 'IT Fundamentals' and 'IT Strategy &amp;amp; Management'. You will need both books for the morning part of the exam. The document total around 900 pages, so you might want to make a schedule plan in advance.&lt;br&gt;
You can get the books by:&lt;br&gt;
1) going to this site, LIGHTBOAT (lightworks.co.jp).&lt;br&gt;
2)Register your account then log in. You will be redirected to My page - LIGHTBOAT.&lt;br&gt;
3) Click e-Learning then you will arrive at トップ - LIGHTBOAT (learningpark.jp).&lt;br&gt;
4) Click on the left picture below to select a book then click anywhere in the panel on the right picture.&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%2Fd8f0euccy6fw2lfwhzyn.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%2Fd8f0euccy6fw2lfwhzyn.png" alt="Select a book" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be on the reading player page now, but I suggest you download it by clicking at the save icon since the learning site allow you to open only one tab at a time.&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%2Fifgr2cf75nmxk3j1aegm.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%2Fifgr2cf75nmxk3j1aegm.png" alt="The FE Textbooks" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Past Exam Question &amp;amp; Answer&lt;/strong&gt;&lt;br&gt;
You can download questions and answer of all the past exam dated back to year 2007 from this link FE Past Examination Questions and Answers | ITPEC.org. The more recent the more relevant it is though.&lt;/p&gt;

&lt;h2&gt;
  
  
  However, the afternoon part from October 2023 and earlier wouldn't be relevant anymore because they change the format of that part.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  The New FE Exam
&lt;/h2&gt;

&lt;p&gt;Since April 2024, the FE Exam's format has been changed a bit.&lt;br&gt;
For the first part, they only adjust the numbers of questions from 80 to 60, and also decrease time from 120 to 90 minutes, but the contents of the test stays the same. So there's no need to worry about the learning materials I provide you earlier.&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%2Fk8c4on9wy30sfkkz2a3m.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%2Fk8c4on9wy30sfkkz2a3m.png" alt="The new FE exam details" width="567" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As for the second part, the time is still 100 minutes, but the contents will be changed from 8 questions with multiple sub-questions to 20 smaller questions.&lt;br&gt;
In fact, this format should be easier for developers, as all code questions use pseudocode instead of language-specific questions like Java or C++ and there also has no network-related questions unlike earlier exams.&lt;br&gt;
If you can code and know a bit of data structures &amp;amp; algorithms, you should be fine.&lt;br&gt;
You could find some examples of the new part 2 FE questions here FE-B-SampleQuestions.pdf (itpec.org)&lt;br&gt;
And before I forget this, in Southeast Asia, apart from Philippines, you could also take the ITPE exam in Thailand too. You could find information about the exam in Thailand in this link. I must admit that it's not so English friendly though. You can follow this guide for a step-by-step registration process.&lt;/p&gt;

&lt;p&gt;That should conclude it. I hope it could help you somehow. If you have any questions, feel free to leave some comments.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Applying Domain-Driven Design to Problem Design and Project Management</title>
      <dc:creator>Wichai Sawangpongkasame</dc:creator>
      <pubDate>Sun, 21 Sep 2025 14:35:00 +0000</pubDate>
      <link>https://dev.to/kradasa4/applying-domain-driven-design-to-problem-design-and-project-management-bf7</link>
      <guid>https://dev.to/kradasa4/applying-domain-driven-design-to-problem-design-and-project-management-bf7</guid>
      <description>&lt;p&gt;Normally, when I study DDD, I mostly view it as a developer who try to align oneself with the business domain expert and focus on concepts like ubiquitous language, bounded-context, model discovery, and such.&lt;/p&gt;

&lt;p&gt;However, I've come across a talk session that elaborate on designing problems and debriefing project's requirement with DDD and how it change the approach we take on problems. I find it interesting and would like to share the idea here.&lt;/p&gt;

&lt;p&gt;If our domain is a hospital and we look at it without domain knowledge, we might assume there's only one user, the patient.&lt;/p&gt;

&lt;p&gt;However, if we talk to a domain expert, we'll find that as a user interact with different parts of the system, their status from a business unit perspective changes entirely.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;when a user goes to the reception desk, they are a &lt;em&gt;Customer&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;After registering and waiting for their doctor's appointment, they become a &lt;em&gt;Patient&lt;/em&gt;. &lt;/li&gt;
&lt;li&gt;Once they've been treated and are at the payment counter, they become a &lt;em&gt;Debtor&lt;/em&gt;. &lt;/li&gt;
&lt;li&gt;After paying and waiting for their prescription, they might become a &lt;em&gt;Prescription Recipient&lt;/em&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, when we apply domain knowledge, we can clearly identify four separate subsystems:&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;Customer&lt;/strong&gt; is a CRM (Customer Relationship Management) system.&lt;/p&gt;

&lt;p&gt;2) &lt;strong&gt;Patient&lt;/strong&gt; is the medical records system (which will be our core domain).&lt;/p&gt;

&lt;p&gt;3) &lt;strong&gt;Debtor&lt;/strong&gt; is part of the finance system.&lt;/p&gt;

&lt;p&gt;4) &lt;strong&gt;Prescription Recipient&lt;/strong&gt; uses the pharmacy inventory system.&lt;/p&gt;

&lt;p&gt;If we don't break down these subsystems and instead view them as a single "hospital system," our approach to designing a solution will be completely different. Storing patient entities would result in bloated tables that lack specific meaning.&lt;/p&gt;

&lt;p&gt;Additionally, the speaker's point about using strategic design to divide problems into domain and subdomain was excellent. For example, if our domain is a hospital, we could reclassify the domains as follows:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core Domain&lt;/strong&gt;: The core business, such as medical records.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generic Subdomains&lt;/strong&gt;: Things that stay the same for any business, like CRM or finance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supporting Subdomains&lt;/strong&gt;: Things that are important, but not the most critical, and are needed to support the core, such as the pharmacy inventory system.&lt;/p&gt;

&lt;p&gt;Breaking down problems this way allows us to apply different solutions to each part. For instance, if we have a staff shortage, we can categorize the problems this way so our team can focus on what's truly important.&lt;/p&gt;

&lt;p&gt;For the &lt;em&gt;core domain&lt;/em&gt;, we can have internal staff manage it to retain domain knowledge and dedicate maximum resources to maintain our competitiveness, since this is our core business.&lt;/p&gt;

&lt;p&gt;For &lt;em&gt;generic subdomains&lt;/em&gt;, we should follow the principle of 'buy before build.' If something is generic, there should already be products available. This way, we don't have to waste our own resources on a domain we might not be proficient in. We can leverage a product from someone who specializes in that domain instead, or hire a vendor for project management.&lt;/p&gt;

&lt;p&gt;For &lt;em&gt;supporting subdomains&lt;/em&gt;, we could assign two team members and hire a trusted partner under a T&amp;amp;M (time and materials) contract.&lt;/p&gt;

&lt;p&gt;If we view the entire problem as a single entity, it's unlikely that we would come up with these kinds of solutions. But once we separate them, the requirements for each part become much clearer, and we can appropriately allocate resources—including people, time, and budget—to each specific problem.&lt;/p&gt;

&lt;p&gt;From my experience as a developer who had worked with both project-based and product-based company, I find there are many problems that can be solved much more easily, and sometimes without any code if we really understand the business need.&lt;/p&gt;

&lt;p&gt;The original talk in Thai by Mr.Twin was recorded at this &lt;a href="https://www.facebook.com/watch/?v=382406354017669" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>domaindrivendesign</category>
      <category>projectmanagement</category>
    </item>
    <item>
      <title>A, AAAA, CNAME, NS — Use Cases of Basic DNS Record Types</title>
      <dc:creator>Wichai Sawangpongkasame</dc:creator>
      <pubDate>Fri, 21 Mar 2025 14:44:25 +0000</pubDate>
      <link>https://dev.to/kradasa4/a-aaaa-cname-ns-use-cases-of-basic-dns-record-types-1oe6</link>
      <guid>https://dev.to/kradasa4/a-aaaa-cname-ns-use-cases-of-basic-dns-record-types-1oe6</guid>
      <description>&lt;p&gt;This short article is based on Route 53 supported record types, but it supposes to be a general knowledge that can be applied on any cloud platforms and DNS providers.&lt;/p&gt;

&lt;p&gt;I'll only cover the most common ones you have a high chance to come across which are A, AAAA, CNAME, NS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A - map a hostname to IPv4&lt;/li&gt;
&lt;li&gt;AAAA - map a hostname to IPv6&lt;/li&gt;
&lt;li&gt;CNAME - map a hostname to another hostname&lt;/li&gt;
&lt;li&gt;NS - point to the name of the authoritative name server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That might sound simple enough, you might end up here because you don't understand when to use each of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  A &amp;amp; AAAA
&lt;/h2&gt;

&lt;p&gt;These guys are the simplest ones as A simply stands for Address.&lt;/p&gt;

&lt;p&gt;A record is for IPv4 address, which means you can route &lt;a href="http://www.example.com" rel="noopener noreferrer"&gt;www.example.com&lt;/a&gt; to IPv4 like 192.0.2.1 or something like that. On AWS, is&lt;br&gt;
&lt;code&gt;www.example.com -&amp;gt; 192.0.2.1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;AAAA record is likewise, but for IPv6.&lt;br&gt;
&lt;code&gt;www.example.com -&amp;gt; 2001:0000:130F:0000:0000:09C0:876A:130B&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Keep in mind that if you point two A or AAAA record with the same hostname to different IP addresses, it will randomly route towards those IP addresses. If you want to load balance, there are many better ways to do that.&lt;/p&gt;

&lt;p&gt;For instance, if you're on AWS, you could make use of AWS's Application Load Balancer (ALB) by associating a single A record domain name with the ALB IP and let ALB load balances the traffic to all the destined resources.&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%2F7gnb0tf34g6tirmzby1q.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%2F7gnb0tf34g6tirmzby1q.png" alt="Route53 (a DNS service) will return a random A or AAAA that is associated with the domain name." width="617" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, if your site has an English version along with a Chinese version that restricts some contents, you might want to host that on a different IP under the same hostname and route people from China to the Chinese version, but in that case, you could configure Route53's routing policy to route traffics based on geolocation.&lt;/p&gt;

&lt;p&gt;That's a story for another time. The point is you have better ways to load balance/localize that's not setting up two A record type with different IP.&lt;/p&gt;

&lt;h2&gt;
  
  
  CNAME
&lt;/h2&gt;

&lt;p&gt;CNAME stands for Canonical Name. It's a type you'd use to map a domain name to another domain name.&lt;br&gt;
&lt;code&gt;www.foo-bar.com -&amp;gt; www.example.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's simple enough, you can even route a traffic to a domain name hosted by another DNS provider.&lt;/p&gt;

&lt;p&gt;However, you can't create CNAME record for the top node of a DNS, a.k.a zone apex. For instance, foo-bar.com can't be a CNAME, but &lt;a href="http://www.foo-bar.com" rel="noopener noreferrer"&gt;www.foo-bar.com&lt;/a&gt; and test.foo-bar.com can. If you want to achieve that on AWS, you could use Alias Records instead, it can be enabled when you create A or AAAA record.&lt;/p&gt;

&lt;p&gt;Apart from that, you can't have any other record with the same name as CNAME record. If you have a record of any type with &lt;a href="http://www.foo-bar.com" rel="noopener noreferrer"&gt;www.foo-bar.com&lt;/a&gt; name, you can't create CNAME record with &lt;a href="http://www.foo-bar.com" rel="noopener noreferrer"&gt;www.foo-bar.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  NS
&lt;/h2&gt;

&lt;p&gt;NS stands for Name Server. So, yeah, it's the same ns as in the nslookup command. NS record is a record that points to the authoritative name server.&lt;/p&gt;

&lt;p&gt;At this point, you might be baffled like I used to. "What does it mean by authoritative name server?", you may ask. To put it simply, it's a record you use to tell DNS server who is responsible for the domain that is being looked up.&lt;/p&gt;

&lt;p&gt;By default, on AWS, an NS record is automatically created when you create a Hosted Zone. It lists the four authoritative name servers of the Hosted Zone.&lt;/p&gt;

&lt;p&gt;You can leverage this knowledge in many scenarios such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Delegation: If your site is getting big, you can separate hosted zone for a subdomain. For instance, you already have example.com and sub.example.com and as it grows, you come to have aaa.sub.example.com, bbb.sub.example.com and such. On AWS, you can just create another Hosted Zone of sub.example.com which contains A records of how aaa.sub.example.com and bbb.sub.example.com should resolve, then create an NS record on the root domain Hosted Zone (example.com) that has the name of sub.example.com and set the value to be default NS record of that Hosted Zone. The benefit of this is you can give the permissions to handle the subdomain to another team while restricting the permission for the root domain, hence least privilege permission is achieved.&lt;br&gt;
&lt;code&gt;sub.example.com -&amp;gt; ns-1.example.com&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Migration: You are migrating services from AWS to Google Cloud Platform (GCP), and you want GCP to handle the DNS routing from now on while continue using the same domain name, like, &lt;a href="http://www.example.com" rel="noopener noreferrer"&gt;www.example.com&lt;/a&gt;. You can create an A record with that name on GCP and change your A record on AWS to NS. This will tell the DNS server that GCP is the one who has the authority to tell where &lt;a href="http://www.example.com" rel="noopener noreferrer"&gt;www.example.com&lt;/a&gt; should resolve to. In this case, you can't just use CNAME instead of NS to route traffic because CNAME can't co-exist with another record of the same name.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;It might be just a basic knowledge, but I hope the elaborated use cases of CNAME and NS record types could help you understand it better somehow.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Basic Network Troubleshooting Commands</title>
      <dc:creator>Wichai Sawangpongkasame</dc:creator>
      <pubDate>Wed, 06 Jul 2022 06:25:29 +0000</pubDate>
      <link>https://dev.to/kradasa4/basic-network-troubleshooting-commands-al7</link>
      <guid>https://dev.to/kradasa4/basic-network-troubleshooting-commands-al7</guid>
      <description>&lt;p&gt;In this article, I will just talk about a few commands I find useful for different situations. Also, I'm currently a Windows user so I might not dive deep into their variation on different OS.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;1. Ping&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ping [IP address or domain name]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can basically use ping with either IP address or domain name (ping will check on the DNS system behind the scene). By default, at least in Windows, ping will send 4 requests to the destination and tell you if any of the packets is lost on the way. If there is none, that means the server is still up and running (and your internet connection is running smoothly).&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%2Fm4cq52cryojjujcy3796.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%2Fm4cq52cryojjujcy3796.png" alt="Ping output on Windows" width="644" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My Use Case: Basically, I would use this to check whether the destination server is up or not, but make sure that your internet connection is not down too.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;2. Telnet&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As ping works at the network level, it won't know about the concept of port which is at the session layer. So telnet comes to the rescue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;telnet [IP address or domain name] [port]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you know, any server can specifically allow only the desired port for security purposes. For instance, you might be able to ping to an address like xxx.xxx.x.x, but the destination might not allow you to connect to its port 8080 (supposedly say that 8080 is its Spring Boot server port). So if you need to work on any specific port, always telnet to check it first. Perhaps the problem might not come from your side.&lt;/p&gt;

&lt;p&gt;My Use Case: Sometimes when you get an integration work you might need your client's IT or security team to allow you to access some of their specific service which is running on a specific port. You could use telnet to check whether they have allowed you to access it already or not.&lt;/p&gt;

&lt;p&gt;The process could take a few minutes, but mostly because the destination is not contactable and after a while you'll get this message.&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%2Fp2i09p1d422x4k9jy9bm.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%2Fp2i09p1d422x4k9jy9bm.png" alt="Telnet failed response" width="800" height="48"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the other hand, if the port is open you will almost get a response immediately and the successful response will result in a blank screen showing up which means the port is open and you could connect to it.&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%2F45mlih4teym26ndxbgjx.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%2F45mlih4teym26ndxbgjx.png" alt="Telnet successful response" width="316" height="42"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, unlike ping, telnet isn't available by default on any OS (as far as I know).&lt;br&gt;
In Windows, you have to turn it on by going to Control Panel &amp;gt; Programs &amp;gt; Programs and Features then, on the sidebar, select Turn Windows features on or off.&lt;/p&gt;

&lt;p&gt;A new window will be opened, just scroll down until you find 'Telnet Client'. Make sure you check that box then click OK. Now, you will be able to use telnet on your command prompt or any other CLI.&lt;/p&gt;

&lt;p&gt;If you're a Mac OS user, just install it using your Homebrew.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install telnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;3. Trace Route&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As the name suggests, this command will trace the router in the path to a given destination and back so it tells us more information than ping. It's like pinging each router on the way to the destination instead of just the destination itself.&lt;/p&gt;

&lt;p&gt;TraceRoute is available by default in both Windows and Mac OS (but not in Linux) though with a different command. It's tracert in Windows but traceroute in Mac OS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tracert [IP address or domain name]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So you could use these commands to troubleshoot some problems, like bottlenecks in which you could pinpoint the router that cause the problem. You might need some domain knowledge here, since you have to know who is responsible for each address. It might be your VPN provider, your partners, your client or whoever.&lt;/p&gt;

&lt;p&gt;The point is, with this command, you can pinpoint that there is something wrong that causes packet loss along the way and now you know that you should get some network engineer to look into this.&lt;/p&gt;

&lt;p&gt;My Use Case: It's quite confusing, but there was once a time I can't connect to my client's internal database although I can telnet to that database port. I thought there was something wrong with my database connection string. It turned out that there was a problem with the path on the way back. I mean, to access that internal DB, I have to go through remote access with VPN proxy and pass through some partners' routers then land on the client's LAN which works out perfectly and result in a successful telnet response. However, on the way back, some client's IT guy configures it so that it will use a different path on the way back and some routers on that path have firewalls that didn't allow me yet. That's why I can telnet just fine, but still can't connect to the DB which I can successfully sign in, but failed to handshake with it due to the obstructed routing path on the way back.&lt;/p&gt;

&lt;p&gt;For further knowledge about trace route, you might find this article useful How to Read a Traceroute - InMotion Hosting Support Center&lt;/p&gt;




&lt;p&gt;These are the basic commands I find useful in daily work. I believe you could learn more related flags elsewhere. I just want to give a vivid picture of how these can be useful in your line of work as a developer. I hope you find it somehow useful. Till next time.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
