SlideShare a Scribd company logo
1 of 56
Download to read offline
Your code sucks,
   let’s !x it!
   Object Calisthenics and Code readability




            Rafael Dohms
Rafael Dohms




                                                    photo credit: Eli White
PHP Evangelist, Speaker and
contributor. He is a very active member of the
PHP Community, having helped create and
manage two PHP User Groups in Brazil. He
shared the lead of PHPSP for 3 wonderful
years making a positive mark on the local market.
Developer, gamer and lover of code he also hosts
Brazil’s first PHP Podcast: PHPSPCast, as well
as contributing to well known projects. 

He moved to the Netherlands in search of
new challenges and is now part of the team at
WEBclusive.
What’s the talk about?


• Why does my code suck?
• How can we fix it?
Is it Maintainable?   Is it Readable?


          Why does my
          code suck?
  Is it Reusable?     Is it Testable?
<?php                                                 Does it look like this?
$list=mysql_connect("******","*******","*****");
if(!$list)echo 'Cannot login.';
else{
    mysql_select_db("******", $list);
    $best=array("0","0","0","0","0","0");
    $id=mysql_num_rows(mysql_query("SELECT * FROM allnews"));
    $count=0;
    for($i=0;$i<6;$i++){
        while(mysql_query("SELECT language FROM allnews WHERE id=$id-$count")!="he")$count+
+;
        $best[$i]=mysql_query("SELECT id FROM allnews WHERE id=$id-$count");}
    $id=$id-$count;
    $maxdate=mktime(0,0,0,date('m'),date('d')-7,date('Y'));
    while(mysql_query("SELECT date FROM allnews WHERE id=$id-$count")>=$maxdate){
        if(mysql_query("SELECT language FROM allnews WHERE id=$id-$count")=="he"){
            $small=$best[0];
            while($i=0;$i<6;$i++){
                if(mysql_query("SELECT score FROM allnews WHERE id=
$small)"<mysql_query("SELECT score FROM allnews WHERE id=$best[i+1]"))
                         $small=$best[i+1];}
                    if(mysql_query("SELECT score FROM allnews WHERE id=
$small")<mysql_query("SELECT score FROM Rebecca WHERE id=$id-$count")){
                                      If allnews Black was a developer
                         while($i=0;$i<6;$i++){
                             if($small==$best[i])$best[i]=mysql_query("SELECT id FROM
allnews WHERE id=$id-$count");}}}}
    while($i=0;$i<6;$i++)
    echo '<a href="news-page.php?id='.$best[i].'"><div class="box '.mysql_query("SELECT
type FROM allnews WHERE id=$best[i]").'">'.mysql_query("SELECT title FROM allnews WHERE id=
$best[i]").'<div class="img" style="background-image:url(images/'.mysql_query("SELECT
image1 FROM allnews WHERE id=$best[i]").');"></div></div></a>';
    mysql_close($list);
}
?>
How do we fix it?
cal·is·then·ics - noun - /ˌkaləsˈTHeniks/
     Calisthenics are a form of dynamic
      exercise consisting of a variety of
    simple, often rhythmical, movements,
    generally using minimal equipment or
                  apparatus.



Object Calisthenics
                            A variety of simple, often
                         rhythmical, exercises to achieve
                          better OO and code quality
“So here’s an exercise that can help you to internalize
      principles of good object-oriented design and actually
                                       use them in real life.”

                                                -- Jeff Bay




Object Calisthenics
                            Important:

                         PHP != JAVA

                    Adaptations will be done
“You need to write code that minimizes the time it would


Object Calisthenics
           take someone else to understand it—even if that
                                      someone else is you.”



         +
           -- Dustin Boswell and Trevor Foucher




 Readability Tips
                                 I’m a tip
Disclaimer:
“These are guidelines, not rules”
OC #1
“Only one indentation
  level per method”
function validateProducts($products) {

        // Check to make sure that our valid fields are in there
        $requiredFields = array(
            'price',
            'name',
            'description',
            'type',
        );

        $valid = true;

    0   foreach ($products as $rawProduct) {

            1   $fields = array_keys($rawProduct);

                foreach ($requiredFields as $requiredField) {
                  2 if (!in_array($requiredField, $fields)) {
                      3 $valid = false;
                    }
                }
        }

        return $valid;
}
function validateProducts($products) {

      // Check to make sure that our valid fields are in there
      $requiredFields = array(
          'price',
          'name',
          'description',
          'type',
      );

      $valid = true;

    0 foreach ($products as
          whitespace
          $validationResult
                                $rawProduct) {
                                = validateSingleProduct($rawProduct, $requiredFields);

          1   if ( ! $validationResult){

              }
               2  $valid = false;

      }

      return $valid;
}

function validateSingleProduct($product, $requiredFields)
{
    $valid = true;               duplicated logic
      $fields = array_keys($rawProduct);

    0 foreach(!in_array($requiredField, $fields))
              ($requiredFields as $requiredField)     {

        1 if                                          {

          } 2
              $valid = false;

      }
      return $valid;
}
function validateProducts($storeData) {

    $requiredFields = array('price','name','description','type'); cheating!
                                                            I see
    foreach ($storeData['products'] as $rawProduct) {
        if ( ! validateSingleProduct($rawProduct, $requiredFields)) return false;
    }

    return true;   Single line IF, simple operations         return early
}

function validateSingleProduct($product, $requiredFields)
{
    $fields = array_keys($rawProduct);
    $missingFields = array_diff($requiredFields, $fields);

    return (count($missingFields) == 0);
}                        C (native) functions are
                             faster then PHP
List is more readable the plural

function validateProductList($products) iteration
                                   faster
{
    $invalidProducts = array_filter($products, 'isInvalidProduct');

    return (count($invalidProducts) === 0);
}
                                       readable return: zero invalid products
           reusable method
function isInvalidProduct($rawProduct)
{
    $requiredFields = array('price', 'name', 'description', 'type');

    $fields          = array_keys($rawProduct);
    $missingFields   = array_diff($requiredFields, $fields);

    return (count($missingFields) > 0);
}

                           method name matches “true” result
Key Benefits

• Cohesiveness
• Methods does only one thing
• Increases re-use
OC #2
“Do not use the ‘else’
      keyword”
public function createPost($request)
{
    $entity = new Post();

    $form = new MyForm($entity);
    $form->bind($request);

    if ($form->isValid()){

        $repository = $this->getRepository('MyBundle:Post');
        if (!$repository->exists($entity) ) {
            $repository->save($entity);
            return $this->redirect('create_ok');
        } else {
            $error = "Post Title already exists";
            return array('form' => $form, 'error' => $error);
        }

    } else {
        $error = "Invalid fields";
        return array('form' => $form, 'error' => $error);
    }

}
public function createPost($request)
{
    $entity = new Post();

    $form = new MyForm($entity);
    $form->bind($request);

    if ($form->isValid()){

        $repository = $this->getRepository('MyBundle:Post');
        if (!$repository->exists($entity) ) {
            $repository->save($entity);
            return $this->redirect('create_ok');
        } else {
            $error = "Post Title already exists";
            return array('form' => $form, 'error' => $error);
        }

    } else {
        $error = "Invalid fields";
        return array('form' => $form, 'error' => $error);
    }

}
public function createPost($request)
{
    $entity = new Post();

    $form = new MyForm($entity);
    $form->bind($request);

    if ($form->isValid()){

        $repository = $this->getRepository('MyBundle:Post');
        if (!$repository->exists($entity) ) {
             $repository->save($entity);
         intermediate variable
             return $this->redirect('create_ok');
        } else {
             $error = "Post Title already exists";
             return array('form' => $form, 'error' => $error);
        }
    intermediate variable
    } else {
        $error = "Invalid fields";
        return array('form' => $form, 'error' => $error);
    }

}
Separate code
                                                              into blocks.
public function createPost($request)
{                                                             Its like using
    $entity     = new Post();
    $repository = $this->getRepository('MyBundle:Post');     Paragraphs.
      $form = new MyForm($entity);
      $form->bind($request);
                                             removed intermediates
      if ( ! $form->isValid()){
          return array('form' => $form, 'error' => 'Invalid fields');
      }
    early return
      if ($repository->exists($entity)){
          return array('form' => $form, 'error' => 'Duplicate post title');
      }

      $repository->save($entity);

      return $this->redirect('create_ok');

}
Key Benefits


• Helps avoid code duplication
• Makes code clearer (single path)
Ad
                     ap
       OC #3




                      te
                          d
 “Wrap all primitive
types and string, if it
   has behaviour”
class UIComponent
{
//...
    public function repaint($animate = true){
            //...
    }
}

//...
$component->repaint(false);


                  unclear operation
class UIComponent
{
    //...
    public function repaint( Animate $animate ){
            //...
    }
}

class Animate
                  This can now encapsulate all
{
                  animation related operations
    public $animate;

    public function __construct( $animate = true ) {
        $this->animate = $animate;}

}

//...
$component->repaint( new Animate(false) );
Key Benefits


• Type Hinting
• Encapsulation of operations
Ad
                      ap
                       te
                          d
        OC #4
“Only one -> per line, if
 not getter or fluent”
Source: CodeIgniter




                         properties are harder to mock
$this->base_url = $this->CI->config->site_url().'/'.$this->CI->uri->segment(1).$this-
>CI->uri->slash_segment(2, 'both');


                                              no whitespace
$this->base_uri = $this->CI->uri->segment(1).$this->CI->uri->slash_segment(2, 'leading');



                            move everything to uri object

       $this->getCI()->getUriBuilder()->getBaseUri(‘leading’);



                   - Underlying encapsulation problem
                   - Hard to debug and test
                   - Hard to read and understand
Source: Zend Framework App




    fluent interface
$filterChain->addFilter(new Zend_Filter_Alpha())
            ->addFilter(new Zend_Filter_StringToLower());


      operator alignment




                                     only getters (no operations)

  $user = $this->get('security.context')->getToken()->getUser();


               where did my                  return null?
             autocomplete go?

                                                            Source: Symfony 2 Docs.
Key Benefits

• Readability
• Easier Mocking
• Easier to Debug
• Demeter’s Law
OC #5
“Do not Abbreviate”
?
if($sx >= $sy) {                      ?
    if ($sx > $strSysMatImgW) {
        $ny = $strSysMatImgW * $sy / $sx;
        $nx = $strSysMatImgW;
    }
                                ?
    if ($ny > $strSysMatImgH) {
        $nx = $strSysMatImgH * $sx / $sy;
        $ny = $strSysMatImgH;
    }

} else {

         ?
    if ($sy > $strSysMatImgH) {
        $nx = $strSysMatImgH * $sx / $sy;
        $ny = $strSysMatImgH;
    }

         ?
    if($nx > $strSysMatImgW) {
        $ny = $strSysMatImgW * $sy / $sx;
        $nx = $strSysMatImgW;
    }
}
Why?


Its repeated many times,
       and i’m lazy.
                  Underlying Problem!

  You need to transfer those operations into a separate class.
Why?
                          more then one
                          responsibility?

function processResponseHeadersAndDefineOutput($response) { ... }




      This method name is too long to type,
                 and i’m lazy.
get from where?
                                  Use clearer names:
function getPage($data) { ... }   fetchPage()
                                  downloadPage()




                                  Use a thesaurus:
function startProcess() { ... }
                                  fork, create, begin, open


      Table row?
                                  Easy understanding, complete scope:
$tr->process(“site.login”);
                                  $translatorService
Key Benefits


• Clearer communication
• Indicates underlying problems
Ad
                 ap
                     te
                     d
      OC #6
“Keep your classes
     small”
Increased to include
     docblocks          15-20 lines per method



  100 lines per class
15 classes per package
                            read this as
                        namespace or folder
Key Benefits

• Single Responsibility
• Objective methods
• Slimmer namespaces
• Less clunky folders
Ad
                    ap
         OC #7




                      te
                          d
 “Limit the number of
instance variables in a
   class (max: 2 5)”
class MyRegistrationService
                     {

                         protected   $userService;
                         protected   $passwordService;
                         protected   $logger;
All DB interaction       protected   $translator;
   should be in          protected   $entityManager;
    userService          protected   $imageCropper;    Use and event based
                                                      system and move this
                         // ...                             to listener
                     }




                            Limit: 5
Key Benefits


• Shorter dependency list
• Easier Mocking for unit test
OC #8
“Use first class
  collections”
Doctrine:
      ArrayCollection


$collection->getIterator();

$collection->filter(...);

$collection->append(...);

$collection->map(...);
Key Benefits


• Implements collection operations
• Uses SPL interfaces
Dr
                   op
                    pe
                        d
        OC #9
“Do not use accessors
   (getter/setter)”
/**
  * THIS CLASS WAS GENERATED BY THE DOCTRINE ORM. DO NOT EDIT THIS FILE.
  */
class DoctrineTestsModelsCMSCmsUserProxy
    extends DoctrineTestsModelsCMSCmsUser
    implements DoctrineORMProxyProxy
{

    public function getId()
    {
        $this->__load();          Example: Doctrine uses getters to
        return parent::getId();     inject lazy loading operations
    }

    public function getStatus()
    {
        $this->__load();
        return parent::getStatus();
    }
Key Benefits


• Injector operations
• Encapsulation of transformations
Cr
                  ea
                   te
                      d!
   OC #10 (bonus!)
“Document your code!”
really?

//check to see if the section above set the $overall_pref variable to void
if ($overall_pref == 'void')




// implode the revised array of selections in group three into a string
// variable so that it can be transferred to the database at the end of the
// page
$groupthree = implode($groupthree_array, "nr");


         Documenting because i’m doing it wrong in an anusual way
$priority = isset($event['priority']) ? $event['priority'] : 0;
                            Add a simple comment:
if   (!isset($event['event'])) {
      throw new //Strips special chars and camel cases to onXxx
                 InvalidArgumentException(...));
}

if (!isset($event['method'])) {
    $event['method'] = 'on'.preg_replace(array(
                                                    Don’t explain bad
      '/(?<=b)[a-z]/ie',                               code, fix it!
      '/[^a-z0-9]/i'
    ), array('strtoupper("0")', ''), $event['event']);
}

$definition->addMethodCall(
   'addListenerService',
   array($event['event'],
   array($listenerId,                   What does this do?
   $event['method']),
   $priority
));




                                                                  Source: Symfony2
Do a mind dump,
                                                       then clean it up.
      A note on cost of
       running function
/**
* Checks whether an element is contained in the collection.
* This is an O(n) operation, where n is the size of the collection.
*
* @todo implement caching for better performance
* @param mixed $element The element to search for.
* @return boolean TRUE if the collection contains the element, or FALSE.
*/
function contains($element);
                                                  Generate API docs
                                                    ex: docBlox
   mark todo items so the
    changes don’t get lost
Key Benefits

• Automatic API documentation
• Transmission of “line of thought”
• Avoids confusion
Recap
•   #1 - Only one indentation level per method.

•   #2 - Do not use the ‘else’ keyword.

•   #3 - Wrap primitive types and string, if it has behavior.

•   #4 - Only one -> per line, if not getter or fluent.

•   #5 - Do not Abbreviate.

•   #6 - Keep your classes small

•   #7 - Limit the number of instance variables in a class (max: 5)

•   #8 - Use first class collections

•   #9 - Use accessors (getter/setter)

•   #10 - Document your code!
@rdohms                  http://doh.ms
rafael @doh.ms          http://slides.doh.ms




             Questions?


         https://joind.in/6125
Recommended Links:                                       https://joind.in/6125




                    The ThoughtWorks Anthology
                    http://goo.gl/OcSNx

                    The Art of Readable Code
                    http://goo.gl/unrij


DISCLAIMER: This talk re-uses some of the examples used by Guilherme Blanco in his
original Object Calisthenic talk. These principles were studied and applied by us while we
worked together in previous jobs. The result taught us all a lesson we really want to spread
to other developers.

More Related Content

What's hot

Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기경원 이
 
OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...
OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...
OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...Christopher Frohoff
 
[2019] 200만 동접 게임을 위한 MySQL 샤딩
[2019] 200만 동접 게임을 위한 MySQL 샤딩[2019] 200만 동접 게임을 위한 MySQL 샤딩
[2019] 200만 동접 게임을 위한 MySQL 샤딩NHN FORWARD
 
MongoDB - Aggregation Pipeline
MongoDB - Aggregation PipelineMongoDB - Aggregation Pipeline
MongoDB - Aggregation PipelineJason Terpko
 
Laravel でやってみるクリーンアーキテクチャ #phpconfuk
Laravel でやってみるクリーンアーキテクチャ #phpconfukLaravel でやってみるクリーンアーキテクチャ #phpconfuk
Laravel でやってみるクリーンアーキテクチャ #phpconfukShohei Okada
 
Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHPGuilherme Blanco
 
Laravel Design Patterns
Laravel Design PatternsLaravel Design Patterns
Laravel Design PatternsBobby Bouwmann
 
Solid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJSSolid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJSRafael Casuso Romate
 
Writing and using Hamcrest Matchers
Writing and using Hamcrest MatchersWriting and using Hamcrest Matchers
Writing and using Hamcrest MatchersShai Yallin
 
Country State City Dropdown in PHP
Country State City Dropdown in PHPCountry State City Dropdown in PHP
Country State City Dropdown in PHPVineet Kumar Saini
 
Event sourcing - what could possibly go wrong ? Devoxx PL 2021
Event sourcing  - what could possibly go wrong ? Devoxx PL 2021Event sourcing  - what could possibly go wrong ? Devoxx PL 2021
Event sourcing - what could possibly go wrong ? Devoxx PL 2021Andrzej Ludwikowski
 
End to end todo list app with NestJs - Angular - Redux & Redux Saga
End to end todo list app with NestJs - Angular - Redux & Redux SagaEnd to end todo list app with NestJs - Angular - Redux & Redux Saga
End to end todo list app with NestJs - Angular - Redux & Redux SagaBabacar NIANG
 
Node.js Express
Node.js  ExpressNode.js  Express
Node.js ExpressEyal Vardi
 

What's hot (20)

Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
 
NestJS
NestJSNestJS
NestJS
 
OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...
OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...
OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...
 
[2019] 200만 동접 게임을 위한 MySQL 샤딩
[2019] 200만 동접 게임을 위한 MySQL 샤딩[2019] 200만 동접 게임을 위한 MySQL 샤딩
[2019] 200만 동접 게임을 위한 MySQL 샤딩
 
MongoDB - Aggregation Pipeline
MongoDB - Aggregation PipelineMongoDB - Aggregation Pipeline
MongoDB - Aggregation Pipeline
 
Laravel でやってみるクリーンアーキテクチャ #phpconfuk
Laravel でやってみるクリーンアーキテクチャ #phpconfukLaravel でやってみるクリーンアーキテクチャ #phpconfuk
Laravel でやってみるクリーンアーキテクチャ #phpconfuk
 
Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHP
 
Support de cours angular
Support de cours angularSupport de cours angular
Support de cours angular
 
Angular
AngularAngular
Angular
 
Laravel Design Patterns
Laravel Design PatternsLaravel Design Patterns
Laravel Design Patterns
 
Solid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJSSolid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJS
 
Writing and using Hamcrest Matchers
Writing and using Hamcrest MatchersWriting and using Hamcrest Matchers
Writing and using Hamcrest Matchers
 
Object calisthenics
Object calisthenicsObject calisthenics
Object calisthenics
 
SOLID PRINCIPLES
SOLID PRINCIPLESSOLID PRINCIPLES
SOLID PRINCIPLES
 
Country State City Dropdown in PHP
Country State City Dropdown in PHPCountry State City Dropdown in PHP
Country State City Dropdown in PHP
 
Event sourcing - what could possibly go wrong ? Devoxx PL 2021
Event sourcing  - what could possibly go wrong ? Devoxx PL 2021Event sourcing  - what could possibly go wrong ? Devoxx PL 2021
Event sourcing - what could possibly go wrong ? Devoxx PL 2021
 
Support de cours Spring M.youssfi
Support de cours Spring  M.youssfiSupport de cours Spring  M.youssfi
Support de cours Spring M.youssfi
 
End to end todo list app with NestJs - Angular - Redux & Redux Saga
End to end todo list app with NestJs - Angular - Redux & Redux SagaEnd to end todo list app with NestJs - Angular - Redux & Redux Saga
End to end todo list app with NestJs - Angular - Redux & Redux Saga
 
Node.js Express
Node.js  ExpressNode.js  Express
Node.js Express
 
Support NodeJS avec TypeScript Express MongoDB
Support NodeJS avec TypeScript Express MongoDBSupport NodeJS avec TypeScript Express MongoDB
Support NodeJS avec TypeScript Express MongoDB
 

Viewers also liked

Writing Code That Lasts - #Magento2Seminar, Utrecht
Writing Code That Lasts - #Magento2Seminar, UtrechtWriting Code That Lasts - #Magento2Seminar, Utrecht
Writing Code That Lasts - #Magento2Seminar, UtrechtRafael Dohms
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix itRafael Dohms
 
Composer The Right Way - 010PHP
Composer The Right Way - 010PHPComposer The Right Way - 010PHP
Composer The Right Way - 010PHPRafael Dohms
 
Geoffrey Chaucer Slide
Geoffrey Chaucer SlideGeoffrey Chaucer Slide
Geoffrey Chaucer Slidejessvo11
 
Assembly language (coal)
Assembly language (coal)Assembly language (coal)
Assembly language (coal)Hareem Aslam
 
Feminist myths and magic medicine
Feminist myths and magic medicineFeminist myths and magic medicine
Feminist myths and magic medicineNaoise
 
Fisiologia da Membrana
Fisiologia da MembranaFisiologia da Membrana
Fisiologia da MembranaCaio Maximino
 
Charla interacciones farmaco nutrientes
Charla interacciones farmaco nutrientesCharla interacciones farmaco nutrientes
Charla interacciones farmaco nutrientesJuan Delgado Delgado
 
Plan regional 2006
Plan regional 2006Plan regional 2006
Plan regional 2006edu_gam
 
Presentación tesis doctoral María Jesús Marcos
Presentación tesis doctoral María Jesús MarcosPresentación tesis doctoral María Jesús Marcos
Presentación tesis doctoral María Jesús Marcoscole
 
Johannesburg,South Africa
Johannesburg,South AfricaJohannesburg,South Africa
Johannesburg,South AfricaSyed Atif
 
La globalización: consecuencias humanas
La globalización: consecuencias humanasLa globalización: consecuencias humanas
La globalización: consecuencias humanasMarcela Mikowski
 
Contoh Tugasan : Tajuk Rakan Sebaya
Contoh Tugasan : Tajuk Rakan SebayaContoh Tugasan : Tajuk Rakan Sebaya
Contoh Tugasan : Tajuk Rakan Sebayanazri15
 
Modelo de Negócios - Business Model Canvas
Modelo de Negócios - Business Model CanvasModelo de Negócios - Business Model Canvas
Modelo de Negócios - Business Model CanvasMaurício Magalhães
 

Viewers also liked (20)

Writing Code That Lasts - #Magento2Seminar, Utrecht
Writing Code That Lasts - #Magento2Seminar, UtrechtWriting Code That Lasts - #Magento2Seminar, Utrecht
Writing Code That Lasts - #Magento2Seminar, Utrecht
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix it
 
Composer The Right Way - 010PHP
Composer The Right Way - 010PHPComposer The Right Way - 010PHP
Composer The Right Way - 010PHP
 
Geoffrey Chaucer Slide
Geoffrey Chaucer SlideGeoffrey Chaucer Slide
Geoffrey Chaucer Slide
 
Assembly language (coal)
Assembly language (coal)Assembly language (coal)
Assembly language (coal)
 
Feminist myths and magic medicine
Feminist myths and magic medicineFeminist myths and magic medicine
Feminist myths and magic medicine
 
Fisiologia da Membrana
Fisiologia da MembranaFisiologia da Membrana
Fisiologia da Membrana
 
Charla interacciones farmaco nutrientes
Charla interacciones farmaco nutrientesCharla interacciones farmaco nutrientes
Charla interacciones farmaco nutrientes
 
Plan regional 2006
Plan regional 2006Plan regional 2006
Plan regional 2006
 
Presentación tesis doctoral María Jesús Marcos
Presentación tesis doctoral María Jesús MarcosPresentación tesis doctoral María Jesús Marcos
Presentación tesis doctoral María Jesús Marcos
 
Apostila pqo cap_08_v2
Apostila pqo cap_08_v2Apostila pqo cap_08_v2
Apostila pqo cap_08_v2
 
Mi presentación
Mi presentaciónMi presentación
Mi presentación
 
Johannesburg,South Africa
Johannesburg,South AfricaJohannesburg,South Africa
Johannesburg,South Africa
 
Gestor de proyectos
Gestor  de proyectosGestor  de proyectos
Gestor de proyectos
 
La globalización: consecuencias humanas
La globalización: consecuencias humanasLa globalización: consecuencias humanas
La globalización: consecuencias humanas
 
Seguridad industrial norma ohsas 18001
Seguridad industrial norma ohsas 18001Seguridad industrial norma ohsas 18001
Seguridad industrial norma ohsas 18001
 
TeóRico 2 SP(Resumen)
TeóRico 2 SP(Resumen)TeóRico 2 SP(Resumen)
TeóRico 2 SP(Resumen)
 
Contoh Tugasan : Tajuk Rakan Sebaya
Contoh Tugasan : Tajuk Rakan SebayaContoh Tugasan : Tajuk Rakan Sebaya
Contoh Tugasan : Tajuk Rakan Sebaya
 
Modelo de Negócios - Business Model Canvas
Modelo de Negócios - Business Model CanvasModelo de Negócios - Business Model Canvas
Modelo de Negócios - Business Model Canvas
 
Administracion de un centro de computo
Administracion de un centro de computoAdministracion de un centro de computo
Administracion de un centro de computo
 

Similar to You code sucks, let's fix it

Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConRafael Dohms
 
Your code sucks, let's fix it - PHP Master Series 2012
Your code sucks, let's fix it - PHP Master Series 2012Your code sucks, let's fix it - PHP Master Series 2012
Your code sucks, let's fix it - PHP Master Series 2012Rafael Dohms
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix itRafael Dohms
 
Your code sucks, let's fix it (CakeFest2012)
Your code sucks, let's fix it (CakeFest2012)Your code sucks, let's fix it (CakeFest2012)
Your code sucks, let's fix it (CakeFest2012)Rafael Dohms
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistenceHugo Hamon
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutesBarang CK
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 MinutesAzim Kurt
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersKacper Gunia
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency InjectionRifat Nabi
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your CodeAbbas Ali
 
Writing code you won’t hate tomorrow - PHPCE18
Writing code you won’t hate tomorrow - PHPCE18Writing code you won’t hate tomorrow - PHPCE18
Writing code you won’t hate tomorrow - PHPCE18Rafael Dohms
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11Michelangelo van Dam
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxMichelangelo van Dam
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design PatternsHugo Hamon
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developersStoyan Stefanov
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needKacper Gunia
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Seri Moth
 
Propel sfugmd
Propel sfugmdPropel sfugmd
Propel sfugmdiKlaus
 

Similar to You code sucks, let's fix it (20)

Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
Your code sucks, let's fix it - PHP Master Series 2012
Your code sucks, let's fix it - PHP Master Series 2012Your code sucks, let's fix it - PHP Master Series 2012
Your code sucks, let's fix it - PHP Master Series 2012
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix it
 
Your code sucks, let's fix it (CakeFest2012)
Your code sucks, let's fix it (CakeFest2012)Your code sucks, let's fix it (CakeFest2012)
Your code sucks, let's fix it (CakeFest2012)
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutes
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
 
Oops in php
Oops in phpOops in php
Oops in php
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your Code
 
Writing code you won’t hate tomorrow - PHPCE18
Writing code you won’t hate tomorrow - PHPCE18Writing code you won’t hate tomorrow - PHPCE18
Writing code you won’t hate tomorrow - PHPCE18
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
 
Propel sfugmd
Propel sfugmdPropel sfugmd
Propel sfugmd
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 

More from Rafael Dohms

The Individual Contributor Path - DPC2024
The Individual Contributor Path - DPC2024The Individual Contributor Path - DPC2024
The Individual Contributor Path - DPC2024Rafael Dohms
 
Application Metrics - IPC2023
Application Metrics - IPC2023Application Metrics - IPC2023
Application Metrics - IPC2023Rafael Dohms
 
How'd we get here? A guide to Architectural Decision Records
How'd we get here? A guide to Architectural Decision RecordsHow'd we get here? A guide to Architectural Decision Records
How'd we get here? A guide to Architectural Decision RecordsRafael Dohms
 
Architectural Decision Records - PHPConfBR
Architectural Decision Records - PHPConfBRArchitectural Decision Records - PHPConfBR
Architectural Decision Records - PHPConfBRRafael Dohms
 
Application Metrics (with Prometheus examples)
Application Metrics (with Prometheus examples)Application Metrics (with Prometheus examples)
Application Metrics (with Prometheus examples)Rafael Dohms
 
Application metrics - Confoo 2019
Application metrics - Confoo 2019Application metrics - Confoo 2019
Application metrics - Confoo 2019Rafael Dohms
 
Application Metrics (with Prometheus examples) #PHPDD18
Application Metrics (with Prometheus examples) #PHPDD18Application Metrics (with Prometheus examples) #PHPDD18
Application Metrics (with Prometheus examples) #PHPDD18Rafael Dohms
 
Application metrics with Prometheus - DPC18
Application metrics with Prometheus - DPC18Application metrics with Prometheus - DPC18
Application metrics with Prometheus - DPC18Rafael Dohms
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonfRafael Dohms
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...Rafael Dohms
 
Composer the Right Way - PHPSRB16
Composer the Right Way - PHPSRB16Composer the Right Way - PHPSRB16
Composer the Right Way - PHPSRB16Rafael Dohms
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - #PHPSRB16
“Writing code that lasts” … or writing code you won’t hate tomorrow. - #PHPSRB16“Writing code that lasts” … or writing code you won’t hate tomorrow. - #PHPSRB16
“Writing code that lasts” … or writing code you won’t hate tomorrow. - #PHPSRB16Rafael Dohms
 
Composer the Right Way - MM16NL
Composer the Right Way - MM16NLComposer the Right Way - MM16NL
Composer the Right Way - MM16NLRafael Dohms
 
Composer The Right Way - PHPUGMRN
Composer The Right Way - PHPUGMRNComposer The Right Way - PHPUGMRN
Composer The Right Way - PHPUGMRNRafael Dohms
 
Composer the Right Way - PHPBNL16
Composer the Right Way - PHPBNL16Composer the Right Way - PHPBNL16
Composer the Right Way - PHPBNL16Rafael Dohms
 
“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.Rafael Dohms
 
A Journey into your Lizard Brain - PHP Conference Brasil 2015
A Journey into your Lizard Brain - PHP Conference Brasil 2015A Journey into your Lizard Brain - PHP Conference Brasil 2015
A Journey into your Lizard Brain - PHP Conference Brasil 2015Rafael Dohms
 
“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.Rafael Dohms
 
“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.Rafael Dohms
 
“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.Rafael Dohms
 

More from Rafael Dohms (20)

The Individual Contributor Path - DPC2024
The Individual Contributor Path - DPC2024The Individual Contributor Path - DPC2024
The Individual Contributor Path - DPC2024
 
Application Metrics - IPC2023
Application Metrics - IPC2023Application Metrics - IPC2023
Application Metrics - IPC2023
 
How'd we get here? A guide to Architectural Decision Records
How'd we get here? A guide to Architectural Decision RecordsHow'd we get here? A guide to Architectural Decision Records
How'd we get here? A guide to Architectural Decision Records
 
Architectural Decision Records - PHPConfBR
Architectural Decision Records - PHPConfBRArchitectural Decision Records - PHPConfBR
Architectural Decision Records - PHPConfBR
 
Application Metrics (with Prometheus examples)
Application Metrics (with Prometheus examples)Application Metrics (with Prometheus examples)
Application Metrics (with Prometheus examples)
 
Application metrics - Confoo 2019
Application metrics - Confoo 2019Application metrics - Confoo 2019
Application metrics - Confoo 2019
 
Application Metrics (with Prometheus examples) #PHPDD18
Application Metrics (with Prometheus examples) #PHPDD18Application Metrics (with Prometheus examples) #PHPDD18
Application Metrics (with Prometheus examples) #PHPDD18
 
Application metrics with Prometheus - DPC18
Application metrics with Prometheus - DPC18Application metrics with Prometheus - DPC18
Application metrics with Prometheus - DPC18
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
 
Composer the Right Way - PHPSRB16
Composer the Right Way - PHPSRB16Composer the Right Way - PHPSRB16
Composer the Right Way - PHPSRB16
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - #PHPSRB16
“Writing code that lasts” … or writing code you won’t hate tomorrow. - #PHPSRB16“Writing code that lasts” … or writing code you won’t hate tomorrow. - #PHPSRB16
“Writing code that lasts” … or writing code you won’t hate tomorrow. - #PHPSRB16
 
Composer the Right Way - MM16NL
Composer the Right Way - MM16NLComposer the Right Way - MM16NL
Composer the Right Way - MM16NL
 
Composer The Right Way - PHPUGMRN
Composer The Right Way - PHPUGMRNComposer The Right Way - PHPUGMRN
Composer The Right Way - PHPUGMRN
 
Composer the Right Way - PHPBNL16
Composer the Right Way - PHPBNL16Composer the Right Way - PHPBNL16
Composer the Right Way - PHPBNL16
 
“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.
 
A Journey into your Lizard Brain - PHP Conference Brasil 2015
A Journey into your Lizard Brain - PHP Conference Brasil 2015A Journey into your Lizard Brain - PHP Conference Brasil 2015
A Journey into your Lizard Brain - PHP Conference Brasil 2015
 
“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.
 
“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.
 
“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.“Writing code that lasts” … or writing code you won’t hate tomorrow.
“Writing code that lasts” … or writing code you won’t hate tomorrow.
 

Recently uploaded

Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 

Recently uploaded (20)

Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 

You code sucks, let's fix it

  • 1. Your code sucks, let’s !x it! Object Calisthenics and Code readability Rafael Dohms
  • 2. Rafael Dohms photo credit: Eli White PHP Evangelist, Speaker and contributor. He is a very active member of the PHP Community, having helped create and manage two PHP User Groups in Brazil. He shared the lead of PHPSP for 3 wonderful years making a positive mark on the local market. Developer, gamer and lover of code he also hosts Brazil’s first PHP Podcast: PHPSPCast, as well as contributing to well known projects.  He moved to the Netherlands in search of new challenges and is now part of the team at WEBclusive.
  • 3. What’s the talk about? • Why does my code suck? • How can we fix it?
  • 4. Is it Maintainable? Is it Readable? Why does my code suck? Is it Reusable? Is it Testable?
  • 5. <?php Does it look like this? $list=mysql_connect("******","*******","*****"); if(!$list)echo 'Cannot login.'; else{ mysql_select_db("******", $list); $best=array("0","0","0","0","0","0"); $id=mysql_num_rows(mysql_query("SELECT * FROM allnews")); $count=0; for($i=0;$i<6;$i++){ while(mysql_query("SELECT language FROM allnews WHERE id=$id-$count")!="he")$count+ +; $best[$i]=mysql_query("SELECT id FROM allnews WHERE id=$id-$count");} $id=$id-$count; $maxdate=mktime(0,0,0,date('m'),date('d')-7,date('Y')); while(mysql_query("SELECT date FROM allnews WHERE id=$id-$count")>=$maxdate){ if(mysql_query("SELECT language FROM allnews WHERE id=$id-$count")=="he"){ $small=$best[0]; while($i=0;$i<6;$i++){ if(mysql_query("SELECT score FROM allnews WHERE id= $small)"<mysql_query("SELECT score FROM allnews WHERE id=$best[i+1]")) $small=$best[i+1];} if(mysql_query("SELECT score FROM allnews WHERE id= $small")<mysql_query("SELECT score FROM Rebecca WHERE id=$id-$count")){ If allnews Black was a developer while($i=0;$i<6;$i++){ if($small==$best[i])$best[i]=mysql_query("SELECT id FROM allnews WHERE id=$id-$count");}}}} while($i=0;$i<6;$i++) echo '<a href="news-page.php?id='.$best[i].'"><div class="box '.mysql_query("SELECT type FROM allnews WHERE id=$best[i]").'">'.mysql_query("SELECT title FROM allnews WHERE id= $best[i]").'<div class="img" style="background-image:url(images/'.mysql_query("SELECT image1 FROM allnews WHERE id=$best[i]").');"></div></div></a>'; mysql_close($list); } ?>
  • 6. How do we fix it?
  • 7. cal·is·then·ics - noun - /ˌkaləsˈTHeniks/ Calisthenics are a form of dynamic exercise consisting of a variety of simple, often rhythmical, movements, generally using minimal equipment or apparatus. Object Calisthenics A variety of simple, often rhythmical, exercises to achieve better OO and code quality
  • 8. “So here’s an exercise that can help you to internalize principles of good object-oriented design and actually use them in real life.” -- Jeff Bay Object Calisthenics Important: PHP != JAVA Adaptations will be done
  • 9. “You need to write code that minimizes the time it would Object Calisthenics take someone else to understand it—even if that someone else is you.” + -- Dustin Boswell and Trevor Foucher Readability Tips I’m a tip
  • 11. OC #1 “Only one indentation level per method”
  • 12. function validateProducts($products) { // Check to make sure that our valid fields are in there $requiredFields = array( 'price', 'name', 'description', 'type', ); $valid = true; 0 foreach ($products as $rawProduct) { 1 $fields = array_keys($rawProduct); foreach ($requiredFields as $requiredField) { 2 if (!in_array($requiredField, $fields)) { 3 $valid = false; } } } return $valid; }
  • 13. function validateProducts($products) { // Check to make sure that our valid fields are in there $requiredFields = array( 'price', 'name', 'description', 'type', ); $valid = true; 0 foreach ($products as whitespace $validationResult $rawProduct) { = validateSingleProduct($rawProduct, $requiredFields); 1 if ( ! $validationResult){ } 2 $valid = false; } return $valid; } function validateSingleProduct($product, $requiredFields) { $valid = true; duplicated logic $fields = array_keys($rawProduct); 0 foreach(!in_array($requiredField, $fields)) ($requiredFields as $requiredField) { 1 if { } 2 $valid = false; } return $valid; }
  • 14. function validateProducts($storeData) { $requiredFields = array('price','name','description','type'); cheating! I see foreach ($storeData['products'] as $rawProduct) { if ( ! validateSingleProduct($rawProduct, $requiredFields)) return false; } return true; Single line IF, simple operations return early } function validateSingleProduct($product, $requiredFields) { $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); } C (native) functions are faster then PHP
  • 15. List is more readable the plural function validateProductList($products) iteration faster { $invalidProducts = array_filter($products, 'isInvalidProduct'); return (count($invalidProducts) === 0); } readable return: zero invalid products reusable method function isInvalidProduct($rawProduct) { $requiredFields = array('price', 'name', 'description', 'type'); $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) > 0); } method name matches “true” result
  • 16. Key Benefits • Cohesiveness • Methods does only one thing • Increases re-use
  • 17. OC #2 “Do not use the ‘else’ keyword”
  • 18. public function createPost($request) { $entity = new Post(); $form = new MyForm($entity); $form->bind($request); if ($form->isValid()){ $repository = $this->getRepository('MyBundle:Post'); if (!$repository->exists($entity) ) { $repository->save($entity); return $this->redirect('create_ok'); } else { $error = "Post Title already exists"; return array('form' => $form, 'error' => $error); } } else { $error = "Invalid fields"; return array('form' => $form, 'error' => $error); } }
  • 19. public function createPost($request) { $entity = new Post(); $form = new MyForm($entity); $form->bind($request); if ($form->isValid()){ $repository = $this->getRepository('MyBundle:Post'); if (!$repository->exists($entity) ) { $repository->save($entity); return $this->redirect('create_ok'); } else { $error = "Post Title already exists"; return array('form' => $form, 'error' => $error); } } else { $error = "Invalid fields"; return array('form' => $form, 'error' => $error); } }
  • 20. public function createPost($request) { $entity = new Post(); $form = new MyForm($entity); $form->bind($request); if ($form->isValid()){ $repository = $this->getRepository('MyBundle:Post'); if (!$repository->exists($entity) ) { $repository->save($entity); intermediate variable return $this->redirect('create_ok'); } else { $error = "Post Title already exists"; return array('form' => $form, 'error' => $error); } intermediate variable } else { $error = "Invalid fields"; return array('form' => $form, 'error' => $error); } }
  • 21. Separate code into blocks. public function createPost($request) { Its like using $entity = new Post(); $repository = $this->getRepository('MyBundle:Post'); Paragraphs. $form = new MyForm($entity); $form->bind($request); removed intermediates if ( ! $form->isValid()){ return array('form' => $form, 'error' => 'Invalid fields'); } early return if ($repository->exists($entity)){ return array('form' => $form, 'error' => 'Duplicate post title'); } $repository->save($entity); return $this->redirect('create_ok'); }
  • 22. Key Benefits • Helps avoid code duplication • Makes code clearer (single path)
  • 23. Ad ap OC #3 te d “Wrap all primitive types and string, if it has behaviour”
  • 24. class UIComponent { //... public function repaint($animate = true){ //... } } //... $component->repaint(false); unclear operation
  • 25. class UIComponent { //... public function repaint( Animate $animate ){ //... } } class Animate This can now encapsulate all { animation related operations public $animate; public function __construct( $animate = true ) { $this->animate = $animate;} } //... $component->repaint( new Animate(false) );
  • 26. Key Benefits • Type Hinting • Encapsulation of operations
  • 27. Ad ap te d OC #4 “Only one -> per line, if not getter or fluent”
  • 28. Source: CodeIgniter properties are harder to mock $this->base_url = $this->CI->config->site_url().'/'.$this->CI->uri->segment(1).$this- >CI->uri->slash_segment(2, 'both'); no whitespace $this->base_uri = $this->CI->uri->segment(1).$this->CI->uri->slash_segment(2, 'leading'); move everything to uri object $this->getCI()->getUriBuilder()->getBaseUri(‘leading’); - Underlying encapsulation problem - Hard to debug and test - Hard to read and understand
  • 29. Source: Zend Framework App fluent interface $filterChain->addFilter(new Zend_Filter_Alpha()) ->addFilter(new Zend_Filter_StringToLower()); operator alignment only getters (no operations) $user = $this->get('security.context')->getToken()->getUser(); where did my return null? autocomplete go? Source: Symfony 2 Docs.
  • 30. Key Benefits • Readability • Easier Mocking • Easier to Debug • Demeter’s Law
  • 31. OC #5 “Do not Abbreviate”
  • 32. ? if($sx >= $sy) { ? if ($sx > $strSysMatImgW) { $ny = $strSysMatImgW * $sy / $sx; $nx = $strSysMatImgW; } ? if ($ny > $strSysMatImgH) { $nx = $strSysMatImgH * $sx / $sy; $ny = $strSysMatImgH; } } else { ? if ($sy > $strSysMatImgH) { $nx = $strSysMatImgH * $sx / $sy; $ny = $strSysMatImgH; } ? if($nx > $strSysMatImgW) { $ny = $strSysMatImgW * $sy / $sx; $nx = $strSysMatImgW; } }
  • 33. Why? Its repeated many times, and i’m lazy. Underlying Problem! You need to transfer those operations into a separate class.
  • 34. Why? more then one responsibility? function processResponseHeadersAndDefineOutput($response) { ... } This method name is too long to type, and i’m lazy.
  • 35. get from where? Use clearer names: function getPage($data) { ... } fetchPage() downloadPage() Use a thesaurus: function startProcess() { ... } fork, create, begin, open Table row? Easy understanding, complete scope: $tr->process(“site.login”); $translatorService
  • 36. Key Benefits • Clearer communication • Indicates underlying problems
  • 37. Ad ap te d OC #6 “Keep your classes small”
  • 38. Increased to include docblocks 15-20 lines per method 100 lines per class 15 classes per package read this as namespace or folder
  • 39. Key Benefits • Single Responsibility • Objective methods • Slimmer namespaces • Less clunky folders
  • 40. Ad ap OC #7 te d “Limit the number of instance variables in a class (max: 2 5)”
  • 41. class MyRegistrationService { protected $userService; protected $passwordService; protected $logger; All DB interaction protected $translator; should be in protected $entityManager; userService protected $imageCropper; Use and event based system and move this // ... to listener } Limit: 5
  • 42. Key Benefits • Shorter dependency list • Easier Mocking for unit test
  • 43. OC #8 “Use first class collections”
  • 44. Doctrine: ArrayCollection $collection->getIterator(); $collection->filter(...); $collection->append(...); $collection->map(...);
  • 45. Key Benefits • Implements collection operations • Uses SPL interfaces
  • 46. Dr op pe d OC #9 “Do not use accessors (getter/setter)”
  • 47. /** * THIS CLASS WAS GENERATED BY THE DOCTRINE ORM. DO NOT EDIT THIS FILE. */ class DoctrineTestsModelsCMSCmsUserProxy extends DoctrineTestsModelsCMSCmsUser implements DoctrineORMProxyProxy { public function getId() { $this->__load(); Example: Doctrine uses getters to return parent::getId(); inject lazy loading operations } public function getStatus() { $this->__load(); return parent::getStatus(); }
  • 48. Key Benefits • Injector operations • Encapsulation of transformations
  • 49. Cr ea te d! OC #10 (bonus!) “Document your code!”
  • 50. really? //check to see if the section above set the $overall_pref variable to void if ($overall_pref == 'void') // implode the revised array of selections in group three into a string // variable so that it can be transferred to the database at the end of the // page $groupthree = implode($groupthree_array, "nr"); Documenting because i’m doing it wrong in an anusual way
  • 51. $priority = isset($event['priority']) ? $event['priority'] : 0; Add a simple comment: if (!isset($event['event'])) { throw new //Strips special chars and camel cases to onXxx InvalidArgumentException(...)); } if (!isset($event['method'])) { $event['method'] = 'on'.preg_replace(array( Don’t explain bad '/(?<=b)[a-z]/ie', code, fix it! '/[^a-z0-9]/i' ), array('strtoupper("0")', ''), $event['event']); } $definition->addMethodCall( 'addListenerService', array($event['event'], array($listenerId, What does this do? $event['method']), $priority )); Source: Symfony2
  • 52. Do a mind dump, then clean it up. A note on cost of running function /** * Checks whether an element is contained in the collection. * This is an O(n) operation, where n is the size of the collection. * * @todo implement caching for better performance * @param mixed $element The element to search for. * @return boolean TRUE if the collection contains the element, or FALSE. */ function contains($element); Generate API docs ex: docBlox mark todo items so the changes don’t get lost
  • 53. Key Benefits • Automatic API documentation • Transmission of “line of thought” • Avoids confusion
  • 54. Recap • #1 - Only one indentation level per method. • #2 - Do not use the ‘else’ keyword. • #3 - Wrap primitive types and string, if it has behavior. • #4 - Only one -> per line, if not getter or fluent. • #5 - Do not Abbreviate. • #6 - Keep your classes small • #7 - Limit the number of instance variables in a class (max: 5) • #8 - Use first class collections • #9 - Use accessors (getter/setter) • #10 - Document your code!
  • 55. @rdohms http://doh.ms rafael @doh.ms http://slides.doh.ms Questions? https://joind.in/6125
  • 56. Recommended Links: https://joind.in/6125 The ThoughtWorks Anthology http://goo.gl/OcSNx The Art of Readable Code http://goo.gl/unrij DISCLAIMER: This talk re-uses some of the examples used by Guilherme Blanco in his original Object Calisthenic talk. These principles were studied and applied by us while we worked together in previous jobs. The result taught us all a lesson we really want to spread to other developers.