Ryuta Hamasaki
Web developer and bass player based in Tokyo.
2019-05-08
【シューマイ】Tech Lead Engineerから最新技術を学べ!Laravel編
Ryuta Hamasaki
Laravel / Angular / Vue.js
オブジェクト指向プログラミング
において、メンテナンスしやすい
プログラムを作るための5つの原則
Robert C. Martin (Uncle Bob)
Clean Coder, Clean Architectureの人。
去年のLaraconのトリ。
仕入元
Web App
Slack通知
発注者
class OrderProcessor
{
public function __construct(Slack $slack) {
$this->slack = $slack;
}
public function process(Order $order)
{
if (! $order->getAmount() > 0) {
throw new Exception('Order amount must be more than zero.');
}
$order->place();
$message = $this->getMessage($order);
$this->slack->to('#order')->send($message);
}
protected function getMessage(Order $order) : string
{
$format = '@%s Order has been processed. OrderID: %d';
$userName = $order->getUserName();
$message = sprintf($format, $userName, $order->getId());
return $message;
}
}
interface OrderNotificationInterface
{
public function notify(Order $order) : void;
}
class SlackNotification implements OrderNotificationInterface
{
public function __construct(Slack $slack) {
$this->slack = $slack;
}
public function notify(Order $order) : void
{
$message = $this->getMessage($order);
$this->slack->to('#order')->send($message);
}
protected function getMessage(Order $order) : string
{
$format = '@%s Order has been processed. OrderID: %d';
$userName = $order->getUserName();
$message = sprintf($format, $userName, $order->getId());
return $message;
}
}
class OrderProcessor
{
public function __construct(OrderNotificationInterface $notification) {
$this->notification = $notification;
}
public function process(Order $order)
{
if (! $order->getAmount() > 0) {
throw new Exception('Order amount must be more than zero.');
}
$order->place();
$this->notification->notify($order);
}
}
class OrderProcessor
{
public function __construct(OrderNotificationInterface $notification) {
$this->notification = $notification;
}
public function process(Order $order)
{
if (! $order->getAmount() > 0) {
throw new Exception('Order amount must be more than zero.');
}
$order->place();
$this->notification->notify($order);
}
}
class OrderProcessor
{
public function __construct(OrderNotificationInterface $notification) {
$this->notification = $notification;
}
public function process(Order $order)
{
if (! $order->getAmount() > 0) {
throw new Exception('Order amount must be more than zero.');
}
if (! $order->isApproved()) {
throw new Exception('Order is not approved.');
}
$order->place();
$this->notification->notify($order);
}
}
class OrderProcessor
{
public function __construct(OrderNotificationInterface $notification) {
$this->notification = $notification;
}
public function process(Order $order)
{
if (! $order->getAmount() > 0) {
throw new Exception('Order amount must be more than zero.');
}
if (! $order->isApproved()) {
throw new Exception('Order is not approved.');
}
if (! $order->isCancelled()) {
throw new Exception('Cancelled order cannot be processed.');
}
$order->place();
$this->notification->notify($order);
}
}
interface OrderValidationInterface
{
public function validate(Order $order) : void;
}
class OrderHasAmount implements OrderValidationInterface
{
public function validate(Order $order) : void
{
if (! $order->getAmount() > 0) {
throw new Exception('Order amount must be more than zero.');
}
}
}
class OrderIsApproved implements OrderValidationInterface
{
public function validate(Order $order) : void
{
if (! $order->isApproved()) {
throw new Exception('Order is not approved.');
}
}
}
class OrderIsNotCancelled implements OrderValidationInterface
{
public function validate(Order $order) : void
{
if (! $order->isCancelled()) {
throw new Exception('Cancelled order cannot be processed.');
}
}
}
class OrderProcessor
{
public function __construct(
OrderNotificationInterface $notification,
array $validators
) {
$this->notification = $notification;
$this->$validators = $validators;
}
public function process(Order $order)
{
foreach ($this->validators as $validator) {
$validator->validate($order);
}
$order->place();
$this->notification->notify($order);
}
}
class OrderServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(OrderProcessor::class, function ($app) {
new OrderProcessor(
$this->app->make(OrderNotificationInterface::class),
[
new OrderHasAmount,
new OrderIsApproved,
new OrderIsNotCancelled
]
);
});
}
}
仕入元
Web App
メール通知
発注者
class EmailNotification implements OrderNotificationInterface
{
protected $aws;
protected $ses;
public function __construct(Aws $aws) {
$this->aws = $aws;
}
public function createSes() : void
{
$this->ses = $this->aws->createSes(['region' => 'us-east-1']);
}
public function notify(Order $order) : void
{
$options = [
'from' => 'mail@example.com',
'to' => $order->getUserEmail(),
'subject' => 'Order has been processed',
'body' => $this->getMessage($order)
];
$this->ses->sendEmail($options);
}
}
class OrderProcessor
{
public function __construct(OrderNotificationInterface $notification, array $validators) {
$this->notification = $notification;
$this->$validators = $validators;
}
public function process(Order $order)
{
foreach ($this->validators as $validator) {
$validator->validate($order);
}
$order->place();
if ($this->notification instanceof EmailNotification) {
$this->notification->createSes();
}
$this->notification->notify($order);
}
}
class EmailNotification implements OrderNotificationInterface
{
protected $ses;
public function __construct(Aws $aws) {
$this->aws = $aws;
}
public function createSes() : void
{
$this->ses = $this->aws->createSes(['region' => 'us-east-1']);
}
public function notify(Order $order) : void
{
$this->createSes();
$options = [
'from' => 'mail@example.com',
'to' => $order->getUserEmail(),
'subject' => 'Order has been processed',
'body' => $this->getMessage($order)
];
$this->ses->sendEmail($options);
}
}
class OrderProcessor
{
public function __construct(
OrderNotificationInterface $notification,
array $validators
) {
$this->notification = $notification;
$this->$validators = $validators;
}
public function process(Order $order)
{
foreach ($this->validators as $validator) {
$validator->validate($order);
}
$order->place();
$this->notification->notify($order);
}
}
(Laracastsにもシリーズがあります)
By Ryuta Hamasaki