クリーンアーキテクチャの効用(中間報告)
-
記述する場所に迷わなくなった
- 各モジュールの役割が明確だから
-
各モジュールごとの記述の統一性が生じる
- コードが理解しやすい
-
データの流れが一方向のパイプ(ほとんど)
- 状態を持っているのは、オブジェクト同士の関係の方
-
設計ファイルに落とし込める要素が多い
- 柔軟さを得られる代わりに理解しにくい向きも
記述する場所に迷わなくなった
- どこに何を
- Use Cases: 業務シナリオ。Presentersを通じて、ユーザに結果を提供する
- 欲しいデータはWhat何ですか?「英単語名詞一つ」で表現してください。それがRepositoryから得られるとしましょう。どのように・どうやって得られるかは考える必要はありません
- 得たデータをどこに反映しますか?適切なUI部品を選んで送り出すだけです
- Gateways(Repository, DataStore): ビジネスロジックそのもの。業務上の関心をUse Casesに提供する
- Use Casesから要求されたデータをDataStoreから持ってきて加工します
- データに意味を与えるのが役割です
- Entities: 永続化され、統合されたデータの塊
- Use Casesで使うデータの器
- Presenters: 既存のデータ構造とUI部品のアダプタ
- オリジナルのUI部品を作ることが大半かも
- Controllers: UIイベントとUse Casesの接続。シナリオを呼び出すだけ
- Use Cases: 業務シナリオ。Presentersを通じて、ユーザに結果を提供する
なぜ、これまで自分のソフトウェア設計は迷走していたのか(内省)
- 方法論と実装に乖離がある?
- 方法論をよく理解できていない
従来のソフトウェアに関する「システム設計」の方法論
- システム設計とは入力・出力・入出力をするブロックだけで、システムを構成すること
- システムの各ブロックの分割のやり方が、方法論の各論になる
構造化手法(順次、選択、反復)
-
機能分割の方向に発展
- システムを「機能」ブロックで分ける
- 入力は引数、出力が戻り値
- 入出力を守っている限り、機能ブロックは交換可能モジュールとなる
入出力を何にするか(分割入れ方)は、設計者の裁量
往々にして再利用できないモジュールになる
機能によるデータ処理に矛盾が生じやすい=バグ発生
並行性を持たせるのが非常に難しい
データフロー解析
-
システムとはデータを変換していく一連の流れと捉える
- 処理が主体ではなく、処理と処理の間のデータ(構造)でシステムを分割
- 入力データ構造に対して、出力データ構造への変換を従とする
- 処理よりも、データ構造の方が長く再利用される
仕様書からの「データ構造」の抽出が課題
オブジェクト指向システム設計
-
データ構造を直接考えるのではなく、抽象データ型としてのオブジェクトで分割する
- 業務シナリオを書き下し、その中で名詞がオブジェクトで、動詞がメソッド(機能)
- UML; ソフトウェアシステムを設計する際に、一体、どんな要素が必要なのか
- 業務シナリオ=ユースケース図
- 各個別機能=オブジェクト間の呼び出し関係=シーケンス図
- 並行性という振る舞い
- 従来の方法論は、UMLに統合された感がある。決定版。
業務シナリオを書き下しても、表記の揺れで同じオブジェクトにした方がいいのに別のものになったりする
結局、自然言語で吟味して頑張るよりも実装してテストできる状態で頑張ってしまう
-
UMLが、ソフトウェアシステムを表現する上で非常に的確とわかるが、お絵描きだけに止まりがち
- UMLで書いてそのまま実行可能なプログラムになる(バイナリになるという意味ではない)取り組みもあったが、、、世に出てないよね
一方で、パターンランゲージからソフトウェアアーキテクチャの流れ
- GoFから
- 機能を再利用する(ライブラリ型)のではなく、設計を再利用する(フレームワーク型)という考え方
-
必要なシステムが、どのアーキテクチャに当てはまるか?
- MVCとかMVPとかMVVMとか?
- 不必要にパターンを導入した実装とかね(猛反省)
-
結局は、ソフトウェアシステムとはレイヤードアーキテクチャ
- 抽象化層を導入するのがソフトウェア設計の本質である、と言ってたのは誰だっけ?
-
この流れの先端に、クリーンアーキテクチャがある(ようだ)
- レイヤード→ヘキサゴナル→オニオン→クリーンアーキテクチャ
各モジュールごとの記述の統一性が生じる
- Usecaseを手順と割り切ってしまえば、
- データの入手先はRepositoryだし
- 出力先はPresenterだ
- そして、PresenterがUI部品そのものだ
-
RepositoryとDataStoreで分ける考え方も、
- Table構造は、UI部品的にも必要なので、基本DataStoreの機能は従来提供されていた
- ただ、あえて、Table構造を変換する層とサービスをRepositoryと分けることで、
- 各個別Usecaseへのデータ提供すればいいのやなと迷わなくなる
- むしろ、DataStoreのインタフェースを綺麗に保つことがRepositoryの役割かも
見た目を変えたければPresenterだけいじれば良い
-
データが足りなければRepositoryのメソッドが増える
- データが欲しかったUsecaseの一メソッドの中が修正される
データの流れが一方向のパイプ(ほとんど)
- 状態遷移がもしあるとしたら? 今後の実装で検討したい
設計ファイルに落とし込める要素が多い
- 複数のDataSourceを統合した形でDataStoreとする
- 今回は、表示順序が元テーブルには項目がないので、それを補完した
- 正規化していないテーブルスキーマを、実際は正規化されているものとしたい
- 保守の都合で、処置としてテーブルスキーマ変更せずに、テーブルを追加した場合、とか?
- こういうときに有用
- 設定ファイルをシステムのバージョンをキーにすればシステム移行でテーブル構成が変わってても、ロジックはいっさい変える必要なし
-
各要素の役割がはっきりしているから、各オブジェクトの生成部分を設定ファイルに記述できる
- 設定ファイルも一種のデータベースとすれば、データベースから入力→画面への反映ということでアプリ起動までコードをいっさい書かなくて、よくなるのではないか
- アプリの実行がデータベースベースにできると何がいいかというと、
- 処理の中断をデータベースのバックアップで代用できる可能性が出てくるから
- 設定ファイルも一種のデータベースとすれば、データベースから入力→画面への反映ということでアプリ起動までコードをいっさい書かなくて、よくなるのではないか
-
データベース構造の基本をTableにするかツリーを構造にするか(NoSQL的アプローチ)
- joinがなければアプリケーションロジックからはツリー構造の方が性能いいらしいね
- もし、SQL言語として、内部構造Tableかツリーか気にせず、問い合わせができるドライバを構成できるなら、
- 設定ファイルがツリーであっても扱うロジックはすべてSQLベースにできそう
- それが適切かは置いておいて
-
さらに、アーキテクチャ上、PresentersとContollersに別れたが、DOM構造そのものもデータベースに格納されたデータと考えれば、
- SQL言語でツリー構造にアクセスできるなら、DOM構造向けのドライバとして構成できると、Presenterとして書いてあるコードも、実はものすごくスッキリできる可能性がある(のではないか)
- 設定ファイルをMongoDBに突っ込んでおくのが最短...?
- データベースに読み書きしてる感覚で、DOM操作
- createElementとかappendChildとかもー、書きたくないのだがそれがドライバ次第でSQL的言語構造を持ったオブジェクトを与えるだけでできるとしたら、、、?!
- それってdocument.querySelector()と何が違うの、とかね
- XQueryってキーワードがあったような??
- どっちでもできればええのや
- MongoDBがこんなんって本当ですか(経験なし)
- そんなこんな
クリーンアーキテクチャのいいところ(*個人の感想です)
-
ユースケースをクラス(オブジェクト)として抽出している点
- イベントの処理先がこれまでの(私の実装では)MVC、MVPでいうModelだった
- Aの場合、Bの場合、組み合わせた場合の状態遷移がすべてModelに押し込まれてわやや
- 実装コードが汚いと開発も進めにくい、、、
- イベントは一旦、ユースケースで引き取るでー
- Modelが単純になる
- Usecaseが状態に応じて、処理をふり分けるでー
- 素晴らしい
- MVPでいう、Pは、Viewの状態を一時的に持つらしいから今回の実装で状態をUsecaseにもたせたのは、もチョットなんか工夫できる余地があるのかもしれない
- MVPのPとクリーンアーキテクチャのPが対応しているとは先入観で、実は対応してなくてもいいのかもしれない
- MVPって何やったんや、みたいな感覚を持った
- イベントの処理先がこれまでの(私の実装では)MVC、MVPでいうModelだった
クリーンアーキテクチャのチョット?なところ
- あるの? あるか
-
動的に生成処理するところ特に、イベントハンドラを持つUI部品をPresenterという枠組みでどこまで提供できるのか?
- 静的なUI部品は、今回はControllerで実装した
- 動的な部分は、単にPresenterだけではなく、Usecaseの生成、Controllerの生成手順を踏むべき?
- 単なるViewでいいのならPresenterに任せるというので良さそう。
- Usecaseは当然、複数あり得る。Controllerも?
実装経験を積むことで再報告したい
まとめ
- クリーンアーキテクチャの効用
- 記述する場所に迷わなくなった
- 各モジュールごとの記述の統一性が生じる
- データの流れが一方向のパイプ(ほとんど)
- 設計ファイルに落とし込める要素が多い
- 記述する場所に迷わなくなった
- 発展的な課題
- 設定ファイルもデータベースとして扱う
- データベース基盤がTableかツリーかを気にしなくても良い、クエリ処理実装
- DOM構造をデータベースとするドライバが構成できるかどうか
- MongoDBが面白いかもしれない(今更