Skip to content

Refactor Flow

This document describes our procedures to track and handle refactor items in our project. Refactor is used as a generalisation of any non-feature nor bug improvement of the code base, something that doesn't mean to change app's external behaviour.

Examples

  • A refactor to update legacy code base
  • A refactor after an improperly implemented or rushed feature
  • Removal of old unused code

Procedure

We want to prevent refactors being implemented during other features, as this complicates PRs and appropriate testing is easy to overlook. So, when a tech debt item is identified and it's unrelated with current work, it is preferable to track it and leave it to correct later:

  1. Create an element on WIP grid, C-Planned phase
  2. Use Bugs / Ideas Template
  3. Process in the same manner as a bug would be

Refactoring Principles

When refactoring, use Martin Fowler's principles:

1. Understand the Code

Before refactoring, make sure you understand the existing code thoroughly. Identify its purpose, functionality, and potential issues.

2. Ensure You Have Tests

Ensure there are comprehensive tests in place for the code you're refactoring. This ensures you don't inadvertently introduce bugs during the refactoring process.

3. Follow the SOLID Principles

  • Single Responsibility Principle (SRP): Each class/method should have only one reason to change
  • Open/Closed Principle (OCP): Code should be open for extension but closed for modification
  • Liskov Substitution Principle (LSP): Subtypes must be substitutable for their base types without altering the correctness of the program
  • Interface Segregation Principle (ISP): Clients should not be forced to depend on interfaces they do not use
  • Dependency Inversion Principle (DIP): High-level modules should not depend on low-level modules; both should depend on abstractions

4. Code Smells

Be aware of code smells like duplicated code, long methods, large classes, and excessive comments. Refactor these areas first.

5. Refactor Step-by-Step

Refactor one small piece at a time. Each refactoring step should be small, understandable, and testable. Commit after each successful refactoring step.

6. Use Descriptive Names

Use meaningful and descriptive names for variables, functions, and classes. A good name can often eliminate the need for a comment.

7. Keep Functions Small

Functions should ideally do one thing. If a function is too long or complex, break it down into smaller, more manageable functions.

8. Comments and Documentation

Eliminate unnecessary comments. Well-written code is self-explanatory. If a comment is needed, it should explain why, not what the code does (unless the 'what' is exceptionally complex).

9. Version Control

Use version control effectively. Commit your changes often, so you can easily revert to a working state if a refactoring step goes wrong.

10. Performance Considerations

While refactoring, keep an eye on performance. Some refactorings might impact performance, so always profile your code after significant changes.

11. Refactoring Patterns

Study common refactoring patterns like Extract Method, Move Method, Extract Class, and Replace Conditional with Polymorphism. Knowing when and how to apply these patterns is key to effective refactoring.

12. Continuous Refactoring

Refactoring is an ongoing process, not a one-time task. Regularly review your code and refactor as needed. This keeps the codebase healthy and maintainable.

Remember

Refactoring is an art that improves the code's design without changing its behavior. It requires a deep understanding of both the problem domain and the programming language. Always strive for simplicity, readability, and maintainability in your code.

Last modified by: Unknown