Wiz テックブログ

Wizは、最新のIoTやICTサービスをお客様に届ける「ITの総合商社」です。

AOP、Laravelのライブラリ紹介

AOPとは

AOPAspect Oriented Programming)とは、コンピュータプログラムの特定の振る舞いを「アスペクト」と呼ばれる機能単位として分離して記述し、プログラム中の様々な対象に適用出来るようにする手法です。既存のオブジェクト指向プログラミング言語や開発環境に補助的に投入されることが多いです。

背景

オブジェクト指向プログラミングでは、お互いに関連するデータ(属性)とそれらに対する操作の集合でオブジェクトをプログラムの基礎単位として記述して行きますが、ロギング(Logging)のような様々なオブジェクトで共通して現れますが単一のオブジェクトやメソッドなどとして切り出して定義することが出来ないような横断的な機能(横断的関心事)が存在する場合があります。

例えばissueBookとreturnBookの2つのメソッドをもつクラスLibraryServiceの例を見てみましょう。仕様としては、パラメーターと返却値をログに記録することです。ここで、ロギングは、アプリケーションに実装したい横断的関心事です。

<?php
class LibraryService {
    public function issueBook(int $memberID, int $bookID): bool {
        \Log::info("Executing method issueBook($memberID, $bookID) of LibraryService");
        
        $status = false;
        
        // Business logic to issue a book from Library
        \Log::info("Returning from method issueBook of LibraryService : $status");
        
        return $status;
    }
    public function returnBook(int $memberID, int $bookID): bool {
        \Log::info("Executing method returnBook($memberID, $bookID) of LibraryService");
        
        $status = false;
        
        // Business logic to return the issues book
        \Log::info("Returning from method returnBook of LibraryService : $status");
        
        return $status;
    }
}

ここで、ライブラリに新しい本を追加する必要があるため、LibraryServiceに別のメソッドaddBookを記述します。メソッドaddBookを作成するときは、パラメータと返却値をログに記録する必要があります。したがって、addBookメソッドのコードは次のようになります。

<?php
    public function addBook(int $bookID): bool {
        \Log::info("Executing method addBook($bookID) of LibraryService");

        $status = false;
        // Business logic to return the issues book

        \Log::info("Returning from method addBook of LibraryService : $status");
        
        return $status;
    }

上記のような従来のアプローチの欠点:

  • パラメーターと返却値をログに記録する同様のロジックは、複数のメソッドに分散されているため、冗長なコードが作成されます。これにより、メンテナンスが非常に困難になります。
  • アプリケーションロギングの要件を変更すると、LibraryServiceの複数のメソッドのコードが変更されます。
  • LibraryServiceに新しいメソッドを追加すると、新しく追加されたメソッドでログコードが再度書き換えられます。したがって、既存のロギングロジックを再利用することはできません。
  • LibraryServiceの主な責任は、ロギングではなく、ライブラリのさまざまな操作を提供することです。LibraryServiceにロギングするコードを保持することはお勧めできません。

AOPは、上記の全ての欠点を克服するアプリケーションのロギングの関心(Concern)(および他のすべての横断的関心事)を実装するのに役立ちます。AOPは、横断的関心事をアプリケーションの主要なビジネスロジックから分離し、さまざまなアプリケーションオブジェクトに適切に織り込みます。

横断的関心事(Cross Cutting Concerns)

どのエンタープライズアプリケーションでも、主要なビジネスロジックに加えて、対処する必要のある多くの関心事項があります。これらの関心は、アプリケーション全体および複数のアプリケーション層に広がっています。このような関心事項は、ロギング、トランザクション処理、パフォーマンスモニタリング、セキュリティなどがあります。これらの関心事項は、アプリケーションの横断的関心事として知られています。

f:id:FattyRabbit:20210226171047p:plain

AOPは、アプリケーションの横断的関心事を実装して、それらをメインのビジネスロジックから分離し、その結果、アプリケーションが疎結合になるようにします。

用語

Aspectアスペクト

アスペクトとは、ロギング、パフォーマンス監視、トランザクション処理など、アプリケーションに実装したい関心(横断的関心事)のことです。

Advice(アドバイス

アドバイスは、アスペクトの実際の実装です。アスペクトは概念であり、アドバイスは概念の具体的な実装です。

Join Point(ジョインポイント)

ジョインポイントは、アスペクトを適用することができるプログラムの実行中の位置やタイミングです。メソッドの実行前/実行後、例外をスローする前、インスタンス変数を変更する前/後などです。

Point cut(ポイントカット)

ポイントカットは、アスペクトが適用される結合ポイントを示します。アドバイスはポイントカット式に関連付けられ、ポイントカット式に一致する結合ポイントに適用されます。

その他

Target、Proxy、Weaving

Laravelのライブラリ

Laravelでよく使っているのが以下の物です。

github.com

PHPフレームワークのBEAR.Sundayのパッケージの一つであるRay.AOPをLaravel向けにラッパーしたライブラリです。Ray.AOPはLaravel以外でも利用可能です。

TransactionalやLogExceptions等既に使えるモジュールもあるし、新たにAOPのモジュールを追加することも可能です。

個人的な印象

個人的にはJavaのSpringBootで初めてAOPを経験したので、Laravel(Php)のPointCutの設定方法の違いを感じました。

Laravel-Aspectでは新しくアスペクトを作成する時もアノテーションを作成してそのアノテーションを対象になるクラスやメソッドに付け、インターセプター(MethodInterceptor)が取得しジョインポイントやポイントカットを判断する方法をとっています。

qiita.com

ですが、SpringBootではアスペクトにジョインポイントやポイントカット定義をアスペクトのメソッドにアノテーションで定義しています。

qiita.com

Laravelの機能との差

Laravelと似ている所は特定の層やイベントに限っていることでAOPとは差があります。

Middleware

LaravelのMiddlewareはControllerに利用させるためにHTTPリクエストに対して処理を追加する

Listener, Observer, Subscriber

特定のイベントを捕捉する仕組み

まとめ

AOPは以下の理由と利点があります。

  • 補助的に投入することで主要なビジネスロジックと分離
  • アプリケーション層に関係なく使用

最後に

Wizではエンジニアを募集しております。 興味のある方、ぜひご覧下さい。

【フロントエンドエンジニア】

場所にとらわれず自社メディア成長に貢献したいフロントエンドエンジニア募集! - 株式会社WizのWebエンジニアの求人 - Wantedly

【バックエンドエンジニア】

勤務地自宅を叶える!バックエンドエンジニアとして事業を成長させたい方募集 - 株式会社WizのWebエンジニアの求人 - Wantedly