<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Tayna]]></title><description><![CDATA[Software Developer | Computer Engineer]]></description><link>https://tayna.dev</link><generator>RSS for Node</generator><lastBuildDate>Wed, 15 Apr 2026 23:56:31 GMT</lastBuildDate><atom:link href="https://tayna.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Simplifying Our Codebase with Finite State Machines (FSM)]]></title><description><![CDATA[Initially posted in DBA Blog: Simplifying Our Codebase with FSM
Introduction
Every application has states. Whether we define them or not, we cannot escape from managing them, even if we are not fully aware of them. But the side effects of having unde...]]></description><link>https://tayna.dev/simplifying-our-codebase-with-finite-state-machines-fsm</link><guid isPermaLink="true">https://tayna.dev/simplifying-our-codebase-with-finite-state-machines-fsm</guid><category><![CDATA[state-machines]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[fintech]]></category><category><![CDATA[backend]]></category><category><![CDATA[Ruby on Rails]]></category><dc:creator><![CDATA[Tayna Oliveira]]></dc:creator><pubDate>Sun, 18 Dec 2022 16:34:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1671380199424/ISuVZE7gN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Initially posted in DBA Blog:</em> <a target="_blank" href="https://dbadbadba.com/blog/simplifying-our-codebase-with-finite-state-machines"><em>Simplifying Our Codebase with FSM</em></a></p>
<h3 id="heading-introduction">Introduction</h3>
<p>Every application has states. Whether we define them or not, we cannot escape from managing them, even if we are not fully aware of them. But the side effects of having undefined states are bloated databases and overly complicated logic. This complexity becomes increasingly challenging to deal with each time we need to change some logic, and our work becomes more stressful.</p>
<p>The purpose of this post is to present Finite State Machines (FSM) as a design pattern helpful in managing the different states of a software application.</p>
<p>Those with an engineering background or who like to create automation for fun may already understand the FSM concept and its real-world applications. The concept of FSM in software development is equivalent to how we describe different states in the real world. However, the input-output complexities of the virtual environment require different nomenclature than an analog environment.</p>
<h4 id="heading-learning-state-machines-is-like-learning-a-superpower-why-because-states-are-everywhere-and-learning-how-to-manage-their-complexity-easily-is-a-very-powerful-tool">Learning state machines is like learning a SUPERPOWER. Why? Because states are everywhere, and learning how to manage their complexity easily is a very powerful tool.</h4>
<h3 id="heading-and-what-are-these-states-that-we-are-talking-about">And what are these states that we are talking about?</h3>
<p>Let’s consider the example of water. Water can exist in three different states: liquid state, solid state, and gaseous state. External events, such as a temperature change, trigger a transition between these states.</p>
<p>Or, we can consider a lamp, with its <code>On</code> and <code>Off</code> states.</p>
<p>In each of these examples, we have mental models that allow us to describe the states of a current entity intuitively. FSM allows us to do this with our applications.</p>
<h4 id="heading-but-what-are-states-in-the-context-of-software">But what are states in the context of software?</h4>
<p>If you look at your codebase and see entities associated with columns like <code>approved_at</code> (or <code>approved</code> boolean column), <code>pending_at</code>, <code>refunded_at</code>, <code>reproved_at</code>, <code>paused_at</code>, <code>failed_at</code>, <code>deposited_at</code> , <code>canceled_at</code>, or even boolean-similar columns, are columns used to manage possible states that your entity can enter depending on certain conditions. Let's consider the following refund method:</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Transaction</span> &lt; ActiveRecord::Base</span>
  <span class="hljs-comment"># ...</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">refund!</span></span>
    <span class="hljs-comment"># check states one by one 😩</span>
    <span class="hljs-keyword">if</span> pending_at.present? &amp;&amp; canceled_at.blank? &amp;&amp;    deposited_at.blank? &amp;&amp; refunded_at.blank?
      update!(<span class="hljs-symbol">refunded_at:</span> Time.zone.now)
    <span class="hljs-keyword">else</span>
      raise <span class="hljs-string">"Invalid state 🔥🔥🔥🔥🔥"</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>

  <span class="hljs-comment"># ...</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>I’m sure that everyone who codes has seen a code like this. Maybe this code above doesn’t seem so bad to you, but think for a few seconds more and imagine having the 'ifs' for each of the states described above. Do we know exactly what state came before or after the current state? Or which actions to trigger before each state transition?</p>
