Or "Information Hiding"
Modules should be open for extension but closed to modification
if/else
switch
new
3.14
switch ($role) {
case Role::CUSTOMER:
return $this->customerBalance($user);
case Role::MERCHANT:
return $this->merchantBalance($user);
case Role::SUPERVISER:
return $this->userBalance($user);
default:
throw new UnknownRoleException($role);
}
foreach ($balanceProviders as $balanceProvider) {
if ($balanceProvider->supports($role)) {
return $balanceProvider->process($user);
}
}
throw new UnknownRoleException($role);
$notifier->sendWelcomeNotification($user);
$notifier->sendActivationEmail($user, $activationHash);
$users->findPremiumUsers($paging);
$users->findReferralUsers($introducer, $paging);
$notifier->send(new WelcomeNotification($user));
$notifier->send(new ActivationEmail($user, $activationHash));
$users->find(new PremiumUsers($paging));
$users->find(new ReferralUsers($introducer, $paging));
$prices = [];
foreach ($this->orderLines as $orderLine) {
$price = $orderLine->totalPrice();
if ($orderLine->quantity() < 5) {
$price = $price->multiply(0.7);
}
$prices[] = $price;
}
$applyDiscount = function ($next, $orderLine) {
if ($orderLine->quantity() < 5) {
return $next($orderLine);
}
return $next($orderLine)->multiply(0.7);
}
$price = function ($orderLine) {
return $orderLine->totalPrice();
}
$prices = array_map(curry($applyDiscount)($price), $this->orderlines);
class Bar extends Foo
{
public function __construct(Baz $baz)
{
parent::__construct($baz);
}
}
class Bar implements FooInterface
{
private $foo;
public function __construct(Baz $baz)
{
$this->foo = new Foo($baz);
}
}
Don't call us, we call you
class Bar implements FooInterface
{
private $foo;
public function __construct(FooInterface $foo)
{
$this->foo = $foo;
}
}
If for each object O1 of type S there is an object O2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when O1 is substituted for O2 then S is a subtype of T.
Objects of the derived class must behave in a manner consistent with the promises made in the base class' contract.
interface Stream
{
public function write(string $data): void;
public function seek(int $pos): void;
public function read(int $length): string;
}
class InMemoryStream implements Stream
{
public function seek(int $offset): void
{
throw new NotImplemented(
"In memory stream doesn't support seek operation"
);
}
// ...
}
interface ReadableStream
{
public function read(int $length): void;
}
interface WritableStream
{
public function write(string $data): void;
}
interface SeekableStream
{
public function seek(int $pos): void;
}
SOLID is not the goal...
LSP
SOLID
GRASP
OCP
1970
2000
1990
1980
Information
Hiding
LoD
Coupling
Cohesion