Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
LaravelAspectで関心の分離
KenjiroKubota
2017/07/08
Profile
Kenjiro Kubota
istyle.inc
 PHP, HHVM/Hack, Javascript 
DTPDesigner
WebDesigner
FrontEnginner
WebApplicationEngiine...
関心の分離とは
関心の分離(かんしんのぶんり、英語: separation of concerns、SoC)とは、ソフトウェア工
学において、プログラムを機能面において可能な限り重複がない、複数の機構に明確に分割
することをいう。ここでいう「関...
Aspect﴾AOP﴿とは
アスペクト指向プログラミング(アスペクトしこうプログラミング、Aspect Oriented
Programming、AOP)は、オブジェクト指向ではうまく分離できない特徴(クラス間を横断
﴾cross‐cuttin...
横断的関心事を解決する手段
代表的なケースはロギング、トランザクション、キャッシュなどが挙げられます
Laravelで利用する際はRay.Aopを用いている以下のライブラリがオススメ(宣伝)
ytake/laravel‐aspect
利用ケース ロギング
普通はこんな感じ
public function get($id)
{
    Log::info($id);
    $this‐>logger‐>info($id);
}
Logファサードを使ったり、コンストラクトイン...
LaravelAspectを使うと
use YtakeLaravelAspectAnnotationLoggable;
class AspectLoggable
{
    /**
     * @Loggable
     * @param ...
利用ケース トランザクション
普通はこんな感じ?
public function save(array $params)
{
    DB::beginTransaction();
    try {
        $result = $th...
LaravelAspectなら
use YtakeLaravelAspectAnnotationTransactional;
/**
 * @Transactional("master")
 * @LogExceptions
 */
publi...
アノテーションで関心の分離ができる
他にもデフォルトで便利なアノテーションが用意されてます
詳しくはライブラリのREADEMEを見てください。
LaravelAspectに用意されてるアノテーションも便利なんですが
自分たちのアプリに合わせた独自のアノテーションを作り
たいですよね?
サンプルケース
最終ログイン日時の記録
まずはLaravelAspectを導入
$ composer require ‐‐no‐update ytake/laravel‐aspect && composer update
Provider登録
 config/app.php 
'providers' => [
    // added AspectServiceProvider 
    YtakeLaravelAspectAspectServiceProvid...
設定ファイルとかModulesをアプリケーションにコピー
$ php artisan ytake:aspect‐module‐publish
$ php artisan vendor:publish
こんな感じで追加されます
laravel
  ‐ app
    ‐ Modules
      ‐ CacheableModule.php
      ‐ CacheEvictModule.php
      ‐ CachePutModule...
独自アノテーションの定義
use DoctrineCommonAnnotationsAnnotation;
/**
 * @Annotation
 * @Target("METHOD")
 * Class LastLoginTime
 */
class LastLogi...
インターセプターの定義
※ アノテーションが実行されるときの挙動を定義
use RayAopMethodInvocation;
use RayAopMethodInterceptor;
use YtakeLaravelAspectAnnotationAnnotationReaderTrait;
class Last...
// before
$result = $invocation‐>proceed();
// after
beforeはアノテーションを記述したメソッドが実行される前に実行される。
afterはメソッド実行されたあとに実行される
$result...
ポイントカットの定義
※ 特定のアノテーションが実行されるときに起動されるインターセプターを定義
class LastLoginTimePointCut extends CommonPointCut implements PointCutable
{
    /** @var string */
    protected $annotat...
モジュールの追加
※ アノテーションが利用されるクラスを定義する
use AppAspectPointCutLastLoginTimePointCut;
use YtakeLaravelAspectModulesAspectModule;
class LastLoginTimeModule extends A...
最後にModulesを以下に登録してあげればOK
 config/ytake‐laravel‐aop.php 
        'modules' => [
            ...
            // append modul...
まとめ
LaravelAspectをとりあえず導入するだけでも楽々AOPが実現できる
拡張もできるので独自の要件にも対応できる
関心を分離することでいちクラスの責務を追求できるようになります
単一責任の原則
thanks :﴿
Upcoming SlideShare
Loading in …5
×

Laravel aspectで関心の分離

701 views

Published on

since 2017/07/08

Published in: Software
  • Be the first to comment

  • Be the first to like this

Laravel aspectで関心の分離

  1. 1. LaravelAspectで関心の分離 KenjiroKubota 2017/07/08
  2. 2. Profile Kenjiro Kubota istyle.inc  PHP, HHVM/Hack, Javascript  DTPDesigner WebDesigner FrontEnginner WebApplicationEngiiner﴾now﴿
  3. 3. 関心の分離とは 関心の分離(かんしんのぶんり、英語: separation of concerns、SoC)とは、ソフトウェア工 学において、プログラムを機能面において可能な限り重複がない、複数の機構に明確に分割 することをいう。ここでいう「関心﴾関心事﴿」とは、プログラムのある機能や振る舞い、目的 のことである。﴾Wikipedia﴿
  4. 4. Aspect﴾AOP﴿とは アスペクト指向プログラミング(アスペクトしこうプログラミング、Aspect Oriented Programming、AOP)は、オブジェクト指向ではうまく分離できない特徴(クラス間を横断 ﴾cross‐cutting﴿ するような機能)を「アスペクト」とみなし、アスペクト記述言語をもちいて 分離して記述することでプログラムに柔軟性をもたせようとする試み。アスペクトの例とし ては、データ転送帯域の制限や例外の処理などがある。Java にアスペクト指向的要素を追加 したAspectJ が実験的に実装されている。﴾Wikipedia﴿
  5. 5. 横断的関心事を解決する手段
  6. 6. 代表的なケースはロギング、トランザクション、キャッシュなどが挙げられます
  7. 7. Laravelで利用する際はRay.Aopを用いている以下のライブラリがオススメ(宣伝) ytake/laravel‐aspect
  8. 8. 利用ケース ロギング 普通はこんな感じ public function get($id) {     Log::info($id);     $this‐>logger‐>info($id); } Logファサードを使ったり、コンストラクトインジェクションしたloggerを使ったり...
  9. 9. LaravelAspectを使うと use YtakeLaravelAspectAnnotationLoggable; class AspectLoggable {     /**      * @Loggable      * @param null $id      * @return null      */     public function normalLog($id = null)     {         return $id;     } }
  10. 10. 利用ケース トランザクション 普通はこんな感じ? public function save(array $params) {     DB::beginTransaction();     try {         $result = $this‐>eloquent‐>save($params);         DB::commit();         return $result;     } catch(Exception $e) {         DB::rollback();         Log::error($e‐>getMessage());         throw $e;     } }
  11. 11. LaravelAspectなら use YtakeLaravelAspectAnnotationTransactional; /**  * @Transactional("master")  * @LogExceptions  */ public function save(array $params) {     return $this‐>eloquent‐>save($params); }
  12. 12. アノテーションで関心の分離ができる
  13. 13. 他にもデフォルトで便利なアノテーションが用意されてます 詳しくはライブラリのREADEMEを見てください。
  14. 14. LaravelAspectに用意されてるアノテーションも便利なんですが 自分たちのアプリに合わせた独自のアノテーションを作り たいですよね?
  15. 15. サンプルケース 最終ログイン日時の記録
  16. 16. まずはLaravelAspectを導入 $ composer require ‐‐no‐update ytake/laravel‐aspect && composer update
  17. 17. Provider登録  config/app.php  'providers' => [     // added AspectServiceProvider      YtakeLaravelAspectAspectServiceProvider::class,     // added Artisan Command     YtakeLaravelAspectConsoleServiceProvider::class, ]
  18. 18. 設定ファイルとかModulesをアプリケーションにコピー $ php artisan ytake:aspect‐module‐publish $ php artisan vendor:publish
  19. 19. こんな感じで追加されます laravel   ‐ app     ‐ Modules       ‐ CacheableModule.php       ‐ CacheEvictModule.php       ‐ CachePutModule.php       ‐ TransactionalModule.php       ‐ LoggableModule.php       ‐ LogExceptionsModule.php       ‐ PostConstructModule.php       ‐ RetryOnFailureModule.php          ‐ config     ‐ ytake‐laravel‐aop.php
  20. 20. 独自アノテーションの定義
  21. 21. use DoctrineCommonAnnotationsAnnotation; /**  * @Annotation  * @Target("METHOD")  * Class LastLoginTime  */ class LastLoginTime extends Annotation {     // } アスペクト利用時は以下の様になる ‐>  @LastLoginTime() 
  22. 22. インターセプターの定義 ※ アノテーションが実行されるときの挙動を定義
  23. 23. use RayAopMethodInvocation; use RayAopMethodInterceptor; use YtakeLaravelAspectAnnotationAnnotationReaderTrait; class LastLoginTimeInterceptor implements MethodInterceptor {     use AnnotationReaderTrait;          /**      * @param MethodInvocation $invocation      * @return object      */     public function invoke(MethodInvocation $invocation)     {       // before         $result = $invocation‐>proceed();         // after         $user = $result‐>getUser();         $lastLoginTime = app()‐>make(AppServiceLastLoginTime::class);         if (!$lastLoginTime‐>update($user)) {             throw new ErrorException("Failed Update Last Login Time");         }         return $result;     } }
  24. 24. // before $result = $invocation‐>proceed(); // after beforeはアノテーションを記述したメソッドが実行される前に実行される。 afterはメソッド実行されたあとに実行される $resultにはそのメソッドの返り値が入ります。
  25. 25. ポイントカットの定義 ※ 特定のアノテーションが実行されるときに起動されるインターセプターを定義
  26. 26. class LastLoginTimePointCut extends CommonPointCut implements PointCutable {     /** @var string */     protected $annotation = AppAnnotationLastLoginTime::class;          /**      * @param Container $app      * @return RayAopPointcut      */     public function configure(Container $app)     {         $this‐>setInterceptor(new LastLoginTimeInterceptor);         return $this‐>withAnnotatedAnyInterceptor();     } }
  27. 27. モジュールの追加 ※ アノテーションが利用されるクラスを定義する
  28. 28. use AppAspectPointCutLastLoginTimePointCut; use YtakeLaravelAspectModulesAspectModule; class LastLoginTimeModule extends AspectModule {     /** @var array */     protected $classes = [         AppHttpControllerLoginController::class,     ];          /**      * @return LastLoginTimePointCut      */     public function registerPointCut()     {         return new LastLoginTimePointCut;     } }
  29. 29. 最後にModulesを以下に登録してあげればOK  config/ytake‐laravel‐aop.php          'modules' => [             ...             // append modules             AppModulesLastLoginTimeModule::class,         ],
  30. 30. まとめ LaravelAspectをとりあえず導入するだけでも楽々AOPが実現できる 拡張もできるので独自の要件にも対応できる 関心を分離することでいちクラスの責務を追求できるようになります 単一責任の原則
  31. 31. thanks :﴿

×