SlideShare une entreprise Scribd logo
1  sur  31
Télécharger pour lire hors ligne
LaravelAspectで関心の分離
KenjiroKubota
2017/07/08
Profile
Kenjiro Kubota
istyle.inc
 PHP, HHVM/Hack, Javascript 
DTPDesigner
WebDesigner
FrontEnginner
WebApplicationEngiiner﴾now﴿
関心の分離とは
関心の分離(かんしんのぶんり、英語: separation of concerns、SoC)とは、ソフトウェア工
学において、プログラムを機能面において可能な限り重複がない、複数の機構に明確に分割
することをいう。ここでいう「関心﴾関心事﴿」とは、プログラムのある機能や振る舞い、目的
のことである。﴾Wikipedia﴿
Aspect﴾AOP﴿とは
アスペクト指向プログラミング(アスペクトしこうプログラミング、Aspect Oriented
Programming、AOP)は、オブジェクト指向ではうまく分離できない特徴(クラス間を横断
﴾cross‐cutting﴿ するような機能)を「アスペクト」とみなし、アスペクト記述言語をもちいて
分離して記述することでプログラムに柔軟性をもたせようとする試み。アスペクトの例とし
ては、データ転送帯域の制限や例外の処理などがある。Java にアスペクト指向的要素を追加
したAspectJ が実験的に実装されている。﴾Wikipedia﴿
横断的関心事を解決する手段
代表的なケースはロギング、トランザクション、キャッシュなどが挙げられます
Laravelで利用する際はRay.Aopを用いている以下のライブラリがオススメ(宣伝)
ytake/laravel‐aspect
利用ケース ロギング
普通はこんな感じ
public function get($id)
{
    Log::info($id);
    $this‐>logger‐>info($id);
}
Logファサードを使ったり、コンストラクトインジェクションしたloggerを使ったり...
LaravelAspectを使うと
use YtakeLaravelAspectAnnotationLoggable;
class AspectLoggable
{
    /**
     * @Loggable
     * @param null $id
     * @return null
     */
    public function normalLog($id = null)
    {
        return $id;
    }
}
利用ケース トランザクション
普通はこんな感じ?
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;
    }
}
LaravelAspectなら
use YtakeLaravelAspectAnnotationTransactional;
/**
 * @Transactional("master")
 * @LogExceptions
 */
public function save(array $params)
{
    return $this‐>eloquent‐>save($params);
}
アノテーションで関心の分離ができる
他にもデフォルトで便利なアノテーションが用意されてます
詳しくはライブラリのREADEMEを見てください。
LaravelAspectに用意されてるアノテーションも便利なんですが
自分たちのアプリに合わせた独自のアノテーションを作り
たいですよね?
サンプルケース
最終ログイン日時の記録
まずはLaravelAspectを導入
$ composer require ‐‐no‐update ytake/laravel‐aspect && composer update
Provider登録
 config/app.php 
'providers' => [
    // added AspectServiceProvider 
    YtakeLaravelAspectAspectServiceProvider::class,
    // added Artisan Command
    YtakeLaravelAspectConsoleServiceProvider::class,
]
設定ファイルとかModulesをアプリケーションにコピー
$ php artisan ytake:aspect‐module‐publish
$ php artisan vendor:publish
こんな感じで追加されます
laravel
  ‐ app
    ‐ Modules
      ‐ CacheableModule.php
      ‐ CacheEvictModule.php
      ‐ CachePutModule.php
      ‐ TransactionalModule.php
      ‐ LoggableModule.php
      ‐ LogExceptionsModule.php
      ‐ PostConstructModule.php
      ‐ RetryOnFailureModule.php
      
  ‐ config
    ‐ ytake‐laravel‐aop.php
独自アノテーションの定義
use DoctrineCommonAnnotationsAnnotation;
/**
 * @Annotation
 * @Target("METHOD")
 * Class LastLoginTime
 */
class LastLoginTime extends Annotation
{
    //
}
アスペクト利用時は以下の様になる
‐>  @LastLoginTime() 
インターセプターの定義
※ アノテーションが実行されるときの挙動を定義
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;
    }
}
// before
$result = $invocation‐>proceed();
// after
beforeはアノテーションを記述したメソッドが実行される前に実行される。
afterはメソッド実行されたあとに実行される
$resultにはそのメソッドの返り値が入ります。
ポイントカットの定義
※ 特定のアノテーションが実行されるときに起動されるインターセプターを定義
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();
    }
}
モジュールの追加
※ アノテーションが利用されるクラスを定義する
use AppAspectPointCutLastLoginTimePointCut;
use YtakeLaravelAspectModulesAspectModule;
class LastLoginTimeModule extends AspectModule
{
    /** @var array */
    protected $classes = [
        AppHttpControllerLoginController::class,
    ];
    
    /**
     * @return LastLoginTimePointCut
     */
    public function registerPointCut()
    {
        return new LastLoginTimePointCut;
    }
}
最後にModulesを以下に登録してあげればOK
 config/ytake‐laravel‐aop.php 
        'modules' => [
            ...
            // append modules
            AppModulesLastLoginTimeModule::class,
        ],
