コード重複を防ぐためのコールバックの使用


コールバック関数やその他の関数を使うのも便利ですcallable コード重複の束を防ぐために.
あなたがエンティティのライフサイクルでデータを暗号化して解読するイベント加入者を持っていると言いましょう.エンティティが格納されると、いくつかのデータが暗号化されますそして、実体がロードされるとき、データは解読されます.
ここでは、おそらくいくぶん工夫されていますが、以下の例を示します:
final class EncryptionSubscriber
{
    public function __construct(private CryptographerInterface $cryptographer) { }

    private function getEncryptedProperties(Entity $entity): array {
        // some code to detect the encrypted properties of the entity.
        return ['encrypted'];
    }

    public function onSave(Event $event): void {
        $entity = $event->getEntity();

        foreach ($this->getEncryptedProperties($entity) as $property) {
            $value = $entity->getValue($property);
            $entity->setValue($property, $this->cryptographer->encrypt($value));
        }
    }

    public function onLoad(Event $event): void {
        $entity = $event->getEntity();

        foreach ($this->getEncryptedProperties($entity) as $property) {
            $value = $entity->getValue($property);
            $entity->setValue($property, $this->cryptographer->decrypt($value));
        }
    }
}

これがそんなに悪くない間onSave and onLoad 実質的に同じ方法のみsetValue() 異なる.そして、正直に、これらのような2つの小さい機能で;気にしないかもしれない.しかし、3つ以上の方法が同じであることがしばしば起こります.または、関数はより精巧な方法です一方、彼らはまだ小さいものだけで異なります.

コールバックヘルパーの抽出


この複製の解決策は、すべてのロジックを一度含む1つのヘルパーメソッドを抽出することです.しかし、論理が異なる点で、我々はAを呼びますcallable 噴射される.原作onSave and onLoad その後、そのヘルパーメソッドに移り、callable を指定します.
final class EncryptionSubscriber
{
    // ...

    public function onSave(Event $event): void
    {
        $this->processEvent($event, fn($value) => $this->cryptographer->encrypt($value));
    }

    public function onLoad(Event $event): void
    {
        $this->processEvent($event, fn($value) => $this->cryptographer->decrypt($value));
    }

    private function processEvent(Event $event, callable $callback): void
    {
        $entity = $event->getEntity();
        foreach ($this->getEncryptedProperties($entity) as $property) {
            $value = $entity->getValue($property);
            $entity->setValue($property, $callback($value)); // [tl! highlight]
        }
    }
}
ご覧の通り、我々はprocessEvent() を受信するメソッドcallable $callback . このコールバックは以前のencrypt or decrypt 呼び出し.これにより、メソッド全体が非常に一般的な実装になります.特定の違いだけがコールバックで処理されます.
コールバックがその仕事をするためにより多くの文脈を必要とするならば、それは$callback() コール.
一方onSave and onLoad まだいくつかの必要な重複があります量は少なく、違いはスポットに簡単です.そして、いくつかの速記の助けを借りてfn それは非常に読みやすいです.

考えとコメント?


私が言ったように、このようなことに時間と場所があります.重複が最小なら気にする必要はないかもしれない.しかし、私はそれが知っている良いツールだと思います.他に良い例がありますか?私たちの残りの部分と共有してください.そして、あなたが他のコメントを持っている場合は、以下をドロップします.