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

# Repositoryとは?

* 永続されるべきデータを取得するための**インタフェース**
* 依存関係逆転の話はよくわかってない(後回し)
* ひとまず、以下のLaborRepositoryから。

```javascript
window.addEventListener("DOMContentLoaded", function(evt){

  const repository   = new LaborRepository(COMPANY);
  const presenter    = new Presenter();
  const filterUC     = new filterUsecase(repository, presenter);
  const viewController = new Controller(filterUC);

  viewController.onload(evt);
})
```

---
# LaborRepository: 0版
* 素朴
    * LINQ的 メソッドを持つTableオブジェクトの集合        
    * メソッドの戻り値は基本Tableにするという思想
* となると、
    * TableからArrayにするまでが**長い**

```javascript
   //こんなのとか
class FilterUsecase {
   //こんなのとか
  filterByDepartment(table){//Usecase中ではpresenterが受け取れる配列データ構造に変換
    //この場合はTable -> Arrayへ; "所属"の列だけを抜き出して配列へ
    return table.select("所属").uniq()
      .left_join(this.repository.from("所属部門"), (a, b)=>{return a["所属"]==b["部門名"]}.orderby("表示順")
      .select("所属").toArray()   
  }
  //こんなのとか
  filterByMember(table){
      return table.select("氏名").uniq()
         .left_join(this.repository.from("従業員"),(a, b)=>{a["氏名"]==b["名前"]}).orderby("表示順").toArray()
  }
}
```

# DomainModelとしては、最終結果に近い結果を得るのが適切
   * 　これまでは勤務実績を条件付きで検索
      * const 勤務実績表 = this.repository.q("勤務実績", this.cond)
      * const departments = this.filterByDepartment(勤務実績表)          
   * テーブル構造や属性名は、会社固有とみなすべき
    * RepositoryにはCOMPANY情報が必要

# UsecaseはDomainModelのデータ形式変換が役割
   * const departments = this.repository.departments(this.cond)
   * これくらい単純な方が良いことになる
   * しかし、これではRepositoryへのAPIが増えることになる

# Usecaseは「手順」を記述する役割もある
   * ここは高水準なAPIをrepositoryが備えるべき

---
# LaborRepositoryの修正

![Repositoryは壁](https://qiita-image-store.s3.amazonaws.com/0/192607/298dd1f7-ab2f-d803-dcf2-d36c5e895949.png)


---
# DomainModelへの考察

## 納得
* Repository側にデータ変換があるのでUsecaseが明確に
    * Entity->DomainModel
* 一方でUsecaseとしてのデータ変換は**必ず**残る
    * Viewが必要とするデータ構造をRepositoryは用意できない
    * ViewがRepositoryの事を知らんで良いように
    * RepositoryがViewの事を知らんで良いように

## 疑問
* できるだけデータ渡すから、View側でよろしくやってよ
    * ありがち: データ**構造**が変わるたびにView側も変更が
* なんとかならんの? => **なります**

## 問題になる場合とは、動的なページ
* データ構造がページ構造に反映する場合
    * 単なる配列や値程度のデータ**要素**の話では問題にならない
* データには**構造がある**
    * ツリーとか
    * 新入社員はデータが何年もない=>人によってツリー構造がちがう
* Repositoryから得られたデータの内部構造を知らなくてもデータ構造がわかるように
    * やりとりするデータに構造を得られるようなイテレータを定義しておくなどできるとViewが頑健になる
* 戻り値もinterfaceということはそういうこと?
* ~~たぶんそのはず~~いやわからんわ

---
# まとめ

* Repositoryがなぜインターフェースか？
    * Usecase本来の役割が明確になる
        * 業務手順を記述すること 
    * 一方でUsecaseとしてのデータ変換は必ず残る
      * Viewが必要とするデータ構造をRepositoryは**用意できない**
      * ViewがRepositoryの事を知らんで良いように
      * RepositoryがViewの事を知らんで良いように
    * DomainModelがイテレータとか持ってるとViewが助かる(はず)
* 戻り値もインターフェースとはどういうことか?必要なの?
    * まだわかんねぇ
    
---
# DataStore編に続く

## 全記事
* [JavaScriptでクリーンアーキテクチャはどうすればいいのか(前編)](https://qiita.com/Gatz/items/d6b0250bfab6e1e74d69)
* [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編)
* [JavaScriptでクリーンアーキテクチャはどうすればいいのか(DataStore編)](https://qiita.com/Gatz/items/d93f6ae895c65b8785e5)
* [JavaScriptでクリーンアーキテクチャはどうすればいいのか(DomainModel編)](https://qiita.com/Gatz/items/d88124c9db1facb6f67a)