24. Single responsibility principle
● Bad code example:
<?php
class InsurancePDFCreator {
// … some code
public function createPDFContents(Policy $policy);
public function downloadInsuranceCompanyLogos();
}
25. Single responsibility principle
● Good code example:
<?php
class InsurancePDFCreator {
// … some code
public function createPDFContents(Policy $policy);
}
// somewhere else
class InsuranceCompanyLogosDownloader {
public function download();
}
26. Conclusion
● Define your desired contexts carefully
● Make sure that there is only one responsibility for a
operation, class, method, module, etc.
● If you need to have a more abstract operations that
combine several stuff, find for them more abstract
names.
● And... Single Responsibility Principle is not
enough
30. Interface Segregation Principle
● Imagine this code:
<?php
class UsersManager {
public function createUser($username, $email);
public function deleteUserPicture($userId);
public function notifyUser($userId, $msg);
}
31. Interface Segregation Principle
It's bad because:
● It's provides a general-purpose interface
● When you include this class, you usually call one of
those methods
32. Interface Segregation Principle
The good way to do it:
● Use a set of client-specific classes (interfaces)
instead of one general-purpose interface
● Be more specific in your context
34. Conclusion
● Is extension to the Single Responsibility Principle
● Favored usage of client-specific interfaces, rather
then one general-purpose (mothership) interface
37. Open-Closed Principle
<?php
// somewhere else a naughty developer writes this:
class MyProductDiscountCalc extends ProductDiscountCalculator {
public function calculateDiscount(Product $product)
{
// Hardcoded discount here
return 300;
}
}
38. Open-Closed Principle
Why is this so bad?
● ProductDiscountCalculator is not an interface, but a
specific class
● We can push into usage it's replacement
● The code relies on ProductDiscountCalculator, but
it's children are changing the behavior and this is
bad
40. Open-Closed Principle
“But who is using specific types anyways? Can't we just use
interfaces?”
- Yes, that's why we should look at the next principles.
41. Open-Closed Principle
I bet you are puzzled now!
Don't be afraid, open-closed principle is used best
with his fellow brother the Liskov Substitution
principle!
42. Open-Closed Principle
● It bit better way to do it:
class MyProductDiscountCalc extends ProductDiscountCalculator {
public function myCalculateDiscount(Product $product)
{
// Hardcoded discount here
return 300;
}
}
45. Liskov Substitution Principle
Basically we must make sure that new derived
classes are extending the base classes without
changing their behavior. It's that easy.
48. Liskov Substitution Principle
Let's remember the previous example:
class ProductDiscountCalculator {
public function calculateDiscount(Product $product);
}
class MyProductDiscountCalculator ...
public function myCalculateDiscount(Product $product);
}
49. Liskov Substitution Principle
How do you know which is which?
<?php
if ($calc instanceof ProductDiscountCalculator) {
$calc->calculateDiscount($product);
}
if ($calc instanceof MyProductDiscountCalculator) {
$calc->myCalculateDiscount($product);
}
51. Liskov Substitution Principle
● One solution is to use abstract method:
<?php
abstract class AbstractDiscountCalc {
public function calculateDiscount(Product $product) {
return $this->getDiscountForProduct($product);
}
abstract protected function
getDiscountForProduct(Product $product);
}
52. Liskov Substitution Principle
<?php
class DefaultProductDiscountCalc extends AbstractDiscountCalc
{
protected function getDiscountForProduct(Product $product)
{
// our main algorithm for $discountRate
return $product->getPrice / $discountRate;
}
}
57. Dependency inversion principle
● So our previous example would use an interface:
<?php
interface DiscountCalculator {
public function calculateDiscount(Product $product);
}