Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Rewriting 15-Year-Old Code
Anna Filina
PRO
October 17, 2017
Programming
1
180
Rewriting 15-Year-Old Code
Anna Filina
PRO
October 17, 2017
Tweet
Share
More Decks by Anna Filina
See All by Anna Filina
Upgrading Legacy to the Latest PHP Version
afilina
PRO
0
41
Avoid Costly Framework Upgrades
afilina
PRO
1
1.1k
Fantastic Bugs and How to Avoid Them
afilina
PRO
1
680
Adding Tests to Untestable Legacy Code
afilina
PRO
3
720
You Don't Need More Developers
afilina
PRO
2
850
Fantastic Bugs and How to Avoid Them
afilina
PRO
0
130
Ship 10 Times Faster With These Designs
afilina
PRO
0
340
Effortless Software Development
afilina
PRO
0
320
Rewriting Legacy Code
afilina
PRO
0
370
Other Decks in Programming
See All in Programming
Value and Record Types
hschwentner
0
550
VisualProgramming_GoogleHome_LINE
nearmugi
1
230
Android スキルセットをフル活用して始めるスマートテレビアプリ開発
satsukies
1
200
React Nativeアプリを DDDで開発している話
nihemak
0
140
How we run a Realtime Puzzle Fighting Game on AWS Serverless
falken
0
250
Angular-basierte Micro Frontends mit Module Federation @API Summit
manfredsteyer
PRO
0
110
Lancersをコンテナへ本番移行する取り組み
rvirus0817
1
330
Java アプリとAWS の良い関係 - AWS でJava アプリを実行する一番簡単な方法教えます / AWS for Javarista
kanamasa
2
1.2k
Terraform Plan/Apply結果の自動通知
ymmy02
0
280
Haskellでオブジェクト指向プログラミング
koheisakata
0
110
IE Graduation (IE の功績を讃える)
jxck
20
12k
Oracle REST Data Service: APEX Office Hours
thatjeffsmith
0
760
Featured
See All Featured
How to name files
jennybc
40
61k
Three Pipe Problems
jasonvnalue
89
8.7k
How GitHub (no longer) Works
holman
296
140k
YesSQL, Process and Tooling at Scale
rocio
157
12k
Art, The Web, and Tiny UX
lynnandtonic
280
17k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
498
130k
KATA
mclloyd
7
8.7k
What’s in a name? Adding method to the madness
productmarketing
11
1.6k
Keith and Marios Guide to Fast Websites
keithpitt
404
21k
The Language of Interfaces
destraynor
148
20k
Docker and Python
trallard
27
1.6k
Faster Mobile Websites
deanohume
294
28k
Transcript
@afilina Rewriting 15-Year-Old Code Mtl.rb - October 17, 2017
Anna Filina • Project rescue expert • Legacy fixer •
Developer • Conference speaker • Trainer
You inherited a 17-year-old codebase Code doesn't age like wine.
The Web Was 600px Wide
Feeling Old Yet? • Y2K bug. • Internet Explorer 5.
• ICQ was starting to be cool. • Rounded corners = status symbol.
Code smells
Mixed Concerns <% products = Product.all total = 0 products.each
do |product| total += product.qty * product.price end %> <p>Total: <%= total %></p>
Poorly Named Variables a = #... array = #... item3
= #...
Global Functions & Constants require_relative '../../functions.rb' MyClass::my_method(param) # namespaced function?
my_method(DEV_MODE)
Inexplicable Conditions if order_id > 20117 # use this sql
else # use that sql end # weakness = time to refactor
Long Methods public function importCsv($path, $googleApiKey, $databaseDsn, $databaseUser, $databasePassword) {
// Convert CSV to array of conferences $lines = file($path); $csv = array_map('str_getcsv', $lines); $conferences = []; foreach ($csv as $line) { $conference = new Conference(); $conference->name = $line[0]; $conference->location = $line[1]; $conferences[] = $conference; // Get coordinates for location $location = urlencode($conference->location); $url = 'https://maps.googleapis.com/maps/api/geocode/json?address='.$location.'&key='.$googleApiKey; $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $response = curl_exec($curl); curl_close($curl); $json = json_decode($response); if (count($json->results) == 0) { continue; } $latitude = $json->results[0]->geometry->location->lat; $longitude = $json->results[0]->geometry->location->lng; $coordinates = $latitude.','.$longitude; $conference->coordinates = $coordinates; // Save conference to database $pdo = new PDO($databaseDsn, $databaseUser, $databasePassword); $statement = $pdo->prepare('REPLACE INTO conference (name, location, coordinates) VALUES (?, ?, ?)'); $statement->execute([ $conference->name, $conference->location, $conference->coordinates, ]);
Average Legacy Code File • 3000-6000 lines of code. •
Half of it is commented "in case we need it later". • Method length of 800 lines. • Abuse of helper classes. • Sometimes no classes at all.
Codebase • 5,000 classes. • 20,000 methods. • 1,500,000 lines
of code.
Before you code
Strategy • Make a strategy based on constraints. • Full
rewrite vs progressive: ◦By class. ◦By feature. ◦By HTTP call. • How to run code side-by-side: ◦DB/Session sharing. ◦mod_rewrite.
Data Can Be Lost, Stuff Can Break • Backup: test
restore. • Nullify sensitive data. • Staging: simulate deployments/ upgrades/batch processes. • Automate tests before code changes. • Make a risk assessment: ◦ Don't be too optimistic. ◦ Account for side-effects.
Build With Real Legacy Data
(Failed) rewrite example
PHP 3 to PHP 5.6 • HTML + PHP +
SQL in same file. • Includes all over the place. • IFs that concatenate SQL. • Previous rewrite attempt: ◦ Failed, made things worse. ◦ Folders of dead code. ◦ Classes with static functions (no instances).
Solution • Rewrite complex forms using a framework: ◦ mod_rewrite
for concerned pages. • Rewrite biggest feature as OOP: ◦ Design extraction. ◦ Flexible architecture. ◦ Automated tests.
New feature should not take longer than a sprint.
Design extraction
Avoid Code Bias • Old code → design docs. •
Validate design docs: ◦Clarify business rules. • Improve design: ◦Reduce technical debt. ◦More flexible. • Design docs → new code.
Fixing bugs
Code Duplication • Sometimes, the bug is repeated 80+ times.
• Remove duplications ASAP.
Fix Long Methods • Extract broken part into its own
method. • Write unit tests for it. • Fix it. • Call it from the mega-method.
Spot Logical Groups Code block Comment Code block Comment Convert
CSV to array of conferences. Get coordinates for conference location. Save conference to database. Code block Comment
Extract & Test Code block Comment Code block Method Code
block Comment Call method
Name Code block Method Code block Method Call method Call
method Code block Method Call method conferences_from_csv location_coordinates save_conference
Rewrite example #2
ASP Classic to PHP 5.6 • 15+ spaghetti and hacks.
• Language no longer supported. • Huge ERP with lots of code.
Solution • Rewrite page by page to a framework. •
mod_rewrite for concerned pages. • DB session adapter in both apps. • Page in any language = HTTP request. ◦ Automated testing possible!
HTTP Tests
On Testing Before you code You better test So that
on weekends You may rest. -- Me
Stuck?
None
Try Something New • Bounce ideas. ◦ New people to
avoid tunnel vision. • Has this been done before? • Can I try another approach?
Takeaways • Make a strategy. • You touch it, you
refactor it. • Use known tools & methodologies. • Get inspiration from others. • Refactoring gets easier. • Every problem has a solution.
Refactoring: Improving the Design of Existing Code Martin Fowler
@afilina afilina.com joind.in