Dawid Mazur / @dwdmzr
"Experienced" PHP Developer @ Clearcode
Dawid Mazur / @dwdmzr
¯\_(ツ)_/¯ @ Clearcode
class Invoice {
public function setStatus(string $status) : void {}
public function getFullPrice() : float {}
}
class Contract {
public function calculateInvoice() : Invoice {}
public function printPdf() : void {}
}
class Contract {
private function isPaidMonthly() : bool {}
private function getMonthlyInvoice() : Invoice {}
private function getFullInvoice() : Invoice {}
public function calculateInvoice() : Invoice {
if ($this->isPaidMonthly()) {
return $this->getMonthlyInvoice();
}
return $this->getFullInvoice();
}
public function printPdf() : void {}
}
class Contract {
private function isPaidMonthly() : bool {}
private function getMonthlyInvoice() : Invoice {}
private function getFullInvoice() : Invoice {}
public function calculateInvoice() : Invoice {
if ($this->isPaidMonthly()) {
return $this->getMonthlyInvoice();
}
return $this->getFullInvoice();
}
public function printPdf() : void {}
}
interface InvoiceGeneratingStrategy {
public function generateInvoice() : Invoice;
}
class MonthlyInvoiceGeneratingStrategy implements InvoiceGeneratingStrategy {
public function generateInvoice(): Invoice {}
}
class QuarterlyInvoiceGeneratingStrategy implements InvoiceGeneratingStrategy {
public function generateInvoice(): Invoice {}
}
class FullInvoiceGeneratingStrategy implements InvoiceGeneratingStrategy {
public function generateInvoice(): Invoice {}
}
class Contract {
private function isPaidMonthly() : bool {}
private function getInvoiceGeneratingStrategy() : InvoiceGeneratingStrategy {}
public function calculateInvoice() : Invoice {
return $this->getInvoiceGeneratingStrategy()->generateInvoice();
}
public function printPdf() : void {}
}
class Contract {
private function isPaidMonthly() : bool {}
private function getInvoiceGeneratingStrategy() : InvoiceGeneratingStrategy {}
public function calculateInvoice() : Invoice {
return $this->getInvoiceGeneratingStrategy()->generateInvoice();
}
public function printPdf() : void {}
}
abstract class Contract {
abstract protected function getInvoiceGeneratingStrategy() : InvoiceGeneratingStrategy;
public function calculateInvoice() : Invoice {
return $this->getInvoiceGeneratingStrategy()->generateInvoice();
}
public function printPdf() : void {}
}
class MonthlyPaidContract extends Contract {
protected function getInvoiceGeneratingStrategy(): InvoiceGeneratingStrategy
{
return new MonthlyInvoiceGeneratingStrategy();
}
}
class FullyPaidContract extends Contract {
protected function getInvoiceGeneratingStrategy(): InvoiceGeneratingStrategy
{
return new FullInvoiceGeneratingStrategy();
}
}
abstract class Contract {
abstract protected function getInvoiceGeneratingStrategy() : InvoiceGeneratingStrategy;
abstract protected function getPdfPrintingTemplate() : ContractTemplate;
public function calculateInvoice() : Invoice {
return $this->getInvoiceGeneratingStrategy()->generateInvoice();
}
public function printPdf() : void {
$template = $this->getPdfPrintingTemplate();
// do some printing magic
// (ノ°∀°)ノ⌒・*:.。. .。.:*・゜゚・*☆
}
}
abstract class Contract {
abstract protected function getInvoiceGeneratingStrategy() : InvoiceGeneratingStrategy;
abstract protected function getPdfPrintingTemplate() : ContractTemplate;
public function calculateInvoice() : Invoice {
return $this->getInvoiceGeneratingStrategy()->generateInvoice();
}
public function printPdf() : void {
$template = $this->getPdfPrintingTemplate();
// do some printing magic
// (ノ°∀°)ノ⌒・*:.。. .。.:*・゜゚・*☆
}
}
class MonthlyPaidContract extends Contract {
protected function getInvoiceGeneratingStrategy(): InvoiceGeneratingStrategy
{
return new MonthlyInvoiceGeneratingStrategy();
}
protected function getPdfPrintingTemplate(): ContractTemplate
{
return new MonthlyPaidContractTemplate();
}
}
abstract class ContractComponentFactory {
abstract public function getInvoiceGeneratingStrategy() : InvoiceGeneratingStrategy;
abstract public function getPdfPrintingTemplate() : ContractTemplate;
}
class MonthlyPaidContractComponentFactory extends ContractComponentFactory {
public function getInvoiceGeneratingStrategy(): InvoiceGeneratingStrategy
{
return new MonthlyInvoiceGeneratingStrategy();
}
public function getPdfPrintingTemplate(): ContractTemplate
{
return new MonthlyPaidContractTemplate();
}
}
class Contract {
public function __construct(
ContractComponentFactory $componentFactory
) {
$this->factory = $componentFactory;
}
public function calculateInvoice() : Invoice {
return $this->factory->getInvoiceGeneratingStrategy()->generateInvoice();
}
public function printPdf() : void {
$template = $this->factory->getPdfPrintingTemplate();
// (/ ̄ー ̄)/~~☆’.・.・:★’.・.・:☆
}
}
$contract = new Contract(
new MonthlyPaidContractComponentFactory()
);
class OrderContractComponentFactory extends ContractComponentFactory {
public function getInvoiceGeneratingStrategy(): InvoiceGeneratingStrategy
{
return new FullInvoiceGeneratingStrategy();
}
public function getPdfPrintingTemplate(): ?ContractTemplate
{
return null;
}
}
class Contract {
(...)
public function printPdf() : void {
$template = $this->factory->getPdfPrintingTemplate();
if ($template) {
// do some printing magic
// (ノ>ω<)ノ :。・:*:・゚’★,。・:*:・゚’☆
}
}
}
class OrderContractComponentFactory extends ContractComponentFactory {
public function getInvoiceGeneratingStrategy(): InvoiceGeneratingStrategy
{
return new FullInvoiceGeneratingStrategy();
}
public function getPdfPrintingTemplate(): ContractTemplate
{
return new NullContractTemplate();
}
}
abstract class ContractTemplate {
abstract public function getPagesToPrint() : array;
}
class NullContractTemplate extends ContractTemplate {
public function getPagesToPrint() : array {
return [];
}
}
class Invoice {
(...)
public function setStatus(string $status) : void {
switch ($status) {
case InvoiceStatus::PAID:
$this->yayMoreMoneySms($this->getFullPrice());
break;
}
$this->status = $status;
}
}
class Invoice {
(...)
public function setStatus(string $status) : void {
switch ($status) {
case InvoiceStatus::PAID:
$this->yayMoreMoneySms($this->getFullPrice());
break;
case InvoiceStatus::OVERDUE:
$this->dispatchMareczek(
$this->getFullPrice() * 1.25,
$this->getFullAddress()
);
break;
}
$this->status = $status;
}
}
interface Observer {
public function update(Subject $subject) : void;
}
interface Subject {
public function attach(Observer $observer) : void;
public function detach(Observer $observer) : void;
public function notify(Observer $observer) : void;
// some helper functions
public function getStatus() : string;
public function getFullPrice() : float;
public function getFullAddress() : string;
}
class Invoice implements Subject {
public function attach(Observer $observer) : void {}
public function detach(Observer $observer) : void {}
public function notify(Observer $observer) : void {
$observer->update($this);
}
public function setStatus(string $status) : void {
$this->status = $status;
foreach ($this->observers as $observer) {
$this->notify($observer);
}
}
}
class MareczekObserver implements Observer {
private function dispatchMareczek(float $howMuch, string $address) {}
public function update(Subject $subject): void
{
if ($subject->getStatus() === InvoiceStatus::OVERDUE) {
$this->dispatchMareczek(
$subject->getFullPrice() * 1.25,
$subject->getFullAddress()
);
}
}
}
class MareczekObserver implements Observer {
private function dispatchMareczek(float $howMuch, string $currency, string $address) {}
public function update(Subject $subject): void
{
if ($subject->getStatus() === InvoiceStatus::OVERDUE) {
$this->dispatchMareczek(
$subject->getFullPrice() * 1.25,
$subject->getCurrency(),
$subject->getFullAddress()
);
}
}
}
class Money {
private $amount;
private $currency;
private function validateCurrency(string $currency) : bool {}
public function multiply(float $multiplier) : Money {}
public function changeCurrency(string $currency) : Money {}
public function __construct(int $amount, string $currency)
{
$this->validateCurrency($currency);
$this->amount = $amount;
$this->currency = $currency;
}
}
class Money {
private $amount;
private $currency;
private function validateCurrency(string $currency) : bool {}
public function multiply(float $multiplier) : Money {
return new Money(
ceil($this->amount * $multiplier),
$currency
);
}
public function changeCurrency(string $currency) : Money {}
public function __construct(int $amount, string $currency)
{
$this->validateCurrency($currency);
$this->amount = $amount;
$this->currency = $currency;
}
}
class MareczekObserver implements Observer {
private function dispatchMareczek(Money $howMuch, string $address) {}
public function update(Subject $subject): void
{
if ($subject->getStatus() === InvoiceStatus::OVERDUE) {
$this->dispatchMareczek(
$subject->getFullPrice()->multiply(1.25),
$subject->getFullAddress()
);
}
}
}
abstract class InvoiceCommand
{
abstract public function execute();
abstract public function undo();
abstract public function getLogData() : string;
abstract public function serialize() : string;
}
class PayInvoiceCommand extends InvoiceCommand
{
public function execute() {}
public function undo() {}
public function getLogData(): string {}
public function serialize(): string {}
}
class DebugPayInvoiceCommand extends PayInvoiceCommand {
private function debug($data) {}
public function execute()
{
$this->debug($this->data);
parent::execute();
}
}
class ProfiledPayInvoiceCommand extends PayInvoiceCommand {
private function startProfiling() {}
private function stopProfiling() {}
public function execute()
{
$this->startProfiling();
parent::execute();
$this->stopProfiling();
}
}
class ProfiledDebugPayInvoiceCommand extends PayInvoiceCommand {
private function startProfiling() {}
private function stopProfiling() {}
private function debug($data) {}
public function execute()
{
$this->debug($this->data);
$this->startProfiling();
parent::execute();
$this->stopProfiling();
}
}
:d
abstract class CommandDecorator extends InvoiceCommand {
protected $decoratedCommand;
function __construct(InvoiceCommand $decoratedCommand)
{
$this->decoratedCommand = $decoratedCommand;
}
}
class DebugCommandDecorator extends CommandDecorator {
private function debug($data) {}
public function execute()
{
$this->debug($this->data);
$this->decoratedCommand->execute();
}
public function undo() {$this->decoratedCommand->undo();}
public function getLogData(): string {$this->decoratedCommand->getLogData();}
public function serialize(): string {$this->decoratedCommand->serialize();}
}
class ProfileCommandDecorator extends CommandDecorator {
private function startProfiling() {}
private function stopProfiling() {}
public function execute()
{
$this->startProfiling();
$this->decoratedCommand->execute();
$this->stopProfiling();
}
public function undo() {$this->decoratedCommand->undo();}
public function getLogData(): string {$this->decoratedCommand->getLogData();}
public function serialize(): string {$this->decoratedCommand->serialize();}
}
$command = new DebugCommandDecorator(
new ProfileCommandDecorator(
new PayInvoiceCommand()
)
);
Questions?
@dwdmzr
dwdmzr
dwd.mazur
Slides
dawidmazur.eu/phpers-summit
Feedback is very welcome
joind.in/event/phpers-summit-2018
Check out Coding Dojo Silesia!
codingdojosilesia