Turning monsters into friends
Barry O'Sullivan
@barryosull
DDDEU 2021
@barryosull
Barry O'Sullivan
How we discuss legacy
REWRITE IT!
BURN IT!
SWITCH TO TYPESCRIPT!
OLD DEVS WERE LAZY/RUBBISH!
WOOF!
1
2
3
NO POWER FANTASY FOR YOU!
Software: Prepare to die edition
I'M THE BEST
Dev
Legacy
1. Ego
2. Ignorance
The two main blockers
"All models are wrong but some are useful"
"True ignorance is not the absence of knowledge, but the refusal to acquire it"
Exploring and gaining context
Explore
Iterate/Refactor
Build a model
Q
Iteration leads to discovery
Explore instead of conquer
Let designs/patterns emerge
Don't force it, be patient
Iterative approach
Respect the legacy code
Build a mental map
What you gain
Working with care
"I'll have it done at half past never"
Refactoring hands-on sessions are typically:
The goal is to try out the techniques and ideas safely, not to get value straight away
"The truth may be out there,
but the lies are inside your head."
A good place to start
- Not definitive or proscriptive
- Allow you to try out these ideas safely
- You'll discover your own techniques
Java
Library: Hibernate
https://github.com/hibernate/hibernate-orm
Javascript
Library: Sequelize
https://github.com/sequelize/sequelize/
Extract and name conditionals
Steps:
Name the system rules
if ( typeof selector !== "string" || !selector ||
nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
return results;
}
var isInvalidSelector = (typeof selector !== "string" || !selector);
var isValidType = (nodeType !== 1 && nodeType !== 9 && nodeType !== 11);
if (isInvalidSelector || isValidType) {
return results;
}
Before
After
Steps:
Session
main/lib/dialects/abstract/query-generator.js#L728
Discover and express system rules in your own language
Goal
Javascript:
hibernate-core/src/main/java/org/hibernate/boot/model/
source/internal/hbm/ModelBinder.java#L388
Java:
Separating noise from signal
Extract and name implementation details
Steps:
let connection = mysql.createConnection(config);
let title = 'Refactor this mess';
let completed = 'false';
let sql = `INSERT INTO todos (title, completed) VALUES('${title}', ${completed})`;
connection.query(sql);
function saveNewTodo(title, completed)
{
let connection = mysql.createConnection(config);
let sql = `INSERT INTO todos (title, completed) VALUES('${title}', ${completed})`;
connection.query(sql);
}
let title = 'Refactor this mess';
let completed = 'false';
saveNewTodo(title, completed);
Before
After
Steps:
Session
Explore & describe the behaviour of the system, not the implementation
Goal
main/lib/dialects/abstract/query-generator.js#L728
Javascript:
hibernate-core/src/main/java/org/hibernate/boot/model/
source/internal/hbm/ModelBinder.java#L388
Java:
Use git history to gain context
Steps:
Understand the context of the developers
Steps:
Session
Explore the lifecycle of the code and understand its history
Goal
main/lib/dialects/abstract/query-generator.js#L728
Javascript:
hibernate-core/src/main/java/org/hibernate/boot/model/
source/internal/hbm/ModelBinder.java#L388
Java:
Working with legacy is about:
Legacy will teach you more about writing software then any green field project.
Improving something existing is harder and more rewarding than making something new. Embrace the challenge.