LoginSignup
28

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-09-19
1 / 7

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

まず以下の記事を推す。

持続可能な開発を目指す ~ ドメイン・ユースケース駆動(クリーンアーキテクチャ) + 単方向に制限した処理 + 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で実践

勤務実績一覧

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

UIイメージ

 選択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編へ続く

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28