SlideShare ist ein Scribd-Unternehmen logo
1 von 111
Downloaden Sie, um offline zu lesen
@asgrim
Best practices for crafting high
quality PHP apps
James Titcumb
ScotlandPHP 2018
Please clone & composer install:
https://github.com/asgrim/quality-tutorial
$ whoami
James Titcumb
www.jamestitcumb.com
www.roave.com
@asgrim
Please clone & composer install:
https://github.com/asgrim/quality-tutorial
@asgrim
@asgrim
What is “quality”?
@asgrim
photo: Rob Allen https://flic.kr/p/qmGpsq
@asgrim
@asgrim
@asgrim
Quality.
@asgrim
"The best code is no code at all”
-- Jeff Atwood
source: https://blog.codinghorror.com/the-best-code-is-no-code-at-all/
@asgrim
Trade-offs.
@asgrim
Prototyping & short-lived apps/sites
@asgrim
Products
Long-lived projects. Open source software.
@asgrim
What is quality in applications?
@asgrim
What about time/cost…?
@asgrim
“A freelancer at $25 an hour for 100 hours still
costs more than a freelancer at $150 an hour that
takes 10 hours to do the same task”
-- Brandon Savage
source: http://www.brandonsavage.net/earning-more-money-as-a-php-freelancer/
@asgrim
Get an expert in.
@asgrim
Complexity
@asgrim
Processes
@asgrim
This talk...
● Planning
● Development
● Testing
● Continuous integration
● Code reviews
● Deployments
@asgrim
Planning
@asgrim
Planning is communication
@asgrim
Use business terminology
@asgrim
Explore and discover
@asgrim
Build a model of the business
@asgrim
@asgrim
@asgrim
The model must be fluid.
@asgrim
“Estimates”
@asgrim
Development
@asgrim
Care about code
@asgrim
“There are only two hard things in Computer
Science: cache invalidation and naming things.”
-- Phil Karlton
source: https://martinfowler.com/bliki/TwoHardThings.html
@asgrim
SimpleBeanFactoryAwareAspectInstanceFactory
@asgrim
Loader
@asgrim
Describe intent
@asgrim
“Give awkward names to awkward concepts”
-- Eric Evans
source: https://skillsmatter.com/conferences/8231-ddd-exchange-2017
@asgrim
SOLID
@asgrim
KISS
@asgrim
Object Calisthenics
@asgrim
Avoid early abstraction
@asgrim
“Code for your use-case,
not for your re-use-case”
-- Marco Pivetta
source: https://ocramius.github.io/extremely-defensive-php/#/39
@asgrim
Care about your API
@asgrim
A public method is like a child:
once you've written it,
you are going to maintain it
for the rest of its life!
-- Stefan Priebsch
@asgrim
Strict type declarations.
Use declare(strict_types=1); by default
@asgrim
Immutable value objects
declare(strict_types=1);
use AssertAssertion; // beberlei/assert library !
final class PostalCode
{
private const VALIDATION_EXPRESSION = '(GIR 0AA)|((([A-Z-[QVX]][0-9][0-...
/** @var string */
private $value;
public function __construct(string $value) {
$this->assertValidPostalCode($value);
$this->value = $value;
}
private function assertValidPostalCode(string $value) : string {
Assertion::regex($value, self::VALIDATION_EXPRESSION);
}
public function __toString() : string {
return $this->value;
}
}
@asgrim
Value objects are valid!
declare(strict_types=1);
final class Thing {
public function assignPostalCode(PostalCode $postalCode) : void
{
// ... we can trust $postalCode is a valid postal code
}
}
// 12345 is not valid - EXCEPTION!
$myThing->assignPostalCode(new PostalCode('12345'));
// assignPostalCode is happy
$myThing->assignPostalCode(new PostalCode('PO1 1AA'));
// With STRICT types, this will also FAIL
$myThing->assignPostalCode(new PostalCode(12345));
@asgrim
Testing
@asgrim
Testing is NOT a separate line item
@asgrim
Testing should be an assumption
@asgrim
You’re already testing.
@asgrim
Still need convincing?
@asgrim
How?
@asgrim
Reduce complexity
@asgrim
Reduce complexity
public function process(Stuff a, string b, int c) : MoreStuff
{
// lots of complicated code
// lots of complicated code
// lots of complicated code
// lots of complicated code
// lots of complicated code
// lots of complicated code
// lots of complicated code
// lots of complicated code
// lots of complicated code
// lots of complicated code
// lots of complicated code
// lots of complicated code
// lots of complicated code
// lots of complicated code
@asgrim
Reduce complexity
public function meaningfulThing(Stuff a, string b, int c) : More
{
// call nicer, meaningful methods below
}
private function throwStuffIntoFire(Stuff a) : Fire
{
// smaller, meaningful chunk of code
}
private function combineStringWithFire(Fire a, string b) : string
{
// simple, lovely code!
}
private function postFlowersToSpain(int c) : void
@asgrim
More complexity = more tests
@asgrim
Test coverage
@asgrim
Line coverage
<?php
function foo(bool $a, bool $b) {
if ($a) {
echo "A";
}
if ($b) {
echo "B";
}
}
// generate coverage using calls:
foo(true, false);
foo(false, true);
@asgrim
Line coverage
<?php
function foo(bool $a, bool $b) {
if ($a) {
echo "A";
}
if ($b) {
echo "B";
}
}
// generate coverage using calls:
foo(true, false);
foo(false, true);
@asgrim
Branch coverage
<?php
function foo(bool $a, bool $b) {
if ($a) {
echo "A";
}
if ($b) {
echo "B";
}
}
// generate coverage using calls:
foo(true, false);
foo(false, true);
@asgrim
Branch coverage
<?php
function foo(bool $a, bool $b) {
if ($a) {
echo "A";
}
if ($b) {
echo "B";
}
}
// generate coverage using calls:
foo(true, false);
foo(false, true);
@asgrim
Branch coverage
<?php
function foo(bool $a, bool $b) {
if ($a) {
echo "A";
}
if ($b) {
echo "B";
}
}
// generate coverage using calls:
foo(true, false);
foo(false, true);
foo(false, false); // NEW TEST!!!
@asgrim
Branch coverage
<?php
function foo(bool $a, bool $b) {
if ($a) {
echo "A";
}
if ($b) {
echo "B";
}
}
// generate coverage using calls:
foo(true, false);
foo(false, true);
foo(false, false); // NEW TEST!!!
foo(true, true); // NEW TEST!!!
@asgrim
Prevent coverage leaking
@asgrim
Prevent coverage leaking
<?php
namespace Foo;
/**
* @covers FooBar
*/
final class BarTest extends TestCase
{
// write some tests!
}
@asgrim
Are the tests testing?
@asgrim
Example of a test not testing…
public function testPurchaseTickets()
{
$event = Event::create(uniq('event', true)
$customer = Customer::create(uniq('name', true));
$shop->purchaseTicket(1, $event, [$customer]);
}
@asgrim
@asgrim
Assert you’re asserting
public function testPurchaseTickets()
{
$event = Event::create(uniq('event', true)
$customer = Customer::create(uniq('name', true));
$receipt = $shop->purchaseTicket(1, $event, [$customer]);
self::assertSame($event, $receipt->event());
$customersInReceipt = $receipt->customers();
self::assertCount(1, $customersInReceipt);
self::assertContains($customer, $customersInReceipt);
}
@asgrim
@asgrim
Test the tests are testing!
@asgrim
Mutation testing
function add(int $a, int $b) : int {
return $a + $b;
}
function testAdd() {
$result = add(2, 3);
// self::assertSame(5, $result);
}
@asgrim
Mutation testing
function add(int $a, int $b) : int {
return $a - $b;
}
function testAdd() {
$result = add(2, 3);
// self::assertSame(5, $result);
}
@asgrim
Mutation testing
function add(int $a, int $b) : int {
return $a - $b;
}
function testAdd() {
$result = add(2, 3);
self::assertSame(5, $result);
// /// test will now fail with mutation
}
@asgrim
What about other tests?
@asgrim
Integration tests
@asgrim
Behaviour tests
@asgrim
BAD! Do not do this.
Feature: Ability to print my boarding pass
Scenario: A checked in passenger can print their boarding pass
Given I have a flight booked
And I have checked in
When I visit the home page
And I click the ".manage-booking" button
And I enter "CJM23L" in the ".bref-ipt-fld" field
And I click the "Find Booking" button
Then I should see the ".booking-ref.print" button
When I click the ".booking-ref.print" button
Then I should see the print dialogue
@asgrim
Better Behaviour test
Feature: Ability to print my boarding pass
Policies:
- Boarding passes are only available when already checked in
- If customer cannot print boarding pass, they can collect at
The airport
- more business rules etc...
Scenario: A checked in passenger can print their boarding pass
Given I have a flight booked for LHR-MIA on 24th May
And I have previously checked in for the flight
When I display my booking reference "CJM23L"
Then I should be able to print my boarding pass
And the boarding pass should display flight details correctly
@asgrim
Why is this important?
@asgrim
Automate these tests
@asgrim
Automated tests
Application (and UI, API, etc.)
Domain / Business Logic
Infrastructure (DBAL, APIs, etc.)
@asgrim
Automated tests
Application (and UI, API, etc.)
Domain / Business Logic
Infrastructure (DBAL, APIs, etc.)
@asgrim
Testing at domain layer
Application (UI, API, etc.)
Domain / Business Logic
Infrastructure (DB, APIs, etc.)
// Testing via the UI
public function iDisplayMyBookingReference(string $reference)
{
$page = $this->getSession()->getPage();
$page->click(".manage-booking");
$page->findField(".bref-ipt-fld")->setValue($reference);
$page->click("Find Booking");
}
// Using the domain layer directly in tests
public function iDisplayMyBookingReference(string $reference)
{
$this->booking = $this->retrieveBooking($reference);
}
@asgrim
Some UI testing is okay!!!
Feature: Ability to print my boarding pass
Policies:
- Boarding passes are only available when already checked in
- If customer cannot print boarding pass, they can collect at
The airport
- more business rules etc...
@ui
Scenario: A checked in passenger can print their boarding pass
Given I have a flight booked for LHR-OTP on 24th May
And I have previously checked in for the flight
When I display my booking reference "CJM23L"
Then I should be able to print my boarding pass
And the boarding pass should display flight details correctly
@asgrim
Automate all the things!
@asgrim
Continuous Integration
@asgrim
Tests cost money to run
(manually)
@asgrim
Travis-CI.com
@asgrim
Jenkins
@asgrim
What to automate?
@asgrim
The goal?
@asgrim
Code reviews
@asgrim
What to look for in code review?
@asgrim
What to look for in code review?
Code style.
@asgrim
What to look for in code review?
Small, atomic changes.
@asgrim
What to look for in code review?
Composer versions.
@asgrim
What to look for in code review?
Structure & good practices.
@asgrim
What to look for in code review?
Tests.
@asgrim
What to look for in code review?
Documentation.
@asgrim
What to look for in code review?
Security.
@asgrim
What to look for in code review?
Insight.
@asgrim
It takes practice.
@asgrim
Deployments
@asgrim
Automate deployments!
@asgrim
One-click deployments
@asgrim
“Move fast and break things”
-- a stupid Facebook mantra
@asgrim
“Move fast and break things with stable infra”
-- Facebook mantra since 2014
@asgrim
Continuous Delivery & Deployment
@asgrim
Better quality
@asgrim
Better quality = Higher confidence
@asgrim
Better quality = Higher confidence = Happy customers
Any questions?
James Titcumb
@asgrim
@asgrim
Resources
● Event Storming - Alberto Brandolini
○ http://ziobrando.blogspot.co.uk/2013/11/introducing-event-storming.html
● “Good Design is Imperfect Design” - Eric Evans
○ https://skillsmatter.com/skillscasts/9171-good-design-is-imperfect-design
● “Writing code that lasts” - Rafael Dohms
○ https://www.youtube.com/watch?v=I0y5jU61pS4
● Object Calisthenics - William Durand
○ https://williamdurand.fr/2013/06/03/object-calisthenics/
● “Driving Design through Examples” - Ciaran McNulty
○ https://www.youtube.com/watch?v=83GbyDpJDI4
● Code Review Checklist
○ https://github.com/asgrim/code-review-checklist/blob/master/index.md

Weitere ähnliche Inhalte

Was ist angesagt?

Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)James Titcumb
 
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)James Titcumb
 
Best practices for crafting high quality PHP apps (php[world] 2019)
Best practices for crafting high quality PHP apps (php[world] 2019)Best practices for crafting high quality PHP apps (php[world] 2019)
Best practices for crafting high quality PHP apps (php[world] 2019)James Titcumb
 
Best practices for crafting high quality PHP apps (Bulgaria 2019)
Best practices for crafting high quality PHP apps (Bulgaria 2019)Best practices for crafting high quality PHP apps (Bulgaria 2019)
Best practices for crafting high quality PHP apps (Bulgaria 2019)James Titcumb
 
Crafting Quality PHP Applications (PHP Joburg Oct 2019)
Crafting Quality PHP Applications (PHP Joburg Oct 2019)Crafting Quality PHP Applications (PHP Joburg Oct 2019)
Crafting Quality PHP Applications (PHP Joburg Oct 2019)James Titcumb
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming Enguest9bcef2f
 
Moving away from legacy code with BDD
Moving away from legacy code with BDDMoving away from legacy code with BDD
Moving away from legacy code with BDDKonstantin Kudryashov
 
TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016CiaranMcNulty
 
Beyond MVC: from Model to Domain
Beyond MVC: from Model to DomainBeyond MVC: from Model to Domain
Beyond MVC: from Model to DomainJeremy Cook
 
"Managing API Complexity". Matthew Flaming, Temboo
"Managing API Complexity". Matthew Flaming, Temboo"Managing API Complexity". Matthew Flaming, Temboo
"Managing API Complexity". Matthew Flaming, TembooYandex
 
Unbreakable Domain Models PHPUK 2014 London
Unbreakable Domain Models PHPUK 2014 LondonUnbreakable Domain Models PHPUK 2014 London
Unbreakable Domain Models PHPUK 2014 LondonMathias Verraes
 
Scti 2011 minicurso jquery
Scti 2011 minicurso jqueryScti 2011 minicurso jquery
Scti 2011 minicurso jqueryciberglo
 
JavaScript, Beyond the Curly Braces
JavaScript, Beyond the Curly BracesJavaScript, Beyond the Curly Braces
JavaScript, Beyond the Curly BracesChicago ALT.NET
 
Driving Design with PhpSpec
Driving Design with PhpSpecDriving Design with PhpSpec
Driving Design with PhpSpecCiaranMcNulty
 
[Practical] Functional Programming in Rails
[Practical] Functional Programming in Rails[Practical] Functional Programming in Rails
[Practical] Functional Programming in RailsGilbert B Garza
 
Deliver Business Value Faster with AWS Step Functions
Deliver Business Value Faster with AWS Step FunctionsDeliver Business Value Faster with AWS Step Functions
Deliver Business Value Faster with AWS Step FunctionsDaniel Zivkovic
 

Was ist angesagt? (20)

Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
 
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
 
Best practices for crafting high quality PHP apps (php[world] 2019)
Best practices for crafting high quality PHP apps (php[world] 2019)Best practices for crafting high quality PHP apps (php[world] 2019)
Best practices for crafting high quality PHP apps (php[world] 2019)
 
Best practices for crafting high quality PHP apps (Bulgaria 2019)
Best practices for crafting high quality PHP apps (Bulgaria 2019)Best practices for crafting high quality PHP apps (Bulgaria 2019)
Best practices for crafting high quality PHP apps (Bulgaria 2019)
 
Crafting Quality PHP Applications (PHP Joburg Oct 2019)
Crafting Quality PHP Applications (PHP Joburg Oct 2019)Crafting Quality PHP Applications (PHP Joburg Oct 2019)
Crafting Quality PHP Applications (PHP Joburg Oct 2019)
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming En
 
Moving away from legacy code with BDD
Moving away from legacy code with BDDMoving away from legacy code with BDD
Moving away from legacy code with BDD
 
TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016
 
Beyond MVC: from Model to Domain
Beyond MVC: from Model to DomainBeyond MVC: from Model to Domain
Beyond MVC: from Model to Domain
 
"Managing API Complexity". Matthew Flaming, Temboo
"Managing API Complexity". Matthew Flaming, Temboo"Managing API Complexity". Matthew Flaming, Temboo
"Managing API Complexity". Matthew Flaming, Temboo
 
Unbreakable Domain Models PHPUK 2014 London
Unbreakable Domain Models PHPUK 2014 LondonUnbreakable Domain Models PHPUK 2014 London
Unbreakable Domain Models PHPUK 2014 London
 
Scti 2011 minicurso jquery
Scti 2011 minicurso jqueryScti 2011 minicurso jquery
Scti 2011 minicurso jquery
 
Jquery 1
Jquery 1Jquery 1
Jquery 1
 
JavaScript Needn't Hurt!
JavaScript Needn't Hurt!JavaScript Needn't Hurt!
JavaScript Needn't Hurt!
 
JavaScript, Beyond the Curly Braces
JavaScript, Beyond the Curly BracesJavaScript, Beyond the Curly Braces
JavaScript, Beyond the Curly Braces
 
TDD with PhpSpec
TDD with PhpSpecTDD with PhpSpec
TDD with PhpSpec
 
Driving Design with PhpSpec
Driving Design with PhpSpecDriving Design with PhpSpec
Driving Design with PhpSpec
 
[Practical] Functional Programming in Rails
[Practical] Functional Programming in Rails[Practical] Functional Programming in Rails
[Practical] Functional Programming in Rails
 
Deliver Business Value Faster with AWS Step Functions
Deliver Business Value Faster with AWS Step FunctionsDeliver Business Value Faster with AWS Step Functions
Deliver Business Value Faster with AWS Step Functions
 
Um2010
Um2010Um2010
Um2010
 

Ähnlich wie Best practices for crafting high quality PHP apps (ScotlandPHP 2018)

James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...Codemotion
 
Post Sharp Talk
Post Sharp TalkPost Sharp Talk
Post Sharp Talkwillmation
 
Application Layer in PHP
Application Layer in PHPApplication Layer in PHP
Application Layer in PHPPer Bernhardt
 
Bringing modern PHP development to IBM i (ZendCon 2016)
Bringing modern PHP development to IBM i (ZendCon 2016)Bringing modern PHP development to IBM i (ZendCon 2016)
Bringing modern PHP development to IBM i (ZendCon 2016)James Titcumb
 
Great Developers Steal
Great Developers StealGreat Developers Steal
Great Developers StealBen Scofield
 
Effecient javascript
Effecient javascriptEffecient javascript
Effecient javascriptmpnkhan
 
Socket applications
Socket applicationsSocket applications
Socket applicationsJoão Moura
 
Lightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClientLightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClientAdam Wiggins
 
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020Andrzej Jóźwiak
 
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)James Titcumb
 
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHP Oxford June Meetup 2...
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHP Oxford June Meetup 2...Adding 1.21 Gigawatts to Applications with RabbitMQ (PHP Oxford June Meetup 2...
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHP Oxford June Meetup 2...James Titcumb
 
Need for Speed: Removing speed bumps in API Projects
Need for Speed: Removing speed bumps in API ProjectsNeed for Speed: Removing speed bumps in API Projects
Need for Speed: Removing speed bumps in API ProjectsŁukasz Chruściel
 
Client-side JavaScript Vulnerabilities
Client-side JavaScript VulnerabilitiesClient-side JavaScript Vulnerabilities
Client-side JavaScript VulnerabilitiesOry Segal
 
Diving into HHVM Extensions (php[tek] 2016)
Diving into HHVM Extensions (php[tek] 2016)Diving into HHVM Extensions (php[tek] 2016)
Diving into HHVM Extensions (php[tek] 2016)James Titcumb
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsMichelangelo van Dam
 
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)James Titcumb
 
JavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesJavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesSiarhei Barysiuk
 

Ähnlich wie Best practices for crafting high quality PHP apps (ScotlandPHP 2018) (20)

James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
 
Postman On Steroids
Postman On SteroidsPostman On Steroids
Postman On Steroids
 
Rack Middleware
Rack MiddlewareRack Middleware
Rack Middleware
 
Post Sharp Talk
Post Sharp TalkPost Sharp Talk
Post Sharp Talk
 
Application Layer in PHP
Application Layer in PHPApplication Layer in PHP
Application Layer in PHP
 
Bringing modern PHP development to IBM i (ZendCon 2016)
Bringing modern PHP development to IBM i (ZendCon 2016)Bringing modern PHP development to IBM i (ZendCon 2016)
Bringing modern PHP development to IBM i (ZendCon 2016)
 
Great Developers Steal
Great Developers StealGreat Developers Steal
Great Developers Steal
 
Effecient javascript
Effecient javascriptEffecient javascript
Effecient javascript
 
Socket applications
Socket applicationsSocket applications
Socket applications
 
Lightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClientLightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClient
 
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
 
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
 
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHP Oxford June Meetup 2...
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHP Oxford June Meetup 2...Adding 1.21 Gigawatts to Applications with RabbitMQ (PHP Oxford June Meetup 2...
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHP Oxford June Meetup 2...
 
Need for Speed: Removing speed bumps in API Projects
Need for Speed: Removing speed bumps in API ProjectsNeed for Speed: Removing speed bumps in API Projects
Need for Speed: Removing speed bumps in API Projects
 
Java Script Best Practices
Java Script Best PracticesJava Script Best Practices
Java Script Best Practices
 
Client-side JavaScript Vulnerabilities
Client-side JavaScript VulnerabilitiesClient-side JavaScript Vulnerabilities
Client-side JavaScript Vulnerabilities
 
Diving into HHVM Extensions (php[tek] 2016)
Diving into HHVM Extensions (php[tek] 2016)Diving into HHVM Extensions (php[tek] 2016)
Diving into HHVM Extensions (php[tek] 2016)
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the tests
 
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
 
JavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesJavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best Practices
 

Mehr von James Titcumb

Living the Best Life on a Legacy Project (phpday 2022).pdf
Living the Best Life on a Legacy Project (phpday 2022).pdfLiving the Best Life on a Legacy Project (phpday 2022).pdf
Living the Best Life on a Legacy Project (phpday 2022).pdfJames Titcumb
 
Tips for Tackling a Legacy Codebase (ScotlandPHP 2021)
Tips for Tackling a Legacy Codebase (ScotlandPHP 2021)Tips for Tackling a Legacy Codebase (ScotlandPHP 2021)
Tips for Tackling a Legacy Codebase (ScotlandPHP 2021)James Titcumb
 
Climbing the Abstract Syntax Tree (Midwest PHP 2020)
Climbing the Abstract Syntax Tree (Midwest PHP 2020)Climbing the Abstract Syntax Tree (Midwest PHP 2020)
Climbing the Abstract Syntax Tree (Midwest PHP 2020)James Titcumb
 
Climbing the Abstract Syntax Tree (php[world] 2019)
Climbing the Abstract Syntax Tree (php[world] 2019)Climbing the Abstract Syntax Tree (php[world] 2019)
Climbing the Abstract Syntax Tree (php[world] 2019)James Titcumb
 
Climbing the Abstract Syntax Tree (PHP Russia 2019)
Climbing the Abstract Syntax Tree (PHP Russia 2019)Climbing the Abstract Syntax Tree (PHP Russia 2019)
Climbing the Abstract Syntax Tree (PHP Russia 2019)James Titcumb
 
Climbing the Abstract Syntax Tree (ScotlandPHP 2018)
Climbing the Abstract Syntax Tree (ScotlandPHP 2018)Climbing the Abstract Syntax Tree (ScotlandPHP 2018)
Climbing the Abstract Syntax Tree (ScotlandPHP 2018)James Titcumb
 
Kicking off with Zend Expressive and Doctrine ORM (PHP South Africa 2018)
Kicking off with Zend Expressive and Doctrine ORM (PHP South Africa 2018)Kicking off with Zend Expressive and Doctrine ORM (PHP South Africa 2018)
Kicking off with Zend Expressive and Doctrine ORM (PHP South Africa 2018)James Titcumb
 
Climbing the Abstract Syntax Tree (PHP Developer Days Dresden 2018)
Climbing the Abstract Syntax Tree (PHP Developer Days Dresden 2018)Climbing the Abstract Syntax Tree (PHP Developer Days Dresden 2018)
Climbing the Abstract Syntax Tree (PHP Developer Days Dresden 2018)James Titcumb
 
Climbing the Abstract Syntax Tree (Southeast PHP 2018)
Climbing the Abstract Syntax Tree (Southeast PHP 2018)Climbing the Abstract Syntax Tree (Southeast PHP 2018)
Climbing the Abstract Syntax Tree (Southeast PHP 2018)James Titcumb
 
Kicking off with Zend Expressive and Doctrine ORM (PHP MiNDS March 2018)
Kicking off with Zend Expressive and Doctrine ORM (PHP MiNDS March 2018)Kicking off with Zend Expressive and Doctrine ORM (PHP MiNDS March 2018)
Kicking off with Zend Expressive and Doctrine ORM (PHP MiNDS March 2018)James Titcumb
 
Climbing the Abstract Syntax Tree (PHP UK 2018)
Climbing the Abstract Syntax Tree (PHP UK 2018)Climbing the Abstract Syntax Tree (PHP UK 2018)
Climbing the Abstract Syntax Tree (PHP UK 2018)James Titcumb
 
Climbing the Abstract Syntax Tree (Forum PHP 2017)
Climbing the Abstract Syntax Tree (Forum PHP 2017)Climbing the Abstract Syntax Tree (Forum PHP 2017)
Climbing the Abstract Syntax Tree (Forum PHP 2017)James Titcumb
 
Dip Your Toes in the Sea of Security (IPC Fall 2017)
Dip Your Toes in the Sea of Security (IPC Fall 2017)Dip Your Toes in the Sea of Security (IPC Fall 2017)
Dip Your Toes in the Sea of Security (IPC Fall 2017)James Titcumb
 
Climbing the Abstract Syntax Tree (IPC Fall 2017)
Climbing the Abstract Syntax Tree (IPC Fall 2017)Climbing the Abstract Syntax Tree (IPC Fall 2017)
Climbing the Abstract Syntax Tree (IPC Fall 2017)James Titcumb
 
Dip Your Toes in the Sea of Security (PHP South Africa 2017)
Dip Your Toes in the Sea of Security (PHP South Africa 2017)Dip Your Toes in the Sea of Security (PHP South Africa 2017)
Dip Your Toes in the Sea of Security (PHP South Africa 2017)James Titcumb
 
Climbing the Abstract Syntax Tree (PHP South Africa 2017)
Climbing the Abstract Syntax Tree (PHP South Africa 2017)Climbing the Abstract Syntax Tree (PHP South Africa 2017)
Climbing the Abstract Syntax Tree (PHP South Africa 2017)James Titcumb
 
Get Started with RabbitMQ (CoderCruise 2017)
Get Started with RabbitMQ (CoderCruise 2017)Get Started with RabbitMQ (CoderCruise 2017)
Get Started with RabbitMQ (CoderCruise 2017)James Titcumb
 
Dip Your Toes in the Sea of Security (CoderCruise 2017)
Dip Your Toes in the Sea of Security (CoderCruise 2017)Dip Your Toes in the Sea of Security (CoderCruise 2017)
Dip Your Toes in the Sea of Security (CoderCruise 2017)James Titcumb
 

Mehr von James Titcumb (18)

Living the Best Life on a Legacy Project (phpday 2022).pdf
Living the Best Life on a Legacy Project (phpday 2022).pdfLiving the Best Life on a Legacy Project (phpday 2022).pdf
Living the Best Life on a Legacy Project (phpday 2022).pdf
 
Tips for Tackling a Legacy Codebase (ScotlandPHP 2021)
Tips for Tackling a Legacy Codebase (ScotlandPHP 2021)Tips for Tackling a Legacy Codebase (ScotlandPHP 2021)
Tips for Tackling a Legacy Codebase (ScotlandPHP 2021)
 
Climbing the Abstract Syntax Tree (Midwest PHP 2020)
Climbing the Abstract Syntax Tree (Midwest PHP 2020)Climbing the Abstract Syntax Tree (Midwest PHP 2020)
Climbing the Abstract Syntax Tree (Midwest PHP 2020)
 
Climbing the Abstract Syntax Tree (php[world] 2019)
Climbing the Abstract Syntax Tree (php[world] 2019)Climbing the Abstract Syntax Tree (php[world] 2019)
Climbing the Abstract Syntax Tree (php[world] 2019)
 
Climbing the Abstract Syntax Tree (PHP Russia 2019)
Climbing the Abstract Syntax Tree (PHP Russia 2019)Climbing the Abstract Syntax Tree (PHP Russia 2019)
Climbing the Abstract Syntax Tree (PHP Russia 2019)
 
Climbing the Abstract Syntax Tree (ScotlandPHP 2018)
Climbing the Abstract Syntax Tree (ScotlandPHP 2018)Climbing the Abstract Syntax Tree (ScotlandPHP 2018)
Climbing the Abstract Syntax Tree (ScotlandPHP 2018)
 
Kicking off with Zend Expressive and Doctrine ORM (PHP South Africa 2018)
Kicking off with Zend Expressive and Doctrine ORM (PHP South Africa 2018)Kicking off with Zend Expressive and Doctrine ORM (PHP South Africa 2018)
Kicking off with Zend Expressive and Doctrine ORM (PHP South Africa 2018)
 
Climbing the Abstract Syntax Tree (PHP Developer Days Dresden 2018)
Climbing the Abstract Syntax Tree (PHP Developer Days Dresden 2018)Climbing the Abstract Syntax Tree (PHP Developer Days Dresden 2018)
Climbing the Abstract Syntax Tree (PHP Developer Days Dresden 2018)
 
Climbing the Abstract Syntax Tree (Southeast PHP 2018)
Climbing the Abstract Syntax Tree (Southeast PHP 2018)Climbing the Abstract Syntax Tree (Southeast PHP 2018)
Climbing the Abstract Syntax Tree (Southeast PHP 2018)
 
Kicking off with Zend Expressive and Doctrine ORM (PHP MiNDS March 2018)
Kicking off with Zend Expressive and Doctrine ORM (PHP MiNDS March 2018)Kicking off with Zend Expressive and Doctrine ORM (PHP MiNDS March 2018)
Kicking off with Zend Expressive and Doctrine ORM (PHP MiNDS March 2018)
 
Climbing the Abstract Syntax Tree (PHP UK 2018)
Climbing the Abstract Syntax Tree (PHP UK 2018)Climbing the Abstract Syntax Tree (PHP UK 2018)
Climbing the Abstract Syntax Tree (PHP UK 2018)
 
Climbing the Abstract Syntax Tree (Forum PHP 2017)
Climbing the Abstract Syntax Tree (Forum PHP 2017)Climbing the Abstract Syntax Tree (Forum PHP 2017)
Climbing the Abstract Syntax Tree (Forum PHP 2017)
 
Dip Your Toes in the Sea of Security (IPC Fall 2017)
Dip Your Toes in the Sea of Security (IPC Fall 2017)Dip Your Toes in the Sea of Security (IPC Fall 2017)
Dip Your Toes in the Sea of Security (IPC Fall 2017)
 
Climbing the Abstract Syntax Tree (IPC Fall 2017)
Climbing the Abstract Syntax Tree (IPC Fall 2017)Climbing the Abstract Syntax Tree (IPC Fall 2017)
Climbing the Abstract Syntax Tree (IPC Fall 2017)
 
Dip Your Toes in the Sea of Security (PHP South Africa 2017)
Dip Your Toes in the Sea of Security (PHP South Africa 2017)Dip Your Toes in the Sea of Security (PHP South Africa 2017)
Dip Your Toes in the Sea of Security (PHP South Africa 2017)
 
Climbing the Abstract Syntax Tree (PHP South Africa 2017)
Climbing the Abstract Syntax Tree (PHP South Africa 2017)Climbing the Abstract Syntax Tree (PHP South Africa 2017)
Climbing the Abstract Syntax Tree (PHP South Africa 2017)
 
Get Started with RabbitMQ (CoderCruise 2017)
Get Started with RabbitMQ (CoderCruise 2017)Get Started with RabbitMQ (CoderCruise 2017)
Get Started with RabbitMQ (CoderCruise 2017)
 
Dip Your Toes in the Sea of Security (CoderCruise 2017)
Dip Your Toes in the Sea of Security (CoderCruise 2017)Dip Your Toes in the Sea of Security (CoderCruise 2017)
Dip Your Toes in the Sea of Security (CoderCruise 2017)
 

Kürzlich hochgeladen

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 

Kürzlich hochgeladen (20)

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 

Best practices for crafting high quality PHP apps (ScotlandPHP 2018)