JavaScriptでクリーンアーキテクチャはどうすればいいのか(前編)

#クリーンアーキテクチャとは

##まず以下の記事を推す。

###[持続可能な開発を目指す ~ ドメイン・ユースケース駆動（クリーンアーキテクチャ） + 単方向に制限した処理 + FRP](https://qiita.com/kondei/items/41c28674c1bfd4156186)

私なりの要点は次の通り
* 内側から、DomainModel/Usecase/Interface Adapter/External Adapter
* Interface Adapterが内と外を変換する単一方向のパイプのようなもの
* 外から内への入力がController、内から外への出力がPresenter、入出力を分離する必要がない場合はGateway
* Usecaseに業務手順を書き下す。業務手順の明示的なテストができるって凄い
* Usecase中では、Contolerからの入力で、DB−Gatewayからデータを得て、Presenterに出力し反映など。パイプを繋ぎ直しているようなイメージ
* 出力パイプであるPresenterは**他のUsecaseの入力になったりはしない**(ようにすべき)
* 出力先が別れる時はUsecase中で分ける。パイプはステートレスだから完全に個別にテストできる。素晴らしい


---
## 実装で理解したい場合

###[クリーンアーキテクチャの右下の図](https://nrslib.com/clean-flow-of-control/)

* インタフェースがうんたらは置いておいて、いかに単一方向のパイプであるかイメージできた
* 生成する順番は、outportつまり外側から、interactor=Usecase、その次にcontroller。以下が秀逸

```Java
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翻訳)](https://blog.tai2.net/the_clean_architecture.html)

---
## JavaScriptで実践
### 勤務実績一覧
* 人を選んだら過去勤務実績を年度/毎月(概要あり)のタブ区切りで表示する
  * 毎月、何時間働いたか、その内訳は何か
* 選択ユースケース
  1. 選択した所属部門に属する人だけ絞込可能
      * 選択可能な従業員の勤務形態も同時変更
  2. さらに選択した勤務形態(社員/パート)でも絞込可能
      * この場合は所属部門は絞り込まれない
  3. 同様に、勤務した個別月から絞込可能

### UIイメージ
　![選択UI](https://qiita-image-store.s3.amazonaws.com/0/192607/7f3dc9a6-9956-908c-6aa3-8481e56c08f7.png)

---
### 早速困ったこと
* Usecaseの粒度
  * ひとまず、class Usecaseで一つ
  * FilterUsecase#changeDepartment(i, department)
  * FilterUsecase#changeLabortype(i, labortype)
  * FilterUsecase#changeMember(i, member)
* UIセレクトボックス中の選択状態は?どこに?
  * filterUC.cond = {department: ?, labortype: ?, member: ?}
  * ひとまずUsecaseに?持たせる(いいの?)

```javascript
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編)](https://qiita.com/Gatz/items/6a03b60a2bd903e44202)
* [JavaScriptでクリーンアーキテクチャはどうすればいいのか(Presenter編)](https://qiita.com/Gatz/items/e70d6e854b3bbfef105e)
* [JavaScriptでクリーンアーキテクチャはどうすればいいのか(initializer編)](https://qiita.com/Gatz/items/c224000a510bf0f74298)
* [JavaScriptでクリーンアーキテクチャはどうすればいいのか(Repository編)](https://qiita.com/Gatz/items/ca0c5b7db7321d99451c)
* [JavaScriptでクリーンアーキテクチャはどうすればいいのか(DataStore編)](https://qiita.com/Gatz/items/d93f6ae895c65b8785e5)
* [JavaScriptでクリーンアーキテクチャはどうすればいいのか(DomainModel編)](https://qiita.com/Gatz/items/d88124c9db1facb6f67a)