<p>We probably would need to read a lot of methods and maybe walk through a few different classes to understand the context of the entity and its possible states. Only then would you be able to abstract what is going on (<em>and even then, maybe not</em> 😅).</p>
<p>Wouldn’t it be great to have a clear way of defining these states and managing them? The good news is that we can do that with Finite State Machines.</p>
<h3 id="heading-what-is-fsm-in-the-context-of-software">What is FSM in the context of software?</h3>
<p>A state machine is a mathematical abstraction used to design algorithms that draw the state flow for an entity. The FSM is one of a finite number of states at any given time. A state machine reads an input (<em>event</em>) and switches to a different state based on the input. The FSM describes all the states, the transition between these states, the events that will trigger each transition when a transition should happen (<em>guard</em>), and the actions to execute (<em>like sending an email or calling another method</em>) once a transition is executed.</p>
<ul>
<li><p><strong>state:</strong> A description of the status of a system/entity at a given moment.</p>
</li>
<li><p><strong>transition</strong>: A set of actions to be delivered when an event is received that will trigger a change from one state to another.</p>
</li>
<li><p><strong>event:</strong> The "external" stimulus a system receives, often causing a change in its state. Once an event occurs, the system can either change, remain in its current state, and/or perform an action.</p>
</li>
<li><p><strong>actions (callbacks):</strong> Any operation needed to ensure the expected behavior given a specific state. An action can start before or after a transition, or an event can trigger it.</p>
</li>
<li><p><strong>guard conditionals:</strong> A condition that must be met for an event to trigger a transition.</p>
</li>
</ul>
<h4 id="heading-why-should-i-use-an-fsm-in-my-codebase-if-i-can-manage-states-with-control-flows">Why should I use an FSM in my codebase if I can manage states with control flows?</h4>
<p>The benefits of using a state machine in our codebase are:</p>
<ul>
<li><p>Less cognitive load:</p>
<ul>
<li>Use of declarative programming: Focus on what needs to be done, not how to do it</li>
</ul>
</li>
<li><p>Previsibility: rules are well defined</p>
<ul>
<li>No weird states since all states are defined. They name all possible states and define which the application should never enter.</li>
</ul>
</li>
</ul>
<p>State machines avoid situations where data silently becomes invalid. When used atomically with a database, we have security in state transitions.</p>
<p>Simply put, FSM makes it much easier to maintain and change the application states. Less time, less money, less effort.</p>
<h3 id="heading-modeling-a-software-problem-using-state-machine">Modeling a software problem using State Machine</h3>
<p>Let’s solve a real software modeling problem that most fintech encounter. We will use a Ruby state machines framework, AASM, although the state machine model can be applied to other languages. The solution will be divided into three steps, each presenting a new scenario demonstrating the ease and flexibility of state machines. We will focus only on modeling the problem, describing the states, and a few transitions between these states.</p>
<h4 id="heading-step-1-simple-deposit">Step 1: Simple Deposit</h4>
<p>Consider a scenario where we have one Application with users' accounts, and we're asked to create a feature that invests the user's local fund (App) into an external investment account (Investment Platform).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671380477624/pnEK0yBiI.png" alt class="image--center mx-auto" /></p>
<p>To model this problem, one of the solutions is to create a <code>Transaction</code> entity. We will have three states to represent each moment of this transaction.</p>
<ul>
<li><p><code>draft</code>: The transaction's initial state. This will be the state when a new transaction record is created.</p>
</li>
<li><p><code>depositing</code>: This state will represent a successful request to transfer money from the App to the Investment Platform. We need to keep in mind that we are dealing with instantaneous transfers. A bank transaction can take a few business days to be completed.</p>
</li>
<li><p><code>deposited</code>: Once the money hits the Investment Platform, we will use this state to represent that money has been deposited into the destination account.</p>
</li>
</ul>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">module</span> <span class="hljs-title">TransactionStateMachine</span>    </span>
    <span class="hljs-comment"># ...</span>
