SlideShare una empresa de Scribd logo
1 de 121
Descargar para leer sin conexión
WRITING SOLID CODE
(IN PRACTICE)
WRITING SOLID CODE IN PRACTICE
ABOUT ME
Tomasz Wojcik (@prgTW)
• backend dev@backoffice team
• been with DocPlanner since dinosaurs
• worships Grumpy Cat, morning coffee

and code reviews in the middle of the night
ó actually :P
/prgTW /prgTW /prgTW
WRITING SOLID CODE IN PRACTICE
WHAT “SOLID” STANDS FOR | THEORY
WRITING SOLID CODE IN PRACTICE
• SRP
• OCP
• LSP
• ISP
• DIP
WHAT “SOLID” STANDS FOR | THEORY
WRITING SOLID CODE IN PRACTICE
• SRP
• OCP
• LSP
• ISP
• DIP
Single Responsibility Principle
WHAT “SOLID” STANDS FOR | THEORY
WRITING SOLID CODE IN PRACTICE
• SRP
• OCP
• LSP
• ISP
• DIP
Single Responsibility Principle
Open/Closed Principle
WHAT “SOLID” STANDS FOR | THEORY
WRITING SOLID CODE IN PRACTICE
• SRP
• OCP
• LSP
• ISP
• DIP
Single Responsibility Principle
Open/Closed Principle
Liskov Substitution Principle
WHAT “SOLID” STANDS FOR | THEORY
WRITING SOLID CODE IN PRACTICE
• SRP
• OCP
• LSP
• ISP
• DIP
Single Responsibility Principle
Open/Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
WHAT “SOLID” STANDS FOR | THEORY
WRITING SOLID CODE IN PRACTICE
• SRP
• OCP
• LSP
• ISP
• DIP
Single Responsibility Principle
Open/Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
WHAT “SOLID” STANDS FOR | THEORY
WRITING SOLID CODE IN PRACTICE
CODE EXAMPLE
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}

CODE EXAMPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}

CODE EXAMPLE | PRACTICE
Typical answers:
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}

CODE EXAMPLE | PRACTICE
Typical answers:
• hardcoded integer & strings
• introduce constants
• move to method arguments
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}

CODE EXAMPLE | PRACTICE
Typical answers:
• hardcoded integer & strings
• introduce constants
• move to method arguments
• extract code to methods
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}

CODE EXAMPLE | PRACTICE
Typical answers:
• hardcoded integer & strings
• introduce constants
• move to method arguments
• extract code to methods
• many return points
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}

CODE EXAMPLE | PRACTICE
Typical answers:
• hardcoded integer & strings
• introduce constants
• move to method arguments
• extract code to methods
• many return points
• throw exception 

in error handling
WRITING SOLID CODE IN PRACTICE
LET’S START REFACTORING
WRITING SOLID CODE IN PRACTICE
SINGLE RESPONSIBILITY PRINCIPLE
WRITING SOLID CODE IN PRACTICE
SINGLE RESPONSIBILITY PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• class/module should have only single responsibility
SINGLE RESPONSIBILITY PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• class/module should have only single responsibility
• the above is defined as single reason for change
SINGLE RESPONSIBILITY PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• class/module should have only single responsibility
• the above is defined as single reason for change
• related services should be aligned with this responsibility
SINGLE RESPONSIBILITY PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}

SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}













$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}





















file_put_contents($cacheFile, $randomEmoji);
cache control
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}



























$response = file_get_contents('https://api.github.com/emojis');
 fetching data
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}





























if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}
error handling
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}







































$emojis = json_decode($response, true); data transformation
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}









































$randomEmoji = array_rand($emojis);






return $randomEmoji;
random emoji logic
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
• cache control
• fetching data
• error handling
• data transformation
• random emoji logic
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
class FileCache• cache control
• fetching data
• error handling
• data transformation
• random emoji logic
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
class FileCache
class FileGetContentsFetcher
• cache control
• fetching data
• error handling
• data transformation
• random emoji logic
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
class FileCache
class FileGetContentsFetcher
throw new Exception
• cache control
• fetching data
• error handling
• data transformation
• random emoji logic
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
custom one
WRITING SOLID CODE IN PRACTICE
class FileCache
class FileGetContentsFetcher
throw new Exception
class JsonSerializer
• cache control
• fetching data
• error handling
• data transformation
• random emoji logic
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
custom one
WRITING SOLID CODE IN PRACTICE
class FileCache
class FileGetContentsFetcher
throw new Exception
class JsonSerializer
class RandomGithubEmoji
• cache control
• fetching data
• error handling
• data transformation
• random emoji logic
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
custom one
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{















$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);







return $randomEmoji;

}

}













$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}





















file_put_contents($cacheFile, $randomEmoji);
cache control
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{















$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);







return $randomEmoji;

}

}

SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
cache control












$cache = new FileCache(__DIR__ . '/random_emoji');



$randomEmoji = $cache->fetch();

if (null !== $randomEmoji)

{

return $randomEmoji;

}



















$cache->put($randomEmoji);

WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}





if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}



























$response = file_get_contents('https://api.github.com/emojis');
 fetching data
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}





if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}

SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
fetching data


























$response = (new FileGetContentsFetcher)->fetch('https://api.github.com/emojis');
WRITING SOLID CODE IN PRACTICE
































return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 error handling
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{



}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}

WRITING SOLID CODE IN PRACTICE
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
error handling
































throw new UnableToFetchEmojiException;
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{



}



$emojis = json_decode($response, true);

$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}

WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}





$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}







































$emojis = json_decode($response, true); data transformation
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cacheFile = __DIR__ . '/random_emoji';



if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)

{

return file_get_contents($cacheFile);

}



$response = file_get_contents('https://api.github.com/emojis');

if (!$response)

{

return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';

}





$randomEmoji = array_rand($emojis);



file_put_contents($cacheFile, $randomEmoji);



return $randomEmoji;

}

}

SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
data transformation






































$emojis = (new JsonSerializer)->deserialize($response, 'json');
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cache = new FileCache(__DIR__ . '/random_emoji');

$randomEmoji = $cache->fetch();

if (null !== $randomEmoji)

{

return $randomEmoji;

}



$response = (new FileGetContentsFetcher)->fetch('https://api.github.com/emojis');

if (!$response)

{

throw new UnableToFetchEmojiException;

}



$emojis = (new JsonSerializer)->deserialize($response, 'json');

$randomEmoji = array_rand($emojis);



$cache->put($randomEmoji);



return $randomEmoji;

}

}
SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{

public function fetch(): string

{

$cache = new FileCache(__DIR__ . '/random_emoji');

$randomEmoji = $cache->fetch();

if (null !== $randomEmoji)

{

return $randomEmoji;

}



$response = (new FileGetContentsFetcher)->fetch('https://api.github.com/emojis');

if (!$response)

{

throw new UnableToFetchEmojiException;

}



$emojis = (new JsonSerializer)->deserialize($response, 'json');

$randomEmoji = array_rand($emojis);



$cache->put($randomEmoji);



return $randomEmoji;

}

}












