This document discusses object-oriented programming and design principles. It begins by describing the classical and modern views of objects, with the classical view being that an object represents a physical thing and the modern view being that an object is a collection of related behaviors. The document then discusses how polymorphism and encapsulation are better approaches than inheritance alone. It introduces the SOLID principles for creating high-quality APIs, including the single responsibility, open/closed, Liskov substitution, interface segregation and dependency inversion principles. Finally, it discusses how to recognize "bad" or "stupid" code that violates these principles.
14. Classic View
$lion = new Lion;
$lion->roar();
$lion->walkTo($point);
$lion->hunt($zebra);
$lion->sleep();
Does A Lion Have
A Button To Make
It Roar?
15. Classic View
$lion = new Lion;
$lion->roar();
$lion->walkTo($point);
$lion->hunt($zebra);
$lion->sleep();
Does A Lion Have
A Button To Make
It Roar?What Does It
Mean For An
Object To “Hunt”?
16. Classic View
$lion = new Lion;
$lion->roar();
$lion->walkTo($point);
$lion->hunt($zebra);
$lion->sleep();
Does A Lion Have
A Button To Make
It Roar?What Does It
Mean For An
Object To “Hunt”?
What Is A Lion In
Relation To Our
Application?
22. “Modern” View
Object == Collection Of (Related)
Behaviors
Methods == Behavior
Properties == Details Of Behavior
23. Classic View == “(conceptually) is a”
Modern View == “behaves as a”
24. interface Number {
function getValue();
function __toString();
function add(Number $n);
function subtract(Number $n);
function equals(Number $n);
function isLessThan(Number $n);
function isGreaterThan(Number $n);
}
33. Polymorphic Code
class Integer implements Number {
public function add(Number $a) {
return new Integer(
$this->getValue() +
(int) $a->getValue()
);
}
}
34. Polymorphic Code
class Float implements Number {
public function add(Number $a) {
return new Float(
$this->getValue() +
(float) $a->getValue()
);
}
}
59. S - Single Responsibility Principle
O-
L -
I -
D-
A Good API
Does One
Thing
60.
61.
62. S - Single Responsibility Principle
O- Open / Closed Principle
L -
I -
D-
A Good API
Never Changes
63.
64.
65.
66.
67.
68. S - Single Responsibility Principle
O- Open / Closed Principle
L - Liskov Substitution Principle
I -
D-
A Good API
Behaves Like
Its Contract
69.
70.
71.
72. S - Single Responsibility Principle
O- Open / Closed Principle
L - Liskov Substitution Principle
I - Interface Segregation Principle
D-
A Good API
Has A Narrow
Responsibility
73.
74. S - Single Responsibility Principle
O- Open / Closed Principle
L - Liskov Substitution Principle
I - Interface Segregation Principle
D- Dependency Inversion Principle
A Good API
Depends Upon
Abstractions
75.
76.
77. S - Single Responsibility Principle
O- Open / Closed Principle
L - Liskov Substitution Principle
I - Interface Segregation Principle
D- Dependency Inversion Principle
103. What Good OOP Gives You
Modular Code
Reusable Code
Extendable Code
Easy To Read Code
Maintainable Code
Easy To Change Code
Easy To Understand Code
Clean Abstractions (mostly)
104. What Good OOP Costs You
Tends To Have More “Layers”
Tends To Be Slower At Runtime
Tends To Have Larger Codebases
Tends To Result In Over-Abstraction
Tends To Require More Effort To Write
Tends To Require More Tacit Knowledge
106. interface Car {
public function turnLeft();
public function turnRight();
public function goFaster();
public function goSlower();
public function shiftUp();
public function shiftDown();
public function start();
}
107. interface Steerable {
public function steer($angle);
}
interface Acceleratable {
public function accelerate($amt);
}
interface Shiftable {
public function shiftDown();
public function shiftUp();
}
111. interface MailSystemInterface {
public function format(array $message);
public function mail(array $message);
}
What Responsibility?
Formatting Messages
112. interface MailSystemInterface {
public function format(array $message);
public function mail(array $message);
}
What Responsibility?
Formatting Messages
Encoding Messages
113. interface MailSystemInterface {
public function format(array $message);
public function mail(array $message);
}
What Responsibility?
Formatting Messages
Encoding Messages
Assembling Headers
114. interface MailSystemInterface {
public function format(array $message);
public function mail(array $message);
}
What Responsibility?
Formatting Messages
Encoding Messages
Assembling Headers
Calling Sendmail
115. interface MailSystemInterface {
public function format(array $message);
public function mail(array $message);
}
What Responsibility?
Formatting Messages
Encoding Messages
Assembling Headers
Calling Sendmail
Setting INI settings…?
116. interface MailSystemInterface {
public function format(array $message);
public function mail(array $message);
}
What Responsibility?
Open For Extension?
117. interface MailSystemInterface {
public function format(array $message);
public function mail(array $message);
}
What Responsibility?
Open For Extension?
Edits Require
Copy/Paste
118. interface MailSystemInterface {
public function format(array $message);
public function mail(array $message);
}
What Responsibility?
Open For Extension?
Liskov Substitution...
119. interface MailSystemInterface {
public function format(array $message);
public function mail(array $message);
}
What Responsibility?
Open For Extension?
Liskov Substitution...
One Interface...
Many Responsibilites
120. interface MailSystemInterface {
public function format(array $message);
public function mail(array $message);
}
What Responsibility?
Open For Extension?
Liskov Substitution...
One Interface...
What Dependencies?
121. interface MessageFormatter {
public function format(Message $message);
}
interface MessageEncoder {
public function encode(Message $message);
}
interface MessageTransport {
public function send(Message $message);
}
122. class MailSystem {
public function __construct(
MessageFormatter $messageFormatter,
MessageEncoder $messageEncoder,
MessageTransport $messageTransport
) {}
public function mail(Message $message);
}