👨‍💻
Software Engineering
Refactoring: Improving the Design of Existing Code
Refactoring: Improving the Design of Existing Code
  • Overview
  • Chapter 2
    • Defining Refactoring
    • Why Should We Refactor?
    • When Should We Refactor?
    • Problems with Refactoring
    • Refactoring, Architecture, and Yagni
    • Refactoring & the Wider Software Development Process
    • Refactoring & Performance
    • Going Further
  • Chapter 3
    • Bad Smells in Code
    • Smell: Mysterious Name
    • Smell: Duplicated Code
    • Smell: Long Function
Powered by GitBook
On this page
  • 🦥 Slowing Down New Features?
  • 🏠 Code Ownership
  • 🌿 Branches
  • ⚗️ Testing
  • 🐲 Legacy Code
  • 🛢️ Databases
  1. Chapter 2

Problems with Refactoring

It's important to understand the tradeoffs when applying a technique.

🦥 Slowing Down New Features?

The perception of refactoring as slowing things down is common. It is perhaps, the biggest barrier to people doing enough refactoring.

  • While many believe that refactoring slows down the development of new features, the whole purpose of refactoring is to speed things up.

  • Sometimes we need to make a judgement call based on our professional skills as a programmer.

    • A new feature can be so small that it makes sense to add it while leaving a large refactor for another day.

    • If the code that needs refactoring is in an area we rarely touch, and the cost vs. inconvenience isn't felt very often, then it may make sense to skip it (for now).

    • Delaying a refactoring can be useful if we're not exactly sure what improvement should be made.

  • Too little refactoring is far more prevalent than too much. Most people should try to refactor more often.

  • While managers are often criticized for squelching refactoring for speed, developers are guilty as well.

  • It's important for managers and technical leads to show team members that they value improving the health of the code base. Those with less experience need lots of mentoring to accelerate them through the process.

The primary goal of refactoring isn't "clean code" or "good practices" - it's economic. We refactor because it makes us faster when adding new features & fixing bugs.

🏠 Code Ownership

  • Team ownership of code is preferrable over individual ownership.

  • Programmers may have individual responsibility for areas of a system.

    • That should imply that they monitor changes in that area vs blocking them.

🌿 Branches

  • Long-lived Feature Branches create problems for refactoring due to merge conflicts.

  • Feature branches should be short-lived (days instead of weeks)

    • Break large features into smaller chunks.

    • Use feature toggles/flags to switch off in-process features that can't be broken down.

  • Integrate as frequently as possible!

    • Embrace Continuous Integration

    • Continuous Integration and refactoring work well together.

⚗️ Testing

  • In most cases, if we want to refactor, we need self-testing code.

    • We need to be able to catch errors quickly.

    • To catch errors quickly, we need a comprehensive test suite.

  • Self-testing code not only enables refactoring, it makes it much safer to add new features.

  • Without self-testing code, it's reasonable to worry that refactoring carries too much risk of introducing bugs.

🐲 Legacy Code

  • Refactoring can be a fantastic tool to help understand a legacy system.

  • However, if a legacy system has no tests, you can't safely refactor it.

  • Can we just add tests then? Not so fast...

    • A system is only easy to put under tests if it was designed with testing in mind.

    • There's no simple answer here.

    • Follow the advice in Working Effectively with Legacy Code.

  • Even if we have tests, refactoring legacy code should be tackled in relevant pieces.

    • Refactor areas that are visited frequently and where we realize the benefit of making the code easier to understand.

🛢️ Databases

  • Unlike regular refactorings, database changes are best separated over multiple releases to production. This makes it easier to reverse any change that causes a problem.

  • When renaming a field, gradually move to it by releasing parallel support for both fields, then retire the unused, old field.

    • This approach is known as parallel change or expand and contract.

PreviousWhen Should We Refactor?NextRefactoring, Architecture, and Yagni

Last updated 11 months ago