new FileCache(__DIR__ . '/random_emoji');













new FileGetContentsFetcher











new JsonSerializer
DEPENDENCY INJECTION | PRACTICE
WRITING SOLID CODE IN PRACTICE
DEPENDENCY INVERSION PRINCIPLE
WRITING SOLID CODE IN PRACTICE
DEPENDENCY INVERSION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• used to decouple software modules
DEPENDENCY INVERSION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• used to decouple software modules
• high-level modules shouldn’t depend on low-level-modules, they both should
depend on abstractions
DEPENDENCY INVERSION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• used to decouple software modules
• high-level modules shouldn’t depend on low-level-modules, they both should
depend on abstractions
• class members should be interfaces or abstracts
DEPENDENCY INVERSION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• used to decouple software modules
• high-level modules shouldn’t depend on low-level-modules, they both should
depend on abstractions
• class members should be interfaces or abstracts
• class shouldn’t derive from concretions (composition over inheritance)
DEPENDENCY INVERSION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• used to decouple software modules
• high-level modules shouldn’t depend on low-level-modules, they both should
depend on abstractions
• class members should be interfaces or abstracts
• class shouldn’t derive from concretions (composition over inheritance)
• methods shouldn’t derive from already implemented methods
DEPENDENCY INVERSION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• used to decouple software modules
• high-level modules shouldn’t depend on low-level-modules, they both should
depend on abstractions
• class members should be interfaces or abstracts
• class shouldn’t derive from concretions (composition over inheritance)
• methods shouldn’t derive from already implemented methods
• variables must be created via injection or creational patterns (eg. factories)
DEPENDENCY INVERSION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
DEPENDENCY INVERSION PRINCIPLE | THEORY
https://en.wikipedia.org/wiki/Dependency_inversion_principle
WRITING SOLID CODE IN PRACTICE
DEPENDENCY INVERSION PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
DEPENDENCY INVERSION PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
DEPENDENCY INVERSION PRINCIPLE | THEORY
https://en.wikipedia.org/wiki/Dependency_inversion_principle
WRITING SOLID CODE IN PRACTICE
DEPENDENCY INVERSION PRINCIPLE | THEORY
https://en.wikipedia.org/wiki/Dependency_inversion_principle
WRITING SOLID CODE IN PRACTICE
DEPENDENCY INVERSION PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
DEPENDENCY INVERSION PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
DEPENDENCY INJECTION
(NOT PART OF SOLID ACTUALLY)
WRITING SOLID CODE IN PRACTICE
DEPENDENCY INJECTION | THEORY
WRITING SOLID CODE IN PRACTICE
• providing dependencies from outside of the dependent class
DEPENDENCY INJECTION | THEORY
WRITING SOLID CODE IN PRACTICE
• providing dependencies from outside of the dependent class
• class mustn’t use new or static methods
DEPENDENCY INJECTION | THEORY
WRITING SOLID CODE IN PRACTICE
<?php



class RandomGithubEmoji

{
/** @var Cache Interface */

private $cache ;



/** @var FetcherInterface */

private $fetcher;



/** @var SerializerInterface */

private $serializer;



public function __construct(Cache Interface $cache , FetcherInterface $fetcher, SerializerInterface $serializer)
{

$this->cache = $cache ;

$this->fetcher = $fetcher;

$this->serializer = $serializer;

}


// ...
}
DEPENDENCY INJECTION | PRACTICE
WRITING SOLID CODE IN PRACTICE
DEPENDENCY INJECTION | PRACTICE






/** @var CacheFactoryInterface */

private $cacheFactory;















CacheFactoryInterface $cacheFactory


$this->cacheFactory = $cacheFactory;
<?php



class RandomGithubEmoji

{
/** @var Cache Interface */

private $cache ;



/** @var FetcherInterface */

private $fetcher;



/** @var SerializerInterface */

private $serializer;



public function __construct(Cache Interface $cache , FetcherInterface $fetcher, SerializerInterface $serializer)
{

$this->cache = $cache ;

$this->fetcher = $fetcher;

$this->serializer = $serializer;

}


// ...
}
WRITING SOLID CODE IN PRACTICE
OPEN/CLOSED PRINCIPLE
WRITING SOLID CODE IN PRACTICE
OPEN/CLOSED PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• class should be open for extension
• class behaviour can be changed in derived classes
• protected instead of private methods
OPEN/CLOSED PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• class should be open for extension
• class behaviour can be changed in derived classes
• protected instead of private methods
• class should be closed for modification
• there should be no reason to change class code
• interfaces
OPEN/CLOSED PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• class should be open for extension
• class behaviour can be changed in derived classes
• protected instead of private methods
• class should be closed for modification
• there should be no reason to change class code
• interfaces
• think of dependencies coming from 3rd party vendors
OPEN/CLOSED PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
OPEN/CLOSED PRINCIPLE | PRACTICE
<?php



interface RandomEmojiInterface

{

public function fetch(): string

}
WRITING SOLID CODE IN PRACTICE
OPEN/CLOSED PRINCIPLE | PRACTICE
<?php



interface RandomEmojiInterface

{

public function fetch(): string

}
WRITING SOLID CODE IN PRACTICE
<?php











class Emoji

{

/** @var string */

private $url;



public function __construct(string $url)

{

$this->url = $url;

}



public function getUrl(): string

{

return $this->url;

}

}



interface RandomEmojiInterface

{

public function fetch(): Emoji

}
OPEN/CLOSED PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php











class Emoji

{

/** @var string */

private $url;



public function __construct(string $url)

{

$this->url = $url;

}



public function getUrl(): string

{

return $this->url;

}

}



interface RandomEmojiInterface

{

public function fetch(): Emoji

}
OPEN/CLOSED PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
















/** @var string */

private $url;



public function __construct(string $url)

{

$this->url = $url;

}



public function getUrl(): string

{

return $this->url;

}











<?php

interface EmojiInterface

{

public function getUrl(): string;



// here we COULD add additional features

}



class Emoji implements EmojiInterface

{





















}



interface RandomEmojiInterface

{

public function fetch(): EmojiInterface;

}
OPEN/CLOSED PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
INTERFACE SEGREGATION PRINCIPLE
WRITING SOLID CODE IN PRACTICE
INTERFACE SEGREGATION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• many specific interfaces are better than one generic
INTERFACE SEGREGATION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• many specific interfaces are better than one generic
• client shouldn’t be aware and forced to depend on methods it doesn’t use
INTERFACE SEGREGATION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• many specific interfaces are better than one generic
• client shouldn’t be aware and forced to depend on methods it doesn’t use
• helps keeping parts of the system decoupled
INTERFACE SEGREGATION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
INTERFACE SEGREGATION PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



interface CacheInterface

{

public function get($key);



public function put($something);



}



class FileCache implements CacheInterface

{

// get, put

}
INTERFACE SEGREGATION PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



interface CacheInterface

{

public function get($key);



public function put($something);



public function getMany(array $keys);



public function putMany(array $items);

}



class FileCache implements CacheInterface

