SlideShare a Scribd company logo
HOW TO WORK WITH
LEGACY CODE
PHPERS RZESZÓW #2
MICHAŁ SZCZUR
PHP Developer since 2010
bass guitarist and trumpeter
michalszczur.pl
Created by /Michał Szczur @partikus
AGENDA
What is legacy code
When code can be called Legacy?
How to start and not die
Step by step to heaven
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
ASSUMPTIONS
YOU DON'T KNOW BUSINESS LOGIC
MOSTLY PROCEDURAL CODE
NO SEPARATION, JUST A FEW LARGE FILES
YOU NEED TO CHANGE STH
HOW TO START?
ANALYZE
COVER
IT MEANS WRITE TESTS
WHAT SHOULD WE
TEST?
How to work with legacy code PHPers Rzeszow #2
How to work with legacy code PHPers Rzeszow #2
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 receivers';
$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
THANKS!
QUESTIONS?
SLIDES: SLIDESHARE.NET/MICHASZCZUR
TWITTER: @PARTIKUS
HOMEPAGE: MICHALSZCZUR.PL
LINKS
CasperJS
Symfony Components
Working Effectively with Legacy Code by Michael Feathers
Page Object Pattern (Martin Fowler)
Page Object Pattern (Selenium Docs)
Marek Matulka - Modernising the Legacy

More Related Content

PPTX
Let's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, Germany
PDF
NodeJS The edge of Reason - Lille fp#6
TXT
PDF
Practica csv
PDF
PhoneGap: Local Storage
PDF
Dependency Injection
PDF
Pemrograman Web 9 - Input Form DB dan Session
DOCX
Karan chanana
Let's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, Germany
NodeJS The edge of Reason - Lille fp#6
Practica csv
PhoneGap: Local Storage
Dependency Injection
Pemrograman Web 9 - Input Form DB dan Session
Karan chanana

What's hot (18)

TXT
Xmpp prebind
PDF
Pemrograman Web 8 - MySQL
PDF
Drush. Secrets come out.
PDF
The Origin of Lithium
PDF
Introduction to ReasonML
PDF
CakeFest 2013 keynote
PDF
PHP Static Code Review
PDF
Perkenalan ReasonML
PDF
Keep It Simple Security (Symfony cafe 28-01-2016)
PDF
New in cakephp3
PDF
Agile database access with CakePHP 3
PPTX
KEY
Php 101: PDO
DOCX
PDF
Php (1)
PDF
Advanced Querying with CakePHP 3
PDF
Migrare da symfony 1 a Symfony2
PDF
Future of HTTP in CakePHP
Xmpp prebind
Pemrograman Web 8 - MySQL
Drush. Secrets come out.
The Origin of Lithium
Introduction to ReasonML
CakeFest 2013 keynote
PHP Static Code Review
Perkenalan ReasonML
Keep It Simple Security (Symfony cafe 28-01-2016)
New in cakephp3
Agile database access with CakePHP 3
Php 101: PDO
Php (1)
Advanced Querying with CakePHP 3
Migrare da symfony 1 a Symfony2
Future of HTTP in CakePHP
Ad

Viewers also liked (16)

PDF
矢状縫合早期癒合症の術後発達に関する検討
PPT
Limajuliette webpage smooth esp 2012
PDF
PDF
正確な咬合面形態を持つ、3次元実体モデル作成の検討
PPTX
Hối phiếu – kỳ phiếu
DOCX
Shopping Cart Code
DOCX
The role of your coaches
PDF
593素数
PPTX
Coplanar concurrent forces
PDF
Professional english for_students_of_logistics_disclaimer
PPT
Routes of drug administration
PDF
How Google Works
PDF
A Guide to SlideShare Analytics - Excerpts from Hubspot's Step by Step Guide ...
PDF
2015 Upload Campaigns Calendar - SlideShare
PPTX
What to Upload to SlideShare
PDF
Getting Started With SlideShare
矢状縫合早期癒合症の術後発達に関する検討
Limajuliette webpage smooth esp 2012
正確な咬合面形態を持つ、3次元実体モデル作成の検討
Hối phiếu – kỳ phiếu
Shopping Cart Code
The role of your coaches
593素数
Coplanar concurrent forces
Professional english for_students_of_logistics_disclaimer
Routes of drug administration
How Google Works
A Guide to SlideShare Analytics - Excerpts from Hubspot's Step by Step Guide ...
2015 Upload Campaigns Calendar - SlideShare
What to Upload to SlideShare
Getting Started With SlideShare
Ad

Similar to How to work with legacy code PHPers Rzeszow #2 (20)

PDF
How to work with legacy code
KEY
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
PDF
The History of PHPersistence
PDF
PHP and Rich Internet Applications
ODP
Php 102: Out with the Bad, In with the Good
ODP
My app is secure... I think
PDF
PHP and Rich Internet Applications
PDF
PHP-UK 2025: Ending Injection Vulnerabilities
PDF
PHP Tips & Tricks
PDF
Redis for your boss
PPTX
Let's write secure drupal code! - Drupal Camp Pannonia 2019
PDF
Smelling your code
ODP
My app is secure... I think
PPTX
21. CodeIgniter search
PDF
veracruz
PDF
veracruz
PDF
veracruz
PDF
veracruz
KEY
Good Evils In Perl (Yapc Asia)
ODP
My app is secure... I think
How to work with legacy code
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
The History of PHPersistence
PHP and Rich Internet Applications
Php 102: Out with the Bad, In with the Good
My app is secure... I think
PHP and Rich Internet Applications
PHP-UK 2025: Ending Injection Vulnerabilities
PHP Tips & Tricks
Redis for your boss
Let's write secure drupal code! - Drupal Camp Pannonia 2019
Smelling your code
My app is secure... I think
21. CodeIgniter search
veracruz
veracruz
veracruz
veracruz
Good Evils In Perl (Yapc Asia)
My app is secure... I think

Recently uploaded (20)

PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Empathic Computing: Creating Shared Understanding
PDF
Approach and Philosophy of On baking technology
PDF
NewMind AI Monthly Chronicles - July 2025
PDF
CIFDAQ's Market Insight: SEC Turns Pro Crypto
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Modernizing your data center with Dell and AMD
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
cuic standard and advanced reporting.pdf
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Empathic Computing: Creating Shared Understanding
Approach and Philosophy of On baking technology
NewMind AI Monthly Chronicles - July 2025
CIFDAQ's Market Insight: SEC Turns Pro Crypto
Encapsulation_ Review paper, used for researhc scholars
Chapter 3 Spatial Domain Image Processing.pdf
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
Advanced methodologies resolving dimensionality complications for autism neur...
Modernizing your data center with Dell and AMD
MYSQL Presentation for SQL database connectivity
Dropbox Q2 2025 Financial Results & Investor Presentation
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
The AUB Centre for AI in Media Proposal.docx
Mobile App Security Testing_ A Comprehensive Guide.pdf
Unlocking AI with Model Context Protocol (MCP)
The Rise and Fall of 3GPP – Time for a Sabbatical?
cuic standard and advanced reporting.pdf
Network Security Unit 5.pdf for BCA BBA.
Building Integrated photovoltaic BIPV_UPV.pdf

How to work with legacy code PHPers Rzeszow #2