Code Refactoring Techniques in Software Engineering – PZPN Case Study
Mikołaj Zakrzowski
Existing code is not always ideal – but there is a solution. The IT community proves that the code refactoring process is crucial and beneficial for the business.
What is Code Refactoring?
Code refactoring is the process of improving the design, structure, and quality of existing code without changing its external behaviour.
This can involve changing the code's organization, structure, or logic to make it easier to understand, modify, and maintain. Result? Clean code and new internal structure.
Refactoring aims to improve the quality of the code, make it more scalable and maintainable, and reduce the likelihood of bugs and other issues.
Refactoring is an ongoing process that should be performed regularly as part of a software development cycle – preferably using agile methodology. It can help by reducing a chaotic and stressful environment if used properly.
When Should You Consider Software Refactoring?
Code refactoring is vital because it helps to improve the quality, maintainability, and readability of the software code. It also makes it easier to understand and modify.
Think of it like cleaning and organizing your closet – it makes things easier to find and use and improves the overall experience. So maybe it's time to find your inner programming Marie Kondo?
Additional benefits include reducing technical costs, enhancing performance, and making the code more scalable and flexible. Refactoring also helps to fix bugs and refine the overall design of the code, improving the overall frequent testing experience.
When To Refactor the Existing Code:
- The original code has become hard to maintain and understand due to its complexity or disorganization.
- New functionality or changes to the source code are challenging to implement, often requiring significant modifications to the existing code.
- Performance optimization and risk reduction are sought by simplifying the code and removing unnecessary elements.
- Modularity, reusability, and maintainability are needed to support the long-term development and evolution of the software.
- The goal is to improve code quality and address technical debt by tackling code rot, such as duplicated code, elongated methods, and intricate control structures.
- The architecture and design of the code require improvement to align with industry standards and best practices.
- Complex code needs to be broken down into smaller, more manageable units to improve testability and verifiability.
It is important to note that refactoring should be done incrementally and with care, as it can introduce new bugs or affect the code's functionality if not done correctly.
Additionally, it is also a good idea to have a testing team involved. This way, you can ensure the comprehensive suite of tests is conducted – so that the code remains functional after refactoring.
How to Perform Code Refactoring: the Main Techniques
The Top 10 Main Techniques For Performing Code Refactoring Include:
- Extract Method: Moving a code block into a separate, named function to improve readability and maintainability.
- Rename: Renaming variables, functions, or classes to better reflect their purpose and improve code readability.
- Extract Class: Moving related variables and functions into a separate class to improve code organization and modularity.
- Replace Temp with Query: Replacing temporary variables with direct method calls to improve code clarity.
- Replace Conditional with Polymorphism: Replacing conditional statements with polymorphic methods improves code maintainability and reduces the risk of bugs.
- Remove Middle Man: Removing unnecessary intermediaries to improve code clarity and performance.
- Introduce Parameter Object: Grouping related parameters into a single object to improve code readability and maintainability.
- Inline Method: Replacing method calls with the method body to improve code performance.
- Merge Functions into Class: Moving standalone functions into a class to improve code organization and modularity.
- Composing Method: Breaking down an extensive, complex method into more minor, manageable techniques for improved readability, maintainability, and modularity.
When to Refactor Code – Pros & Cons
After this introductory class '101' on refactored code, we can move to risk consideration. The process is complex and needs to be well-thought before proceeding with it (with the help of the QA and testing team).
Here are some helpful pros & cons to consider:
The Benefits of Refactoring Code
The core benefits of code refactoring are:
- Improved readability and maintainability: Refactoring helps to make the code easier to understand and maintain by breaking down complex code into smaller, more manageable units and improving the overall organization and structure of the code.
- Better performance: Refactoring can optimize the performance of the code by removing unnecessary elements and simplifying complex code structures.
- Reduced bugs: Refactoring can reduce the risk of bugs by eliminating unnecessary code and making it easier to test and verify the code's functionality.
- Increased modularity and reusability: Refactoring makes the code more modular and reusable by breaking down complex code into smaller, well-defined methods and improving the overall architecture and design of the code.
- Improved quality and reduced technical debt: Refactoring helps improve the code's overall quality and reduce technical debt by fixing code smells and aligning the architecture and design of the code with best practices and design patterns.
- Better alignment with industry standards: Refactoring can help to align the code with industry standards and best practices, making it easier to integrate with other systems and tools and support the long-term evolution and growth of the software.
- Easier testing and verification: Refactoring can make the code easier to test and verify by breaking down complex code into smaller, more manageable units that can be easily tested and validated.
The Downsides of Code Refactoring
Some cons of code refactoring are:
- Time consumption: Refactoring can be time-consuming, taking resources away from other development tasks.
- Risk of introducing bugs: Refactoring involves changing the code, which can introduce new bugs or cause existing ones to reappear.
- Compatibility issues: Refactoring can cause compatibility issues with other parts of the system that rely on the code being refactored.
- Requires specialized skills: Refactoring requires a good understanding of the code, its design and architecture, and the ability to recognize areas that can be improved.
- Difficulty in testing: Refactoring can make it challenging to test the code, especially if the changes are significant and the code relies on a complex system of dependencies.
- Requires careful planning: Refactoring requires careful planning to ensure that changes do not negatively impact the code's functionality.
- Can be expensive: Depending on the scale of the refactoring project, the costs associated with it can be substantial, including software development time, testing, and debugging.
Will Code Refactoring Negatively Affect the Functioning of my Production Application?
The simple answer? No, if done properly. Refactoring code can influence the functioning of a production application if the changes made during refactoring alter the application's behaviour in unintended ways.
It is essential to thoroughly test the application after refactoring to ensure it continues functioning as expected.
Software developers can perform refactoring changes in such a way that will reduce the risk of potential risks. This can be done by having proper version control of legacy code/duplicate code, and backup systems in place can help mitigate the risks associated with refactoring in a production environment.
If everything works correctly after the test-driven development, it is time to implement the written clean code in production.
How to Conduct Successful Code Refactoring – Best Practices
Exemplary Steps To Conduct Successful Code Refactoring:
- Identify the need for refactoring: Analyse the code and determine which parts require refactoring to improve its quality and maintainability.
- Plan the refactoring process: Determine the changes you want to make, and develop a plan for implementing them.
- Test the code: Before making changes to the code, ensure that it is thoroughly tested to identify any potential issues or bugs.
- Make small, incremental changes: Refactor small parts of the code simultaneously, ensuring that each change is tested before moving on to the next.
- Automate the testing process: Use automated tools to quickly and easily test the code after each change, reducing the risk of introducing new bugs.
- Document the changes: Keep detailed records of the changes you make during the refactoring process, including any updates to documentation and code comments.
- Monitor and evaluate the results: Regularly monitor the code and the results of the refactoring process to ensure that the desired outcomes are achieved.
- Repeat as necessary: Refactoring is an ongoing process. Code should be regularly reviewed and updated to ensure that it remains maintainable and scalable. Note! It is good to separate the refactoring process from the existing code to prevent code duplication.
- Remember! Refactor first before adding any new features. Also, involve your QA and testing team, as their work can detect mistakes and improve the functionality of written code.
Case Study – Refactoring Code in PZPN
PZPN (Polish Football Association) is Poland's governing body of association football. Our client has an application (developed and maintained by hero/dot & TISA) that main goal is to help train the youth in the football community – it acts as a proxy.
Using that application, football schools apply for support from PZPN. Certification programme created by the Association. In 2022 1182 football schools applied for the certification programme, proving that Poland loves football!
The mentioned system runs on two applications, one of them being organisational (CERT-ORG) and the second one financial (FIN-ORG). They work harmoniously to coordinate the football school registration process (via CERT-ORG) and keep track of spending and financial aid (FIN-ORG).
Challange
The main challenge PZPN faced with this application was long loading times. The code was prone to queue errors, and the system was too complicated. In addition, it often led to frustration when the system had to operate with many inquiries simultaneously. Goal? To make everything more efficient and smoother working.
As part of our work at hero/dot, we are responsible for refactoring the code of the PZPN application FIN-ORG integrating the data from the CERT-ORG to the CERT-FIN system. The end goal was to optimise the data transfer times between those two systems. Also create greater integrity during synchronisation between them.
We used technologies and programming languages such as .NET Core (update from 5.0 to 6.0), C# coding language, and a few elements coded in T-SQL using the Dapper repository. This enabled the team to use new features of the .NET platform that allowed a swift refactoring process of the code.
The refactor was done due to the identification of a few crucial issues. These issues affected integration time and guaranteed consistency and quality of deposited data. First, the workflow of the FIN-ORG system created a significant number of notifications that. As a result – were creating a metaphorical 'queue' – just like the one in your local bakery at 7 AM.
Solution
After a thorough investigation, the development team decided to delete the FIN-ORG application. Then move the data model (copies of mapped data from CERT-FIN) to the project of the CERT-ORG application. As a result, there was no need to transfer data between systems. Thus leading to a shorter dependency chain between systems/queues moving data between CERT-ORG and CERT-FIN.
Results
What are the main benefits achieved through this process? Efficiency, faster work, less prone to errors and stable code. Even though the goal may not always be visible during the process, the result will prove worth it. No more extended waiting times, key features are working smoother, and what's important – the system is easier to work with.
Code that is shorter, logical and well-structured will also be easier to work with. Even when something does not work correctly, it is easier to locate and fix the issue than when it's cluttered. Additionally, it's beneficial for creating unit testing, as the code will be easy to understand for all involved parties. As for the application, it is cheaper to maintain and less prone to malfunction.
Refactoring code – Further Steps and Summary
Local variables, unnecessary methods, new classes, unit tests – the whole Thesaurus of code refactoring...
We are glad you made it to this point, as it is not an easy topic to discuss. Yet it is vital for the digital world today.
If you are to keep the most important information from this article, then we would suggest remembering that Marie Kondo of programming would approve of all the steps you will take to make sure that your code is clean, made using streamline methods, has tool support of all the newest versions on the market and is free of technical debt.
Speaking of simplifying methods and implementation details – the refactoring process can be challenging – but can be tamed with the right people on board.
If you need the support of an experienced team with code refactoring for your business, we would be more than happy to help you. Our experts will recognise your needs and find tailor-made solutions.
Feel free to contact us at hello@herodot.com – let's code your vision together!
Need expert assistance with your digital project?