SlideShare a Scribd company logo
Refactoring legacy code guided by tests in
WordPress
WC Rome, 2017/12/16
Luca Tumedei
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 1
About me
—freelance WordPress developer
—been working with Modern Tribe for 3.5 years now
—creator of wp-browser and lover of tests
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 2
Long time no see
<?php
/*
Plugin Name: My New Plugin
Plugin URI: https://example.com
Version: 0.1.0
Description: Really new; from scratch.
Author: Luca Tumedei
Author URI: http://example.com
*/
Starting from scratch is not an option.
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 3
Dramatis personae - Modern Tribe and The Events
Calendar plugin
—Modern Tribe is a remote (and awesome) agency
providing digital products and services
—The Events Calendar is MT's most famous
WordPress plugin
—The Events Calendar is just one of the many free
and premium WordPress plugins MT actively
maintains
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 4
Dramatis personae - MT developers
—there are 21 developers maintaining MT's plugins
—in their history about 100 different developers
worked on the plugins
—the skill, habits, beliefs and mantras of each might
vary...
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 5
Dramatis personae - the users
—The Events Calendar has about 600.000 active
installations
—The Events Calendar is the base for many of
Modern Tribe premium plugins and services
—third-party developers are users too
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 6
Still a work in progress
—this is not about how "we did it"
—this is about how "we are doing it" and what we
found out along the way
—you can see The Events Calendar code on GitHub
and judge for yourself
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 7
Refactoring
"Code refactoring is the process of restructuring
existing computer code, changing the factoring,
without changing its external behavior."
—Wikipedia
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 8
Legacy code
"Michael Feathers introduced a definition of legacy
code as code without tests, which reflects the
perspective of legacy code being difficult to work
with in part due to a lack of automated regression
tests."
—Wikipedia
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 9
Guided by tests
"Write the tests, then change the code. I need
coffee."
—me, on Slack
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 10
Why then?
—the code was not testable as it was
—tests allow to iterate faster
—faster iterations means shipping new features and
bug fixes faster
We win, users win, everybody wins!
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 11
You are already doing TDD
—you modify the code
—you go on a site page and try it out
—you fix it and try again
You are just doing it slowly, inefficiently and in an
under-engineered way.
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 12
Problem - Testing WordPress is impossible
—Codeception and wp-browser are the tools we
chose
—some of the other options include the Core suite,
WordHat, Behat
—at the very minimum you can always do
acceptance testing
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 13
Why Codeception and wp-browser?
—I might have something to do with it
—wp-browser provides Codeception modules
dedicated to WordPress
—Codeception supports all levels of testing:
acceptance, functional, integration and unit
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 14
Our first acceptance test
$I = new AcceptanceTester( $scenario );
$I->am( 'a WordPress site admin' );
$I->wantTo( 'be able to activate The Events Calendar plugin' );
$I->loginAsAdmin();
$I->amOnPluginsPage();
$I->activatePlugin( 'the-events-calendar' );
$I->seePluginActivated( 'the-events-calendar' );
This runs in .6 seconds. Faster than a person, if you
were guessing.
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 15
A second acceptance test for the front-end
$I = new AcceptanceTester( $scenario );
$I->am( 'a calendar visitor' );
$I->wantTo( 'be able to see the calendar' );
$format = 'Y-m-d H:i:s';
$meta = [
'_EventStartDate' => date( $format , strtotime( 'tomorrow 9am' ) ),
'_EventEndDate' => date( $format , strtotime( 'tomorrow 11am' ) ),
];
$I->havePostInDatabase( [
'post_type' => 'tribe_events',
'meta_input' => $meta,
'post_title' => 'Test Event'
] );
$I->amOnPage( '/events' );
$I->see( 'Test Event' );
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 16
The flow
—write tests and run them to make sure current
code passes them
—refactor the code
—run tests and fix the code until tests pass again
Repeat n times as you would do by hand.
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 17
Problem - PHP 5.2 compatibility
—"it cannot be done in PHP 5.2" is a sad excuse
—production code can be 5.2 compatible, test code
does not need to be
—acceptance tests can run against a PHP 5.2
webserver
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 18
Problem - hardcoded file inclusion
—getting hold of one element is nigh impossible due
to a forest of side effects
—there is always an include or require
somewhere
—we wrote our own autoloader but you can use
Composer and xrstf/composer-php52 to generate
your PHP 5.2 compatible autoload file
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 19
Reorganizing files and classes
—we nested folders "by subject"
—we use __ as a folder separator
—some class names are long...
Tribe__Events__REST__V1__Endpoints__...
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 20
A simple autoloader
function my_autoloader( $class ){
if( 0 !== strpos( $class, 'MyPlugin_' ) ){
return;
}
// `MyPlugin_Foo_Bar_MyClass` to `Foo/Bar/MyClass`
$path = str_replace( '_', '/', str_replace( 'My_Plugin_', '', $class ) );
include dirname( __FILE__ ) . '/src/' . $path . '.php';
}
spl_autoload_register( 'my_autoloader' );
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 21
Problem - the Main class
/**
* Main Tribe Events Calendar class.
*/
// Don't load directly
if ( ! defined( 'ABSPATH' ) ) {
die( '-1' );
}
if ( ! class_exists( 'Tribe__Events__Main' ) ) {
/**
* The Events Calendar Class
*
* This is where all the magic happens, the unicorns run wild and the leprechauns use WordPress to schedule events.
*/
class Tribe__Events__Main {
Emphasis on "This is where all the magic happens".
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 22
Bow to your god object!
—the class did everything: from localization to
managing currency symbols
—it was a Petri dish of anti-patterns
—it was tens of thousands lines long (it's still ~5000)
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 23
Naming things is difficult
"There are only two hard things in Computer
Science: cache invalidation and naming things."
-- Phil Karlton
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 24
Naming things is important
—names are only useful for people, the server does
not care if your classes are called Francine and
Waldo
—names indicate what something is supposed to do
—adding yet another method to Main is easier than
adding it to
Admin_Views_Single_Event_Metabox
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 25
Reducing Main
—break it down into smaller, specialized, classes
—STOP. ADDING. METHODS. TO. IT.
—create subsidiary "Mains" and stop calling things
"Main"
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 26
Deprecating files, classes and hooks
—we moved a lot of things during the process of
refactoring
—we used __deprecated_file(),
__deprecated_function() and
__deprecated_hook() extensively in our code
—we tried to avoid breaking compatibility 99% of
the times
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 27
Problem - it's never time to refactor
"That thing developers do that costs money."
—any Project Manager
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 28
Guerrilla refactoring
—leave the code a little better than you found it
—refactoring and writing tests should be part of
every estimate
—tests should be in the same PR as the code, lead
developers should enforce it
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 29
Filling in the blanks
Developer 1 writes this:
function test_multi(){
$this->assertEquals( 4, func( 2 ) );
$this->assertEquals( 4, func( 2, 2 ) );
$this->assertEquals( 6, func( 2, 3 ) );
$this->assertEquals( 0, func( 0, 3 ) );
}
Developer 2 writes the func() code to make the
tests pass.
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 30
Using a CI to run the tests
—we use Travis CI, there are many others
—tests will run on each PR with visible results that
can prevent PRs from being merged
—removes the "I cannot run the tests" excuse
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 31
Some random good things we did
—lead by example
—test setup parties (nerds rejoice)
—discuss code, not theories, patterns and best
practices in dev meetings
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 32
Takeaways - 1
—it's about changing the people, not the code
—in the long run you want better developers, not
better code
—better developers write better code; writing good
code is an habit, not a function of time
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 33
Takeaways - 2
—do it for the time (and money) you will save, not
for the code
—do it to release more often
—use a CI system
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 34
Takeaways - 3
—start with an acceptance test
—do not separate code and tests in PRs and/or
issue trackers
—let go of the code coverage metrics
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 35
Questions?
Thanks for listening to me, questions?
Are you a good person? Apply to work at Modern
Tribe: tri.be/careers/
@lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 36

More Related Content

What's hot

Finding an unusual cause of max_user_connections in MySQL
Finding an unusual cause of max_user_connections in MySQLFinding an unusual cause of max_user_connections in MySQL
Finding an unusual cause of max_user_connections in MySQL
Olivier Doucet
 
Simple SQL Change Management with Sqitch
Simple SQL Change Management with SqitchSimple SQL Change Management with Sqitch
Simple SQL Change Management with Sqitch
David Wheeler
 
A Node.JS bag of goodies for analyzing Web Traffic
A Node.JS bag of goodies for analyzing Web TrafficA Node.JS bag of goodies for analyzing Web Traffic
A Node.JS bag of goodies for analyzing Web Traffic
Philip Tellis
 
Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java
Baruch Sadogursky
 
VCL template abstraction model and automated deployments to Fastly
VCL template abstraction model and automated deployments to FastlyVCL template abstraction model and automated deployments to Fastly
VCL template abstraction model and automated deployments to Fastly
Fastly
 
Moving In: how to port your content from * to Drupal
Moving In: how to port your content from * to DrupalMoving In: how to port your content from * to Drupal
Moving In: how to port your content from * to Drupal
Emma Jane Hogbin Westby
 
EWD 3 Training Course Part 11: Handling Errors in QEWD
EWD 3 Training Course Part 11: Handling Errors in QEWDEWD 3 Training Course Part 11: Handling Errors in QEWD
EWD 3 Training Course Part 11: Handling Errors in QEWD
Rob Tweed
 
Doctrine Php Object Relational Mapper
Doctrine Php Object Relational MapperDoctrine Php Object Relational Mapper
Doctrine Php Object Relational Mapper
guesta3af58
 
A web perf dashboard up & running in 90 minutes presentation
A web perf dashboard up & running in 90 minutes presentationA web perf dashboard up & running in 90 minutes presentation
A web perf dashboard up & running in 90 minutes presentation
Justin Dorfman
 
Choosing a Javascript Framework
Choosing a Javascript FrameworkChoosing a Javascript Framework
Choosing a Javascript Framework
All Things Open
 
Presentation: Everything you wanted to know about writing async, high-concurr...
Presentation: Everything you wanted to know about writing async, high-concurr...Presentation: Everything you wanted to know about writing async, high-concurr...
Presentation: Everything you wanted to know about writing async, high-concurr...
Baruch Sadogursky
 
Advanced VCL: how to use restart
Advanced VCL: how to use restartAdvanced VCL: how to use restart
Advanced VCL: how to use restart
Fastly
 
Beyond Breakpoints: A Tour of Dynamic Analysis
Beyond Breakpoints: A Tour of Dynamic AnalysisBeyond Breakpoints: A Tour of Dynamic Analysis
Beyond Breakpoints: A Tour of Dynamic Analysis
Fastly
 
The magic of (data parallel) distributed systems and where it all breaks - Re...
The magic of (data parallel) distributed systems and where it all breaks - Re...The magic of (data parallel) distributed systems and where it all breaks - Re...
The magic of (data parallel) distributed systems and where it all breaks - Re...
Holden Karau
 
About Node.js
About Node.jsAbout Node.js
About Node.js
Artemisa Yescas Engler
 
Ansible project-deploy
Ansible project-deployAnsible project-deploy
Ansible project-deploy
Ramon de la Fuente
 
Time for Comet?
Time for Comet?Time for Comet?
Time for Comet?
Simon Willison
 
Measuring Real User Performance in the Browser
Measuring Real User Performance in the BrowserMeasuring Real User Performance in the Browser
Measuring Real User Performance in the Browser
Nicholas Jansma
 
Managing dependencies with gradle
Managing dependencies with gradleManaging dependencies with gradle
Managing dependencies with gradle
Liviu Tudor
 
Let's go HTTPS-only! - More Than Buying a Certificate
Let's go HTTPS-only! - More Than Buying a CertificateLet's go HTTPS-only! - More Than Buying a Certificate
Let's go HTTPS-only! - More Than Buying a Certificate
Steffen Gebert
 

What's hot (20)

Finding an unusual cause of max_user_connections in MySQL
Finding an unusual cause of max_user_connections in MySQLFinding an unusual cause of max_user_connections in MySQL
Finding an unusual cause of max_user_connections in MySQL
 
Simple SQL Change Management with Sqitch
Simple SQL Change Management with SqitchSimple SQL Change Management with Sqitch
Simple SQL Change Management with Sqitch
 
A Node.JS bag of goodies for analyzing Web Traffic
A Node.JS bag of goodies for analyzing Web TrafficA Node.JS bag of goodies for analyzing Web Traffic
A Node.JS bag of goodies for analyzing Web Traffic
 
Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java
 
VCL template abstraction model and automated deployments to Fastly
VCL template abstraction model and automated deployments to FastlyVCL template abstraction model and automated deployments to Fastly
VCL template abstraction model and automated deployments to Fastly
 
Moving In: how to port your content from * to Drupal
Moving In: how to port your content from * to DrupalMoving In: how to port your content from * to Drupal
Moving In: how to port your content from * to Drupal
 
EWD 3 Training Course Part 11: Handling Errors in QEWD
EWD 3 Training Course Part 11: Handling Errors in QEWDEWD 3 Training Course Part 11: Handling Errors in QEWD
EWD 3 Training Course Part 11: Handling Errors in QEWD
 
Doctrine Php Object Relational Mapper
Doctrine Php Object Relational MapperDoctrine Php Object Relational Mapper
Doctrine Php Object Relational Mapper
 
A web perf dashboard up & running in 90 minutes presentation
A web perf dashboard up & running in 90 minutes presentationA web perf dashboard up & running in 90 minutes presentation
A web perf dashboard up & running in 90 minutes presentation
 
Choosing a Javascript Framework
Choosing a Javascript FrameworkChoosing a Javascript Framework
Choosing a Javascript Framework
 
Presentation: Everything you wanted to know about writing async, high-concurr...
Presentation: Everything you wanted to know about writing async, high-concurr...Presentation: Everything you wanted to know about writing async, high-concurr...
Presentation: Everything you wanted to know about writing async, high-concurr...
 
Advanced VCL: how to use restart
Advanced VCL: how to use restartAdvanced VCL: how to use restart
Advanced VCL: how to use restart
 
Beyond Breakpoints: A Tour of Dynamic Analysis
Beyond Breakpoints: A Tour of Dynamic AnalysisBeyond Breakpoints: A Tour of Dynamic Analysis
Beyond Breakpoints: A Tour of Dynamic Analysis
 
The magic of (data parallel) distributed systems and where it all breaks - Re...
The magic of (data parallel) distributed systems and where it all breaks - Re...The magic of (data parallel) distributed systems and where it all breaks - Re...
The magic of (data parallel) distributed systems and where it all breaks - Re...
 
About Node.js
About Node.jsAbout Node.js
About Node.js
 
Ansible project-deploy
Ansible project-deployAnsible project-deploy
Ansible project-deploy
 
Time for Comet?
Time for Comet?Time for Comet?
Time for Comet?
 
Measuring Real User Performance in the Browser
Measuring Real User Performance in the BrowserMeasuring Real User Performance in the Browser
Measuring Real User Performance in the Browser
 
Managing dependencies with gradle
Managing dependencies with gradleManaging dependencies with gradle
Managing dependencies with gradle
 
Let's go HTTPS-only! - More Than Buying a Certificate
Let's go HTTPS-only! - More Than Buying a CertificateLet's go HTTPS-only! - More Than Buying a Certificate
Let's go HTTPS-only! - More Than Buying a Certificate
 

Similar to Refactoring legacy code guided by tests in WordPress

Panmind at Ruby Social Club Milano
Panmind at Ruby Social Club MilanoPanmind at Ruby Social Club Milano
Panmind at Ruby Social Club Milano
Panmind
 
I got 99 trends and a # is all of them
I got 99 trends and a # is all of themI got 99 trends and a # is all of them
I got 99 trends and a # is all of them
Roberto Suggi Liverani
 
LinuxCon 2013 Steven Dake on Using Heat for autoscaling OpenShift on Openstack
LinuxCon 2013 Steven Dake on Using Heat for autoscaling OpenShift on OpenstackLinuxCon 2013 Steven Dake on Using Heat for autoscaling OpenShift on Openstack
LinuxCon 2013 Steven Dake on Using Heat for autoscaling OpenShift on Openstack
OpenShift Origin
 
Luigi presentation NYC Data Science
Luigi presentation NYC Data ScienceLuigi presentation NYC Data Science
Luigi presentation NYC Data Science
Erik Bernhardsson
 
TYPO3 Scheduler
TYPO3 SchedulerTYPO3 Scheduler
TYPO3 Scheduler
Krystian Szymukowicz
 
FOSDEM2018 Janus Lua plugin presentation
FOSDEM2018 Janus Lua plugin presentationFOSDEM2018 Janus Lua plugin presentation
FOSDEM2018 Janus Lua plugin presentation
Lorenzo Miniero
 
Zero to scaleable in ten minutes
Zero to scaleable in ten minutesZero to scaleable in ten minutes
Zero to scaleable in ten minutes
Matt Walters
 
DevOps_project.pdf
DevOps_project.pdfDevOps_project.pdf
DevOps_project.pdf
Prateek Srivastava
 
WordCamp Belfast DevOps for Beginners
WordCamp Belfast DevOps for BeginnersWordCamp Belfast DevOps for Beginners
WordCamp Belfast DevOps for Beginners
Stewart Ritchie
 
Resilience: the key requirement of a [big] [data] architecture - StampedeCon...
Resilience: the key requirement of a [big] [data] architecture  - StampedeCon...Resilience: the key requirement of a [big] [data] architecture  - StampedeCon...
Resilience: the key requirement of a [big] [data] architecture - StampedeCon...
StampedeCon
 
Boost your productivity with Scala tooling!
Boost your productivity  with Scala tooling!Boost your productivity  with Scala tooling!
Boost your productivity with Scala tooling!
MeriamLachkar1
 
Fix me if you can - DrupalCon prague
Fix me if you can - DrupalCon pragueFix me if you can - DrupalCon prague
Fix me if you can - DrupalCon prague
hernanibf
 
Ekoparty 2017 - The Bug Hunter's Methodology
Ekoparty 2017 - The Bug Hunter's MethodologyEkoparty 2017 - The Bug Hunter's Methodology
Ekoparty 2017 - The Bug Hunter's Methodology
bugcrowd
 
Workshop: Functional testing made easy with PHPUnit & Selenium (phpCE Poland,...
Workshop: Functional testing made easy with PHPUnit & Selenium (phpCE Poland,...Workshop: Functional testing made easy with PHPUnit & Selenium (phpCE Poland,...
Workshop: Functional testing made easy with PHPUnit & Selenium (phpCE Poland,...
Ondřej Machulda
 
No Hugging, No Learning
No Hugging, No LearningNo Hugging, No Learning
No Hugging, No Learning
Olaf Alders
 
Just In Time Scalability Agile Methods To Support Massive Growth Presentation
Just In Time Scalability  Agile Methods To Support Massive Growth PresentationJust In Time Scalability  Agile Methods To Support Massive Growth Presentation
Just In Time Scalability Agile Methods To Support Massive Growth Presentation
Timothy Fitz
 
Just In Time Scalability Agile Methods To Support Massive Growth Presentation
Just In Time Scalability  Agile Methods To Support Massive Growth PresentationJust In Time Scalability  Agile Methods To Support Massive Growth Presentation
Just In Time Scalability Agile Methods To Support Massive Growth Presentation
Eric Ries
 
Azure from scratch part 4
Azure from scratch part 4Azure from scratch part 4
Azure from scratch part 4
Girish Kalamati
 
AWS Sydney Summit 2013 - Your First Week with Amazon EC2
AWS Sydney Summit 2013 - Your First Week with Amazon EC2AWS Sydney Summit 2013 - Your First Week with Amazon EC2
AWS Sydney Summit 2013 - Your First Week with Amazon EC2
Amazon Web Services
 
HAXTheWeb @ Apereo 19
HAXTheWeb @ Apereo 19HAXTheWeb @ Apereo 19
HAXTheWeb @ Apereo 19
btopro
 

Similar to Refactoring legacy code guided by tests in WordPress (20)

Panmind at Ruby Social Club Milano
Panmind at Ruby Social Club MilanoPanmind at Ruby Social Club Milano
Panmind at Ruby Social Club Milano
 
I got 99 trends and a # is all of them
I got 99 trends and a # is all of themI got 99 trends and a # is all of them
I got 99 trends and a # is all of them
 
LinuxCon 2013 Steven Dake on Using Heat for autoscaling OpenShift on Openstack
LinuxCon 2013 Steven Dake on Using Heat for autoscaling OpenShift on OpenstackLinuxCon 2013 Steven Dake on Using Heat for autoscaling OpenShift on Openstack
LinuxCon 2013 Steven Dake on Using Heat for autoscaling OpenShift on Openstack
 
Luigi presentation NYC Data Science
Luigi presentation NYC Data ScienceLuigi presentation NYC Data Science
Luigi presentation NYC Data Science
 
TYPO3 Scheduler
TYPO3 SchedulerTYPO3 Scheduler
TYPO3 Scheduler
 
FOSDEM2018 Janus Lua plugin presentation
FOSDEM2018 Janus Lua plugin presentationFOSDEM2018 Janus Lua plugin presentation
FOSDEM2018 Janus Lua plugin presentation
 
Zero to scaleable in ten minutes
Zero to scaleable in ten minutesZero to scaleable in ten minutes
Zero to scaleable in ten minutes
 
DevOps_project.pdf
DevOps_project.pdfDevOps_project.pdf
DevOps_project.pdf
 
WordCamp Belfast DevOps for Beginners
WordCamp Belfast DevOps for BeginnersWordCamp Belfast DevOps for Beginners
WordCamp Belfast DevOps for Beginners
 
Resilience: the key requirement of a [big] [data] architecture - StampedeCon...
Resilience: the key requirement of a [big] [data] architecture  - StampedeCon...Resilience: the key requirement of a [big] [data] architecture  - StampedeCon...
Resilience: the key requirement of a [big] [data] architecture - StampedeCon...
 
Boost your productivity with Scala tooling!
Boost your productivity  with Scala tooling!Boost your productivity  with Scala tooling!
Boost your productivity with Scala tooling!
 
Fix me if you can - DrupalCon prague
Fix me if you can - DrupalCon pragueFix me if you can - DrupalCon prague
Fix me if you can - DrupalCon prague
 
Ekoparty 2017 - The Bug Hunter's Methodology
Ekoparty 2017 - The Bug Hunter's MethodologyEkoparty 2017 - The Bug Hunter's Methodology
Ekoparty 2017 - The Bug Hunter's Methodology
 
Workshop: Functional testing made easy with PHPUnit & Selenium (phpCE Poland,...
Workshop: Functional testing made easy with PHPUnit & Selenium (phpCE Poland,...Workshop: Functional testing made easy with PHPUnit & Selenium (phpCE Poland,...
Workshop: Functional testing made easy with PHPUnit & Selenium (phpCE Poland,...
 
No Hugging, No Learning
No Hugging, No LearningNo Hugging, No Learning
No Hugging, No Learning
 
Just In Time Scalability Agile Methods To Support Massive Growth Presentation
Just In Time Scalability  Agile Methods To Support Massive Growth PresentationJust In Time Scalability  Agile Methods To Support Massive Growth Presentation
Just In Time Scalability Agile Methods To Support Massive Growth Presentation
 
Just In Time Scalability Agile Methods To Support Massive Growth Presentation
Just In Time Scalability  Agile Methods To Support Massive Growth PresentationJust In Time Scalability  Agile Methods To Support Massive Growth Presentation
Just In Time Scalability Agile Methods To Support Massive Growth Presentation
 
Azure from scratch part 4
Azure from scratch part 4Azure from scratch part 4
Azure from scratch part 4
 
AWS Sydney Summit 2013 - Your First Week with Amazon EC2
AWS Sydney Summit 2013 - Your First Week with Amazon EC2AWS Sydney Summit 2013 - Your First Week with Amazon EC2
AWS Sydney Summit 2013 - Your First Week with Amazon EC2
 
HAXTheWeb @ Apereo 19
HAXTheWeb @ Apereo 19HAXTheWeb @ Apereo 19
HAXTheWeb @ Apereo 19
 

Recently uploaded

Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise EditionWhy Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Envertis Software Solutions
 
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
mz5nrf0n
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
Green Software Development
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
Neo4j
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
Green Software Development
 
socradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdfsocradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdf
SOCRadar
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Deuglo Infosystem Pvt Ltd
 
SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024
Hironori Washizaki
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
Philip Schwarz
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
lorraineandreiamcidl
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j
 
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s EcosystemUI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
Peter Muessig
 
Oracle 23c New Features For DBAs and Developers.pptx
Oracle 23c New Features For DBAs and Developers.pptxOracle 23c New Features For DBAs and Developers.pptx
Oracle 23c New Features For DBAs and Developers.pptx
Remote DBA Services
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
Aftab Hussain
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
Remote DBA Services
 
SMS API Integration in Saudi Arabia| Best SMS API Service
SMS API Integration in Saudi Arabia| Best SMS API ServiceSMS API Integration in Saudi Arabia| Best SMS API Service
SMS API Integration in Saudi Arabia| Best SMS API Service
Yara Milbes
 

Recently uploaded (20)

Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise EditionWhy Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
 
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
 
socradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdfsocradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdf
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
 
SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
 
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s EcosystemUI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
 
Oracle 23c New Features For DBAs and Developers.pptx
Oracle 23c New Features For DBAs and Developers.pptxOracle 23c New Features For DBAs and Developers.pptx
Oracle 23c New Features For DBAs and Developers.pptx
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
 
SMS API Integration in Saudi Arabia| Best SMS API Service
SMS API Integration in Saudi Arabia| Best SMS API ServiceSMS API Integration in Saudi Arabia| Best SMS API Service
SMS API Integration in Saudi Arabia| Best SMS API Service
 

Refactoring legacy code guided by tests in WordPress

  • 1. Refactoring legacy code guided by tests in WordPress WC Rome, 2017/12/16 Luca Tumedei @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 1
  • 2. About me —freelance WordPress developer —been working with Modern Tribe for 3.5 years now —creator of wp-browser and lover of tests @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 2
  • 3. Long time no see <?php /* Plugin Name: My New Plugin Plugin URI: https://example.com Version: 0.1.0 Description: Really new; from scratch. Author: Luca Tumedei Author URI: http://example.com */ Starting from scratch is not an option. @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 3
  • 4. Dramatis personae - Modern Tribe and The Events Calendar plugin —Modern Tribe is a remote (and awesome) agency providing digital products and services —The Events Calendar is MT's most famous WordPress plugin —The Events Calendar is just one of the many free and premium WordPress plugins MT actively maintains @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 4
  • 5. Dramatis personae - MT developers —there are 21 developers maintaining MT's plugins —in their history about 100 different developers worked on the plugins —the skill, habits, beliefs and mantras of each might vary... @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 5
  • 6. Dramatis personae - the users —The Events Calendar has about 600.000 active installations —The Events Calendar is the base for many of Modern Tribe premium plugins and services —third-party developers are users too @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 6
  • 7. Still a work in progress —this is not about how "we did it" —this is about how "we are doing it" and what we found out along the way —you can see The Events Calendar code on GitHub and judge for yourself @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 7
  • 8. Refactoring "Code refactoring is the process of restructuring existing computer code, changing the factoring, without changing its external behavior." —Wikipedia @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 8
  • 9. Legacy code "Michael Feathers introduced a definition of legacy code as code without tests, which reflects the perspective of legacy code being difficult to work with in part due to a lack of automated regression tests." —Wikipedia @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 9
  • 10. Guided by tests "Write the tests, then change the code. I need coffee." —me, on Slack @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 10
  • 11. Why then? —the code was not testable as it was —tests allow to iterate faster —faster iterations means shipping new features and bug fixes faster We win, users win, everybody wins! @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 11
  • 12. You are already doing TDD —you modify the code —you go on a site page and try it out —you fix it and try again You are just doing it slowly, inefficiently and in an under-engineered way. @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 12
  • 13. Problem - Testing WordPress is impossible —Codeception and wp-browser are the tools we chose —some of the other options include the Core suite, WordHat, Behat —at the very minimum you can always do acceptance testing @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 13
  • 14. Why Codeception and wp-browser? —I might have something to do with it —wp-browser provides Codeception modules dedicated to WordPress —Codeception supports all levels of testing: acceptance, functional, integration and unit @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 14
  • 15. Our first acceptance test $I = new AcceptanceTester( $scenario ); $I->am( 'a WordPress site admin' ); $I->wantTo( 'be able to activate The Events Calendar plugin' ); $I->loginAsAdmin(); $I->amOnPluginsPage(); $I->activatePlugin( 'the-events-calendar' ); $I->seePluginActivated( 'the-events-calendar' ); This runs in .6 seconds. Faster than a person, if you were guessing. @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 15
  • 16. A second acceptance test for the front-end $I = new AcceptanceTester( $scenario ); $I->am( 'a calendar visitor' ); $I->wantTo( 'be able to see the calendar' ); $format = 'Y-m-d H:i:s'; $meta = [ '_EventStartDate' => date( $format , strtotime( 'tomorrow 9am' ) ), '_EventEndDate' => date( $format , strtotime( 'tomorrow 11am' ) ), ]; $I->havePostInDatabase( [ 'post_type' => 'tribe_events', 'meta_input' => $meta, 'post_title' => 'Test Event' ] ); $I->amOnPage( '/events' ); $I->see( 'Test Event' ); @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 16
  • 17. The flow —write tests and run them to make sure current code passes them —refactor the code —run tests and fix the code until tests pass again Repeat n times as you would do by hand. @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 17
  • 18. Problem - PHP 5.2 compatibility —"it cannot be done in PHP 5.2" is a sad excuse —production code can be 5.2 compatible, test code does not need to be —acceptance tests can run against a PHP 5.2 webserver @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 18
  • 19. Problem - hardcoded file inclusion —getting hold of one element is nigh impossible due to a forest of side effects —there is always an include or require somewhere —we wrote our own autoloader but you can use Composer and xrstf/composer-php52 to generate your PHP 5.2 compatible autoload file @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 19
  • 20. Reorganizing files and classes —we nested folders "by subject" —we use __ as a folder separator —some class names are long... Tribe__Events__REST__V1__Endpoints__... @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 20
  • 21. A simple autoloader function my_autoloader( $class ){ if( 0 !== strpos( $class, 'MyPlugin_' ) ){ return; } // `MyPlugin_Foo_Bar_MyClass` to `Foo/Bar/MyClass` $path = str_replace( '_', '/', str_replace( 'My_Plugin_', '', $class ) ); include dirname( __FILE__ ) . '/src/' . $path . '.php'; } spl_autoload_register( 'my_autoloader' ); @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 21
  • 22. Problem - the Main class /** * Main Tribe Events Calendar class. */ // Don't load directly if ( ! defined( 'ABSPATH' ) ) { die( '-1' ); } if ( ! class_exists( 'Tribe__Events__Main' ) ) { /** * The Events Calendar Class * * This is where all the magic happens, the unicorns run wild and the leprechauns use WordPress to schedule events. */ class Tribe__Events__Main { Emphasis on "This is where all the magic happens". @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 22
  • 23. Bow to your god object! —the class did everything: from localization to managing currency symbols —it was a Petri dish of anti-patterns —it was tens of thousands lines long (it's still ~5000) @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 23
  • 24. Naming things is difficult "There are only two hard things in Computer Science: cache invalidation and naming things." -- Phil Karlton @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 24
  • 25. Naming things is important —names are only useful for people, the server does not care if your classes are called Francine and Waldo —names indicate what something is supposed to do —adding yet another method to Main is easier than adding it to Admin_Views_Single_Event_Metabox @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 25
  • 26. Reducing Main —break it down into smaller, specialized, classes —STOP. ADDING. METHODS. TO. IT. —create subsidiary "Mains" and stop calling things "Main" @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 26
  • 27. Deprecating files, classes and hooks —we moved a lot of things during the process of refactoring —we used __deprecated_file(), __deprecated_function() and __deprecated_hook() extensively in our code —we tried to avoid breaking compatibility 99% of the times @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 27
  • 28. Problem - it's never time to refactor "That thing developers do that costs money." —any Project Manager @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 28
  • 29. Guerrilla refactoring —leave the code a little better than you found it —refactoring and writing tests should be part of every estimate —tests should be in the same PR as the code, lead developers should enforce it @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 29
  • 30. Filling in the blanks Developer 1 writes this: function test_multi(){ $this->assertEquals( 4, func( 2 ) ); $this->assertEquals( 4, func( 2, 2 ) ); $this->assertEquals( 6, func( 2, 3 ) ); $this->assertEquals( 0, func( 0, 3 ) ); } Developer 2 writes the func() code to make the tests pass. @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 30
  • 31. Using a CI to run the tests —we use Travis CI, there are many others —tests will run on each PR with visible results that can prevent PRs from being merged —removes the "I cannot run the tests" excuse @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 31
  • 32. Some random good things we did —lead by example —test setup parties (nerds rejoice) —discuss code, not theories, patterns and best practices in dev meetings @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 32
  • 33. Takeaways - 1 —it's about changing the people, not the code —in the long run you want better developers, not better code —better developers write better code; writing good code is an habit, not a function of time @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 33
  • 34. Takeaways - 2 —do it for the time (and money) you will save, not for the code —do it to release more often —use a CI system @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 34
  • 35. Takeaways - 3 —start with an acceptance test —do not separate code and tests in PRs and/or issue trackers —let go of the code coverage metrics @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 35
  • 36. Questions? Thanks for listening to me, questions? Are you a good person? Apply to work at Modern Tribe: tri.be/careers/ @lucatume - theaveragedev.com - Modern Tribe - The Events Calendar 36