Pro Yearly is on sale from $80 to $50! »

FlutterとAngularDartを DIとClean Architectureで いい感じにする

Aa2271fde3c839f2ab82d1d27dbbc650?s=47 takayuki-hayashi
July 18, 2018
1.3k

FlutterとAngularDartを DIとClean Architectureで いい感じにする

Aa2271fde3c839f2ab82d1d27dbbc650?s=128

takayuki-hayashi

July 18, 2018
Tweet

Transcript

  1. FlutterとAngularDartを DIとClean Architectureで いい感じにする

  2. 自己紹介 • 名前:林 尚之(はやし たかゆき) • Agile(XP)、TDD、DDDとかが好き • 株式会社ユーザベース ◦

    SPEEDA日本事業 CTO • twitter: @t_hyssh 宣伝:9月の「XP祭り 2018」で登壇します
  3. Mobile & Web Mobileの画面 Webの画面 ボタンをクリックすると数字がカウントアップ Webのスタイルがあれなのはご愛嬌・・・

  4. 「ボタンがクリックされると数字がカウントアップ」 という処理 これをFlutterとAngularDartで共通化してみる

  5. 「ボタンがクリックされると数字がカウントアップ」 という処理 ここから共通化可能なドメインロジックを抽出

  6. 「ボタンがクリックされると数字がカ ウントアップ」 ボタンをクリックするという処理は現状では完全 にUI側の処理なので除外

  7. 「数字がカウントアップ」 もうちょっといい表現にしてみる

  8. 「現在のカウントをインクリメントする」 いい感じ

  9. 「現在のカウントをインクリメントする」 この処理をAngularDartとFlutterで共通化する ためには・・・

  10. Clean Architectureの出番

  11. Clean Architectureの出番 Clean Architectureに則れば UseCaseとEntity(Domain Model)は外部リソースや UIに依 存しない。 ポイントは「画面の状態」保存先 (実際はインメモリ)を一番外側に

    持っていく事。その状態を Gatewayを介して取得、保存す る。Gatewayの実装が AngularDartとFlutterで独自の実 装になり、実装は DIされる。
  12. 「現在のカウントをインクリメントする」 これをClean Architectureに合わせて再度修正

  13. 「現在のカウントを取得し、 インクリメントして保存する」 あとはこれをDartのコードにするだけ

  14. Use Case

  15. Domain イミュータブル好きなのでとりあえずイミュータブル

  16. Port(Use Caseレイヤー) • PortはUse Caseレイヤーに存在する仕様 • ドメインの取得や保存の仕様を定義 • このPortの仕様を実装したGatewayがAngularDartとFlutterそ れぞれに存在

    • 上記GatewayをDIする 依存関係逆転の原則( DIP)
  17. Gateway(Flutter) ドメインの情報を基に状態を保存 (保存先はCountViewModelで、こいつを表示側が参照する。詳細は後ほど)

  18. Gateway(AngularDart) ドメインの情報を基に状態を保存 (保存先はCountViewStateで、こいつを表示側が参照する。詳細は後ほど)

  19. 次はこの「状態」を AngularDartとFlutterでどうやって 表示するのか

  20. FlutterはScoped Model AngularDartはChange Detection

  21. Scoped Model(Flutter) • Googleが開発しているマイクロカーネルの OSであるfuchsiaのUI(Flutter)にて採用されている 状態管理の考え、アーキテクチャー • 親Widgetから子孫のWidgetに簡単にModelを渡す事が出来るようになる • Modelの更新時にModelを使用する全ての子

    Widgetを再レンダリング • StatefullWidgetとState<T>を使用しなくてよくなる ◦ その代わりScopedModelDescendantを多用する • 詳細は https://github.com/brianegan/scoped_model
  22. Scoped Modelの使用例

  23. Scoped Modelの使用例(Model)

  24. Scoped Modelの使用例(Widget) ここでScopedModelを使うとMaterialApp の子孫WidgetにてCountModelを参照し やすくなる

  25. Scoped Modelの使用例(Widget) ScopedModelDescendantを使う事で builderの第3引数にmodelが渡される DI(というかService Locator)から UseCaseを取得しドメインロジックを実行

  26. Change Detection(AngularDart) • 詳細はlacoさんのブログを見てもらうのが一番(笑) ◦ https://blog.lacolaco.net/post/translation-angular-2-change-detection-explained/ • ざっくりいうと ◦ Componentの状態や参照しているオブジェクトの状態の変更を検知して再レンダリングしてくれる

    ◦ なのでComponentが参照するオブジェクトを DIの管理下に置いて、前述の Gateway側で更新をすると勝手に 画面が更新される
  27. AngularDartの例(Component) CountStateは単なるDartのクラス。DIの管 理下に置くための設定は必要

  28. これらの考えを基にしつつモジュール化 などをすれば画面側のクラスは状態の 参照とUseCaseの実行(イベントの発 火)のみにする事が可能

  29. AngularDartはDIがビルトインされてい るがFlutterはDIは外部ライブラリーが必 要 自分はGoogleから出てるのを使ってます https://github.com/google/inject.dart

  30. Scoped Model(Flutter)、Change Detection(AngularDart)とDIで下記のよ うな単方向アーキテクチャーに Component(Widget) UseCase Gateway State(Model) *矢印は依存関係ではなく、データの流 れ

    変更の通知
  31. レイヤー詳細 Component(Widget) UseCase Gateway Model(State) Domain Component(Widget)レイヤー Gatewayレイヤー Domainレイヤー UseCaseレイヤー

    <<Interface>> Port
  32. まとめ • DIとScoped Model、依存関係逆転の原則を適用する事でAngularDartとFlutterの間で自然な 形でコードの共通化が可能 • UI(Flutter、AngularDart)に依存しなくなるのでUnit Testも書きやすくなる • 非同期にしたりStream使ってReactiveにするのも簡単

    ◦ なぜなら単なるDartのコードだから • 「ここまでして共通化する必要あるの?」と問われれば 「モバイルPWAとアプリで全く同じ挙動にしたいという仕様でなければ共通化は逆に足かせに なるんじゃないでしょうか」と答えますw • ただし、Clean Architectureに則れば保守性、拡張性の高いコードにしやすいと思うので共通 化しなくてもチャレンジする価値はあると思います