Maintaining Pace and Quality in Software Development
Which part of software development consumes most of your energy? To me, it is bug fixing. Yes, bug fixing is normal and it is part of our code development. However, the cost of bug fixing is oftentimes far higher than building the software itself, even more, it could severely impact our team’s morale as it will drag our energy down, and we surely don’t want that. Also, most of us believe that delivering our code weighs a heavy impact. We know users will rely on the software we built. As the saying goes, with great power comes great responsibility. Hence, we want to do our best in delivering our code.
In this article, I wanna share a few tips of mine on how we can deliver our code well while maintaining pace and quality, and keeping the balance of it, as all things should be. Enjoy reading!
Pre-Development
1. Understanding the Requirements
Software development is far more problem-solving than just typing random words. So, before you start typing your code, it is important for you to put in the effort into knowing what you want to build. After all, we are building software to help people accomplish their goals. In order to do this, you can always try to dig deeper into the requirements by asking questions. Seek as much information as you can about the product you are building, how it works, what it intends to do, and what is your goal in building these products. Put your sense of criticality on how the product that you’re going to develop will help users, what is the impact of your code?
2. Know your system architecture
You already understand the requirements and discover the what and why parts. Now comes the how part. We are software engineers, and it is our job to deliver working software to end users, but oftentimes we forgot that we are also responsible to make it works well and maintainable. Like a mechanical engineer creating sophisticated machines, It is our job to create sophisticated software.
Let’s take a look at the system architecture and the layout of our software. Is it understandable, does things are placed and structured as they should be? You can start from the current one (if any), or you can start building your own system architecture. There are many software patterns we can implement when building software. Consider each option, the tradeoff of using certain architecture, and make a decision. You could also ask your team for input. And don’t forget to learn from the best!
3. Plan the technical aspects
Coming to this part, we already know what we are building, and how we are going to do it. Next, we need to write down all technical aspects on a planning document. Some people call it request-for-comments (RFC), and some call it tech plans. The point remains the same, we have to break down our implementation as clearly as possible.
In this step, we will get an estimation of how we are going to approach the development. We could also discuss the tradeoff of using certain patterns. We could detect any potential bugs/flaws that might occur in our software as well. We can put action to it, like adding validation or creating additional components to handle certain cases or logic. Use tables, diagrams, or any illustration to make it easier for everyone to understand your system. And don’t forget to discuss it thoroughly with your team. It is far more likely that we are also working with another person. Getting all of our team on the same page is very important in making sure we are building software in the correct, intended manner.
4. Plan the test
Yes, you don’t read it wrong. To be sure that we understand the requirements well, we need to plan the test. Even if we still need time to figure out how to develop our product, once again, we need to make a test plan. Try to break down the product journey we are going to develop. We can generate cases from every flow on the journey. Here is an example of a test plan that you can use
On Development
1. Make it modular
When coding, strive to make our code modular. Divide our code into smaller, manageable functions that adhere to the SOLID principle. Each function should have a single responsibility, making it easier to understand, test, and maintain. This modular approach improves code readability and promotes reusability.
2. Do we have a usable module?
During code development, give ourselves time to do research on any usable module in our code. This will prevent our code from duplicating and maintaining the same functions multiple times.
3. Unit testing
Unit testing means we test every component of our code. It is easier for us to test a single function with a single responsibility. Our test cases should cover all possibilities, all the way down to corner cases. Unit tests also work as a guarantee seal that says our code works as it should, any modification should adhere to the unit tests it has. This will provide confidence in the correctness of our code and help identify issues early in the development process.
4. Watch out! The code might be used somewhere else!
When maintaining legacy code, please keep in mind that our changes might have an unintentional effect on the other module. We can prevent this by trying to list down all usage of our module and run the unit tests thoroughly, then see if any broken module got impacted. More often than not, we are required to refactor other parts of our software as well.
5. Refactoring
Good engineers write code that works, but great engineers write code that works and is readable. By this point, we already have developed our logic, and we also have guaranteed that it works as expected by unit testing. Refactoring helps us make our code more readable and easier to maintain. We could rearrange the function so that it is more compact, we can extract some parts of our code into a reusable module. Be proactive to make incremental improvements to the code we are contributing. Always remember that we do not code only for the machine but for future developers handling our product.
Post Development
1. Live test your own code
After we finish our code development, we can do a live functionality test of our module on the local environment based on the test that we have planned during the pre-development process. We can mark each case with these options: Not tested, won’t do, failed, or passed. Don’t forget to re-test on the staging environment once our code merges the master branch! Proactively validating your code helps minimize the chances of bugs or glitches during production use.
2. Take pull request review seriously
Pull request review takes a big part in our software development. To review a code, there is required knowledge of the context and language that we are using. Constructive feedback from peers helps identify potential issues, improve code quality, and foster a culture of collaboration within the team. Embrace code reviews as an opportunity to learn, grow, and deliver better code.
3. Evaluation and make it better
Once the code is live, monitor its performance and gather feedback from users. This iterative process of evaluation allows you to make necessary improvements and refine your code over time.
By reaching this line, I wanna say thank you for reading this post. I hope you find it useful. I know sometimes we face things less than ideal. The drive for keeping our pace and quality for delivering code in a balanced manner is coming from our deepest selves. Let’s try our best. Embrace the power of continuous learning and growth. Stay curious, remain adaptable, and always be open to exploring your best way of delivering your code!