SlideShare ist ein Scribd-Unternehmen logo
1 von 98
Downloaden Sie, um offline zu lesen
SOLID PRINCIPLES
LUCIANO QUEIROZ
DECISIONS
SOLID
PRINCIPLES
Robert Martin aka Uncle Bob
CHANGES
SINGLE RESPONSIBILITY PRINCIPLE
“A CLASS SHOULD HAVE ONE, 

AND ONLY ONE, REASON TO
CHANGE.”
SOLID PRINCIPLES
<?php
class ConfirmationMailMailer
{
private $templating;
private $mailer;
public function __construct(
ITemplatingEngine $templating,
IMailer $mailer
) {
$this->templating = $templating;
$this->mailer = $mailer;
}
public function sendTo(User $user)
{
$message = $this->createMessageFor($user);
$this->sendMessage($message);
}
private function createMessageFor(User $user)
{
$subject = 'Confirm your email address';
$body = $this->templating
->render(
'confirmationMail.html.tpl', [
'confirmationCode' => $user->getConfirmationCode()
]
);
$message = new Message($subject, $body);
$message->setTo($user->getEmailAdress());
return $message;
}
private function sendMessage(IMessage $message)
{
$this->mailer->send($message);
}
SOLID PRINCIPLES
INITIAL SITUATION
ConfirmationMailMailer.php
IMailer.php
usesuses
ITemplatingEngine.php
SOLID PRINCIPLES
RESPONSIBILITIES
▸ Create Confirmation Message
▸ Send Confirmation Message to user
SINGLE RESPONSIBILITY PRINCIPLE
“RESPONSIBILITIES ARE
REASONS TO CHANGE”
SOLID PRINCIPLES
SOLID PRINCIPLES
SINGLE RESPONSIBILITY PRINCIPLE VIOLATIONS
▸ Many instance variables
▸ Many public methods
▸ Each method use variables from other instance
▸ Specific tasks are done by private methods
COLLABORATOR
CLASSES
<?php
class ConfirmationMailFactory
{
private $templating;
public function __construct(ITemplatingEngine $templating)
{
$this->templating = $templating;
}
public function createMessageFor(User $user)
{
$subject = 'Confirm your email address';
$body = $this->templating
->render(
'confirmationMail.html.tpl', [
'confirmationCode' => $user->getConfirmationCode()
]
);
$message = new Message($subject, $body);
$message->setTo($user->getEmailAdress());
return $message;
}
}
<?php
class ConfirmationMailMailer
{
private $confirmationMailFactory;
private $mailer;
public function __construct(
ConfirmationMailFactory $confirmationMailFactory,
IMailer $mailer
) {
$this->confirmationMailFactory = $confirmationMailFactory;
$this->mailer = $mailer;
}
public function sendTo(User $user)
{
$message = $this->confirmationMailFactory->createMessageFor($user);
$this->sendMessage($message);
}
private function sendMessage(IMessage $message)
{
$this->mailer->send($message);
}
}
SOLID PRINCIPLES
REFACTORED
ConfirmationMailMailer.php IMailer.phpuses
ConfirmationMailFactory.php
uses
ITemplatingEngine.phpuses
SOLID PRINCIPLES
SINGLE RESPONSIBILITY PRINCIPLE ADVANTAGES
▸ Smaller classes
▸ Classes easier to understand
▸ Classes easier to test
▸ Classes simpler to maintain
OPEN/CLOSED PRINCIPLE
“YOU SHOULD BE ABLE TO
EXTEND A CLASS`S BEHAVIOR,
WITHOUT MODIFYING IT.”
SOLID PRINCIPLES
<?php
class GenericEncoder
{
public function encodeToFormat($data, $format)
{
if ($format === 'json') {
$encoder = new JsonEncoder();
} elseif ($format === 'xml') {
$encoder = new XmlEncoder();
} else {
throw new InvalidArgumentException('Unknown format');
}
$data = $this->prepareData($data, $format);
return $encoder->encode($data);
}
private function prepareData($data, $format)
{
switch ($format) {
case 'json':
$data = $this->forceArrayKeys($data);
$data = $this->fixKeys($data);
break;
case 'xml':
$data = $this->fixAttributes($data);
break;
default:
throw new InvalidArgumentException(
'Format not supported'
);
}
return $data;
}
}
SOLID PRINCIPLES
INITIAL SITUATION
GenericEncoder.php
XmlEncoder.php
uses
uses
JsonEncoder.php
<?php
class GenericEncoder
{
public function encodeToFormat($data, $format)
{
if (…) {
…
} elseif (…) {
…
} elseif ($format === 'yaml') {
$encoder = new YamlEncoder();
} else {
throw new InvalidArgumentException('Unknown format');
}
}
…
}
SOLID PRINCIPLES
NEW REQUIREMENT SITUATION
GenericEncoder.php
XmlEncoder.php
uses
uses
JsonEncoder.php
YamlEncoder.php
uses
OPEN/CLOSED PRINCIPLE
“A UNIT OF CODE CAN BE
CONSIDERED ‘OPEN’ FOR EXTENSION
WHEN ITS BEHAVIOR CAN BE EASILY
CHANGED WITHOUT MODIFYING IT”
SOLID PRINCIPLES
SOLID PRINCIPLES
OPEN/CLOSED PRINCIPLE VIOLATIONS
▸ Conditions to determine a strategy
▸ Conditions using the same variables or constants are
recurring inside the class or related classes
▸ Contains hard-coded references to other classes or class
names
▸ Objects are being created using the new operator
ABSTRACT
FACTORY
<?php
interface EncoderInterface
{
public function encode($data);
}
class JsonEncoder implements EncoderInterface
{
public function encode($data)
{
// TODO: Implement encode() method.
}
}
class XmlEncoder implements EncoderInterface
{
public function encode($data)
{
// TODO: Implement encode() method.
}
}
class YamlEncoder implements EncoderInterface
{
public function encode($data)
{
// TODO: Implement encode() method.
}
}
SOLID PRINCIPLES
INTRODUCING ENCODER INTERFACE
GenericEncoder.php
XmlEncoder.php
uses
JsonEncoder.phpYamlEncoder.php
implements
EncoderInterface.php
implements
implements
<?php
class EncoderFactory
{
public function createForFormat($format)
{
if ($format === 'json') {
return new JsonEncoder();
} elseif ($format === 'xml') {
return new XmlEncoder();
} elseif ($format === 'yaml') {
return new YamlEncoder();
}
throw new InvalidArgumentException('Unknown format');
}
}
<?php
class GenericEncoder
{
private $encoderFactory;
public function __construct(EncoderFactory $encoderFactory)
{
$this->encoderFactory = $encoderFactory;
}
public function encodeToFormat($data, $format)
{
$encoder = $this->encoderFactory->createForFormat($format);
$data = $this->prepareData($data, $format);
return $encoder->encode($data);
}
}
ABSTRACT FACTORY
OPEN FOR EXTENSION
<?php
interface EncoderFactoryInterface
{
/**
* Create an encoder for the given format
*
* @param string $format
* @return EncoderInterface
*/
public function createForFormat($format)
}
class EncoderFactory implements EncoderFactoryInterface
{
...
}
class GenericEncoder
{
public function __construct(
EncoderFactoryInterface $encoderFactory
) {
...
}
...
}
INTRODUCING DEPENDENCY INVERSION PRINCIPLE
SOLID PRINCIPLES
GenericEncoder.php
XmlEncoder.php
uses
JsonEncoder.phpYamlEncoder.php
implements
EncoderInterface.php
implements
implements
EncoderFactoryInterface.php
uses
creates
<?php
class EncoderFactory implements EncoderFactoryInterface
{
private $factories = [];
/**
* Register a callable that returns an instance of
* EncoderInterface for the given format.
*
* @param string $format
* @param callable $factory
*/
public function addEncoderFactory($format, callable $factory)
{
$this->factories[$format] = $factory;
}
public function createForFormat($format)
{
$factory = $this->factories[$format];
$encoder = $factory;
return $encoder;
}
}
<?php
$encoderFactory = new EncoderFactory();
$encoderFactory->addEncoderFactory(
'xml',
function () {
return new XmlEncoder();
}
);
$encoderFactory->addEncoderFactory(
'json',
function () {
return new JsonEncoder();
}
);
$genericEncoder = new GenericEncoder($encoderFactory);
$data = ...
$jsonEncodedData = $genericEncoder->encode($data, 'json');
<?php
class GenericEncoder
{
private function prepareData($data, $format)
{
switch ($format) {
case 'json':
$data = $this->forceArray($data);
$data = $this->fixKeys($data);
break;
case 'xml':
$data = $this->fixAttributes($data);
break
default:
# code...
break;
}
return $data;
}
}
PORLYMORPHISM
<?php
class GenericEncoder
{
private $encoderFactory;
public function __construct(
EncoderFactoryInterface $encoderFactory
) {
$this->encoderFactory;
}
public function encodeToFormat($data, $format)
{
$encoder = $this->encoderFactory->createForFormat($format);
$data = $encoder->prepareData($data);
return $encoder->encode($data);
}
}
<?php
class JsonEncoder implements EncoderInterface
{
public function encode($data)
{
...
}
public function prepareData($data)
{
$data = $this->forceArray($data);
$data = $this->fixKeys($data);
return $data;
}
}
<?php
class GenericEncoder
{
private $encoderFactory;
public function __construct(
EncoderFactoryInterface $encoderFactory
) {
$this->encoderFactory;
}
public function encodeToFormat($data, $format)
{
$encoder = $this->encoderFactory->createForFormat($format);
$data = $encoder->prepareData($data);
return $encoder->encode($data);
}
}
<?php
class JsonEncoder implements EncoderInterface
{
public function encode($data)
{
$data = $this->prepareData($data);
return json_encode($data);
}
private function prepareData($data)
{
$data = $this->forceArray($data);
$data = $this->fixKeys($data);
return $data;
}
}
<?php
interface EncoderInterface
{
public function encode($data);
}
<?php
class GenericEncoder
{
public function encodeToFormat($data, $format)
{
if ($format === 'json') {
$encoder = new JsonEncoder();
} elseif ($format === 'xml') {
$encoder = new XmlEncoder();
} else {
throw new InvalidArgumentException('Unknown format');
}
$data = $this->prepareData($data, $format);
return $encoder->encode($data);
}
private function prepareData($data, $format)
{
switch ($format) {
case 'json':
$data = $this->forceArrayKeys($data);
$data = $this->fixKeys($data);
break;
case 'xml':
$data = $this->fixAttributes($data);
break;
default:
throw new InvalidArgumentException(
'Format not supported'
);
}
return $data;
}
}
<?php
class GenericEncoder
{
private $encoderFactory;
public function __construct(
EncoderFactoryInterface $encoderFactory
) {
$this->encoderFactory;
}
public function encodeToFormat($data, $format)
{
$encoder = $this->encoderFactory->createForFormat($format);
return $encoder->encode($data);
}
}
LISKOV SUBSTITUTION PRINCIPLE
“DERIVED CLASSES MUST
BE SUBSTITUTABLE FOR
THEIR BASE CLASSES”
SOLID PRINCIPLES
SOLID PRINCIPLES
WE NEED TO UNDERSTAND
▸ Derived classes
▸ Being substitutable
DERIVED
CLASSES
<?php
/**
* A concrete class, all methods are implemented, but can be
* overridden by derived classes
*/
class ConcreteClass
{
public function implementedMethod()
{
}
}
/**
* An abstract class, some methods need to be implemented by
* by derived classes
*/
abstract class AbstractClass
{
abstract public function abstractMethod();
public function implementedMethod()
{
}
}
/**
* An interface, all methods need to be implemented by derived
* classes
*/
interface AnInterface
{
public function abstractMethod();
}
BEING
SUBSTITUTABLE
VIOLATIONS
LISKOV SUBSTITUTION PRINCIPLE
“A DERIVED CLASS DOES NOT
HAVE AN IMPLEMENTATION
FOR ALL METHODS”
SOLID PRINCIPLES
<?php
interface FileInterface
{
public function rename($name);
public function changeOwner($user, $group);
}
<?php
class DropboxFile implements FileInterface
{
public function rename($name)
{
...
}
public function changeOwner($user, $group)
{
throw new BadMethodCallException(
"Not implemented for Dropbox files"
);
}
}
<?php
class DropboxFile implements FileInterface
{
public function rename($name)
{
...
}
public function changeOwner($user, $group)
{
throw new BadMethodCallException(
"Not implemented for Dropbox files"
);
}
}
//ask the user to check if $file is an instance of DropboxFile
if (!($file instanceof DropboxFile)) {
$file->changeOwner(...);
}
<?php
class DropboxFile implements FileInterface
{
...
public function changeOwner($user, $group)
{
//let's do nothing :)
}
}
INTERFACE SEGREGATION PRINCIPLE
“MAKE FINE-GRAINED
INTERFACES THAT ARE
CLIENT SPECIFIC”
SOLID PRINCIPLES
<?php
interface FileInterface
{
public function rename($name);
}
interface FileWithOwnerInterface extends FileInterface
{
public function changeOwner($user, $group);
}
<?php
class DropboxFile implements FileInterface
{
public function rename($name)
{
...
}
}
class LocalFile implements FileWithOwnerInterface
{
public function rename($name)
{
...
}
public function changeOwner($user, $group)
{
...
}
}
SOLID PRINCIPLES
NEW HIERARCHY OF FILE CLASSES
DropboxFile.php
extends
LocalFile.php
implements
FileInterface.php
implements
FileWithOwnerInterface.php
LISKOV SUBSTITUTION PRINCIPLE
“DIFFERENT SUBSTITUTES
RETURN THINGS OF
DIFFERENT TYPES”
SOLID PRINCIPLES
<?php
interface RouterInterface
{
public function getRoutes() : RouterCollection;
}
class SimpleRouter implements RouterInterface
{
public function getRoutes()
{
$routes = [];
//add Route objects to $routes
$routes[] = ...;
return $routes
}
}
class AdvancedRouter implements RouterInterface
{
public function getRoutes()
{
$routeCollection = new RouteCollection();
...
return $routeCollection;
}
}
<?php
interface RouterInterface
{
public function getRoutes() : RouterCollection;
}
class SimpleRouter implements RouterInterface
{
public function getRoutes() : RouteCollection
{
$routes = [];
//add Route objects to $routes2
$routes[] = ...;
return $routes
}
}
class AdvancedRouter implements RouterInterface
{
public function getRoutes() : RouteCollection
{
$routeCollection = new RouteCollection();
...
return $routeCollection;
}
}
LISKOV SUBSTITUTION PRINCIPLE
“A DERIVED CLASS IS LESS
PERMISSIVE WITH REGARD
TO METHOD ARGUMENTS”
SOLID PRINCIPLES
<?php
interface MassMailerInterface
{
public function sendMail(
TransportInterface $transport,
MessageInterface $message,
RecipientsInterface $recipients
);
}
<?php
class SmtpMassMailer implements MassMailerInterface
{
public function sendMail(
TransportInterface $transport,
MessageInterface $message,
RecipientsInterface $recipients
) {
if (!($transport instanceof SmtpTransport)) {
throw new InvalidArgumentException(
'SmtpMassMailer only works with SMTP'
);
}
}
}
LISKOV SUBSTITUTION PRINCIPLE
“NOT EVERY KIND OF MAIL
TRANSPORT IS SUITABLE
FOR MASS MAILING”
SOLID PRINCIPLES
SOLID PRINCIPLES
NEW CLASS DIAGRAM
SmtpTransport.php
TransportInterface.php
extends
TransportWithMassMailSupportInterface.php
implements
<?php
interface MassMailerInterface
{
public function sendMail(
TransportWithMassMailSupportInterface $transport,
MessageInterface $message,
RecipientsInterface $recipients
);
}
<?php
class SmtpMassMailer implements MassMailerInterface
{
public function sendMail(
TransportWithMassMailSupportInterface $transport,
MessageInterface $message,
RecipientsInterface $recipients
) {
…
}
}
SOLID PRINCIPLES
A GOOD SUBSTITUTE
▸ Provides an implementation for all the methods of the
base class.
▸ Returns the type of things the base class prescribes.
▸ Doesn’t put extra constraints on arguments for methods.
INTERFACE SEGREGATION PRINCIPLE
“MAKE FINE-GRAINED
INTERFACES THAT ARE
CLIENT SPECIFIC”
SOLID PRINCIPLES
DEPENDENCY INVERSION PRINCIPLE
“DEPEND ON ABSTRACTIONS,
NOT CONCRETIONS”
SOLID PRINCIPLES
SOLID PRINCIPLES
FIZZ BUZZ ASSIGNMENT
▸ Generate a list of integers, from 1 to n.
▸ Numbers that are divisible by 3 should be replace with
“Fizz”
▸ Numbers that are divisible by 5 should be replaced with
“Buzz”
▸ Numbers that are both divisible by 3 and by 5 should be
replaced with “FizzBuzz”
<?php
class FizzBuzz
{
public static function generateList($limit)
{
$list = [];
for ($number = 1; $number <= $limit; $number++) {
$list[] = self::generateElement($number);
}
return $list;
}
private static function generateElement($number)
{
if ($number % 3 === 0 && $number % 5 === 0) {
return 'FizzBuzz';
}
if ($number % 3 === 0) {
return 'Fizz';
}
if ($number % 5 === 0) {
return 'Buzz';
}
return $number;
}
}
SOLID PRINCIPLES
THEN…
▸ It should be possible to add another rule, without
modifying the FizzBuzz class.
MAKING FIZZBUZZ
OPEN FOR EXTENSION
<?php
class FizzBuzz
{
public static function generateList($limit)
{
...
}
private static function generateElement($number)
{
$fizzBuzzRule = new FizzBuzzRule();
if ($fizzBuzzRule->matches($number)) {
return $fizzBuzzRule->getReplacement();
}
$fizzRule = new FizzRule();
if ($fizzRule->matches($number)) {
return $fizzRule->getReplacement();
}
$buzzRule = new BuzzRule();
if ($buzzRule->matches($number)) {
return $buzzRule->getReplacement();
}
return $number;
}
}
<?php
interface RuleInterface
{
public function matches($number);
public function getReplacement();
}
<?php
class FizzBuzz
{
private $rules = [];
public function addRule(RuleInterface $rule) {
$this->rules[] = $rule;
}
public static function generateList($limit)
{
...
}
private static function generateElement($number)
{
foreach ($this->rules as $rule) {
if ($rule->matches($number)) {
return $rule->getReplacement();
}
}
return $number;
}
}
<?php
class FizzBuzzRule implements RuleInterface
{
...
}
class FizzRule implements RuleInterface
{
...
}
class BuzzRule implements RuleInterface
{
...
}
<?php
$fizzBuzz = new FizzBuzz();
$fizzBuzz->addRule(new FizzBuzzRule());
$fizzBuzz->addRule(new FizzRule());
$fizzBuzz->addRule(new BuzzRule());
...
$list = $fizzBuzz->generateList(100);
SOLID PRINCIPLES
HAVING CONCRETE DEPENDENCIES
FizzBuzz.php
FizzRule.php
BuzzRule.php
FizzBuzzRule.php
SOLID PRINCIPLES
HAVING ABSTRACT DEPENDENCIES
FizzBuzz.php RuleInterface.php
BuzzRule.phpFizzBuzzRule.php FizzRule.php
DEPENDENCY INVERSION PRINCIPLE VIOLATION
“MIXING DIFFERENT
LEVELS OF ABSTRACTION”
SOLID PRINCIPLES
<?php
use DoctrineDBALConnection;
class Authentication
{
private $connection;
public function __construct(Connection $connection)
{
$this->connection = $connection;
}
public function checkCredentials($username, $password)
{
$user = $this->connection->fetchAssoc(
'SELECT * FROM users WHERE username = ?',
[$username]
);
if ($user === null) {
throw new InvalidCredentialsException(
"User not found."
);
}
//validate password
...
}
}
SOLID PRINCIPLES
AUTHENTICATION CLASS DEPENDS ON CONNECTION
Authentication.php Connection.php
<?php
class Authentication
{
private $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function checkCredentials($username, $password)
{
$user = $this->userRepository->ofUsername($username);
if ($user === null) {
throw new InvalidCredentialsException(
"User not found."
);
}
//validate password
...
}
}
<?php
class UserRepository
{
private $connection;
public function __construct(Connection $connection)
{
$this->connection = $connection;
}
public function ofUsername($username)
{
return $this->connection->fetchAssoc(
'SELECT * FROM users WHERE username = ?',
[$username]
);
}
}
SOLID PRINCIPLES
AUTHENTICATION CLASS DEPENDS ON USER REPOSITORY
Authentication.php UserRepository.php Connection.php
<?php
interface UserRepositoryInterface
{
public function ofUsername($username);
}
<?php
class DoctrineDbalUserRepository implements UserRepositoryInterface
{
...
}
class TextFileUserRepository implements UserRepositoryInterface
{
...
}
class InMemoryUserRepository implements UserRepositoryInterface
{
...
}
class MongoDbUserRepository implements UserRepositoryInterface
{
...
}
<?php
class Authentication
{
private $userRepository;
public function __construct(UserRepositoryInterface $userRepository)
{
$this->userRepository = $userRepository;
}
}
SOLID PRINCIPLES
AUTHENTICATION CLASS DEPENDS ON USER REPOSITORY INTERFACE
Authentication.php UserRepositoryInterface.php
TextFileUserRepository.php DoctrineDbalUserRepository.php Connection.php

Weitere ähnliche Inhalte

Was ist angesagt?

Functional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis AtencioFunctional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis AtencioLuis Atencio
 
Refactoring and code smells
Refactoring and code smellsRefactoring and code smells
Refactoring and code smellsPaul Nguyen
 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...Philip Schwarz
 
The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)Scott Wlaschin
 
Python Advanced – Building on the foundation
Python Advanced – Building on the foundationPython Advanced – Building on the foundation
Python Advanced – Building on the foundationKevlin Henney
 
C# conventions & good practices
C# conventions & good practicesC# conventions & good practices
C# conventions & good practicesTan Tran
 
Refactoring Tips by Martin Fowler
Refactoring Tips by Martin FowlerRefactoring Tips by Martin Fowler
Refactoring Tips by Martin FowlerIgor Crvenov
 
Coder sans peur du changement avec la meme pas mal hexagonal architecture
Coder sans peur du changement avec la meme pas mal hexagonal architectureCoder sans peur du changement avec la meme pas mal hexagonal architecture
Coder sans peur du changement avec la meme pas mal hexagonal architectureThomas Pierrain
 
NestJS - O framework progressivo
NestJS - O framework progressivoNestJS - O framework progressivo
NestJS - O framework progressivoWender Machado
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix itRafael Dohms
 
Mysql creating stored function
Mysql  creating stored function Mysql  creating stored function
Mysql creating stored function Prof.Nilesh Magar
 
OO Design and Design Patterns in C++
OO Design and Design Patterns in C++ OO Design and Design Patterns in C++
OO Design and Design Patterns in C++ Ganesh Samarthyam
 
Clean Code I - Best Practices
Clean Code I - Best PracticesClean Code I - Best Practices
Clean Code I - Best PracticesTheo Jungeblut
 

Was ist angesagt? (20)

Functional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis AtencioFunctional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis Atencio
 
Clean code slide
Clean code slideClean code slide
Clean code slide
 
Refactoring and code smells
Refactoring and code smellsRefactoring and code smells
Refactoring and code smells
 
Solid principles
Solid principlesSolid principles
Solid principles
 
Spring Data JPA
Spring Data JPASpring Data JPA
Spring Data JPA
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
 
The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)
 
Clean code
Clean codeClean code
Clean code
 
Python Advanced – Building on the foundation
Python Advanced – Building on the foundationPython Advanced – Building on the foundation
Python Advanced – Building on the foundation
 
C# conventions & good practices
C# conventions & good practicesC# conventions & good practices
C# conventions & good practices
 
Clean code
Clean codeClean code
Clean code
 
Refactoring Tips by Martin Fowler
Refactoring Tips by Martin FowlerRefactoring Tips by Martin Fowler
Refactoring Tips by Martin Fowler
 
Coder sans peur du changement avec la meme pas mal hexagonal architecture
Coder sans peur du changement avec la meme pas mal hexagonal architectureCoder sans peur du changement avec la meme pas mal hexagonal architecture
Coder sans peur du changement avec la meme pas mal hexagonal architecture
 
Clean code
Clean codeClean code
Clean code
 
NestJS - O framework progressivo
NestJS - O framework progressivoNestJS - O framework progressivo
NestJS - O framework progressivo
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix it
 
Mysql creating stored function
Mysql  creating stored function Mysql  creating stored function
Mysql creating stored function
 
OO Design and Design Patterns in C++
OO Design and Design Patterns in C++ OO Design and Design Patterns in C++
OO Design and Design Patterns in C++
 
Clean Code I - Best Practices
Clean Code I - Best PracticesClean Code I - Best Practices
Clean Code I - Best Practices
 

Andere mochten auch

Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID PrinciplesRefactoring Applications using SOLID Principles
Refactoring Applications using SOLID PrinciplesSteven Smith
 
SOLID Design Principles
SOLID Design PrinciplesSOLID Design Principles
SOLID Design PrinciplesAndreas Enbohm
 
The SOLID Principles Illustrated by Design Patterns
The SOLID Principles Illustrated by Design PatternsThe SOLID Principles Illustrated by Design Patterns
The SOLID Principles Illustrated by Design PatternsHayim Makabee
 
SOLID design principles in Ruby
SOLID design principles in RubySOLID design principles in Ruby
SOLID design principles in RubyAnil Wadghule
 
Geecon09: SOLID Design Principles
Geecon09: SOLID Design PrinciplesGeecon09: SOLID Design Principles
Geecon09: SOLID Design PrinciplesBruno Bossola
 
Do we need SOLID principles during software development?
Do we need SOLID principles during software development?Do we need SOLID principles during software development?
Do we need SOLID principles during software development?Anna Shymchenko
 
Ada Lovelace - Candidata ao Oscar das Mulheres de TI!
Ada Lovelace - Candidata ao Oscar das Mulheres de TI!Ada Lovelace - Candidata ao Oscar das Mulheres de TI!
Ada Lovelace - Candidata ao Oscar das Mulheres de TI!Women Techmakers Sorocaba
 
Refactoring to SOLID Code
Refactoring to SOLID CodeRefactoring to SOLID Code
Refactoring to SOLID CodeAdil Mughal
 
Mulheres na TI: o que mudou?
Mulheres na TI: o que mudou?Mulheres na TI: o que mudou?
Mulheres na TI: o que mudou?bacastro
 
A Checklist for Design Reviews
A Checklist for Design ReviewsA Checklist for Design Reviews
A Checklist for Design ReviewsTushar Sharma
 
Applying Design Principles in Practice
Applying Design Principles in PracticeApplying Design Principles in Practice
Applying Design Principles in PracticeTushar Sharma
 

Andere mochten auch (20)

Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID PrinciplesRefactoring Applications using SOLID Principles
Refactoring Applications using SOLID Principles
 
Solid principles
Solid principlesSolid principles
Solid principles
 
SOLID Design Principles
SOLID Design PrinciplesSOLID Design Principles
SOLID Design Principles
 
The SOLID Principles Illustrated by Design Patterns
The SOLID Principles Illustrated by Design PatternsThe SOLID Principles Illustrated by Design Patterns
The SOLID Principles Illustrated by Design Patterns
 
Solid principles
Solid principlesSolid principles
Solid principles
 
SOLID principles
SOLID principlesSOLID principles
SOLID principles
 
NoSQL and CouchDB
NoSQL and CouchDBNoSQL and CouchDB
NoSQL and CouchDB
 
Relax, it's spa time
Relax, it's spa timeRelax, it's spa time
Relax, it's spa time
 
SOLID design principles in Ruby
SOLID design principles in RubySOLID design principles in Ruby
SOLID design principles in Ruby
 
Geecon09: SOLID Design Principles
Geecon09: SOLID Design PrinciplesGeecon09: SOLID Design Principles
Geecon09: SOLID Design Principles
 
SOLID principles
SOLID principlesSOLID principles
SOLID principles
 
Do we need SOLID principles during software development?
Do we need SOLID principles during software development?Do we need SOLID principles during software development?
Do we need SOLID principles during software development?
 
SOLID Design principles
SOLID Design principlesSOLID Design principles
SOLID Design principles
 
Ada Lovelace - Candidata ao Oscar das Mulheres de TI!
Ada Lovelace - Candidata ao Oscar das Mulheres de TI!Ada Lovelace - Candidata ao Oscar das Mulheres de TI!
Ada Lovelace - Candidata ao Oscar das Mulheres de TI!
 
Refactoring to SOLID Code
Refactoring to SOLID CodeRefactoring to SOLID Code
Refactoring to SOLID Code
 
Mulheres na TI - Rails Girls SP 2015
Mulheres na TI - Rails Girls SP 2015Mulheres na TI - Rails Girls SP 2015
Mulheres na TI - Rails Girls SP 2015
 
Mulheres na TI: o que mudou?
Mulheres na TI: o que mudou?Mulheres na TI: o que mudou?
Mulheres na TI: o que mudou?
 
A Checklist for Design Reviews
A Checklist for Design ReviewsA Checklist for Design Reviews
A Checklist for Design Reviews
 
Applying Design Principles in Practice
Applying Design Principles in PracticeApplying Design Principles in Practice
Applying Design Principles in Practice
 
SOLID Principles part 1
SOLID Principles part 1SOLID Principles part 1
SOLID Principles part 1
 

Ähnlich wie SOLID PRINCIPLES

Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using CodeceptionJeroen van Dijk
 
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceMeet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceIvan Chepurnyi
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Leonardo Proietti
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsSam Hennessy
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolveXSolve
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersKacper Gunia
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConRafael Dohms
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in actionJace Ju
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11Michelangelo van Dam
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologyDaniel Knell
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxMichelangelo van Dam
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful softwareJorn Oomen
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hackingJeroen van Dijk
 
PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2eugenio pombi
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosDivante
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf Conference
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteLeonardo Proietti
 

Ähnlich wie SOLID PRINCIPLES (20)

Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using Codeception
 
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceMeet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 
PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
 

Kürzlich hochgeladen

%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...masabamasaba
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...SelfMade bd
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...masabamasaba
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...masabamasaba
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...masabamasaba
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile EnvironmentVictorSzoltysek
 
tonesoftg
tonesoftgtonesoftg
tonesoftglanshi9
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastPapp Krisztián
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesVictorSzoltysek
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Bert Jan Schrijver
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024VictoriaMetrics
 

Kürzlich hochgeladen (20)

%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 

SOLID PRINCIPLES

  • 2.
  • 4.
  • 7.
  • 8.
  • 9. SINGLE RESPONSIBILITY PRINCIPLE “A CLASS SHOULD HAVE ONE, 
 AND ONLY ONE, REASON TO CHANGE.” SOLID PRINCIPLES
  • 10. <?php class ConfirmationMailMailer { private $templating; private $mailer; public function __construct( ITemplatingEngine $templating, IMailer $mailer ) { $this->templating = $templating; $this->mailer = $mailer; } public function sendTo(User $user) { $message = $this->createMessageFor($user); $this->sendMessage($message); } private function createMessageFor(User $user) { $subject = 'Confirm your email address'; $body = $this->templating ->render( 'confirmationMail.html.tpl', [ 'confirmationCode' => $user->getConfirmationCode() ] ); $message = new Message($subject, $body); $message->setTo($user->getEmailAdress()); return $message; } private function sendMessage(IMessage $message) { $this->mailer->send($message); }
  • 12. SOLID PRINCIPLES RESPONSIBILITIES ▸ Create Confirmation Message ▸ Send Confirmation Message to user
  • 13. SINGLE RESPONSIBILITY PRINCIPLE “RESPONSIBILITIES ARE REASONS TO CHANGE” SOLID PRINCIPLES
  • 14. SOLID PRINCIPLES SINGLE RESPONSIBILITY PRINCIPLE VIOLATIONS ▸ Many instance variables ▸ Many public methods ▸ Each method use variables from other instance ▸ Specific tasks are done by private methods
  • 16. <?php class ConfirmationMailFactory { private $templating; public function __construct(ITemplatingEngine $templating) { $this->templating = $templating; } public function createMessageFor(User $user) { $subject = 'Confirm your email address'; $body = $this->templating ->render( 'confirmationMail.html.tpl', [ 'confirmationCode' => $user->getConfirmationCode() ] ); $message = new Message($subject, $body); $message->setTo($user->getEmailAdress()); return $message; } }
  • 17. <?php class ConfirmationMailMailer { private $confirmationMailFactory; private $mailer; public function __construct( ConfirmationMailFactory $confirmationMailFactory, IMailer $mailer ) { $this->confirmationMailFactory = $confirmationMailFactory; $this->mailer = $mailer; } public function sendTo(User $user) { $message = $this->confirmationMailFactory->createMessageFor($user); $this->sendMessage($message); } private function sendMessage(IMessage $message) { $this->mailer->send($message); } }
  • 19. SOLID PRINCIPLES SINGLE RESPONSIBILITY PRINCIPLE ADVANTAGES ▸ Smaller classes ▸ Classes easier to understand ▸ Classes easier to test ▸ Classes simpler to maintain
  • 20. OPEN/CLOSED PRINCIPLE “YOU SHOULD BE ABLE TO EXTEND A CLASS`S BEHAVIOR, WITHOUT MODIFYING IT.” SOLID PRINCIPLES
  • 21. <?php class GenericEncoder { public function encodeToFormat($data, $format) { if ($format === 'json') { $encoder = new JsonEncoder(); } elseif ($format === 'xml') { $encoder = new XmlEncoder(); } else { throw new InvalidArgumentException('Unknown format'); } $data = $this->prepareData($data, $format); return $encoder->encode($data); } private function prepareData($data, $format) { switch ($format) { case 'json': $data = $this->forceArrayKeys($data); $data = $this->fixKeys($data); break; case 'xml': $data = $this->fixAttributes($data); break; default: throw new InvalidArgumentException( 'Format not supported' ); } return $data; } }
  • 23. <?php class GenericEncoder { public function encodeToFormat($data, $format) { if (…) { … } elseif (…) { … } elseif ($format === 'yaml') { $encoder = new YamlEncoder(); } else { throw new InvalidArgumentException('Unknown format'); } } … }
  • 24. SOLID PRINCIPLES NEW REQUIREMENT SITUATION GenericEncoder.php XmlEncoder.php uses uses JsonEncoder.php YamlEncoder.php uses
  • 25. OPEN/CLOSED PRINCIPLE “A UNIT OF CODE CAN BE CONSIDERED ‘OPEN’ FOR EXTENSION WHEN ITS BEHAVIOR CAN BE EASILY CHANGED WITHOUT MODIFYING IT” SOLID PRINCIPLES
  • 26. SOLID PRINCIPLES OPEN/CLOSED PRINCIPLE VIOLATIONS ▸ Conditions to determine a strategy ▸ Conditions using the same variables or constants are recurring inside the class or related classes ▸ Contains hard-coded references to other classes or class names ▸ Objects are being created using the new operator
  • 28. <?php interface EncoderInterface { public function encode($data); } class JsonEncoder implements EncoderInterface { public function encode($data) { // TODO: Implement encode() method. } } class XmlEncoder implements EncoderInterface { public function encode($data) { // TODO: Implement encode() method. } } class YamlEncoder implements EncoderInterface { public function encode($data) { // TODO: Implement encode() method. } }
  • 29. SOLID PRINCIPLES INTRODUCING ENCODER INTERFACE GenericEncoder.php XmlEncoder.php uses JsonEncoder.phpYamlEncoder.php implements EncoderInterface.php implements implements
  • 30. <?php class EncoderFactory { public function createForFormat($format) { if ($format === 'json') { return new JsonEncoder(); } elseif ($format === 'xml') { return new XmlEncoder(); } elseif ($format === 'yaml') { return new YamlEncoder(); } throw new InvalidArgumentException('Unknown format'); } }
  • 31. <?php class GenericEncoder { private $encoderFactory; public function __construct(EncoderFactory $encoderFactory) { $this->encoderFactory = $encoderFactory; } public function encodeToFormat($data, $format) { $encoder = $this->encoderFactory->createForFormat($format); $data = $this->prepareData($data, $format); return $encoder->encode($data); } }
  • 33.
  • 34. <?php interface EncoderFactoryInterface { /** * Create an encoder for the given format * * @param string $format * @return EncoderInterface */ public function createForFormat($format) } class EncoderFactory implements EncoderFactoryInterface { ... } class GenericEncoder { public function __construct( EncoderFactoryInterface $encoderFactory ) { ... } ... }
  • 35. INTRODUCING DEPENDENCY INVERSION PRINCIPLE SOLID PRINCIPLES GenericEncoder.php XmlEncoder.php uses JsonEncoder.phpYamlEncoder.php implements EncoderInterface.php implements implements EncoderFactoryInterface.php uses creates
  • 36. <?php class EncoderFactory implements EncoderFactoryInterface { private $factories = []; /** * Register a callable that returns an instance of * EncoderInterface for the given format. * * @param string $format * @param callable $factory */ public function addEncoderFactory($format, callable $factory) { $this->factories[$format] = $factory; } public function createForFormat($format) { $factory = $this->factories[$format]; $encoder = $factory; return $encoder; } }
  • 37. <?php $encoderFactory = new EncoderFactory(); $encoderFactory->addEncoderFactory( 'xml', function () { return new XmlEncoder(); } ); $encoderFactory->addEncoderFactory( 'json', function () { return new JsonEncoder(); } ); $genericEncoder = new GenericEncoder($encoderFactory); $data = ... $jsonEncodedData = $genericEncoder->encode($data, 'json');
  • 38. <?php class GenericEncoder { private function prepareData($data, $format) { switch ($format) { case 'json': $data = $this->forceArray($data); $data = $this->fixKeys($data); break; case 'xml': $data = $this->fixAttributes($data); break default: # code... break; } return $data; } }
  • 40. <?php class GenericEncoder { private $encoderFactory; public function __construct( EncoderFactoryInterface $encoderFactory ) { $this->encoderFactory; } public function encodeToFormat($data, $format) { $encoder = $this->encoderFactory->createForFormat($format); $data = $encoder->prepareData($data); return $encoder->encode($data); } }
  • 41. <?php class JsonEncoder implements EncoderInterface { public function encode($data) { ... } public function prepareData($data) { $data = $this->forceArray($data); $data = $this->fixKeys($data); return $data; } }
  • 42. <?php class GenericEncoder { private $encoderFactory; public function __construct( EncoderFactoryInterface $encoderFactory ) { $this->encoderFactory; } public function encodeToFormat($data, $format) { $encoder = $this->encoderFactory->createForFormat($format); $data = $encoder->prepareData($data); return $encoder->encode($data); } }
  • 43. <?php class JsonEncoder implements EncoderInterface { public function encode($data) { $data = $this->prepareData($data); return json_encode($data); } private function prepareData($data) { $data = $this->forceArray($data); $data = $this->fixKeys($data); return $data; } }
  • 45. <?php class GenericEncoder { public function encodeToFormat($data, $format) { if ($format === 'json') { $encoder = new JsonEncoder(); } elseif ($format === 'xml') { $encoder = new XmlEncoder(); } else { throw new InvalidArgumentException('Unknown format'); } $data = $this->prepareData($data, $format); return $encoder->encode($data); } private function prepareData($data, $format) { switch ($format) { case 'json': $data = $this->forceArrayKeys($data); $data = $this->fixKeys($data); break; case 'xml': $data = $this->fixAttributes($data); break; default: throw new InvalidArgumentException( 'Format not supported' ); } return $data; } }
  • 46. <?php class GenericEncoder { private $encoderFactory; public function __construct( EncoderFactoryInterface $encoderFactory ) { $this->encoderFactory; } public function encodeToFormat($data, $format) { $encoder = $this->encoderFactory->createForFormat($format); return $encoder->encode($data); } }
  • 47.
  • 48. LISKOV SUBSTITUTION PRINCIPLE “DERIVED CLASSES MUST BE SUBSTITUTABLE FOR THEIR BASE CLASSES” SOLID PRINCIPLES
  • 49. SOLID PRINCIPLES WE NEED TO UNDERSTAND ▸ Derived classes ▸ Being substitutable
  • 51. <?php /** * A concrete class, all methods are implemented, but can be * overridden by derived classes */ class ConcreteClass { public function implementedMethod() { } } /** * An abstract class, some methods need to be implemented by * by derived classes */ abstract class AbstractClass { abstract public function abstractMethod(); public function implementedMethod() { } } /** * An interface, all methods need to be implemented by derived * classes */ interface AnInterface { public function abstractMethod(); }
  • 54. LISKOV SUBSTITUTION PRINCIPLE “A DERIVED CLASS DOES NOT HAVE AN IMPLEMENTATION FOR ALL METHODS” SOLID PRINCIPLES
  • 55. <?php interface FileInterface { public function rename($name); public function changeOwner($user, $group); }
  • 56. <?php class DropboxFile implements FileInterface { public function rename($name) { ... } public function changeOwner($user, $group) { throw new BadMethodCallException( "Not implemented for Dropbox files" ); } }
  • 57. <?php class DropboxFile implements FileInterface { public function rename($name) { ... } public function changeOwner($user, $group) { throw new BadMethodCallException( "Not implemented for Dropbox files" ); } } //ask the user to check if $file is an instance of DropboxFile if (!($file instanceof DropboxFile)) { $file->changeOwner(...); }
  • 58. <?php class DropboxFile implements FileInterface { ... public function changeOwner($user, $group) { //let's do nothing :) } }
  • 59.
  • 60. INTERFACE SEGREGATION PRINCIPLE “MAKE FINE-GRAINED INTERFACES THAT ARE CLIENT SPECIFIC” SOLID PRINCIPLES
  • 61. <?php interface FileInterface { public function rename($name); } interface FileWithOwnerInterface extends FileInterface { public function changeOwner($user, $group); }
  • 62. <?php class DropboxFile implements FileInterface { public function rename($name) { ... } } class LocalFile implements FileWithOwnerInterface { public function rename($name) { ... } public function changeOwner($user, $group) { ... } }
  • 63. SOLID PRINCIPLES NEW HIERARCHY OF FILE CLASSES DropboxFile.php extends LocalFile.php implements FileInterface.php implements FileWithOwnerInterface.php
  • 64. LISKOV SUBSTITUTION PRINCIPLE “DIFFERENT SUBSTITUTES RETURN THINGS OF DIFFERENT TYPES” SOLID PRINCIPLES
  • 65.
  • 66. <?php interface RouterInterface { public function getRoutes() : RouterCollection; } class SimpleRouter implements RouterInterface { public function getRoutes() { $routes = []; //add Route objects to $routes $routes[] = ...; return $routes } } class AdvancedRouter implements RouterInterface { public function getRoutes() { $routeCollection = new RouteCollection(); ... return $routeCollection; } }
  • 67. <?php interface RouterInterface { public function getRoutes() : RouterCollection; } class SimpleRouter implements RouterInterface { public function getRoutes() : RouteCollection { $routes = []; //add Route objects to $routes2 $routes[] = ...; return $routes } } class AdvancedRouter implements RouterInterface { public function getRoutes() : RouteCollection { $routeCollection = new RouteCollection(); ... return $routeCollection; } }
  • 68. LISKOV SUBSTITUTION PRINCIPLE “A DERIVED CLASS IS LESS PERMISSIVE WITH REGARD TO METHOD ARGUMENTS” SOLID PRINCIPLES
  • 69. <?php interface MassMailerInterface { public function sendMail( TransportInterface $transport, MessageInterface $message, RecipientsInterface $recipients ); }
  • 70. <?php class SmtpMassMailer implements MassMailerInterface { public function sendMail( TransportInterface $transport, MessageInterface $message, RecipientsInterface $recipients ) { if (!($transport instanceof SmtpTransport)) { throw new InvalidArgumentException( 'SmtpMassMailer only works with SMTP' ); } } }
  • 71. LISKOV SUBSTITUTION PRINCIPLE “NOT EVERY KIND OF MAIL TRANSPORT IS SUITABLE FOR MASS MAILING” SOLID PRINCIPLES
  • 72. SOLID PRINCIPLES NEW CLASS DIAGRAM SmtpTransport.php TransportInterface.php extends TransportWithMassMailSupportInterface.php implements
  • 73. <?php interface MassMailerInterface { public function sendMail( TransportWithMassMailSupportInterface $transport, MessageInterface $message, RecipientsInterface $recipients ); }
  • 74. <?php class SmtpMassMailer implements MassMailerInterface { public function sendMail( TransportWithMassMailSupportInterface $transport, MessageInterface $message, RecipientsInterface $recipients ) { … } }
  • 75. SOLID PRINCIPLES A GOOD SUBSTITUTE ▸ Provides an implementation for all the methods of the base class. ▸ Returns the type of things the base class prescribes. ▸ Doesn’t put extra constraints on arguments for methods.
  • 76. INTERFACE SEGREGATION PRINCIPLE “MAKE FINE-GRAINED INTERFACES THAT ARE CLIENT SPECIFIC” SOLID PRINCIPLES
  • 77. DEPENDENCY INVERSION PRINCIPLE “DEPEND ON ABSTRACTIONS, NOT CONCRETIONS” SOLID PRINCIPLES
  • 78. SOLID PRINCIPLES FIZZ BUZZ ASSIGNMENT ▸ Generate a list of integers, from 1 to n. ▸ Numbers that are divisible by 3 should be replace with “Fizz” ▸ Numbers that are divisible by 5 should be replaced with “Buzz” ▸ Numbers that are both divisible by 3 and by 5 should be replaced with “FizzBuzz”
  • 79. <?php class FizzBuzz { public static function generateList($limit) { $list = []; for ($number = 1; $number <= $limit; $number++) { $list[] = self::generateElement($number); } return $list; } private static function generateElement($number) { if ($number % 3 === 0 && $number % 5 === 0) { return 'FizzBuzz'; } if ($number % 3 === 0) { return 'Fizz'; } if ($number % 5 === 0) { return 'Buzz'; } return $number; } }
  • 80. SOLID PRINCIPLES THEN… ▸ It should be possible to add another rule, without modifying the FizzBuzz class.
  • 82. <?php class FizzBuzz { public static function generateList($limit) { ... } private static function generateElement($number) { $fizzBuzzRule = new FizzBuzzRule(); if ($fizzBuzzRule->matches($number)) { return $fizzBuzzRule->getReplacement(); } $fizzRule = new FizzRule(); if ($fizzRule->matches($number)) { return $fizzRule->getReplacement(); } $buzzRule = new BuzzRule(); if ($buzzRule->matches($number)) { return $buzzRule->getReplacement(); } return $number; } }
  • 83. <?php interface RuleInterface { public function matches($number); public function getReplacement(); }
  • 84. <?php class FizzBuzz { private $rules = []; public function addRule(RuleInterface $rule) { $this->rules[] = $rule; } public static function generateList($limit) { ... } private static function generateElement($number) { foreach ($this->rules as $rule) { if ($rule->matches($number)) { return $rule->getReplacement(); } } return $number; } }
  • 85. <?php class FizzBuzzRule implements RuleInterface { ... } class FizzRule implements RuleInterface { ... } class BuzzRule implements RuleInterface { ... }
  • 86. <?php $fizzBuzz = new FizzBuzz(); $fizzBuzz->addRule(new FizzBuzzRule()); $fizzBuzz->addRule(new FizzRule()); $fizzBuzz->addRule(new BuzzRule()); ... $list = $fizzBuzz->generateList(100);
  • 87. SOLID PRINCIPLES HAVING CONCRETE DEPENDENCIES FizzBuzz.php FizzRule.php BuzzRule.php FizzBuzzRule.php
  • 88. SOLID PRINCIPLES HAVING ABSTRACT DEPENDENCIES FizzBuzz.php RuleInterface.php BuzzRule.phpFizzBuzzRule.php FizzRule.php
  • 89. DEPENDENCY INVERSION PRINCIPLE VIOLATION “MIXING DIFFERENT LEVELS OF ABSTRACTION” SOLID PRINCIPLES
  • 90. <?php use DoctrineDBALConnection; class Authentication { private $connection; public function __construct(Connection $connection) { $this->connection = $connection; } public function checkCredentials($username, $password) { $user = $this->connection->fetchAssoc( 'SELECT * FROM users WHERE username = ?', [$username] ); if ($user === null) { throw new InvalidCredentialsException( "User not found." ); } //validate password ... } }
  • 91. SOLID PRINCIPLES AUTHENTICATION CLASS DEPENDS ON CONNECTION Authentication.php Connection.php
  • 92. <?php class Authentication { private $userRepository; public function __construct(UserRepository $userRepository) { $this->userRepository = $userRepository; } public function checkCredentials($username, $password) { $user = $this->userRepository->ofUsername($username); if ($user === null) { throw new InvalidCredentialsException( "User not found." ); } //validate password ... } }
  • 93. <?php class UserRepository { private $connection; public function __construct(Connection $connection) { $this->connection = $connection; } public function ofUsername($username) { return $this->connection->fetchAssoc( 'SELECT * FROM users WHERE username = ?', [$username] ); } }
  • 94. SOLID PRINCIPLES AUTHENTICATION CLASS DEPENDS ON USER REPOSITORY Authentication.php UserRepository.php Connection.php
  • 96. <?php class DoctrineDbalUserRepository implements UserRepositoryInterface { ... } class TextFileUserRepository implements UserRepositoryInterface { ... } class InMemoryUserRepository implements UserRepositoryInterface { ... } class MongoDbUserRepository implements UserRepositoryInterface { ... }
  • 97. <?php class Authentication { private $userRepository; public function __construct(UserRepositoryInterface $userRepository) { $this->userRepository = $userRepository; } }
  • 98. SOLID PRINCIPLES AUTHENTICATION CLASS DEPENDS ON USER REPOSITORY INTERFACE Authentication.php UserRepositoryInterface.php TextFileUserRepository.php DoctrineDbalUserRepository.php Connection.php