{

// get, put

// getMany, putMany

}
INTERFACE SEGREGATION PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



interface CacheInterface

{

public function get($key);



public function put($something);



public function getMany(array $keys);



public function putMany(array $items);



public function invalidate($key);



public function invalidateMany(array $keys);



public function invalidataAll();

}



class FileCache implements CacheInterface

{

// get, put

// getMany, putMany
// invalidate, invalidateMany, invalidateAll

}
INTERFACE SEGREGATION PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



interface CacheInterface

{

public function get($key);



public function put($something);



public function getMany(array $keys);



public function putMany(array $items);



public function invalidate($key);



public function invalidateMany(array $keys);



public function invalidataAll();



public function gc();



public function countAll();

}



class FileCache implements CacheInterface

{

// :(

}
INTERFACE SEGREGATION PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
INTERFACE SEGREGATION PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
INTERFACE SEGREGATION PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
INTERFACE SEGREGATION PRINCIPLE | PRACTICE
WRITING SOLID CODE IN PRACTICE
LISKOV SUBSTITUTION PRINCIPLE
(BARBARA LISKOV)
WRITING SOLID CODE IN PRACTICE
https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)
COVARIANCE & CONTRAVARIANCE | LSP | THEORY
WRITING SOLID CODE IN PRACTICE
https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)
COVARIANCE & CONTRAVARIANCE | LSP | THEORY
WRITING SOLID CODE IN PRACTICE
https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)
COVARIANCE & CONTRAVARIANCE | LSP | THEORY
WRITING SOLID CODE IN PRACTICE
https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)
COVARIANCE & CONTRAVARIANCE | LSP | THEORY
WRITING SOLID CODE IN PRACTICE
https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)
COVARIANCE & CONTRAVARIANCE | LSP | THEORY
WRITING SOLID CODE IN PRACTICE
https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)
COVARIANCE & CONTRAVARIANCE | LSP | THEORY
WRITING SOLID CODE IN PRACTICE
LISKOV SUBSTITUTION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• objects of type T can be replaced by any subtype S of type T without altering
desired properties of the program/module (eg. correctness)
LISKOV SUBSTITUTION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• objects of type T can be replaced by any subtype S of type T without altering
desired properties of the program/module (eg. correctness)
• signature requirements
• covariance of return types
• contravariance of method arguments
• no new exceptions being non-derived from exceptions thrown in super type
LISKOV SUBSTITUTION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
• objects of type T can be replaced by any subtype S of type T without altering
desired properties of the program/module (eg. correctness)
• signature requirements
• covariance of return types
• contravariance of method arguments
• no new exceptions being non-derived from exceptions thrown in super type
• behavioral conditions
• preconditions cannot be strengthen in subtype
• postconditions cannot be weakened in subtype
• invariant in supertypes have to be preserved in subtype
LISKOV SUBSTITUTION PRINCIPLE | THEORY
WRITING SOLID CODE IN PRACTICE
COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
WRITING SOLID CODE IN PRACTICE
COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
<?php



interface T

{

}



interface S extends T

{

}
WRITING SOLID CODE IN PRACTICE
<?php



interface T

{

}



interface S extends T

{

}





// ---------------------------





interface A

{

public function do(T $t);

}



interface B extends A

{

public function do(T $t);

}

COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
<?php



interface T

{

}



interface S extends T

{

}
WRITING SOLID CODE IN PRACTICE
<?php



interface T

{

}



interface S extends T

{

}





// ---------------------------





interface A

{

public function do(T $t);

}



interface B extends A

{

public function do(T $t);

}

COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
<?php



interface T

{

}



interface S extends T

{

}
invariance of method argument
WRITING SOLID CODE IN PRACTICE
COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



interface T

{

}



interface S extends T

{

}





// ---------------------------





interface A

{

public function do(T $t);

}



interface B extends A

{

public function do(S $s);

}

COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



interface T

{

}



interface S extends T

{

}





// ---------------------------





interface A

{

public function do(T $t);

}



interface B extends A

{

public function do(S $s);

}

COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
covariance of method argument
WRITING SOLID CODE IN PRACTICE
<?php



interface T

{

}



interface S extends T

{

}





// ---------------------------





interface A

{

public function do(T $t);

}



interface B extends A

{

public function do(S $s);

}

COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
covariance of method argument
not allowed here, why?
WRITING SOLID CODE IN PRACTICE
<?php



interface T

{

}



interface S extends T

{

}





// ---------------------------





interface A

{

public function do(T $t);

}



interface B extends A

{

public function do(S $s);

}

COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
covariance of method argument
not allowed here, why?
… violating A::do signature

… violating “preconditions cannot be strengthen in subtype”
WRITING SOLID CODE IN PRACTICE
COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



interface T

{

}



interface S extends T

{

}



// ---------------------------



class A

{

public function do(): S;

{

}

}



class B extends A

{

public function do(): T;

{

}

}

COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
WRITING SOLID CODE IN PRACTICE
<?php



interface T

{

}



interface S extends T

{

}



// ---------------------------



class A

{

public function do(): S;

{

}

}



class B extends A

{

public function do(): T;

{

}

}

COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
contravariance of return type
WRITING SOLID CODE IN PRACTICE
<?php



interface T

{

}



interface S extends T

{

}



// ---------------------------



class A

{

public function do(): S;

{

}

}



class B extends A

{

public function do(): T;

{

}

}

COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
contravariance of return type
not allowed here, why?
WRITING SOLID CODE IN PRACTICE
<?php



interface T

{

}



interface S extends T

{

}



// ---------------------------



class A

{

public function do(): S;

{

}

}



class B extends A

{

public function do(): T;

{

}

}

COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
contravariance of return type
not allowed here, why?
… violating A::do signature

… violating “postconditions cannot be weakened in subtype”
WRITING SOLID CODE IN PRACTICE
SUMMARY
WRITING SOLID CODE IN PRACTICE
BEFORE | SUMMARY
WRITING SOLID CODE IN PRACTICE
AFTER | SUMMARY
WRITING SOLID CODE IN PRACTICE
BENEFITS OF WRITING SOLID CODE
WRITING SOLID CODE IN PRACTICE
BENEFITS | SUMMARY
WRITING SOLID CODE IN PRACTICE
BENEFITS | SUMMARY
• code is well organised and more declarative
• code is easy to read and understand (short learning curve)
• code is loosely coupled and thus reusable
• code is easy to adapt
• code is easy to extend
• code is easy to refactor
• code is easy to unit test
• code is easy to replace/mock in functional tests
• … etc. etc.
WRITING SOLID CODE IN PRACTICE
Q’N’A
Questions?
WRITING SOLID CODE IN PRACTICE
THANK YOU!
docplanner.com/career
Join us!

Más contenido relacionado

La actualidad más candente

Machine Learning and Inductive Inference
Machine Learning and Inductive InferenceMachine Learning and Inductive Inference
Machine Learning and Inductive Inference
butest
 
Internship project report,Predictive Modelling
Internship project report,Predictive ModellingInternship project report,Predictive Modelling
Internship project report,Predictive Modelling
Amit Kumar
 
