なんなんだ、を考える。 あらゆるクライアントログを一般化する。結論はない。まだまだ考え中。
初期
- 特定画面を開いた
- 特定画面の読込が(一定の基準を元に)完了した
中期
- UIEvent
- 何かUIを操作した
- UIEventを元に実行されたタスクが(成功|失敗)した
- 画面読込後一定時間が経過した
後期
- 特定画面から離れた
- アプリケーションが終了した
ライフサイクル問わず
- 3rd party製ライブラリ等外的要因のEvent
- Background実行されるタスクののEvent
- 開始、終了etc
- 常時接続なストリームからのEvent
Viewにクライアントログ仕込まない場合に何処に仕込むか
一番のモチベーション。 ログを仕込む実装が、Viewコードを汚染してはならない。 Viewは純粋にViewの実装のみに集中できなければならない。
では何処に仕込むか。
- UI Eventを起点とするCommandのpre-process
- 画面読込を起点とするQueryResultのpost-process
- ただし中身が必要かは場合による
- Commandの結果となるEventのpost-process
他
Sessionの概念は必要。ログ世界におけるSessionとは起点と終点があり、何かしらのEventを起点または終点とし、終点までのイベントを関連付ける。
どう一般化する?
ライブラリでの提供は言語機能としてmethod hookが必須となる。refectionによる実現は流石にコストが高い。やりたくない。となるとフレームワークに組み込む必要がある。
フレームワークに組み込むとした場合。ルールを書けばあとはViewに一切ログを仕込むコード書かずPresenterがなんとかしてくれる感じにできそうな気はする。 multi-modules化がだるい。Eventに基づくログ収集のルールを記述するには、本来moduleの中に閉じていたEventをmodule外に出す必要がある。[先日のブログ] (/post/distilling-viper-architecture.html) にて記載したDefinitionsを軸に考えた場合、Eventを外に出せばDTOの一部のデータをmodule外に出す必要がでてくる。これは分かりにくい。Definitionsだけをまとめたmoduleを作るべきか。これもなかなかむずい。moduleの中に閉じていたDefinitionsを丸々外に出す場合のアプリケーション設計全体の学習コスト、理解可読性は正直あまり期待できない。
ではannotation processingはどうか。annotation processingでログ抽出ポイントを定める。ルールを記述する。ルールを記述するとなるとやはりフレームワーク同様にEventをmodule外に出す必要が出てきてしまう…?
本当にmodule外に出さなければいけないのか?それらの画面は関連づいているのだから、1つのmoduleに収めるのが本来は適切であると言える。ただ、moduleを細かく切り出すという行為がビジネス的価値を生み出す世界になっている。Androidのdynamic features等。それを考慮した場合、やはりmodule外に出さなければならない。この先はフレームワークの項に書いた事が追随してくる。
ここまで考えると、やはりログコードをViewの中にベタに仕込むように書くのが正解なのか、という気になってくる。やりたい事に対して規模があまりにでかい。コードは汚いがベタに書くのは正解なのか。まだまだ考える必要がある。この先考える事としては、Definitionsにmodule名を記載してContract出力moduleをコントロールする、lint ruleを吐き出す(他moduleで使用しないようにする)等がある。