Refactoring techniques and Design Patterns have been extensively propagated and advocated for over a decade now. Why we still find hard to change, anaemic or overly complex object-oriented structures? What is missing in our design practices?
We posit that continuously refining the abstractions we build in our code is a necessary ingredient for effective refactoring.
In this series, we use Fowler’s didactic Video Store program to show how the focus on refining abstractions generates practical advanced refactoring strategies that improve design simplicity, expressiveness and flexibility beyond standard object-oriented practice.
Refactoring and Design Patterns
Refactoring is a modularity improving technique that is essential for any evolutionary software development process and indispensable in the skill set of any professional software developer.
In the extremely influential book “Refactoring: Improving the Design of Existing Code”, Martin Fowler defines Refactoring as “a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behaviour”.
Fowler’s Refactoring book and the GoF Design Patterns book have played a fundamental transformational role on the professional community, educating a generation of software developers on their move from the procedural to the object-oriented design paradigm. More recently, Joshua Kerievsky published Refactoring to Patterns, leading refactoring to a new level of abstraction by explicitly combining both approaches.
Despite all these resources, why we still see complex object-oriented structures, contrary to the objectives of simplicity, expressiveness and flexibility, also implied by the refactoring definition?
What is Missing?
High-quality software designs are made of modular and expressive abstractions.
“If developers don’t realise that changing code changes the model, then their refactoring will weaken the model rather than strengthen it.”
Domain-Driven Design, by Eric Evans.
Refactoring and design patterns are misused by a large number of software developers. There is an excessive focus at the syntactical level. A broader and deeper perspective is needed when analysing modularity problems and directing the refactoring process towards greater relevance to its design objectives.
The missing points are:
- each refactoring step is an opportunity for refining abstractions;
- abstraction refinements should improve both modularity and expressiveness.
In summary: refactoring processes should consider the program’s context and domain semantics to explicitly rethink both its design structure and abstractions at each refactoring step.
Effective refactoring transcends the program’s text and syntax to improve modularity and keenly enhance simplicity, expressiveness and flexibility.
Fowler’s book introduces refactoring techniques with a small program for a video store, whose main function is to print a statement of a customer’s charges and their frequent renter points.
In this series, we use Fowler’s very simple and rich didactic example to illustrate the following refactoring strategies:
- Adopt Object-Oriented Modules. Apply proper object-oriented design to reduce syntactical noise and make programs easier and safer to work with. Prepare your program to implement most new requirements by small and focused interventions, without generating unintended side effects.
- Reveal the Relevant Domain Concepts. Listen carefully the domain experts to reduce semantic noise by making their relevant concepts explicit and evident in all design expressions.
- Align with Contextual Variance. Confront program invariants with contextual variances to help make design decisions that improve both consistency and flexibility.
These refactoring strategies have been consistently beneficial to our own software design practice over the years. In case you haven’t yet, we strongly suggest you try them in your daily software development activities. We will be very happy to listen to your feedback with ideas and experience with software design and refactoring.
The source code for this software design exploration can be found here.