Thesis on Hybrid renewable energy system for condo developments
Thesis on Hybrid renewable energy system for condo developmentsThesis on Hybrid renewable energy system for condo developments
Thesis on Hybrid renewable energy system for condo developments
Fasil Ayele
 
Leave Management System Documentation
Leave Management System DocumentationLeave Management System Documentation
Leave Management System Documentation
muzammil siddiq
 
Automated School Time Table Generator
Automated School Time Table GeneratorAutomated School Time Table Generator
Automated School Time Table Generator
Divyen Patel
 

La actualidad más candente (20)

Machine learning ppt.
Machine learning ppt.Machine learning ppt.
Machine learning ppt.
 
Machine Learning and Inductive Inference
Machine Learning and Inductive InferenceMachine Learning and Inductive Inference
Machine Learning and Inductive Inference
 
Supervised learning and unsupervised learning
Supervised learning and unsupervised learningSupervised learning and unsupervised learning
Supervised learning and unsupervised learning
 
Internship project report,Predictive Modelling
Internship project report,Predictive ModellingInternship project report,Predictive Modelling
Internship project report,Predictive Modelling
 
Thesis on Hybrid renewable energy system for condo developments
Thesis on Hybrid renewable energy system for condo developmentsThesis on Hybrid renewable energy system for condo developments
Thesis on Hybrid renewable energy system for condo developments
 
Association Analysis in Data Mining
Association Analysis in Data MiningAssociation Analysis in Data Mining
Association Analysis in Data Mining
 
Logic
LogicLogic
Logic
 
Supermarket Inventory Management System Development.pdf
Supermarket Inventory Management System Development.pdfSupermarket Inventory Management System Development.pdf
Supermarket Inventory Management System Development.pdf
 
Making sense of kusum
Making sense of kusumMaking sense of kusum
Making sense of kusum
 
Leave Management System Documentation
Leave Management System DocumentationLeave Management System Documentation
Leave Management System Documentation
 
Leave Management System: Software Requirements Specification Document(SRS)
Leave Management System: Software Requirements Specification Document(SRS) Leave Management System: Software Requirements Specification Document(SRS)
Leave Management System: Software Requirements Specification Document(SRS)
 
Automated School Time Table Generator
Automated School Time Table GeneratorAutomated School Time Table Generator
Automated School Time Table Generator
 
IRJET - Online Seminar Hall Booking System
IRJET -  	  Online Seminar Hall Booking SystemIRJET -  	  Online Seminar Hall Booking System
IRJET - Online Seminar Hall Booking System
 
Machine Learning Foundations
Machine Learning FoundationsMachine Learning Foundations
Machine Learning Foundations
 
Final thesis presentation
Final thesis presentationFinal thesis presentation
Final thesis presentation
 
Benefits of Energy Monitoring System
Benefits of Energy Monitoring SystemBenefits of Energy Monitoring System
Benefits of Energy Monitoring System
 
Input modeling
Input modelingInput modeling
Input modeling
 
Online railway reservation system
Online railway reservation systemOnline railway reservation system
Online railway reservation system
 
Hospital Management System Documentation Java
Hospital Management System Documentation Java Hospital Management System Documentation Java
Hospital Management System Documentation Java
 
5.5 graph mining
5.5 graph mining5.5 graph mining
5.5 graph mining
 

Destacado

Socials 8 tutorial 2014
Socials 8 tutorial 2014Socials 8 tutorial 2014
Socials 8 tutorial 2014
pkwon
 
Sql server 2012 tutorials writing transact-sql statements
Sql server 2012 tutorials   writing transact-sql statementsSql server 2012 tutorials   writing transact-sql statements
Sql server 2012 tutorials writing transact-sql statements
Steve Xu
 

Destacado (8)

CQRS & Event Sourcing
CQRS & Event SourcingCQRS & Event Sourcing
CQRS & Event Sourcing
 
Middle School Writing Tutorial
Middle School Writing TutorialMiddle School Writing Tutorial
Middle School Writing Tutorial
 
Socials 8 tutorial 2014
Socials 8 tutorial 2014Socials 8 tutorial 2014
Socials 8 tutorial 2014
 
Sql server 2012 tutorials writing transact-sql statements
Sql server 2012 tutorials   writing transact-sql statementsSql server 2012 tutorials   writing transact-sql statements
Sql server 2012 tutorials writing transact-sql statements
 
Writing Clean Code in Swift
Writing Clean Code in SwiftWriting Clean Code in Swift
Writing Clean Code in Swift
 
Writing code you won't hate tomorrow
Writing code you won't hate tomorrowWriting code you won't hate tomorrow
Writing code you won't hate tomorrow
 
[Infographic] How will Internet of Things (IoT) change the world as we know it?
[Infographic] How will Internet of Things (IoT) change the world as we know it?[Infographic] How will Internet of Things (IoT) change the world as we know it?
[Infographic] How will Internet of Things (IoT) change the world as we know it?
 
Guided Reading: Making the Most of It
Guided Reading: Making the Most of ItGuided Reading: Making the Most of It
Guided Reading: Making the Most of It
 

Similar a Writing SOLID code (in practice)

DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)
Oleg Zinchenko
 
Python & Django TTT
Python & Django TTTPython & Django TTT
Python & Django TTT
kevinvw
 

Similar a Writing SOLID code (in practice) (20)

SOLID code in practice - creating good object oriented PHP application @ WDI...
SOLID code in practice  - creating good object oriented PHP application @ WDI...SOLID code in practice  - creating good object oriented PHP application @ WDI...
SOLID code in practice - creating good object oriented PHP application @ WDI...
 
Questioning the status quo
Questioning the status quoQuestioning the status quo
Questioning the status quo
 
OOP
OOPOOP
OOP
 
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguaje
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguajeKotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguaje
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguaje
 
Kotlin+MicroProfile: Ensinando 20 anos para uma linguagem nova
Kotlin+MicroProfile: Ensinando 20 anos para uma linguagem novaKotlin+MicroProfile: Ensinando 20 anos para uma linguagem nova
Kotlin+MicroProfile: Ensinando 20 anos para uma linguagem nova
 
Living With Legacy Code
Living With Legacy CodeLiving With Legacy Code
Living With Legacy Code
 
Objects, Testing, and Responsibility
Objects, Testing, and ResponsibilityObjects, Testing, and Responsibility
Objects, Testing, and Responsibility
 
New Ideas for Old Code - Greach
New Ideas for Old Code - GreachNew Ideas for Old Code - Greach
New Ideas for Old Code - Greach
 
Object Oriented PHP5
Object Oriented PHP5Object Oriented PHP5
Object Oriented PHP5
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
Supercharging WordPress Development in 2018
Supercharging WordPress Development in 2018Supercharging WordPress Development in 2018
Supercharging WordPress Development in 2018
 
Metaprogramming Rails
Metaprogramming RailsMetaprogramming Rails
Metaprogramming Rails
 