まとめ
LaravelAspectをとりあえず導入するだけでも楽々AOPが実現できる
拡張もできるので独自の要件にも対応できる
関心を分離することでいちクラスの責務を追求できるようになります
単一責任の原則
thanks :﴿

Contenu connexe

Tendances

MongoDBを用いたソーシャルアプリのログ解析 〜解析基盤構築からフロントUIまで、MongoDBを最大限に活用する〜
MongoDBを用いたソーシャルアプリのログ解析 〜解析基盤構築からフロントUIまで、MongoDBを最大限に活用する〜MongoDBを用いたソーシャルアプリのログ解析 〜解析基盤構築からフロントUIまで、MongoDBを最大限に活用する〜
MongoDBを用いたソーシャルアプリのログ解析 〜解析基盤構築からフロントUIまで、MongoDBを最大限に活用する〜
Takahiro Inoue
 

Tendances (20)

MongoDBを用いたソーシャルアプリのログ解析 〜解析基盤構築からフロントUIまで、MongoDBを最大限に活用する〜
MongoDBを用いたソーシャルアプリのログ解析 〜解析基盤構築からフロントUIまで、MongoDBを最大限に活用する〜MongoDBを用いたソーシャルアプリのログ解析 〜解析基盤構築からフロントUIまで、MongoDBを最大限に活用する〜
MongoDBを用いたソーシャルアプリのログ解析 〜解析基盤構築からフロントUIまで、MongoDBを最大限に活用する〜
 
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
 
詳説データベース輪読会: 分散合意その2
詳説データベース輪読会: 分散合意その2詳説データベース輪読会: 分散合意その2
詳説データベース輪読会: 分散合意その2
 
人生がときめくAPIテスト自動化 with Karate
人生がときめくAPIテスト自動化 with Karate人生がときめくAPIテスト自動化 with Karate
人生がときめくAPIテスト自動化 with Karate
 
Azure DevOps ハンズオン Vo.3 ~Delivery Plans を用いたプロジェクトのスケジュール管理~
Azure DevOps ハンズオン Vo.3 ~Delivery Plans を用いたプロジェクトのスケジュール管理~Azure DevOps ハンズオン Vo.3 ~Delivery Plans を用いたプロジェクトのスケジュール管理~
Azure DevOps ハンズオン Vo.3 ~Delivery Plans を用いたプロジェクトのスケジュール管理~
 
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方
 
12 分くらいで知るLuaVM
12 分くらいで知るLuaVM12 分くらいで知るLuaVM
12 分くらいで知るLuaVM
 
GKE に飛んでくるトラフィックを 自由自在に操る力 | 第 10 回 Google Cloud INSIDE Games & Apps Online
GKE に飛んでくるトラフィックを 自由自在に操る力 | 第 10 回 Google Cloud INSIDE Games & Apps OnlineGKE に飛んでくるトラフィックを 自由自在に操る力 | 第 10 回 Google Cloud INSIDE Games & Apps Online
GKE に飛んでくるトラフィックを 自由自在に操る力 | 第 10 回 Google Cloud INSIDE Games & Apps Online
 
Azure Data Explorer
Azure Data ExplorerAzure Data Explorer
Azure Data Explorer
 
Azureをフル活用したサーバーレスの潮流について
Azureをフル活用したサーバーレスの潮流についてAzureをフル活用したサーバーレスの潮流について
Azureをフル活用したサーバーレスの潮流について
 
Azure Database for MySQL PostgreSQLを使って運用の手間を省きませんか?
Azure Database for MySQL PostgreSQLを使って運用の手間を省きませんか?Azure Database for MySQL PostgreSQLを使って運用の手間を省きませんか?
Azure Database for MySQL PostgreSQLを使って運用の手間を省きませんか?
 
サーバーサイドな人がフロントエンド技術と仲良くするはじめの一歩
サーバーサイドな人がフロントエンド技術と仲良くするはじめの一歩サーバーサイドな人がフロントエンド技術と仲良くするはじめの一歩
サーバーサイドな人がフロントエンド技術と仲良くするはじめの一歩
 
MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法
 
Yahoo! ニュースにおける ドキュメント管理の事例紹介
Yahoo! ニュースにおけるドキュメント管理の事例紹介Yahoo! ニュースにおけるドキュメント管理の事例紹介
Yahoo! ニュースにおける ドキュメント管理の事例紹介
 
あなたの知らないPostgreSQL監視の世界
あなたの知らないPostgreSQL監視の世界あなたの知らないPostgreSQL監視の世界
あなたの知らないPostgreSQL監視の世界
 
MongoDB〜その性質と利用場面〜
MongoDB〜その性質と利用場面〜MongoDB〜その性質と利用場面〜
MongoDB〜その性質と利用場面〜
 
分割と整合性と戦う
分割と整合性と戦う分割と整合性と戦う
分割と整合性と戦う
 
みんな大好き“全文検索 on AWS”を試してみました!
みんな大好き“全文検索 on AWS”を試してみました!みんな大好き“全文検索 on AWS”を試してみました!
みんな大好き“全文検索 on AWS”を試してみました!
 
