#クリーンアーキテクチャとは
##まず以下の記事を推す。
###持続可能な開発を目指す ~ ドメイン・ユースケース駆動(クリーンアーキテクチャ) + 単方向に制限した処理 + FRP
私なりの要点は次の通り
- 内側から、DomainModel/Usecase/Interface Adapter/External Adapter
- Interface Adapterが内と外を変換する単一方向のパイプのようなもの
- 外から内への入力がController、内から外への出力がPresenter、入出力を分離する必要がない場合はGateway
- Usecaseに業務手順を書き下す。業務手順の明示的なテストができるって凄い
- Usecase中では、Contolerからの入力で、DB−Gatewayからデータを得て、Presenterに出力し反映など。パイプを繋ぎ直しているようなイメージ
- 出力パイプであるPresenterは他のUsecaseの入力になったりはしない(ようにすべき)
- 出力先が別れる時はUsecase中で分ける。パイプはステートレスだから完全に個別にテストできる。素晴らしい
実装で理解したい場合
- インタフェースがうんたらは置いておいて、いかに単一方向のパイプであるかイメージできた
- 生成する順番は、outportつまり外側から、interactor=Usecase、その次にcontroller。以下が秀逸
static void Main(string[] args)
{
var outputPort = CreateOutputPort();
var interactor = CreateInputPort(outputPort);
var controller = new Controller(interactor);
controller.Execute(new[] {"source", "data", "foo", "bar"});
}
- JavaScriptでは、最近、DOMContentLoadedをよく目にします。
原典
###クリーンアーキテクチャ(The Clean Architecture翻訳)
JavaScriptで実践
勤務実績一覧
- 人を選んだら過去勤務実績を年度/毎月(概要あり)のタブ区切りで表示する
- 毎月、何時間働いたか、その内訳は何か
- 選択ユースケース
- 選択した所属部門に属する人だけ絞込可能
- 選択可能な従業員の勤務形態も同時変更
- さらに選択した勤務形態(社員/パート)でも絞込可能
- この場合は所属部門は絞り込まれない
- 同様に、勤務した個別月から絞込可能
- 選択した所属部門に属する人だけ絞込可能
UIイメージ
早速困ったこと
- Usecaseの粒度
- ひとまず、class Usecaseで一つ
- FilterUsecase#changeDepartment(i, department)
- FilterUsecase#changeLabortype(i, labortype)
- FilterUsecase#changeMember(i, member)
- UIセレクトボックス中の選択状態は?どこに?
- filterUC.cond = {department: ?, labortype: ?, member: ?}
- ひとまずUsecaseに?持たせる(いいの?)
class FilterUsecase {
changeDepartment(i, department){//まずは部門で絞込
this.cond = {department : (i < 1) ? null : department}
const 勤務実績表 = this.repository.q("勤務実績", this.cond);
this.oport["memberfilter"].update(勤務実績表, this)
}
// this.outport["memberfilter"]の実態は、Presenterとする
}
class Presenter
constructor(id){
this.node = document.getElementById(id)
}
update(table, usecase){
//勤務実績repositotyから得られたtableを変換してUIに反映する
//1. Table -> Arrayへ変換 -> domへの中間表現 vdomに変換
const arr = this.selectMember(table)
const vdom = this.toSelectBox(arr)
//2. vdomの内容を、DOMに反映
this.node.appendChild(toDom(vdom).addEventLister("change", (evt)=>{
const i = this.selectedIndex;
const member = this.options[i].text
usecase.changeMember(i, member)
}))
}
- Table->Arrayへの変換はPresenterの役割?Usecaseの役割?
- Array->vdomへの変換はPresenterの役割?Usecaseの役割?
- vdom->DOMへの反映時に
- 部門セレクトボックスの選択で、氏名セレクトボックスが更新される
- さらに、氏名セレクトボックスはonchangeイベントハンドラを持つ必要がある
- onchangeイベントによって最終的に特定一名を指定する
- 従って、changeDepartment()がFilterUsecaseにある以上、usecaseレシーバが引数で与えられる必要がある
- 部門を毎回選択する度に、appendChildするNodeListを消して付け加えるのは冗長では?
- optionタグ分だけを入れ替えれば良いはず
- ...
Usecase編へ続く
- JavaScriptでクリーンアーキテクチャはどうすればいいのか(前編)
- JavaScriptでクリーンアーキテクチャはどうすればいいのか(Usecase編)
- JavaScriptでクリーンアーキテクチャはどうすればいいのか(Presenter編)
- JavaScriptでクリーンアーキテクチャはどうすればいいのか(initializer編)
- JavaScriptでクリーンアーキテクチャはどうすればいいのか(Repository編)
- JavaScriptでクリーンアーキテクチャはどうすればいいのか(DataStore編)
- JavaScriptでクリーンアーキテクチャはどうすればいいのか(DomainModel編)