embryo

エンジニアの備忘録

FluxとDDD(レイヤードアーキテクチャ)について考えてみた

トレタ Advent Calendar 2016 - Qiita 16日目の記事になります。 フロントエンドエンジニアのすえだです。

はじめに

  • Flux実装する上で曖昧性をできるだけ無くすために頑張る話です。
  • ***アーキテクチャはこうあるべきみたいな原理主義的な話はありません。あくまで参考です。

この記事で書いていること

  • Fluxについて
  • DDD(レイヤードアーキテクチャ)について
  • FluxとDDDの関係性
  • Fluxのレイヤー化

Fluxについて

f:id:sue71:20161215193554p:plain

単方向に伝搬されるデータでアプリケーションの状態を表現するアーキテクチャパターンです。 CQRSとEvent Sourcingを組み合わせたような形になります。

恩恵

  • 単方向のデータフローにより、行ったり来たりのような処理が少なく振る舞いを理解しやすい
  • DispatcherやActionがシングルトンで表現されるので参照に悩まされづらい

DDD(レイヤードアーキテクチャ)について

f:id:sue71:20161215195056p:plain

DDD自体はドメインモデルを中心に置いたサービス設計手法とのこと。 実装においてはドメインモデルと技術的関心を分離するために 上記のようなレイヤードアーキテクチャが推奨されています。 (Clean Architectureなどいくつか発展型や派生系がありますがここでは基礎となるこれだけを紹介します)

Infra

定義の上では「上位のレイヤーを支える技術的な基盤」とあり、ライブラリやフレームワークなんかもここに含まれるのですが 本記事では簡単のためにDBやAPIなどの永続化を担う層として考えます。

Domain

いわゆるビジネスロジックになりますが 噛み砕いて言うと「あるデータとその振る舞い」を表現する層になります。

Application

アプリケーションに依存する振る舞いです。 ドメイン層のオブジェクトを協調させるような処理を担当します。

Presentation

UIなどユーザーにとってどう見せたいかを実現する層です。

恩恵

  • 責務が分離されているので実装時に迷うことがない
  • レイヤーが分離されているのでフレームワークに依存せず、リプレイスも容易

FluxとDDD

Fluxの各レイヤーをDDDの視点で整理していきます。

View

Presentation層にあたります。理解しやすいので説明を割愛します。

Action

その名の通り「振る舞い」を記述する部分になります。 APIと疎通し、取得したデータをStoreに伝搬するなど、ある振る舞いに依存するドメインモデルの協調動作を取るような働きをしています。このことからActionはアプリケーションロジックを担っていると言えそうです。

Store

Actionから受け取ったイベントをもとにアプリケーションの状態を変更し、Viewに状態の変更を伝えます。 名前から永続化を担当するInfra層かのように見えますがAPIとの疎通は基本的にActionが行うため、永続化の責務はAction(もしくはActionから実行されるInterface)が担っているように見えます。

しかしながらActionはオンメモリのドメインオブジェクトの集合への参照はもっていないため、バリデーションなどのロジックはStoreが受け持つことになり、ドメインのロジックを含んでいると言えます。

また実装によってはDBへの書き込みはStoreで行ったり、Viewからの参照があるためにViewModelのような属性を持ったりすることもありえるでしょう。

このようにStoreの責務が定まっていないことがFlux実装の曖昧性の原因ではないでしょうか。

Fluxのレイヤー化

そこでStoreの責務に焦点をあてて構造化を目指します。

方針

  • Flux実装における Storeの責務が曖昧なので明確にしたい、また必要であれば分割したい
  • Fluxの良さをできるだけ損なわずにDDDの思想を取り入れたい
  • Storeの破棄についてのケア

3つ目は本記事の内容とズレますがここをカバーしていないと夢物語になりそうなので入れておきます。

こんな感じになった

名前は適当です。

f:id:sue71:20161216065620p:plain

Repository

Repositoryパターンの解釈が分かれるところかとは思いますが、Fluxが解決する問題は基本的にオンメモリの上のやり取りなのでここでいうRepositoryパターンで扱うのは APIまたはDBなどとの処理になります。「APIからデータを取得し、DBに保存する」などの責務を追うことになります。

DomainStore

ドメインオブジェクトに対応したデータを格納するオンメモリのデータストアとして機能します。依然としてドメインロジックは持つことになるのですが、以前の状態よりは責務がスッキリしたかと思います。

PresenterStore

ある興味領域の状態を管理します。またDomainStoreの状態を監視しており、その状態変更に応じて状態を変更します。

またPresenterStoreはあるプレゼンテーション層に紐付いたものなので、プレゼンテーション層のライフサイクルにおいて破棄が可能です。 そのため、DomainStoreをシングルトンにすべきかは定めていません。DomainStoreがPresenterStoreによって管理されている場合は PresenterStoreの責任でDomainStoreに保存したデータも破棄することが可能です。

まとめ

  • FluxをDDDの視点で見たときの各レイヤーの関係性を整理した
  • FluxのStoreを構造化してみた

最後に

Flux実装やVirtualDOMの登場でフロントエンド人口は増えてきて嬉しいのですが、ちゃんとアーキテクチャについて議論できる場は減ったように感じます。(フレームワークやライブラリの話になりがち) なので、このタイミングで今までのアーキテクチャの変遷を整理するのは次なる発展のためにも必要なことだと思いました。

またここでは詳しく話しませんでしたが、他のレイヤードアーキテクチャやCQRS、EventSourcingなんかについてもいつか紹介したいと思います。

明日はmasuidriveによる「React + Rails」の話です。お楽しみに!

クローゼットがいっぱいになったので壁にハンガー掛けを作ってみた – @masuidrive blog

DIYについての話でした(・∀・)

参考資料

DDD, CQRS, EventSourcing

Flux and DDD

Layered Architecture