<span class="hljs-keyword">end</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Transaction</span> &lt; ActiveRecord::Base</span>
  <span class="hljs-keyword">include</span> TransactionStateMachine
<span class="hljs-keyword">end</span>

Transaction.new
</code></pre>
<p>We would have a state machine similar to this one:</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">module</span> <span class="hljs-title">TransactionStateMachine</span>    </span>
  <span class="hljs-keyword">include</span> AASM

  aasm <span class="hljs-keyword">do</span>
    state <span class="hljs-symbol">:draft</span>, <span class="hljs-symbol">initial:</span> <span class="hljs-literal">true</span>
    state <span class="hljs-symbol">:depositing</span>
    state <span class="hljs-symbol">:deposited</span>

    <span class="hljs-comment"># events...</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>We declare all the possible transitions between states and which events will trigger the state transition:</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">module</span> <span class="hljs-title">TransactionStateMachine</span></span>
  <span class="hljs-keyword">include</span> AASM

  aasm <span class="hljs-keyword">do</span>
    state <span class="hljs-symbol">:draft</span>, <span class="hljs-symbol">initial:</span> <span class="hljs-literal">true</span>
    state <span class="hljs-symbol">:depositing</span>
    state <span class="hljs-symbol">:deposited</span>

    event <span class="hljs-symbol">:depositing_via_api</span> <span class="hljs-keyword">do</span>
      transitions <span class="hljs-symbol">from:</span> <span class="hljs-symbol">:draft</span>, <span class="hljs-symbol">to:</span> <span class="hljs-symbol">:depositing</span>
    <span class="hljs-keyword">end</span>

    event <span class="hljs-symbol">:api_success</span> <span class="hljs-keyword">do</span>
      transitions <span class="hljs-symbol">from:</span> <span class="hljs-symbol">:depositing</span>, <span class="hljs-symbol">to:</span> <span class="hljs-symbol">:deposited</span>,
                  <span class="hljs-symbol">after:</span> [<span class="hljs-symbol">:update_balances</span>]
    <span class="hljs-keyword">end</span>

    private

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update_balances</span></span>
      <span class="hljs-comment"># ...</span>
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>The <code>update_balances</code> the method is an action that should be performed after the Transaction state transitions from <code>depositing</code> to <code>deposited</code>.</p>
<h4 id="heading-step-2-intermediary-account">Step 2: Intermediary Account</h4>
<p>In another scenario, the transfer would not simply be from the origin account to the destination account but from the origin account to an intermediary account (Middle Account) on the Investment Platform. Then, once money is available on this Middle Account, we can request to allocate the amount to the destination account inside the Investment Platform.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671380527052/DIYSpn3cy.png" alt class="image--center mx-auto" /></p>
<p>What would be the change needed to implement this new criterion?</p>
<p>Since we have the <code>TransactionStateMachine</code> with the states and events in declarative programming, adding new states to our entity is very simple. The flow from APP -&gt; MIDDLE ACCOUNT is mostly the same as in Step 1. The only thing that will change is that we need one more step until the money is available on the destination account inside the Investment Platform.</p>
<p>As shown in the image below, we need to represent the transfer from the MIDDLE ACCOUNT -&gt; DESTINATION ACCOUNT in the Transaction state machine. To represent this in our state machine, we will add two new states:</p>
<ul>
<li><p><code>invested</code>: Once the money hits the Investment Platform account, this state will represent that money is deposited in the destination account.</p>
</li>
<li><p><code>investing</code>: This state will represent the successful request to transfer money from the MIDDLE ACCOUNT -&gt; DESTINABLE ACCOUNT. Unlike the <code>depositing</code> state, this transfer happens inside the Investment Platform.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671380556048/0E9ZPbdv_.png" alt class="image--center mx-auto" /></p>
<p>The same mental model we used to describe the problem above in words, we now use to describe the problem in code. This is because we are using a declarative programming format.</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">module</span> <span class="hljs-title">TransactionStateMachine</span></span>
  <span class="hljs-keyword">include</span> AASM

  aasm <span class="hljs-keyword">do</span>
    state <span class="hljs-symbol">:draft</span>, <span class="hljs-symbol">initial:</span> <span class="hljs-literal">true</span>
    state <span class="hljs-symbol">:depositing</span>
    state <span class="hljs-symbol">:deposited</span>
    state <span class="hljs-symbol">:investing</span> <span class="hljs-comment"># &lt;========== new</span>
    state <span class="hljs-symbol">:invested</span>  <span class="hljs-comment"># &lt;========== new</span>

    event <span class="hljs-symbol">:depositing_via_api</span> <span class="hljs-keyword">do</span>
      <span class="hljs-comment"># ...transitions</span>
    <span class="hljs-keyword">end</span>

    event <span class="hljs-symbol">:api_success</span> <span class="hljs-keyword">do</span>
    <span class="hljs-comment"># we added an after method on the transition from depositing -&gt; deposited</span>
      transitions <span class="hljs-symbol">from:</span> <span class="hljs-symbol">:depositing</span>, <span class="hljs-symbol">to:</span> <span class="hljs-symbol">:deposited</span>, <span class="hljs-symbol">after:</span> <span class="hljs-symbol">:start_next_transfer</span> <span class="hljs-comment"># &lt;========== new</span>
      transitions <span class="hljs-symbol">from:</span> <span class="hljs-symbol">:investing</span>, <span class="hljs-symbol">to:</span> <span class="hljs-symbol">:invested</span> <span class="hljs-comment"># &lt;========== new</span>

    <span class="hljs-keyword">end</span>

    private

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">start_next_transfer</span></span>
      StartTransferWorker.perform_async(<span class="hljs-keyword">self</span>)
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>In addition to the two new states, notice that we have added an <em>after</em> <em>method</em> to the transition from <code>depositing -&gt; deposited</code>. And why is that? Well, with the new criterion of having an intermediary account, we need the transaction transitioned for all of the states to complete the transfer successfully: <code>draft -&gt; depositing -&gt; deposited -&gt; investing -&gt; invested</code>.</p>
<p>The after method <code>start_next_transfer</code> is added because once the state machine realizes that money is available on the MIDDLE ACCOUNT, we must initialize the next transition to complete the transaction flow. This is the reason for calling the <code>start_next_transfer</code> method after the transaction state transition from <code>deposited -&gt; deposited</code>.</p>
<p>This is an example of the FSM actions mentioned above. Since we have these callback (action) methods associated with the transitions between states, we can easily discover what actions must happen in each state the application can enter.</p>
<h4 id="heading-step-3-batch-transaction-hierarchical-fsm">Step 3: Batch Transaction (Hierarchical FSM)</h4>
<p>In a third scenario, we discover some critical information that obligates us to rethink how to represent the transfer between banks (<em>Transaction flow</em>) in our codebase: Each transfer costs <code>$0.20</code>. This new information means that for <strong>1MM transactions = $200,000</strong> (💸💸💸💸).</p>
<p>Let’s consider an example of two transactions, one of $100 and the other of $150 (as shown in the image below).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671380601391/r3B3aVPsT.png" alt class="image--center mx-auto" /></p>
<p>We have two main things that are represented by a <code>transaction</code> record that we show in Step 1 and Step 2:</p>
<ul>
<li><p>the actual transfer between banks accounts (the APP bank account -&gt; INVESTMENT PLATFORM Account)</p>
</li>
<li><p>the individual transfer created in our APP ($100 that a particular user wants to invest)</p>
</li>
</ul>
<p>We used the same entity to represent both logics, but now we don’t want to use this entity to represent the transfer between banks because we will pay $0.20 for each transfer. We need to find a way of batching some transactions to minimize costs.</p>
<p>To batch transactions amounts, we will create a new entity called <code>BankTransaction</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671380621951/MvXWkGjF-.png" alt class="image--center mx-auto" /></p>
<p>This will be a relation of <code>BankTransaction 1...N Transaction</code>.</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BankTransaction</span> &lt; ActiveRecord::Base</span>
  <span class="hljs-keyword">include</span> BankTransactionStateMachine

  has_many <span class="hljs-symbol">:transactions</span>