WayOfNoTrouble.pptx
WayOfNoTrouble.pptxWayOfNoTrouble.pptx
WayOfNoTrouble.pptx
 
トランザクション処理可能な分散DB 「YugabyteDB」入門(Open Source Conference 2022 Online/Fukuoka 発...
トランザクション処理可能な分散DB 「YugabyteDB」入門(Open Source Conference 2022 Online/Fukuoka 発...トランザクション処理可能な分散DB 「YugabyteDB」入門(Open Source Conference 2022 Online/Fukuoka 発...
トランザクション処理可能な分散DB 「YugabyteDB」入門(Open Source Conference 2022 Online/Fukuoka 発...
 

Plus de Kenjiro Kubota

アイスタイル特設サイトにおけるVue.js導入事例(再演)
アイスタイル特設サイトにおけるVue.js導入事例(再演) アイスタイル特設サイトにおけるVue.js導入事例(再演)
アイスタイル特設サイトにおけるVue.js導入事例(再演)
Kenjiro Kubota
 
カメラを利用したアプリを作って約1000人で遊んだ話
カメラを利用したアプリを作って約1000人で遊んだ話カメラを利用したアプリを作って約1000人で遊んだ話
カメラを利用したアプリを作って約1000人で遊んだ話
Kenjiro Kubota
 

Plus de Kenjiro Kubota (20)

いまどき(これから)のPHP開発
いまどき(これから)のPHP開発いまどき(これから)のPHP開発
いまどき(これから)のPHP開発
 
アイスタイル特設サイトにおけるVue.js導入事例(再演)
アイスタイル特設サイトにおけるVue.js導入事例(再演) アイスタイル特設サイトにおけるVue.js導入事例(再演)
アイスタイル特設サイトにおけるVue.js導入事例(再演)
 
gRPC入門
gRPC入門gRPC入門
gRPC入門
 
アイスタイル特設サイトにおけるVue.jsの導入事例
アイスタイル特設サイトにおけるVue.jsの導入事例アイスタイル特設サイトにおけるVue.jsの導入事例
アイスタイル特設サイトにおけるVue.jsの導入事例
 
Akkaとは。アクターモデル とは。
Akkaとは。アクターモデル とは。Akkaとは。アクターモデル とは。
Akkaとは。アクターモデル とは。
 
フロントエンドエンジニアが知るべきFirebaseの世界
フロントエンドエンジニアが知るべきFirebaseの世界フロントエンドエンジニアが知るべきFirebaseの世界
フロントエンドエンジニアが知るべきFirebaseの世界
 
PHP,Go,Elasticsearchによる、@cosmeを5倍速くする取り組み
PHP,Go,Elasticsearchによる、@cosmeを5倍速くする取り組みPHP,Go,Elasticsearchによる、@cosmeを5倍速くする取り組み
PHP,Go,Elasticsearchによる、@cosmeを5倍速くする取り組み
 
カメラを利用したアプリを作って約1000人で遊んだ話
カメラを利用したアプリを作って約1000人で遊んだ話カメラを利用したアプリを作って約1000人で遊んだ話
カメラを利用したアプリを作って約1000人で遊んだ話
 
中・大規模でLaravelを導入するTips
中・大規模でLaravelを導入するTips中・大規模でLaravelを導入するTips
中・大規模でLaravelを導入するTips
 
FirebaseとNuxtでLPを作って見た
FirebaseとNuxtでLPを作って見たFirebaseとNuxtでLPを作って見た
FirebaseとNuxtでLPを作って見た
 
introducing vue-wait-component
introducing vue-wait-componentintroducing vue-wait-component
introducing vue-wait-component
 
HHVM/Hackを本番投入した話
HHVM/Hackを本番投入した話HHVM/Hackを本番投入した話
HHVM/Hackを本番投入した話
 
HackのAsyncCurlで死んだ話
HackのAsyncCurlで死んだ話HackのAsyncCurlで死んだ話
HackのAsyncCurlで死んだ話
 
LaravelでAPI定義を管理する
LaravelでAPI定義を管理するLaravelでAPI定義を管理する
LaravelでAPI定義を管理する
 
2017: A CSS Design Odyssey
2017: A CSS Design Odyssey2017: A CSS Design Odyssey
2017: A CSS Design Odyssey
 
Introducing hhvm hack-async
Introducing hhvm hack-asyncIntroducing hhvm hack-async
Introducing hhvm hack-async
 
Responsableを使ったadr実装
Responsableを使ったadr実装Responsableを使ったadr実装
Responsableを使ったadr実装
 
土日でLineみたいなチャット作ってきた!
土日でLineみたいなチャット作ってきた!土日でLineみたいなチャット作ってきた!
土日でLineみたいなチャット作ってきた!
 
Viewを活用して複雑化と戦う
Viewを活用して複雑化と戦うViewを活用して複雑化と戦う
Viewを活用して複雑化と戦う
 
Laravelでfacadeを使わない開発
Laravelでfacadeを使わない開発Laravelでfacadeを使わない開発
Laravelでfacadeを使わない開発
 

Laravel aspectで関心の分離