Using State Machines to Write Bug-Free Code
Learn how to plan your code and make it bug-free.
Join the DZone community and get the full member experience.Join For Free
The first time you heard of a state machine, what did you think it was? I thought it was a debugger. A debugger I could use to find those annoying bugs in my code. A state machine is not a debugger. However, when you master how to use a state machine, the code you write would be on the bug-free side.
What Is a State Machine?
A state machine is an abstract concept that defines and plans the stages and transitions of an application. The application only transitions upon the occurrence of an event. A state machine indicates the initial state of an app, for example, and what would be the next stage - transition - if a user uses the app.
For example, in a functioning Automated Teller Machine (ATM), where you can insert your card, it displays a message like welcome on its screen. That is how the programmer who programmed the ATM designed the initial state of the machine. Once you insert your card, the ATM changes its display and asks for your password. By inserting your card, the ATM transitions to another state. If you enter the right password, the ATM displays its services — withdraw, account balance, transfer, and so on. Each ATM service is a state the ATM could transition.
By clicking on a service rendered by the ATM, it transitions to another state - where you can either withdraw or transfer funds or check your account balance. It depends on what you click.
If you enter the wrong password, the ATM changes to another state that says "sorry, you enter the wrong password" or something like that.
The programmer has planned every state and transition of the ATM. That means if user A, for example, clicks a button on the ATM, the machine changes to a particular state.
Recently, I wanted to access my account on a platform through Google Chrome. I entered my username and password. The website sent a One Time Code (OTP) to my phone number to ensure I was the person trying to login. When I clicked Sign in, the app moved from the sign-in page and threw a bug — it displayed a blank page. There was no place I could enter the code.
Having a planned state machine would have solved the bug. In an instance where the state machine had been well planned, once you click sign-in and you receive the code on your phone, the next page should either be a page having an empty box where you can enter the code or raise an error and direct you back to the sign-in page.
That is how a state machine helps you write bug-free code. The code you write would have envisaged each state of the code, what makes it transition, and to what state.
How to Design State Machine to Write Bug-free Code
The reason why you have bugs in software the result of an input sent to the wrong state. Remember my account login details sent to a blank page? That was because of an inefficient state machine.
To avoid such bugs, here are steps on how to design a well-planned state machine.
1. Identify the Initial State
Before you write code, identify the first state of your application when it becomes a finished product. As an example, initial states like sign-in and or register page. The initial state in the diagram below is the idle state. The idle state could be the sign-in or register state or both. You should first identify the initial stage when the code you write becomes a finished product.
2. Identify Events
Events are what cause an application to move from a state to another — transition. Events could be anything resulting in changes — input, clicks, camera caption, and more. For example, you ordered goods on an e-commerce website; the website takes you to a page where you can request shipping of the goods. On that same page, there is also an option to cancel your order. Ordering the goods or canceling the order is an event.
Identify each event that could make your application transition; this makes your code bug-free. You would have programmed your code to allow specific actions: whether to take a user to the next page or stage - or throw an error message and take a user back to the previous state.
3. Determine Transition
Map out each state your application would be when an input or an action occurs. When a user uses your app, what are the stages the app could move? For instance, you programmed a web application that allows users to borrow books. The first state of the application displays a search box where a user can search for the names of books. If a user enters the name of a book, the app either takes the user to the page where the book is or displays: sorry, the book is not found or on loan. These are transitions - an application moving from one predetermined state to another because of an event.
However, there is an issue a state machine should solve in the above example. What happens if a user enters the name of the book he is looking for and press the search button; while the app is still processing the search, the user inputted a name of a different book and pressed the search button again?
In this case, code having a well-planned state machine would make the second search ineffective till the first search completes. A state machine you planned based on each state helps you identify bugs and also puts you in control.
Why State Machine Needs to Be Designed From a State Perspective and Not Transition
Design a state machine based on the states an application would fall in; such an application does not run into bugs. The design would consider each state the application would be, and each event that should occur before there is a transition. By this, a programmer writes a lesser code and is in control of its application. An application will only carry out functions it is programmed to do and reject everything else.
More so, code would achieve the business logic behind it. The code, in a strict sense, achieves its aim. Take a book reader app as an example. The book reader allows users to store and read books in it. That is the business logic behind the creation of the app. To make people keep and read books on it.
You write long codes in a state machine designed from a transition perspective. Your code would use a lot of conditions trying to accommodate all possible actions a user could take. Along the line, you may lose control and focus on why you're writing code. Your application risks running into many bugs. Transitions are, most times, unknown at the beginning. The best is to determine the states of your app.
A state machine defines and plans the stages of an application. It is planning code on how it should work. A state machine ensures code is bug-free. It also makes sure the business logic behind writing it is achieved.
Published at DZone with permission of Sabit Ololade. See the original article here.
Opinions expressed by DZone contributors are their own.