從事件系統說起,更好的組織程式碼

RryLee發表於2017-02-27

Object-oriented code has gone a long way to ensuring code extensibility. By creating classes that have well defined responsibilities, your code becomes more flexible and a developer can extend them with subclasses to modify their behaviors. But if they want to share the changes with other developers who have also made their own subclasses, code inheritance is no longer the answer.

摘自 Symfony EventDispatcher Component,確實,對於一些的難以維護的程式碼(幾乎快要成為一個黑盒,可能經歷了3-4待程式設計師之手),面對新的 Feature,你需要在保持舊的邏輯不受到任何影響,最好的方式就是去在程式碼從新增事件(如果可以的話,務必這麼做,特別是對於 TP 的專案,總有一天所有的 TP 程式碼都會遷移到 Laravel 上面)。

最近,產品說,我們的使用者需要在完成一項操作之後收到微信推送的訊息,同時要受到郵件,和簡訊。對於這個需求,想必在沒有事件驅動的情況下,可想而知程式碼有多醜陋。在明確了你需要使用這種程式設計思想之後,大概在產品和你說完這個需求之後,核心程式碼應該已經生成了。


OperationCompleted::class => [
    PushWechatNotification::class,
    SendEmailNotification::class,
    SendSmsNotification::class,
],

接下來的事情也就水到渠成了。程式設計中是以不變應萬變的抽象永遠是最好的設計模式。

後面的是說程式碼的事情了,對事件非常瞭解的同學可以右上角了。分割線!


之前一直以為 laravel 的 events 是對 Symfony 的事件系統的一個封裝,後來看了原始碼之後發現不是,看完 Symfony 事件原始碼之後確實收穫很大。

ImmutableEventDispatcher 這裡對 EventDispatcher 做了一層代理(當時就想到了 immutable-js),對於公司底層核心業務就很有用了,畢竟永遠不知道公司的新同事或者實習生會寫出什麼樣的程式碼,對於這種不變的程式碼還是非常有有必要的,同時也符合現在函式式的哲學思想。


有個小技巧,對於同一個事件觸發的很多不同的監聽器,類似上面傳送提醒的功能,使用訂閱者去解決獲取更為優雅。

<?php

use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\ImmutableEventDispatcher;

require __DIR__ . '/vendor/autoload.php';

$dispatcher = new EventDispatcher;

class OperationSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return [
            'operation.completed' => [
                ['pushWechatNotification', 1],
                ['sendEmailNotification', 2],
                ['sendSmsNotification', 3],
            ],
        ];
    }

    public function pushWechatNotification(Event $event)
    {
        var_dump('pushWechatNotification');
    }

    public function sendEmailNotification(Event $event)
    {
        var_dump('sendEmailNotification');
    }

    public function sendSmsNotification(Event $event)
    {
        var_dump('sendSmsNotification');
    }
}

$dispatcher->addSubscriber(new OperationSubscriber);
$immutableDispatcher = new ImmutableEventDispatcher($dispatcher);
$immutableDispatcher->dispatch('operation.completed');

最後祝願用 TP 的同學在專案中能更多的使用 laravel 元件,寫更多 laravel 風的程式碼!

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章