SlideShare a Scribd company logo
HOW TO WORK WITH
LEGACY CODE
MICHAŁ SZCZUR
PHP Developer since 2010
bass guitarist and trumpeter
michalszczur.pl
Created by /Michał Szczur @partikus
AGENDA
Scope explanation
Dive into legacy mess
How to start and not die
Step by step to heaven
THANKS TO MAREK MATULKA
WHO INSPIRED ME!
WHAT IS LEGACY CODE?
CODE WRITTEN MANY YEARS AGO
BY MYSELF OR OTHER NINJAS
LOW QUALITY CODE
(PRE)HISTORICAL CODE USES NONEXISTING
FRAMEWORKS/LIBRARIES
NO ENVIRONMENT SEPARATION
NO TESTS !!!
WHEN CODE CAN BE CALLED
LEGACY ???
WHEN IT IS
UNMANAGED
WHEN IT IS
TOO BUGGY
WHEN IT IS
TOO HARD TO UNDERSTAND
WHEN IT IS
NONUPGRADABLE
WHEN IT IS
UNDEBUGGABLE
WHEN IT IS
UNREADABLE
WHEN IT IS
TOO COUPLED TO FRAMEWORK
WHEN IT IS
TOO HARD TO ADD NEW FEATURE
WHAT IS NEXT?
FIGHT OR DIE
NO !!!
WE'RE NINJA DEVS
WE LOVE CHALLENGES
LET'S DO IT!
TAKE NEW FRAMEWORK
AND START FROM THE BEGINNING
:(MAYBE SOME DAY IN THE FUTURE
WHAT IS NEXT?
LET'S REFACTOR
BUT WHY ???
EXTENDED LEGACY
CODE
WEB PHP APP
PREASUMPTIONS
YOU DON'T KNOW BUSINESS LOGIC
MOSTLY PROCEDURAL CODE
NO SEPARATION, JUST A FEW LARGE FILES
YOU NEED TO CHANGE STH
ANALYZE
COVER
IT MEANS WRITE TESTS
WHAT SHOULD WE
TEST?
How to work with legacy code
How to work with legacy code
WHY SHOULD WE WRITE TESTS?
LOW LEVEL DOCUMENTATION
FEATURES DESCRIBED BY SCENARIOS (E.G.
GHERKIN)
CLEAN CODE
EASY TO CHANGE (LESS PAIN)
EASY CONTINUOUS DEPLOYMENT
START REFACTORING
# Project structure
/404.php
/database.php
/functions.php
/index.php
/page.php
PROCEDURAL CODE
WRITTEN IN PHP
INLINE PHP FUNCTIONS MIXED WITH HTML,CSS,JS
#/functions.php
function show_all() {
$db = connect_to_db();
$sql = 'SELECT * FROM receivers';
$result = mysql_query($sql) or die(mysql_error());
while ($row = mysql_fetch_array($result)) {
//echo 'ID: ' . $row['id'] . ', mail: ' . $row['mail'];
echo ''.$row['mail'].'';
echo '<form id="'.$row['id'].'" name="n_ID" method="POST" action=
<input type="hidden" name="id" value="'.$row['id'].'" />
<input type="submit" name="delete" value="Delete" />
</form>';
}
if (isset($_POST['delete'])) {
$n_ID = $_POST['id'];
$sql = "DELETE FROM receivers WHERE id = $n_ID";
mysql_query($sql) or die(mysql_error());
WRITE FUNCTIONAL
TEST
// show_all_receivers.js
casper.test.begin('List all receivers', 5, function suite(test) {
casper.start("http://myapp.dev/mailsender.php", function() {
test.assertHttpStatus(200);
test.assertTitle("Homepage | Mail Sender", "Homepage title is expecte
});
casper.thenClick('a#show-all', function() {
test.assertHttpStatus(200);
test.assertTitle(
"Receivers list | Mail Sender",
"Page title is correct"
);
});
casper.run(function() {
test.done();
});
});
PROCEDURAL CODE??
YOU NEED STH MORE
IOC
INVERSION OF CONTROL
DEPENDENCY
INJECTION
IOC IMPLEMENTATION
DON'T REINVENT THE
WHEEL
PACKAGE MANAGER
COMPOSER
RUBYGEMS
MAVEN
COMPONENTS
DEPENDENCY INJECTION
/ /SYMFONY DI PIMPLE AURA DI
WHY SYMFONY
COMPONENTS?
WELL TESTED
DECOUPLED
REUSABLE
WELL DOCUMENTED
AND KNOWN BY COMMUNITY
NEXT STEP IS...
MOVE APP TO /WEB/
# new project structure
/
/web/404.php
/web/database.php
/web/functions.php
/web/index.php
/web/page.php
INSTALL COMPOSER
php -r "readfile('https://getcomposer.org/installer');" > composer-setup.php
php -r "if (hash('SHA384', file_get_contents('composer-setup.php')) ===
php composer-setup.php
php -r "unlink('composer-setup.php');"
INIT COMPOSER CONFIG IN THE ROOT DIR
php composer.phar init
PROJECT STRUCTURE
ls -l
/
/composer.json
/web/
COMPOSER.JSON
{
"name": "michalszczur/legacy-demo",
"authors": [
{
"name": "Michal Szczur",
"email": "job@michalszczur.pl"
}
],
"require": {},
"autoload": {
"psr-4": {
"": "src/"
}
},
"description": "Legacy app demo",
"type": "project",
"license": "proprietary"
ADD DEPENDENCIES
php composer.phar require symfony/dependency-injection
php composer.phar require symfony/config
php composer.phar require symfony/yaml
<?php
# /web/container.php
use SymfonyComponentDependencyInjectionContainerBuilder;
use SymfonyComponentConfigFileLocator;
use SymfonyComponentDependencyInjectionLoaderYamlFileLoader;
require __DIR__.'/../vendor/autoload.php';
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../app/con
$loader->load('services.yml');
$container->compile();
WHICH SERVICES DO WE REALLY
NEED?
function show_all()
{
# Database connection needed
$db = connect_to_db();
$sql = 'SELECT * FROM mail_sender';
$result = mysql_query($sql) or die(mysql_error());
//...
CREATE SEVICES.YMLDEFINITION
SERVICES.YML
parameters:
db_host: localhost
db_port: 3306
db_name: legacyapp
db_user: myuser
db_pass: mypass
services:
db:
class: PDO
arguments: ['mysql:port=%db_port%;host=%db_host%;dbname=%db_name%'
receiver_repository:
class: PDOReceiverRepository
arguments: ['@db']
USE CONTAINER AND REPOSITORY
#index.php
...
require 'container.php';
...
function show_all()
{
# Database connection needed
$receiverRepository = $container->get('receiver_repository');
$result = $receiverRepository->findAll();
...
#index.php
...
$result = $receiverRepository->findAll();
foreach ($result as $row) {
echo ''.$row['mail'].'';
echo '<form id="'.$row['id'].'" name="n_ID" method="POST" action="mai
<input type="hidden" name="id" value="'.$row['id'].'" />
<input type="submit" name="delete" value="Usuń" />
</form>';
}
...
PHP ~ HTML
STILL MIXED TOGETHER
TWIG
TEMPLATE ENGINE FOR PHP
INSTALL TWIG USING COMPOSER
php composer.phar require twig/twig
SERVICES.YML
parameters:
...
twig_paths:
- app/Resources/views
services:
...
twig.loader:
class: Twig_Loader_Filesystem
arguments: ['%twig_paths%']
twig:
class: Twig_Environment
arguments: ['@twig.loader']
#index.php
...
$twig = $container->get('@twig');
$result = $receiverRepository->findAll();
echo $twig->render(
'receiver_list.html.twig',
['receivers' => $result]
);
...
{% for receiver in receivers %}
<form id="{{ receiver.id }}" name="n_ID" method="POST" action="mail_sender.ph
<input type="hidden" name="id" value="{{ receiver.id }}" />
<input type="submit" name="delete" value="Delete" />
</form>
{% endfor %}
BEFORE
function show_all()
{
$db = connect_to_db();
$sql = 'SELECT * FROM mail_sender';
$result = mysql_query($sql) or die(mysql_error());
while ($row = mysql_fetch_array($result)) {
//echo 'ID: ' . $row['id'] . ', mail: ' . $row['mail'];
echo ''.$row['mail'].'';
echo '<form id="'.$row['id'].'" name="n_ID" method="POST" action="mai
<input type="hidden" name="id" value="'.$row['id'].'" />
<input type="submit" name="delete" value="Usuń" />
</form>';
}
...
mysql_free_result($result);
mysql_close($db);
}
AFTER
function show_all() {
$receiverRepository = $container->get('receiver_repository');
$twig = $container->get('@twig');
$result = $receiverRepository->findAll();
echo $twig->render(
'receiver_list.html.twig',
['receivers' => $result]
...
);
LET'S SUM UP
COMMUNICATION
ANALYZE
TESTS
SMALL STEPS
NOT EVERYTHING SIMUNTANOUSLY
PACKAGE MANAGER
DEPENDENCY INJECTION
THIRD PARTY LIBRARIES
DESIGN PATTERNS
SOLID
DECOUPLE
TESTS
QUESTIONS?
SLIDES: SLIDESHARE.NET/MICHASZCZUR
FEEDBACK: JOIND.IN/EVENT/CODETECON-20161
TWITTER: @PARTIKUS
HOMEPAGE: MICHALSZCZUR.PL
THANKS!
LINKS
Marek Matulka - Modernising the Legacy
CasperJS
Symfony Components
Working Effectively with Legacy Code by Michael Feathers
Page Object Pattern (Martin Fowler)
Page Object Pattern (Selenium Docs)

More Related Content

What's hot (19)

DOCX
Karan chanana
karan chanana
 
PDF
Pemrograman Web 8 - MySQL
Nur Fadli Utomo
 
TXT
My shell
Ahmed Salah
 
PDF
Drush. Secrets come out.
Alex S
 
PDF
The Origin of Lithium
Nate Abele
 
PDF
Introduction to ReasonML
Riza Fahmi
 
PDF
CakeFest 2013 keynote
José Lorenzo Rodríguez Urdaneta
 
PDF
Perkenalan ReasonML
Riza Fahmi
 
PDF
PHP Static Code Review
Damien Seguy
 
PDF
Keep It Simple Security (Symfony cafe 28-01-2016)
Oleg Zinchenko
 
PDF
New in cakephp3
markstory
 
PDF
Agile database access with CakePHP 3
José Lorenzo Rodríguez Urdaneta
 
PPTX
Bacbkone js
Артём Курапов
 
KEY
Php 101: PDO
Jeremy Kendall
 
DOCX
Php if
nurhardianti98
 
PDF
Php (1)
pinalsadiwala
 
PDF
Advanced Querying with CakePHP 3
José Lorenzo Rodríguez Urdaneta
 
PDF
Future of HTTP in CakePHP
markstory
 
PDF
jQuery UI Widgets, Drag and Drop, Drupal 7 Javascript
Darren Mothersele
 
Karan chanana
karan chanana
 
Pemrograman Web 8 - MySQL
Nur Fadli Utomo
 
My shell
Ahmed Salah
 
Drush. Secrets come out.
Alex S
 
The Origin of Lithium
Nate Abele
 
Introduction to ReasonML
Riza Fahmi
 
CakeFest 2013 keynote
José Lorenzo Rodríguez Urdaneta
 
Perkenalan ReasonML
Riza Fahmi
 
PHP Static Code Review
Damien Seguy
 
Keep It Simple Security (Symfony cafe 28-01-2016)
Oleg Zinchenko
 
New in cakephp3
markstory
 
Agile database access with CakePHP 3
José Lorenzo Rodríguez Urdaneta
 
Php 101: PDO
Jeremy Kendall
 
Php (1)
pinalsadiwala
 
Advanced Querying with CakePHP 3
José Lorenzo Rodríguez Urdaneta
 
Future of HTTP in CakePHP
markstory
 
jQuery UI Widgets, Drag and Drop, Drupal 7 Javascript
Darren Mothersele
 

Viewers also liked (17)

PDF
実物大立体モデルを用いた手術計画の有用性に関する検討
日本顎顔面再建先進デジタルテクノロジー学会
 
DOC
Revolution essay actual
Henry Palmer
 
PDF
DUO10M, MC PK196BE
Songyang Han
 
PDF
DELIRIOUS Pitch
LuKiGreen
 
PDF
脳磁図を用いた舌神経機能障害の客観的評価
日本顎顔面再建先進デジタルテクノロジー学会
 
PDF
タスクヒエラルキーによる位置制限を用いたハプティックインプラント手術支援システム
日本顎顔面再建先進デジタルテクノロジー学会
 
PDF
ハプティックロボットによる口腔外科手術支援の試み
日本顎顔面再建先進デジタルテクノロジー学会
 
PPT
Fillings-parasonymachinery.com
Parason Machinery
 
PPTX
Shilpa apt
Sairam Koganti
 
PDF
Mathematical formula handbook
BRS ENGINEERING
 
PDF
MS Officeファイル暗号化のマスター鍵を利用したバックドアとその対策
MITSUNARI Shigeo
 
PPTX
Công ty TNHH Coca-cola Việt Nam
tuoi phan
 
PDF
[Survey Report] Vietnam Youth Lifestyle
Q&Me Vietnam Market Research
 
PPSX
Drugs & Pharmaceuticals (PPT)
Dr. Vishal Gosavi
 
PDF
Effective Modern C++ 読書会 Item 35
Keisuke Fukuda
 
PDF
On tap ngu phap tieng anh thi toefl
DoKo.VN Channel
 
PPTX
NMR Spectroscopy
tabirsir
 
実物大立体モデルを用いた手術計画の有用性に関する検討
日本顎顔面再建先進デジタルテクノロジー学会
 
Revolution essay actual
Henry Palmer
 
DUO10M, MC PK196BE
Songyang Han
 
DELIRIOUS Pitch
LuKiGreen
 
脳磁図を用いた舌神経機能障害の客観的評価
日本顎顔面再建先進デジタルテクノロジー学会
 
タスクヒエラルキーによる位置制限を用いたハプティックインプラント手術支援システム
日本顎顔面再建先進デジタルテクノロジー学会
 
ハプティックロボットによる口腔外科手術支援の試み
日本顎顔面再建先進デジタルテクノロジー学会
 
Fillings-parasonymachinery.com
Parason Machinery
 
Shilpa apt
Sairam Koganti
 
Mathematical formula handbook
BRS ENGINEERING
 
MS Officeファイル暗号化のマスター鍵を利用したバックドアとその対策
MITSUNARI Shigeo
 
Công ty TNHH Coca-cola Việt Nam
tuoi phan
 
[Survey Report] Vietnam Youth Lifestyle
Q&Me Vietnam Market Research
 
Drugs & Pharmaceuticals (PPT)
Dr. Vishal Gosavi
 
Effective Modern C++ 読書会 Item 35
Keisuke Fukuda
 
On tap ngu phap tieng anh thi toefl
DoKo.VN Channel
 
NMR Spectroscopy
tabirsir
 
Ad

Similar to How to work with legacy code (20)

PDF
How to work with legacy code PHPers Rzeszow #2
Michał Kruczek
 
PDF
PHP and Rich Internet Applications
elliando dias
 
KEY
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Masahiro Nagano
 
PDF
The History of PHPersistence
Hugo Hamon
 
ODP
My app is secure... I think
Wim Godden
 
PDF
PHP and Rich Internet Applications
elliando dias
 
ODP
Php 102: Out with the Bad, In with the Good
Jeremy Kendall
 
PDF
Redis for your boss
Elena Kolevska
 
PDF
Smelling your code
Raju Mazumder
 
PDF
veracruz
tutorialsruby
 
PDF
veracruz
tutorialsruby
 
PDF
veracruz
tutorialsruby
 
PDF
veracruz
tutorialsruby
 
PDF
PHP Tips & Tricks
Radek Benkel
 
ODP
My app is secure... I think
Wim Godden
 
PPTX
Practical MySQL.pptx
HussainUsman4
 
PPTX
Basics of Working with PHP and MySQL.pptx
jensas21
 
ODP
My app is secure... I think
Wim Godden
 
ODP
My app is secure... I think
Wim Godden
 
PDF
How to write code you won't hate tomorrow
Pete McFarlane
 
How to work with legacy code PHPers Rzeszow #2
Michał Kruczek
 
PHP and Rich Internet Applications
elliando dias
 
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Masahiro Nagano
 
The History of PHPersistence
Hugo Hamon
 
My app is secure... I think
Wim Godden
 
PHP and Rich Internet Applications
elliando dias
 
Php 102: Out with the Bad, In with the Good
Jeremy Kendall
 
Redis for your boss
Elena Kolevska
 
Smelling your code
Raju Mazumder
 
veracruz
tutorialsruby
 
veracruz
tutorialsruby
 
veracruz
tutorialsruby
 
veracruz
tutorialsruby
 
PHP Tips & Tricks
Radek Benkel
 
My app is secure... I think
Wim Godden
 
Practical MySQL.pptx
HussainUsman4
 
Basics of Working with PHP and MySQL.pptx
jensas21
 
My app is secure... I think
Wim Godden
 
My app is secure... I think
Wim Godden
 
How to write code you won't hate tomorrow
Pete McFarlane
 
Ad

Recently uploaded (20)

PDF
Darley - FIRST Copenhagen Lightning Talk (2025-06-26) Epochalypse 2038 - Time...
treyka
 
PPTX
Smart Factory Monitoring IIoT in Machine and Production Operations.pptx
Rejig Digital
 
PDF
5 Things to Consider When Deploying AI in Your Enterprise
Safe Software
 
PDF
Proactive Server and System Monitoring with FME: Using HTTP and System Caller...
Safe Software
 
PDF
Optimizing the trajectory of a wheel loader working in short loading cycles
Reno Filla
 
PDF
Quantum Threats Are Closer Than You Think – Act Now to Stay Secure
WSO2
 
PPTX
Wondershare Filmora Crack Free Download 2025
josanj305
 
PDF
Bitkom eIDAS Summit | European Business Wallet: Use Cases, Macroeconomics, an...
Carsten Stoecker
 
PDF
ArcGIS Utility Network Migration - The Hunter Water Story
Safe Software
 
PDF
“Scaling i.MX Applications Processors’ Native Edge AI with Discrete AI Accele...
Edge AI and Vision Alliance
 
PDF
TrustArc Webinar - Navigating APAC Data Privacy Laws: Compliance & Challenges
TrustArc
 
PDF
My Journey from CAD to BIM: A True Underdog Story
Safe Software
 
PDF
99 Bottles of Trust on the Wall — Operational Principles for Trust in Cyber C...
treyka
 
PPTX
2025 HackRedCon Cyber Career Paths.pptx Scott Stanton
Scott Stanton
 
PDF
Unlocking FME Flow’s Potential: Architecture Design for Modern Enterprises
Safe Software
 
PDF
Hyderabad MuleSoft In-Person Meetup (June 21, 2025) Slides
Ravi Tamada
 
PDF
Understanding The True Cost of DynamoDB Webinar
ScyllaDB
 
PDF
Supporting the NextGen 911 Digital Transformation with FME
Safe Software
 
PDF
Understanding AI Optimization AIO, LLMO, and GEO
CoDigital
 
PPTX
01_Approach Cyber- DORA Incident Management.pptx
FinTech Belgium
 
Darley - FIRST Copenhagen Lightning Talk (2025-06-26) Epochalypse 2038 - Time...
treyka
 
Smart Factory Monitoring IIoT in Machine and Production Operations.pptx
Rejig Digital
 
5 Things to Consider When Deploying AI in Your Enterprise
Safe Software
 
Proactive Server and System Monitoring with FME: Using HTTP and System Caller...
Safe Software
 
Optimizing the trajectory of a wheel loader working in short loading cycles
Reno Filla
 
Quantum Threats Are Closer Than You Think – Act Now to Stay Secure
WSO2
 
Wondershare Filmora Crack Free Download 2025
josanj305
 
Bitkom eIDAS Summit | European Business Wallet: Use Cases, Macroeconomics, an...
Carsten Stoecker
 
ArcGIS Utility Network Migration - The Hunter Water Story
Safe Software
 
“Scaling i.MX Applications Processors’ Native Edge AI with Discrete AI Accele...
Edge AI and Vision Alliance
 
TrustArc Webinar - Navigating APAC Data Privacy Laws: Compliance & Challenges
TrustArc
 
My Journey from CAD to BIM: A True Underdog Story
Safe Software
 
99 Bottles of Trust on the Wall — Operational Principles for Trust in Cyber C...
treyka
 
2025 HackRedCon Cyber Career Paths.pptx Scott Stanton
Scott Stanton
 
Unlocking FME Flow’s Potential: Architecture Design for Modern Enterprises
Safe Software
 
Hyderabad MuleSoft In-Person Meetup (June 21, 2025) Slides
Ravi Tamada
 
Understanding The True Cost of DynamoDB Webinar
ScyllaDB
 
Supporting the NextGen 911 Digital Transformation with FME
Safe Software
 
Understanding AI Optimization AIO, LLMO, and GEO
CoDigital
 
01_Approach Cyber- DORA Incident Management.pptx
FinTech Belgium
 

How to work with legacy code