WebCamp: Developer Day: DDD in PHP on example of Symfony - Олег Зинченко
WebCamp: Developer Day: DDD in PHP on example of Symfony - Олег ЗинченкоWebCamp: Developer Day: DDD in PHP on example of Symfony - Олег Зинченко
WebCamp: Developer Day: DDD in PHP on example of Symfony - Олег Зинченко
 
Xopus Application Framework
Xopus Application FrameworkXopus Application Framework
Xopus Application Framework
 
DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)
 
Drupaljam xl 2019 presentation multilingualism makes better programmers
Drupaljam xl 2019 presentation   multilingualism makes better programmersDrupaljam xl 2019 presentation   multilingualism makes better programmers
Drupaljam xl 2019 presentation multilingualism makes better programmers
 
Python & Django TTT
Python & Django TTTPython & Django TTT
Python & Django TTT
 
Ch8(oop)
Ch8(oop)Ch8(oop)
Ch8(oop)
 
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
 
Make your project up to date
Make your project up to dateMake your project up to date
Make your project up to date
 

Último

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Último (20)

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
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
A Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source MilvusA Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source Milvus
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 

Writing SOLID code (in practice)

  • 2. WRITING SOLID CODE IN PRACTICE ABOUT ME Tomasz Wojcik (@prgTW) • backend dev@backoffice team • been with DocPlanner since dinosaurs • worships Grumpy Cat, morning coffee
 and code reviews in the middle of the night &oacute; actually :P /prgTW /prgTW /prgTW
  • 3. WRITING SOLID CODE IN PRACTICE WHAT “SOLID” STANDS FOR | THEORY
  • 4. WRITING SOLID CODE IN PRACTICE • SRP • OCP • LSP • ISP • DIP WHAT “SOLID” STANDS FOR | THEORY
  • 5. WRITING SOLID CODE IN PRACTICE • SRP • OCP • LSP • ISP • DIP Single Responsibility Principle WHAT “SOLID” STANDS FOR | THEORY
  • 6. WRITING SOLID CODE IN PRACTICE • SRP • OCP • LSP • ISP • DIP Single Responsibility Principle Open/Closed Principle WHAT “SOLID” STANDS FOR | THEORY
  • 7. WRITING SOLID CODE IN PRACTICE • SRP • OCP • LSP • ISP • DIP Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle WHAT “SOLID” STANDS FOR | THEORY
  • 8. WRITING SOLID CODE IN PRACTICE • SRP • OCP • LSP • ISP • DIP Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle Interface Segregation Principle WHAT “SOLID” STANDS FOR | THEORY
  • 9. WRITING SOLID CODE IN PRACTICE • SRP • OCP • LSP • ISP • DIP Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle WHAT “SOLID” STANDS FOR | THEORY
  • 10. WRITING SOLID CODE IN PRACTICE CODE EXAMPLE
  • 11. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 CODE EXAMPLE | PRACTICE
  • 12. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 CODE EXAMPLE | PRACTICE Typical answers:
  • 13. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 CODE EXAMPLE | PRACTICE Typical answers: • hardcoded integer & strings • introduce constants • move to method arguments
  • 14. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 CODE EXAMPLE | PRACTICE Typical answers: • hardcoded integer & strings • introduce constants • move to method arguments • extract code to methods
  • 15. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 CODE EXAMPLE | PRACTICE Typical answers: • hardcoded integer & strings • introduce constants • move to method arguments • extract code to methods • many return points
  • 16. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 CODE EXAMPLE | PRACTICE Typical answers: • hardcoded integer & strings • introduce constants • move to method arguments • extract code to methods • many return points • throw exception 
 in error handling
  • 17. WRITING SOLID CODE IN PRACTICE LET’S START REFACTORING
  • 18. WRITING SOLID CODE IN PRACTICE SINGLE RESPONSIBILITY PRINCIPLE
  • 19. WRITING SOLID CODE IN PRACTICE SINGLE RESPONSIBILITY PRINCIPLE | THEORY
  • 20. WRITING SOLID CODE IN PRACTICE • class/module should have only single responsibility SINGLE RESPONSIBILITY PRINCIPLE | THEORY
  • 21. WRITING SOLID CODE IN PRACTICE • class/module should have only single responsibility • the above is defined as single reason for change SINGLE RESPONSIBILITY PRINCIPLE | THEORY
  • 22. WRITING SOLID CODE IN PRACTICE • class/module should have only single responsibility • the above is defined as single reason for change • related services should be aligned with this responsibility SINGLE RESPONSIBILITY PRINCIPLE | THEORY
  • 23. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
  • 24. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 
 
 
 
 
 
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 
 
 
 
 
 
 
 
 
 file_put_contents($cacheFile, $randomEmoji); cache control SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
  • 25. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 $response = file_get_contents('https://api.github.com/emojis');
 fetching data SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
  • 26. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 } error handling SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
  • 27. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 $emojis = json_decode($response, true); data transformation SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
  • 28. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 $randomEmoji = array_rand($emojis); 
 
 
 return $randomEmoji; random emoji logic SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
  • 29. WRITING SOLID CODE IN PRACTICE • cache control • fetching data • error handling • data transformation • random emoji logic SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
  • 30. WRITING SOLID CODE IN PRACTICE class FileCache• cache control • fetching data • error handling • data transformation • random emoji logic SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
  • 31. WRITING SOLID CODE IN PRACTICE class FileCache class FileGetContentsFetcher • cache control • fetching data • error handling • data transformation • random emoji logic SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
  • 32. WRITING SOLID CODE IN PRACTICE class FileCache class FileGetContentsFetcher throw new Exception • cache control • fetching data • error handling • data transformation • random emoji logic SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE custom one
  • 33. WRITING SOLID CODE IN PRACTICE class FileCache class FileGetContentsFetcher throw new Exception class JsonSerializer • cache control • fetching data • error handling • data transformation • random emoji logic SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE custom one
  • 34. WRITING SOLID CODE IN PRACTICE class FileCache class FileGetContentsFetcher throw new Exception class JsonSerializer class RandomGithubEmoji • cache control • fetching data • error handling • data transformation • random emoji logic SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE custom one
  • 35. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 
 
 
 
 
 
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 
 
 return $randomEmoji;
 }
 }
 
 
 
 
 
 
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 
 
 
 
 
 
 
 
 
 file_put_contents($cacheFile, $randomEmoji); cache control SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
  • 36. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 
 
 
 
 
 
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 
 
 return $randomEmoji;
 }
 }
 SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE cache control 
 
 
 
 
 
 $cache = new FileCache(__DIR__ . '/random_emoji');
 
 $randomEmoji = $cache->fetch();
 if (null !== $randomEmoji)
 {
 return $randomEmoji;
 }
 
 
 
 
 
 
 
 
 
 $cache->put($randomEmoji);

  • 37. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 $response = file_get_contents('https://api.github.com/emojis');
 fetching data SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
  • 38. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE fetching data 
 
 
 
 
 
 
 
 
 
 
 
 
 $response = (new FileGetContentsFetcher)->fetch('https://api.github.com/emojis');
  • 39. WRITING SOLID CODE IN PRACTICE 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 error handling SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }

  • 40. WRITING SOLID CODE IN PRACTICE SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE error handling 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 throw new UnableToFetchEmojiException; <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 
 }
 
 $emojis = json_decode($response, true);
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }

  • 41. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 $emojis = json_decode($response, true); data transformation SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
  • 42. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cacheFile = __DIR__ . '/random_emoji';
 
 if (is_file($cacheFile) && time() - filemtime($cacheFile) <= 3)
 {
 return file_get_contents($cacheFile);
 }
 
 $response = file_get_contents('https://api.github.com/emojis');
 if (!$response)
 {
 return 'https://assets-cdn.github.com/images/icons/emoji/trollface.png?v6';
 }
 
 
 $randomEmoji = array_rand($emojis);
 
 file_put_contents($cacheFile, $randomEmoji);
 
 return $randomEmoji;
 }
 }
 SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE data transformation 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 $emojis = (new JsonSerializer)->deserialize($response, 'json');
  • 43. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cache = new FileCache(__DIR__ . '/random_emoji');
 $randomEmoji = $cache->fetch();
 if (null !== $randomEmoji)
 {
 return $randomEmoji;
 }
 
 $response = (new FileGetContentsFetcher)->fetch('https://api.github.com/emojis');
 if (!$response)
 {
 throw new UnableToFetchEmojiException;
 }
 
 $emojis = (new JsonSerializer)->deserialize($response, 'json');
 $randomEmoji = array_rand($emojis);
 
 $cache->put($randomEmoji);
 
 return $randomEmoji;
 }
 } SINGLE RESPONSIBILITY PRINCIPLE | PRACTICE
  • 44. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 {
 public function fetch(): string
 {
 $cache = new FileCache(__DIR__ . '/random_emoji');
 $randomEmoji = $cache->fetch();
 if (null !== $randomEmoji)
 {
 return $randomEmoji;
 }
 
 $response = (new FileGetContentsFetcher)->fetch('https://api.github.com/emojis');
 if (!$response)
 {
 throw new UnableToFetchEmojiException;
 }
 
 $emojis = (new JsonSerializer)->deserialize($response, 'json');
 $randomEmoji = array_rand($emojis);
 
 $cache->put($randomEmoji);
 
 return $randomEmoji;
 }
 } 
 
 
 
 
 
 new FileCache(__DIR__ . '/random_emoji');
 
 
 
 
 
 
 new FileGetContentsFetcher
 
 
 
 
 
 new JsonSerializer DEPENDENCY INJECTION | PRACTICE
  • 45. WRITING SOLID CODE IN PRACTICE DEPENDENCY INVERSION PRINCIPLE
  • 46. WRITING SOLID CODE IN PRACTICE DEPENDENCY INVERSION PRINCIPLE | THEORY
  • 47. WRITING SOLID CODE IN PRACTICE • used to decouple software modules DEPENDENCY INVERSION PRINCIPLE | THEORY
  • 48. WRITING SOLID CODE IN PRACTICE • used to decouple software modules • high-level modules shouldn’t depend on low-level-modules, they both should depend on abstractions DEPENDENCY INVERSION PRINCIPLE | THEORY
  • 49. WRITING SOLID CODE IN PRACTICE • used to decouple software modules • high-level modules shouldn’t depend on low-level-modules, they both should depend on abstractions • class members should be interfaces or abstracts DEPENDENCY INVERSION PRINCIPLE | THEORY
  • 50. WRITING SOLID CODE IN PRACTICE • used to decouple software modules • high-level modules shouldn’t depend on low-level-modules, they both should depend on abstractions • class members should be interfaces or abstracts • class shouldn’t derive from concretions (composition over inheritance) DEPENDENCY INVERSION PRINCIPLE | THEORY
  • 51. WRITING SOLID CODE IN PRACTICE • used to decouple software modules • high-level modules shouldn’t depend on low-level-modules, they both should depend on abstractions • class members should be interfaces or abstracts • class shouldn’t derive from concretions (composition over inheritance) • methods shouldn’t derive from already implemented methods DEPENDENCY INVERSION PRINCIPLE | THEORY
  • 52. WRITING SOLID CODE IN PRACTICE • used to decouple software modules • high-level modules shouldn’t depend on low-level-modules, they both should depend on abstractions • class members should be interfaces or abstracts • class shouldn’t derive from concretions (composition over inheritance) • methods shouldn’t derive from already implemented methods • variables must be created via injection or creational patterns (eg. factories) DEPENDENCY INVERSION PRINCIPLE | THEORY
  • 53. WRITING SOLID CODE IN PRACTICE DEPENDENCY INVERSION PRINCIPLE | THEORY https://en.wikipedia.org/wiki/Dependency_inversion_principle
  • 54. WRITING SOLID CODE IN PRACTICE DEPENDENCY INVERSION PRINCIPLE | PRACTICE
  • 55. WRITING SOLID CODE IN PRACTICE DEPENDENCY INVERSION PRINCIPLE | PRACTICE
  • 56. WRITING SOLID CODE IN PRACTICE DEPENDENCY INVERSION PRINCIPLE | THEORY https://en.wikipedia.org/wiki/Dependency_inversion_principle
  • 57. WRITING SOLID CODE IN PRACTICE DEPENDENCY INVERSION PRINCIPLE | THEORY https://en.wikipedia.org/wiki/Dependency_inversion_principle
  • 58. WRITING SOLID CODE IN PRACTICE DEPENDENCY INVERSION PRINCIPLE | PRACTICE
  • 59. WRITING SOLID CODE IN PRACTICE DEPENDENCY INVERSION PRINCIPLE | PRACTICE
  • 60. WRITING SOLID CODE IN PRACTICE DEPENDENCY INJECTION (NOT PART OF SOLID ACTUALLY)
  • 61. WRITING SOLID CODE IN PRACTICE DEPENDENCY INJECTION | THEORY
  • 62. WRITING SOLID CODE IN PRACTICE • providing dependencies from outside of the dependent class DEPENDENCY INJECTION | THEORY
  • 63. WRITING SOLID CODE IN PRACTICE • providing dependencies from outside of the dependent class • class mustn’t use new or static methods DEPENDENCY INJECTION | THEORY
  • 64. WRITING SOLID CODE IN PRACTICE <?php
 
 class RandomGithubEmoji
 { /** @var Cache Interface */
 private $cache ;
 
 /** @var FetcherInterface */
 private $fetcher;
 
 /** @var SerializerInterface */
 private $serializer;
 
 public function __construct(Cache Interface $cache , FetcherInterface $fetcher, SerializerInterface $serializer) {
 $this->cache = $cache ;
 $this->fetcher = $fetcher;
 $this->serializer = $serializer;
 } 
 // ... } DEPENDENCY INJECTION | PRACTICE
  • 65. WRITING SOLID CODE IN PRACTICE DEPENDENCY INJECTION | PRACTICE 
 
 
 /** @var CacheFactoryInterface */
 private $cacheFactory;
 
 
 
 
 
 
 
 CacheFactoryInterface $cacheFactory 
 $this->cacheFactory = $cacheFactory; <?php
 
 class RandomGithubEmoji
 { /** @var Cache Interface */
 private $cache ;
 
 /** @var FetcherInterface */
 private $fetcher;
 
 /** @var SerializerInterface */
 private $serializer;
 
 public function __construct(Cache Interface $cache , FetcherInterface $fetcher, SerializerInterface $serializer) {
 $this->cache = $cache ;
 $this->fetcher = $fetcher;
 $this->serializer = $serializer;
 } 
 // ... }
  • 66. WRITING SOLID CODE IN PRACTICE OPEN/CLOSED PRINCIPLE
  • 67. WRITING SOLID CODE IN PRACTICE OPEN/CLOSED PRINCIPLE | THEORY
  • 68. WRITING SOLID CODE IN PRACTICE • class should be open for extension • class behaviour can be changed in derived classes • protected instead of private methods OPEN/CLOSED PRINCIPLE | THEORY
  • 69. WRITING SOLID CODE IN PRACTICE • class should be open for extension • class behaviour can be changed in derived classes • protected instead of private methods • class should be closed for modification • there should be no reason to change class code • interfaces OPEN/CLOSED PRINCIPLE | THEORY
  • 70. WRITING SOLID CODE IN PRACTICE • class should be open for extension • class behaviour can be changed in derived classes • protected instead of private methods • class should be closed for modification • there should be no reason to change class code • interfaces • think of dependencies coming from 3rd party vendors OPEN/CLOSED PRINCIPLE | THEORY
  • 71. WRITING SOLID CODE IN PRACTICE OPEN/CLOSED PRINCIPLE | PRACTICE <?php
 
 interface RandomEmojiInterface
 {
 public function fetch(): string
 }
  • 72. WRITING SOLID CODE IN PRACTICE OPEN/CLOSED PRINCIPLE | PRACTICE <?php
 
 interface RandomEmojiInterface
 {
 public function fetch(): string
 }
  • 73. WRITING SOLID CODE IN PRACTICE <?php
 
 
 
 
 
 class Emoji
 {
 /** @var string */
 private $url;
 
 public function __construct(string $url)
 {
 $this->url = $url;
 }
 
 public function getUrl(): string
 {
 return $this->url;
 }
 }
 
 interface RandomEmojiInterface
 {
 public function fetch(): Emoji
 } OPEN/CLOSED PRINCIPLE | PRACTICE
  • 74. WRITING SOLID CODE IN PRACTICE <?php
 
 
 
 
 
 class Emoji
 {
 /** @var string */
 private $url;
 
 public function __construct(string $url)
 {
 $this->url = $url;
 }
 
 public function getUrl(): string
 {
 return $this->url;
 }
 }
 
 interface RandomEmojiInterface
 {
 public function fetch(): Emoji
 } OPEN/CLOSED PRINCIPLE | PRACTICE
  • 75. WRITING SOLID CODE IN PRACTICE 
 
 
 
 
 
 
 
 /** @var string */
 private $url;
 
 public function __construct(string $url)
 {
 $this->url = $url;
 }
 
 public function getUrl(): string
 {
 return $this->url;
 }
 
 
 
 
 
 <?php
 interface EmojiInterface
 {
 public function getUrl(): string;
 
 // here we COULD add additional features
 }
 
 class Emoji implements EmojiInterface
 {
 
 
 
 
 
 
 
 
 
 
 }
 
 interface RandomEmojiInterface
 {
 public function fetch(): EmojiInterface;
 } OPEN/CLOSED PRINCIPLE | PRACTICE
  • 76. WRITING SOLID CODE IN PRACTICE INTERFACE SEGREGATION PRINCIPLE
  • 77. WRITING SOLID CODE IN PRACTICE INTERFACE SEGREGATION PRINCIPLE | THEORY
  • 78. WRITING SOLID CODE IN PRACTICE • many specific interfaces are better than one generic INTERFACE SEGREGATION PRINCIPLE | THEORY
  • 79. WRITING SOLID CODE IN PRACTICE • many specific interfaces are better than one generic • client shouldn’t be aware and forced to depend on methods it doesn’t use INTERFACE SEGREGATION PRINCIPLE | THEORY
  • 80. WRITING SOLID CODE IN PRACTICE • many specific interfaces are better than one generic • client shouldn’t be aware and forced to depend on methods it doesn’t use • helps keeping parts of the system decoupled INTERFACE SEGREGATION PRINCIPLE | THEORY
  • 81. WRITING SOLID CODE IN PRACTICE INTERFACE SEGREGATION PRINCIPLE | PRACTICE
  • 82. WRITING SOLID CODE IN PRACTICE <?php
 
 interface CacheInterface
 {
 public function get($key);
 
 public function put($something);
 
 }
 
 class FileCache implements CacheInterface
 {
 // get, put
 } INTERFACE SEGREGATION PRINCIPLE | PRACTICE
  • 83. WRITING SOLID CODE IN PRACTICE <?php
 
 interface CacheInterface
 {
 public function get($key);
 
 public function put($something);
 
 public function getMany(array $keys);
 
 public function putMany(array $items);
 }
 
 class FileCache implements CacheInterface
 {
 // get, put
 // getMany, putMany
 } INTERFACE SEGREGATION PRINCIPLE | PRACTICE
  • 84. WRITING SOLID CODE IN PRACTICE <?php
 
 interface CacheInterface
 {
 public function get($key);
 
 public function put($something);
 
 public function getMany(array $keys);
 
 public function putMany(array $items);
 
 public function invalidate($key);
 
 public function invalidateMany(array $keys);
 
 public function invalidataAll();
 }
 
 class FileCache implements CacheInterface
 {
 // get, put
 // getMany, putMany // invalidate, invalidateMany, invalidateAll
 } INTERFACE SEGREGATION PRINCIPLE | PRACTICE
  • 85. WRITING SOLID CODE IN PRACTICE <?php
 
 interface CacheInterface
 {
 public function get($key);
 
 public function put($something);
 
 public function getMany(array $keys);
 
 public function putMany(array $items);
 
 public function invalidate($key);
 
 public function invalidateMany(array $keys);
 
 public function invalidataAll();
 
 public function gc();
 
 public function countAll();
 }
 
 class FileCache implements CacheInterface
 {
 // :(
 } INTERFACE SEGREGATION PRINCIPLE | PRACTICE
  • 86. WRITING SOLID CODE IN PRACTICE INTERFACE SEGREGATION PRINCIPLE | PRACTICE
  • 87. WRITING SOLID CODE IN PRACTICE INTERFACE SEGREGATION PRINCIPLE | PRACTICE
  • 88. WRITING SOLID CODE IN PRACTICE INTERFACE SEGREGATION PRINCIPLE | PRACTICE
  • 89. WRITING SOLID CODE IN PRACTICE LISKOV SUBSTITUTION PRINCIPLE (BARBARA LISKOV)
  • 90. WRITING SOLID CODE IN PRACTICE https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science) COVARIANCE & CONTRAVARIANCE | LSP | THEORY
  • 91. WRITING SOLID CODE IN PRACTICE https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science) COVARIANCE & CONTRAVARIANCE | LSP | THEORY
  • 92. WRITING SOLID CODE IN PRACTICE https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science) COVARIANCE & CONTRAVARIANCE | LSP | THEORY
  • 93. WRITING SOLID CODE IN PRACTICE https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science) COVARIANCE & CONTRAVARIANCE | LSP | THEORY
  • 94. WRITING SOLID CODE IN PRACTICE https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science) COVARIANCE & CONTRAVARIANCE | LSP | THEORY
  • 95. WRITING SOLID CODE IN PRACTICE https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science) COVARIANCE & CONTRAVARIANCE | LSP | THEORY
  • 96. WRITING SOLID CODE IN PRACTICE LISKOV SUBSTITUTION PRINCIPLE | THEORY
  • 97. WRITING SOLID CODE IN PRACTICE • objects of type T can be replaced by any subtype S of type T without altering desired properties of the program/module (eg. correctness) LISKOV SUBSTITUTION PRINCIPLE | THEORY
  • 98. WRITING SOLID CODE IN PRACTICE • objects of type T can be replaced by any subtype S of type T without altering desired properties of the program/module (eg. correctness) • signature requirements • covariance of return types • contravariance of method arguments • no new exceptions being non-derived from exceptions thrown in super type LISKOV SUBSTITUTION PRINCIPLE | THEORY
  • 99. WRITING SOLID CODE IN PRACTICE • objects of type T can be replaced by any subtype S of type T without altering desired properties of the program/module (eg. correctness) • signature requirements • covariance of return types • contravariance of method arguments • no new exceptions being non-derived from exceptions thrown in super type • behavioral conditions • preconditions cannot be strengthen in subtype • postconditions cannot be weakened in subtype • invariant in supertypes have to be preserved in subtype LISKOV SUBSTITUTION PRINCIPLE | THEORY
  • 100. WRITING SOLID CODE IN PRACTICE COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
  • 101. WRITING SOLID CODE IN PRACTICE COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE <?php
 
 interface T
 {
 }
 
 interface S extends T
 {
 }
  • 102. WRITING SOLID CODE IN PRACTICE <?php
 
 interface T
 {
 }
 
 interface S extends T
 {
 }
 
 
 // ---------------------------
 
 
 interface A
 {
 public function do(T $t);
 }
 
 interface B extends A
 {
 public function do(T $t);
 }
 COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE <?php
 
 interface T
 {
 }
 
 interface S extends T
 {
 }
  • 103. WRITING SOLID CODE IN PRACTICE <?php
 
 interface T
 {
 }
 
 interface S extends T
 {
 }
 
 
 // ---------------------------
 
 
 interface A
 {
 public function do(T $t);
 }
 
 interface B extends A
 {
 public function do(T $t);
 }
 COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE <?php
 
 interface T
 {
 }
 
 interface S extends T
 {
 } invariance of method argument
  • 104. WRITING SOLID CODE IN PRACTICE COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
  • 105. WRITING SOLID CODE IN PRACTICE <?php
 
 interface T
 {
 }
 
 interface S extends T
 {
 }
 
 
 // ---------------------------
 
 
 interface A
 {
 public function do(T $t);
 }
 
 interface B extends A
 {
 public function do(S $s);
 }
 COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
  • 106. WRITING SOLID CODE IN PRACTICE <?php
 
 interface T
 {
 }
 
 interface S extends T
 {
 }
 
 
 // ---------------------------
 
 
 interface A
 {
 public function do(T $t);
 }
 
 interface B extends A
 {
 public function do(S $s);
 }
 COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE covariance of method argument
  • 107. WRITING SOLID CODE IN PRACTICE <?php
 
 interface T
 {
 }
 
 interface S extends T
 {
 }
 
 
 // ---------------------------
 
 
 interface A
 {
 public function do(T $t);
 }
 
 interface B extends A
 {
 public function do(S $s);
 }
 COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE covariance of method argument not allowed here, why?
  • 108. WRITING SOLID CODE IN PRACTICE <?php
 
 interface T
 {
 }
 
 interface S extends T
 {
 }
 
 
 // ---------------------------
 
 
 interface A
 {
 public function do(T $t);
 }
 
 interface B extends A
 {
 public function do(S $s);
 }
 COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE covariance of method argument not allowed here, why? … violating A::do signature
 … violating “preconditions cannot be strengthen in subtype”
  • 109. WRITING SOLID CODE IN PRACTICE COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
  • 110. WRITING SOLID CODE IN PRACTICE <?php
 
 interface T
 {
 }
 
 interface S extends T
 {
 }
 
 // ---------------------------
 
 class A
 {
 public function do(): S;
 {
 }
 }
 
 class B extends A
 {
 public function do(): T;
 {
 }
 }
 COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE
  • 111. WRITING SOLID CODE IN PRACTICE <?php
 
 interface T
 {
 }
 
 interface S extends T
 {
 }
 
 // ---------------------------
 
 class A
 {
 public function do(): S;
 {
 }
 }
 
 class B extends A
 {
 public function do(): T;
 {
 }
 }
 COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE contravariance of return type
  • 112. WRITING SOLID CODE IN PRACTICE <?php
 
 interface T
 {
 }
 
 interface S extends T
 {
 }
 
 // ---------------------------
 
 class A
 {
 public function do(): S;
 {
 }
 }
 
 class B extends A
 {
 public function do(): T;
 {
 }
 }
 COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE contravariance of return type not allowed here, why?
  • 113. WRITING SOLID CODE IN PRACTICE <?php
 
 interface T
 {
 }
 
 interface S extends T
 {
 }
 
 // ---------------------------
 
 class A
 {
 public function do(): S;
 {
 }
 }
 
 class B extends A
 {
 public function do(): T;
 {
 }
 }
 COVARIANCE & CONTRAVARIANCE | LSP | PRACTICE contravariance of return type not allowed here, why? … violating A::do signature
 … violating “postconditions cannot be weakened in subtype”
  • 114. WRITING SOLID CODE IN PRACTICE SUMMARY
  • 115. WRITING SOLID CODE IN PRACTICE BEFORE | SUMMARY
  • 116. WRITING SOLID CODE IN PRACTICE AFTER | SUMMARY
  • 117. WRITING SOLID CODE IN PRACTICE BENEFITS OF WRITING SOLID CODE
  • 118. WRITING SOLID CODE IN PRACTICE BENEFITS | SUMMARY
  • 119. WRITING SOLID CODE IN PRACTICE BENEFITS | SUMMARY • code is well organised and more declarative • code is easy to read and understand (short learning curve) • code is loosely coupled and thus reusable • code is easy to adapt • code is easy to extend • code is easy to refactor • code is easy to unit test • code is easy to replace/mock in functional tests • … etc. etc.
  • 120. WRITING SOLID CODE IN PRACTICE Q’N’A Questions?
  • 121. WRITING SOLID CODE IN PRACTICE THANK YOU! docplanner.com/career Join us!