Command & event patterns

Miro Svrtan

@msvrtan

Project setup

git clone

git@github.com:NullTraining/command-event-patterns-bgphp19.git

composer install

php bin/console server:start

http://127.0.0.1:8000/

Build us a bank

Your new and shiny project

Transfer money

<?php
namespace Bank\...\Controller;

class MoneyController{
  public function transfer($from,$to,$amount){
    $source = $this->loadAccount($from);
    $target = $this->loadAccount($to);

    $this->guardCurrentUserOwnsAccount($source);
    $this->guardEnoughMoneyOnSourceAccount($source,$amount);

    $this->withdraw($source,$amount);
    $this->deposit($target,$amount);

    return render(...);
  }

  private function loadAccount($id){
    $acc = $this->...->load($id);
    if($acc instanceof Account){
      return $acc;
    }
    throw AccountException::notFound($id);
  }
  
  ...
}

Transfer money

<?php
namespace Bank\...\Controller;

class MoneyController{

  ...

  private function guardEnoughMoneyOnSourceAccount($acc,$amount){
    if($acc->currentBalance() < $amount){
      throw AccountException::notEnoughFunds();
    }
  }
  private function withdraw($acc,$amount){
    $acc->withdraw($amount);
    $this->...->save($acc);
  }
  private function deposit($acc,$amount){
    $acc->deposit($amount);
    $this->...->save($acc);
  }
}

Email reciever

<?php
namespace Bank\...\Controller;

class MoneyController{
  public function transfer($from,$to,$amount){
    $source = $this->loadAccount($from);
    $target = $this->loadAccount($to);

    $this->guardCurrentUserOwnsAccount($source);
    $this->guardEnoughMoneyOnSourceAccount($source,$amount);

    $this->withdraw($source,$amount);
    $this->deposit($target,$amount);

    $this->sendEmailAboutDeposit($target,$amount);

    return render(...);
  }

  
  ...
}

SMS reciever

<?php
namespace Bank\...\Controller;

class MoneyController{
  public function transfer($from,$to,$amount){
    $source = $this->loadAccount($from);
    $target = $this->loadAccount($to);

    $this->guardCurrentUserOwnsAccount($source);
    $this->guardEnoughMoneyOnSourceAccount($source,$amount);

    $this->withdraw($source,$amount);
    $this->deposit($target,$amount);

    $this->sendEmailAboutDeposit($target,$amount);
    $this->sendSmsAboutDeposit($target,$amount);

    return render(...);
  }

  
  ...
}

Confirm withdrawal

<?php
namespace Bank\...\Controller;

class MoneyController{
  public function transfer($from,$to,$amount){
    $source = $this->loadAccount($from);
    $target = $this->loadAccount($to);

    $this->guardCurrentUserOwnsAccount($source);
    $this->guardEnoughMoneyOnSourceAccount($source,$amount);

    $this->withdraw($source,$amount);
    $this->deposit($target,$amount);

    $this->sendEmailAboutDeposit($target,$amount);
    $this->sendSmsAboutDeposit($target,$amount);
    $this->sendEmailAboutWithdrawal($source,$amount);

    return render(...);
  }

  
  ...
}

External transfers

  public function transfer($from,$to,$amount){
    $source = $this->loadAccount($from);
    $target = $this->loadAccount($to);

    $this->guardCurrentUserOwnsAccount($source);
    $this->guardEnoughMoneyOnSourceAccount($source,$amount);

    $this->withdraw($source,$amount);
    $this->deposit($target,$amount);

    $this->sendEmailAboutDeposit($target,$amount);
    $this->sendSmsAboutDeposit($target,$amount);
    $this->sendEmailAboutWithdrawal($source,$amount);

    return render(...);
  }
  public function outgoingExternalTransfer($from,$to,$amount){
    $source = $this->loadAccount($from);

    $this->guardCurrentUserOwnsAccount($source);
    $this->guardEnoughMoneyOnSourceAccount($source,$amount);

    $this->withdraw($source,$amount);
    $this->contactOtherBankToDeposit(...);

    $this->sendEmailAboutWithdrawal($source,$amount);

    return render(...);
  }

External transfers

...
  public function incomingExternalTransfer($from,$to,$amount){
    $target = $this->loadAccount($to);

    $this->deposit($target,$amount);

    $this->confirmRequestToOtherBank(...);

    $this->sendEmailAboutDeposit($target,$amount);
    $this->sendSmsAboutDeposit($target,$amount);

    return render(...);
  }
 ...

XML API

<?php
namespace Bank\...\Controller;

class MoneyXMLController{
  public function outgoingExternalTransfer($xml){
    ..
  }

  public function incomingExternalTransfer($xml){
    ..
  }  
  ...
}

MoneyController

MoneyXMLController

TransferService

EmailService

SmsService

MoneyController

MoneyXMLController

TransferService

EmailService

SmsService

MoneyController

MoneyXMLController

TransferService

EmailService

SmsService

NotificationService

MoneyController

MoneyXMLController

TransferService

EmailService

SmsService

NotificationService

OutgoingExternal

TransferService

Report transaction over 1000 to authorities

MoneyController

MoneyXMLController

TransferService

EmailService

SmsService

NotificationService

OutgoingExternal

TransferService

ReportToAuthorities

Service

Opening branch in country X

MoneyController

MoneyXMLController

TransferService

EmailService

SmsXService

NotificationService

OutgoingExternal

TransferService

ReportToXAuthorities

Service

Upcoming features

  • audit log
  • ios/android notifications
  • automated payouts (electricity..)
  • ATM withdrawal

Project setup

git clone

git@github.com:NullTraining/command-event-patterns-bgphp19.git

composer install

php bin/console server:start

-OR-

php -S localhost:8000 public/index.php

http://127.0.0.1:8000/

SOLID

MoneyController

MoneyXMLController

TransferService

EmailService

SmsService

NotificationService

OutgoingExternal

TransferService

ReportToAuthorities

Service

Can we find some patterns?

MoneyWithdrawn

Send email

Report to authorities?

Audit log

MoneyWithdrawn

Send email

Report to authorities?

Audit log

MoneyDeposited

Send SMS

Report to authorities?

Audit log

Send email

Send push notification

MoneyWithdrawn

MoneyDeposited

TransferService

IncomingExternal

TransferService

OutgoingExternal

TransferService

MoneyWithdrawn

MoneyDeposited

TransferService

IncomingExternal

TransferService

OutgoingExternal

TransferService

AutomatedPayouts

ATM

ATM deposit

MoneyWithdrawn

TransferService

WithdrawMoney

 

WithdrawMoneyHandler

 

MoneyWithdrawn

MoneyDeposited

TransferService

WithdrawMoney

DepositMoney

 

WithdrawMoneyHandler

 


DepositMoneyHandler


MoneyWithdrawn

MoneyDeposited

TransferService

OutgoingExternal

TransferService

WithdrawMoney

DepositMoney

 

WithdrawMoneyHandler

 


DepositMoneyHandler


MoneyWithdrawn

MoneyDeposited

TransferService

IncomingExternal

TransferService

OutgoingExternal

TransferService

WithdrawMoney

DepositMoney

 

WithdrawMoneyHandler

 


DepositMoneyHandler


Thank you!

Miro Svrtan

@msvrtan

Questions?