Stability through structure preserving change

Refactoring to Patterns[RtP04], by Joshua Kerievsky, is a book about repairing and increasing code quality. It marries the two ideas of refactoring and patterns, which means instead of refactoring alone, which is a technique of making change safe, it brings in the element of patterns, which should restrict those changes to the right ones. Before this book, software patterns were primarily1 presented as static forms.

However, this idea that a pattern is a static form did not align with Christopher Alexander’s works. It’s not how he described patterns in The Timeless Way of Building[TTWoB79]. Patterns were never just an end goal; they were always a process as well. They are a verb and a noun, a self-forming system reinforcing its state through forces and reactions.

Refactoring to Patterns is a book about design patterns in a much truer sense. It is a book on repairing. It is indispensable in this era of building things fast and worrying about maintenance later. The move-fast-and-break-things era might be somewhat over, but we live with the legacy of a decade of products formed by this mindset. People made things that were insecure, unscalable, invasive, corrupting, and, at the same time, ubiquitous, foundational, and critical to our progress.

Refactoring to Patterns admits we don’t get it right the first time. The book recognises the state of systems and repairs them. We know we write code before we’re sure about it, as that’s how you find out it was wrong. We build it up and then refactor it when we recognise the latent patterns.

Before I came across this book, I was stumped to find a way to marry the 15 properties to software development. I had only recognised a few properties, such as repetition with variation and hierarchy of refinement, and some from my preferred paradigm, such as decisions made early and request actions, express interest in state. The value in both refactoring books was in the inspiration that I could find these properties from their constructive steps. When Alexander discussed the 15 properties, he was never far from describing how the property arrived. Each property came with a process to create it from what was around it or was a byproduct of a wholesome process. If the same properties exist in software, they may undergo the same type of transformation. This means they will likely turn up during refactoring or in regularly repeated feature development processes.

Refactoring, with patterns in mind, is an unfolding sequence. Because refactoring is not meant to change behaviour, it is structure (or value) preserving. What’s fantastic is that this means we have two positive outcomes. Pattern refactoring allows you to migrate an old codebase towards a better state. It also suggests thinking about patterns can be put off until later. Refactoring always applies to existing code, implying you don’t need to figure out what patterns to introduce until later. Don’t take this as a suggestion to avoid any up-front planning, but you can stop beating yourself up over not realising you needed a pattern until halfway through a project.

Scale

As a project grows in size, neighbours become distant acquaintances. The original project may have had one developer, then a team, then teams. Refactoring good quality systems into larger ones is always much more successful than creating a large system from scratch. Refactoring appears to be the only way to unfold a system of code. Rewrites don’t carry any of the lessons learned in the code; those exist only in the fallible minds of the team developing the replacement (this is assuming the team is the same as the one that created it; a fresh team is hopelessly cursed to reproduce eerily similar bugs the second time around).

Why is this the only good way to develop a large system? It’s a simple case of acting on incomplete data. In Domain Driven Design[DDD04], the concept of a Ubiquitous language drives a way of thinking about the code centred around the real problem in the language of the problem domain. During development, programmers and architects regularly have revelations regarding the meaning of words used by the experts. These revelations create new meaningful connections between aspects of the code. These connections demand you refactor the code. Revelations often lead to object splits or joins, refactoring objects into more entities or combining methods or objects that aren’t as different as presumed. Sometimes, we reinterpret an existing identity as a transient form of another object or bring another entity into existence that has so far remained unmentioned.

All these changes are only required after many rounds of returning to the experts to get their evaluation of the system once it has been designed or even implemented. A non-expert can only deduce some of the interacting objects and activities they are involved in before writing the first lines of code. We cannot expect the experts to know what they weren’t sharing due to the curse of knowledge2.

The information about how the system should work was always there, just as the laws of physics, the materials, and the landscape upon which a building is built are all there from the first moment of the contract. And just as Christopher Alexander found, even with all that information, the solution is intractable for the human mind. It needs augmenting with processes and tools—a piece-wise process of experimentation, evaluation, repair, and remodelling. In code, this is an iterative and incremental refactoring process.

Architecture needed a way to introduce new features incrementally and evolve the design and implementation. What Christopher Alexander developed was the process of unfolding.

1

Even though the GoF book does mention the patterns as targets for refactoring, it’s near the end of the book (p. 353) and not introduced as a step for each pattern, so it’s easily overlooked.

2

https://en.wikipedia.org/wiki/Curse_of_knowledge the failure to consider how much you take for granted. Like how old programmers, upon observing a limit of 255, assume something about the implementation, but non-technical people would have no idea what that would imply.