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.

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.”

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.

Refining Abstractions

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 his 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.

Align with Contextual Variance. Confront program invariants with contextual variances to help make design decisions that improve both consistency and flexibility.

Build Resonant Abstractions.

These refactoring strategies have been consistently beneficial to our 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 about software design and refactoring.