ドメイン駆動設計を試した話

ReactNativeを使ってアプリを作っている。データベースを操作する非同期関数をMobxのモデルで書き始めてからプログラムの構造が破綻していた。アーキテクチャ設計を適当にやると機能追加できなくなる。mobxにメリットを感じなくなったので、よりデファクトスタンダードなReduxを導入し、ついでにドメイン駆動開発の考え方も勉強した。

やったこと

  • mobxやめてreduxにした
    • runInActionが本末転倒
  • modelをRedux store + serviceに分けた
    • 非同期処理なし
  • daoがentityではなくdtoを返すようにした
  • そのほかいろいろ

Javascript

  • const Func と function()の違い

  • interface generic function

    • interface IGetter {
          get<T>(): T
      }
      class GetA implements IGetter {
          get<A>(): A {...} // Wrong
      }
      class GetA implements IGetter {
          get<T>(): T {...} // OK
      }
      
    • read here: https://www.typescriptlang.org/docs/handbook/generics.html
    • 謎エラー
      • 'xxx' could be instantiated with an arbitrary type which could be unrelated to 'yyy'
      • '' is not assignable to the same property in base type
  • Promise.prototype.finally => ES2018.promise

  • Array.prototype.forEachの第3引数で元の配列をいじれるよ

    • c++のイテレータの感覚だと不思議

OOP

  • Dependency Injection
    • 依存関係をコンストラクタを通して渡し、コンポーネントを疎結合に保つデザインパターン
    • インターフェイスを介せば実装を差し替えられる
    • コンストラクタの引数が多くて初期化が面倒
      • DIContainer, ServiceLocatorなどを使ってインスタンスの組み合わせを事前に定義
  • DI Container
    • Dependency Injectionを実現するためのフレームワーク?
    • @injectableみたいなアノテーションはちょっと苦手
  • ServiceLocator
    • DependencyInjectionを使ったはいいものの、その実体はどこで生成するの?
    • ServiceLocatorに登録しておいて、利用者がここから取り出す
    • DIコンテナがやっていることと同じでは?
    • ServiceLocatorへの依存性が発生する。
      • 不要な依存性が発生する、依存性が分かりにくくなる、テスト困難になる
    • https://www.nuits.jp/entry/servicelocator-vs-dependencyinjection

      DIコンテナを利用する場合は、同様のジレンマが発生しますが、DIコンテナを利用 せずにDIパターンだけを利用する事も出来ます。つまりDIを採用した場合、選択権は利用者にありますがServiceLocatorでは利用者に選択権がありません。

      • ここの説明が一番しっくりきた
  • AbstractFactoryと何が違うん?
  • Inversion of Control

DDD

  • DDD vs OnionArchitecture vs CleanArchitecture
    • DDDのやり方が複数あり、それぞれ登場する言葉が違う。これがややこしい。
    • 大きく分けると
      • ドメイン
      • インフラ(Network, Database, Presentor/UI...)
      • 二つを繋ぐもの(Applocation Service, Adapter...)
  • DAO vs DTO vs Entity
    • Entityはドメインロジックの中に登場する存在
    • DAO(DataAccessObject)はデータベースかのデータにアクセスする責務を果たす。
      • データベース操作を素直に実装すればヨシ
      • ORMよりも単純。RelationalMappingしない。
      • Entity>DTO>DAO>IDatabase
      • 最初Infrastructureレイヤに置いたけど、途中からDTOと同じレイヤに置いた。
        • 結局どこのレイヤに置くのが正しいんだろう?
          • DDDで登場するRepositoryはドメインレイヤのものだが、実装はInfrastructureっぽい。
  • DTO(DataTransferObject)はレイヤを跨いでデータを渡すときに使うもの
  • DDDのEntityとCAのEntityはどう違う?

Redux

  • globalInstanceはstoreに入れる?それとも外部モジュールを使ってアクセスする?
  • 当たり前の話
    • Storeが更新されたらStoreを更新する処理を書いたら無限ループする。
    • アプリケーションが固まりはしなかった。非同期処理だったからかな?

ReactNative

  • SQLite.enablePromise(true);
  • Database
    • 使うときにだけ接続し、使い終わったら切断するパターンが多い
      • インスタンスを使うときにnewして接続し、使い終わったら解放する
      • c#(.NET)はコネクションプールがあるのでオーバヘッド少ない(using ...)
      • Webアプリもコネクションプールを使い、リクエスト毎に借用・解放する
    • ReactNativeも同じことできるのかな?

失敗したこと

  • ReactNativeでProjectRootからimportする
    • 調査不足

その他

  • 業を暴く