Chatting About Refactoring and Design Patterns

No matter your position, if you’ve been developing for a while, you’ll come across refactoring or design patterns.

Design patterns are solutions to common programming problems. For instance, if your codebase has a lot of repetitive code, or it’s filled with long, smelly functions, or if adding a new feature means changing lots of code, you’re not alone. Others have faced these issues, too, and have come up with various effective solutions. These classic, representative solutions are known as design patterns. They’re not tied to any specific programming language but serve as a way of thinking or a blueprint that guides you in making your code cleaner and more readable and maintainable.

Common design patterns include Factory, Singleton, Adapter, Proxy, Observer, and Strategy, among others.

Refactoring, on the other hand, is about improving the quality of your code without adding new features, making it clean and neat. While refactoring doesn’t necessarily require using design patterns, knowing them might make the process more effective, as they complement each other.

However, before refactoring, it’s crucial to ensure your program/system has clear specifications and sufficient unit tests and integration tests. Refactoring has a major requirement: it shouldn’t change the program/system behavior. If your “improvements” alter the behavior, it’s not refactoring but rewriting, which can lead to more problems and a lot of unnecessary headaches.

From practical experience, I’ve seen too many cases where refactoring or implementing design patterns ended in disaster, usually due to unclear specifications or insufficient testing. Often, systems needing refactoring suffer from outdated or non-existent documentation and lack adequate tests.

Therefore, the first step in refactoring is always asking the team or yourself: “Are the specifications clear? Are the unit tests sufficient? Have we done integration testing?”