Slide 1

Slide 1 text

Rock-SOLID code Giuseppe Mazzapica

Slide 2

Slide 2 text

S O L I D . . . . . 5 design principles intended to make software designs more understandable flexible maintainable Robert Cecil Martin (Uncle Bob)

Slide 3

Slide 3 text

Maintainability is obtained: when things are easily understood code must be readable code must be explicit when large, complex problems are split in small problems objects must be small objects bust be focused when things are easily changed objects must be decoupled object relation must be supple

Slide 4

Slide 4 text

S O L I D ingle Responsibility Principle pen/Closed Principle iskov Substitution Principle nterface Segregation Principle ependency Inversion Principle

Slide 5

Slide 5 text

Single Responsibility Principle SRP a class should have only a single responsibility “ a class should do only a single “thing” there should be only a single reason to change a class ü û SOLID

Slide 6

Slide 6 text

SRP High Cohesion Low Coupling Keep togheter things that really belong togheter. Don’t relate unrelated things. ü ü enables:

Slide 7

Slide 7 text

class _Singleton { Poor_Men_Namespace_Plugin feed_the_dog() { public function ... } save_the_world() { public function ... } make_money_in_meantime() { public function ... } 42 43 44 ... 260 261 262 ... 512 513 514 ... 2514 û

Slide 8

Slide 8 text

namespace MyCompany\MyPlugin; class implements { DogSitter DogFeeder ; private $food_provider ( ) { public $food_provider function __construct FoodProvider -> ; $this food_provider = $food_provider } ( ... ) { public $dogs function feedDogs Dog ( , [ , ] ); array_walk $dogs $this ‘feed_dog’ } private $dog ( ) { function feedDog Dog -> ( -> -> ( ) ); $dog $dog eat provideTo $this food_provider 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ü

Slide 9

Slide 9 text

final class { My_Company_My_Plugin () { private function __construct ( , ( , ) ); add_action array ‘init’ ‘init’ $this ( , ( , ) ); add_action array ‘admin_init’ ‘admin_init’ $this ( , ( , ) ); add_filter array ‘the_title’ ‘the_title’ $this ... ( , ( , ) ); add_filter array ‘signup_user_meta’ ‘signup_user_meta’ $this } instance() { public static function ( == :: ) :: = (); if $instance $instance new null self self self :: ; return self $instance } public init() { } function ... ... } My_Company_My_Plugin:: (); instance 13 15 16 17 18 19 ... 99 100 101 102 103 104 105 106 107 ... 2025 2026 2027 û

Slide 10

Slide 10 text

ü MyCompany\MyPlugin; namespace main() { function Autoloader:: ()-> ( , . ); create register __NAMESPACE__ __DIR__ ‘/src’ ( , () { add_action ‘init’ function = Entity\Product(); $cpt new -> (); $cpt register } ); ( , function() { add_action ‘admin_init’ = Admin\PagesRegistar(); $admin_pages_registar new -> ( Admin\Page\OptionsPage() ); $admin_pages_registar new register } ); } ( , . , ); add_action __NAMESPACE__ ‘plugins_loaded’ ‘\\main’ 100 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

Slide 11

Slide 11 text

software entities should be open for extension, but closed for modification. “ implementation inheritance abstraction inheritance ü ûgetters and setters û polymorphism and encapsulation ü S LID O Open/Closed Principle OCP

Slide 12

Slide 12 text

OCP Extending behavior of existing entities without editing their code. Polimorphism ü Composition ü is about Supple behavior obtained via collaboration of specialized objects Abstraction is concretized in many shapes via replaceable concrete implementations

Slide 13

Slide 13 text

class { Dog_Caretaker Chihuahua( ) { public $chihuahua function feed ... } public $great_dane feedGreatDane( ) { function ... } public $german_shepherd feedGermanShepherd( ) { function ... } public $mongrel feedMongrel( ) { function ... 2 3 4 ... 30 31 32 ... 58 59 60 ... 86 87 88 ... û

Slide 14

Slide 14 text

interface { DogFoodProvider provideFood( Dog ); public $dog function } 2 3 4 2 3 4 5 2 3 4 interface Dog { size() : DogSize; public function public $food eat( Food ) : Hunger; function } interface extends PureBreedDog Dog { breed() : DogBreed; public function } ü

Slide 15

Slide 15 text

ü 4 ... 10 11 12 13 14 15 16 17 18 19 20 21 class implements DogCaretaker DogFoodProvider { ... public __construct( function Pantry $pantry, \ArrayAccess $config ) { -> = ; $this pantry $pantry $this config -> = ; $config } public $dog provideFood( Dog ) { function = -> [ :: ]; $type $this config self DOG_FOOD = -> ( ); $amount $this calcFoodAmount size $dog-> () -> -> ( , ) $dog-> ( ); eat pop $this pantry $type $amount

Slide 16

Slide 16 text

objects should be replaceable with instances of their subtypes without altering the correctness of the program “ design by contract ü design via inheritance û SO ID L Liskow Substitution Principle LSP

Slide 17

Slide 17 text

LSP Shifting the design of subtypes from “is-a” to “is-replacable-with” relationship. “Dog” is an “Animal”, but not all references to “Animal” can be replaced with “Dog”. Design to Interface ü Tell, don’t ask! ü is about

Slide 18

Slide 18 text

class { WP_Model_Saver save_object( WP_Model ) { public $obj function ( ( , ) ) { if is_a $obj ‘My_Post_Model’ ( -> () ); wp_update_post to_array $obj } ( ( , ) ) { elseif is_a $obj ‘My_Term_Model’ ( -> (), -> (), -> () ); wp_update_term id type to_array $obj $obj $obj } ( ( , ) ) { elseif is_a $obj ‘My_User_Model’ ( -> () ); wp_update_user to_array $obj } abstract class My_WP_Model { (); abstract public function to_array (); abstract public function id } 7 8 9 10 11 7 8 9 10 11 12 13 14 15 16 û

Slide 19

Slide 19 text

class implements { Post Model persist() : { public function bool ( -> ); return ( ) bool wp_update_post $this data } } class { ModelSaver persistModel( Model ) : { public function $model bool -> (); return $model persist } interface Model { () : ; public function persist bool } 7 8 9 7 8 9 10 11 12 7 8 9 10 11 ü

Slide 20

Slide 20 text

many client-specific interfaces are better than one general purpose interface “ many small, cohesive interfaces ü interfaces “as generic as possible” û SOL D I Interface Segregation Principle ISP

Slide 21

Slide 21 text

ISP Reducing system coupling thanks to small, cohesive contracts: clients should not be forced to depends on things they don’t use. In other words: describe behavior in many small chunks, then make each client depend on the specific chunk it really needs. is about

Slide 22

Slide 22 text

class { Attachment_Model Post_Model implements ... featured_image_id() : { public function int ( , ); _doing_it_wrong __FUNCTION__ ‘...’, ‘1.0’ return 0; } interface Post_Model { id() : ; public function int type() : Post_Type_Object; public function permalink() : ; public function string featured_image_id() : ; public function int ... } 7 8 9 10 11 ... 75 7 ... 42 43 44 45 û

Slide 23

Slide 23 text

ü interface Entity { id() : ; public function int persist() : ; public function bool } 7 8 9 10 7 8 9 10 7 8 9 7 8 ... interface extends Post Entity { status() : PostStatus; public function type() : PostType; public function } interface extends ThumbLiablePost Post { thumbnail() : Attachment; public function } interface extends Attachment Entity { media_url() : ; public function string ...

Slide 24

Slide 24 text

High-level modules should not depend on low-level modules. Both should depend on abstractions. “ Abstractions should not depend on details. Details should depend on abstractions. “ SOLID Dependency Inversion Principle DIP

Slide 25

Slide 25 text

Dependency Inversion Principle DIP it’s about object relations, not objects ü obtained only via auto-wiring DIC is the same of “Dependency Injection” all objects should have an interface û û û

Slide 26

Slide 26 text

class My_Metabox { print_metabox( ) { public $post function = My_Metabox_Fields( ); $fields new $post = My_Template_Engine(); $engine new -> ( , ); $engine $fields render ‘my_metabox’ } } 7 8 9 10 11 12 13 14 15 16 17 18 19 û

Slide 27

Slide 27 text

class My_Metabox { __construct( public function My_Template_Engine , $engine $fields My_Metabox_Fields ) { -> = ; $this engine $engine -> = ; $this fields $fields } print_metabox( ) { public function $post = -> -> ( ); $fields $this fields set_post $post -> -> ( , ); $this engine render ‘my_metabox’ $fields } } 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 û

Slide 28

Slide 28 text

interface MetaboxDataBuilder { buildFor( \WP_Post ) : ; public $post function array } interface TemplateEngine { ( , ) : ; public $template $data function render string array string } interface Metabox { renderBoxFor( \WP_Post ); public $post function } 7 8 9 10 7 8 9 10 7 8 9 10 ü

Slide 29

Slide 29 text

class implements MyMetaboxDataBuilder MetaboxDataBuilder { ... public $post function buildFor( \WP_Post ) : { array return [ => ( , ), ‘title’ ‘My Metabox’ ‘my-txt-domain’ __ => -> ( ) ‘fields’ $this fieldsData $post ]; } ... } 7 8 9 10 11 12 13 14 ... 33 7 8 9 ... 23 24 class implements MustacheEngine TemplateEngine { render( , ) : { public $template $data function string array string ... } } ü

Slide 30

Slide 30 text

class implements TemplateEngineMetabox Metabox { ... __construct( public function TemplateEngine , $engine MetaboxDataBuilder $data_builder, $template string ) { -> = ; $this engine $engine -> = ; $this builder $data_builder -> = ; $this template $template } renderBoxFor( \WP_Post ) { public $post function = -> -> ( ); $data $this builder buildFor $post -> -> ( -> , ); print $data $this engine $this template render } 7 ... 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ü

Slide 31

Slide 31 text

RECAP Keep things focused Keep things clear Keep things distinct Keep things extensible Keep things simple Keep things SOLID

Slide 32

Slide 32 text

PHP developer since 2005, first met WordPress in 2006. Moderator at wordpress.stackexchange.com Giuseppe Mazzapica Biggest German WordPress Agency WordPress.com Featured Service Partner Gold Certified WooCommerce Expert https://gmazzap.me @gmazzap github.com/gmazzap UESTIONS Q ?