<span class="hljs-keyword">end</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Transaction</span> &lt; ActiveRecord::Base</span>
  <span class="hljs-keyword">include</span> TransactionStateMachine

  belongs_to <span class="hljs-symbol">:bank_transaction</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>With this new entity, we can create a new bank transaction, and this record will have the sum of all associated transaction amounts. Considering the example above, we have two transactions: $100 and $150. Once we request to transfer money from one account to another, we will have a bank transaction of $250 representing this transfer between banks.</p>
<p>The <code>TransactionStateMachine</code> will continue the same, but now the events on <code>TransactionStateMachine</code> will be triggered by actions on <code>BankTransactionStateMachine</code>.</p>
<p>This is how the <code>BankTransactionStateMachine</code> would look - very similar to the Transaction state machine. Notice that the events on <code>TransactionStateMachine</code> will be triggered by actions on <code>BankTransactionStateMachine</code>. This is a case of a <em>hierarchical state machine</em> since one state machine transition depends on another state machine.</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">module</span> <span class="hljs-title">BankTransactionStateMachine</span></span>
  <span class="hljs-keyword">include</span> AASM

  aasm <span class="hljs-keyword">do</span>
    state <span class="hljs-symbol">:draft</span>, <span class="hljs-symbol">initial:</span> <span class="hljs-literal">true</span>
    state <span class="hljs-symbol">:creating</span>
    state <span class="hljs-symbol">:pending</span>
    state <span class="hljs-symbol">:settled</span>
    state <span class="hljs-symbol">:failed</span>

    event <span class="hljs-symbol">:created_via_api</span> <span class="hljs-keyword">do</span>
      transitions <span class="hljs-symbol">from:</span> <span class="hljs-symbol">:creating</span>, <span class="hljs-symbol">to:</span> <span class="hljs-symbol">:pending</span>, <span class="hljs-symbol">after:</span> <span class="hljs-symbol">:update_transactions_after_creation</span>
    <span class="hljs-keyword">end</span>

  event <span class="hljs-symbol">:settled_via_api</span> <span class="hljs-keyword">do</span>
      transitions <span class="hljs-symbol">from:</span> <span class="hljs-symbol">:pending</span>, <span class="hljs-symbol">to:</span> <span class="hljs-symbol">:settled</span>, <span class="hljs-symbol">after:</span> <span class="hljs-symbol">:update_transactions_after_settlement</span>
    <span class="hljs-keyword">end</span>

    private

  <span class="hljs-comment"># these actions calls the `transaction` state machine event</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update_transactions_after_creation</span></span>
      transactions.each(&amp;<span class="hljs-symbol">:bank_transaction_created!</span>)
    <span class="hljs-keyword">end</span>

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update_transactions_after_settlement</span></span>
      transactions.each(&amp;<span class="hljs-symbol">:bank_transaction_suceeded!</span>)
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>Once the total amount of transactions is available in the Investment Platform, we can request to transfer money to the destination accounts.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671380641105/--qqGVeW1.png" alt class="image--center mx-auto" /></p>
<p>We can now split the amount and transfer the expected amounts to the users' respective accounts. Since we are transferring money inside the Platform, we do not pay any fee for these transfers.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671380684306/Od6WI741B.png" alt class="image--center mx-auto" /></p>
<p>The <code>TransactionStateMachine</code> is the same. We just changed the event names to a better reading.</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">module</span> <span class="hljs-title">TransactionStateMachine</span></span>
  <span class="hljs-keyword">include</span> AASM

  aasm <span class="hljs-keyword">do</span>
    <span class="hljs-comment"># ...</span>

    event <span class="hljs-symbol">:bank_transaction_suceeded</span> <span class="hljs-keyword">do</span>
      transitions <span class="hljs-symbol">from:</span> <span class="hljs-symbol">:depositing</span>, <span class="hljs-symbol">to:</span> <span class="hljs-symbol">:deposited</span>, <span class="hljs-symbol">after:</span> <span class="hljs-symbol">:start_next_transfer</span>
      transitions <span class="hljs-symbol">from:</span> <span class="hljs-symbol">:investing</span>,  <span class="hljs-symbol">to:</span> <span class="hljs-symbol">:invested</span>,  <span class="hljs-symbol">after:</span> <span class="hljs-symbol">:email_user</span>
    <span class="hljs-keyword">end</span>

  event <span class="hljs-symbol">:bank_transaction_created</span> <span class="hljs-keyword">do</span>
      transitions <span class="hljs-symbol">from:</span> <span class="hljs-symbol">:draft</span>, <span class="hljs-symbol">to:</span> <span class="hljs-symbol">:depositing</span>
    <span class="hljs-keyword">end</span>

    private

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">start_next_transfer</span></span>
      StartTransferWorker.perform_async(<span class="hljs-keyword">self</span>)
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<h3 id="heading-when-should-we-use-fsm-in-our-codebase">When should we use FSM in our codebase?</h3>
<p>Should you use FSM when you have 1 or 2, or 3 states? Is the quantity of states determining when we should use FSM in our codebase? Or is it the complexity of each state?</p>
<p>The short answer here is that <strong>it’s not written in stone</strong>.</p>
<p>I have asked some experienced developers what their rules are for using an FSM approach. The answers are all different. The only thing that all of them agree on is that the more states or complexity between states, the more obvious the benefits of using a state machine become.</p>
<p>We are problem solvers, and it’s up to us to decide when to use it. Some tips are, if you see the following things throughout the codebase, it would probably be beneficial to use a state machine instead:</p>
<ul>
<li><p>Boolean columns in a database</p>
</li>
<li><p>Enums to model situations states</p>
</li>
<li><p>Variables that have meaning only for some part of your application lifecycle</p>
</li>
<li><p>Looping through an if-else structure to check whether a particular flag or enum is set and then executing actions based on that</p>
</li>
</ul>
<h3 id="heading-my-personal-suggestion-is">My personal suggestion is:</h3>
<ul>
<li>Use an FSM approach when dealing with money, payments, bank transactions, and others. You only have to gain in these scenarios. Do not try to guess and think that your application will not change or grow the quantity and complexity of its states.</li>
</ul>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Finite State Machines can model problems in many fields, including mathematics, artificial intelligence, games, or automation. Finite State Machines come from a branch of computer science called "automata theory". Its broad applicability, however, is only beginning to make its way into software applications.</p>
<p>The state machine model can be applied to many programming languages. You can even create your own state machine. FSM is used for modeling frontend and QA tasks too. In each case, there are gains from using FSM modeling. The main idea is to follow the modeling and logic of FSM, where we have all possible states defined and we follow descriptive programming. These two main rules will give us the benefits of using FSM logic in our codebase.</p>
<p>With this new tool at your disposal, you will bring predictability to your codebase and regain some peace of mind when managing your application’s states.</p>
]]></content:encoded></item></channel></rss>