Slide 1

Slide 1 text

Clean Architecture with Vue Vue.js / Nuxt.js Meetup Osaka #0 by andoshin11 Attempting

Slide 2

Slide 2 text

Who am I ? ● Andy (@andoshin11) ● Vue.js Japan User Group ● Frontend Developer @FOLIO ● JS, Ruby, Go, Perl, Python, PHP, Rust(?)

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Vue Fesやります!!

Slide 5

Slide 5 text

本日のゴール ● Clean Architectureの概要を理解する ● 「VueにClean Architectureを導入すべきか」を判断できるようになる

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Clean Architectureの基本 ・オニオン型のレイヤードアーキテクチャ ・各レイヤーの名前は重要ではない ・依存性の矢印が単方向であることが大切 ・内側のレイヤーは外の世界を知らない

Slide 8

Slide 8 text

Clean Architectureの特徴 ● ビジネスロジックがFWやUI、DB、外部API等に依存しない(Testable) ● ビジネスロジックはEntitiesとUsecasesに集約される ● 外界(UI等)からのデータの読み書きはInterface Adapter(Presenter, Controller) を通して行われる

Slide 9

Slide 9 text

アプリケーション実装パターンのおさらい ● MVC ● MVVM ● DDD ● Flux

Slide 10

Slide 10 text

MVC(割愛) ・Model - View - Controller ・Railsが採用しているやつ ・ViewがModelをObserve ・Fat Model, Fat Controller問題 ・「データの振舞い」を定義する余地がない

Slide 11

Slide 11 text

MVVM(割愛) ・Vue Componentがやってるやつ ・Modelは生データおよびDomain Model ・ファサードとしてのVM ・ViewとVMにおいてデータバインディングが成立しているので Presenterやイベントを受け 取るControllerが不要

Slide 12

Slide 12 text

DDD(レイヤードアーキテクチャ) ・業務上の関心事(ドメイン)を中心に据えた 設計手法 ・Domain Layerでデータの振舞を定義 ・責務が分離されているため、フレームワー クやライブラリに依存しづらい ・レイヤー間の依存性は単方向でない

Slide 13

Slide 13 text

Flux ・Facebook社が提唱 ・Redux, Vuex等 ・CQRS ・Event Sourcing ・単方向データフロー

Slide 14

Slide 14 text

Flux はClean Architectureに近い?

Slide 15

Slide 15 text

DDDの観点から見るFlux(Vuex) ● UIコンポーネント - Presentation層にあたる。イベントの発火も。 ● Action - Application層。API通信だけでなくデータ処理に必要な手続き全般を担うた めDomain層も兼ねることが多い。 ● Mutation - StoreのInput Port。ロジックは持たない。 ● Store - オンメモリでデータを永続化。外部への柔軟な Output Portを持つ。

Slide 16

Slide 16 text

Vuexを利用したFluxパターン(課題) ● Actionsにアプリケーションロジックが集約しがち。 ● ドメインモデル(振舞いを持ったデータモデル)ってどこに書くんだっけ? ● Storeの構造がViewを意識したものになりがち ● Gettersを全てのViewに用意するのは厳しい ● Mutation(≒ Store)にロジックを書く人間が後を断たない (書けてしまうので) ● 本当にTestable?

Slide 17

Slide 17 text

スケールしなさそう・・・

Slide 18

Slide 18 text

今回の設計方針 ・より厳密なレイヤー分割を行う ・業務上の関心と技術上の関心を分離 → Domain Modelの活用(DDD Like) ・シンプルなイベント伝達 → 単方向データフロー(Flux Like) ・依存性も単方向にしてよりテスタブルに → Clean Architecture ・フレームワークや外部のI/Fに依存しない → Gatewayの活用

Slide 19

Slide 19 text

スケールさせるぞ!!

Slide 20

Slide 20 text

Container Controller Use Case Repository Store Entity Presenter UI Components Query Command

Slide 21

Slide 21 text

アプローチ ● Controllerからイベントを発火 ● Usecaseにビジネスロジックを記述。DI(依存性の注入)はControllerで ● データモデルの振舞いを定義する Entity層を用意 ● Repository内でStoreにアクセス ● UIはPresenterで抽出したデータセットの写像である

Slide 22

Slide 22 text

実装編 https://github.com/andoshin11/clean-architecture-example-vue

Slide 23

Slide 23 text

登場人物 今回はNuxtつかってません!! (土下座)

Slide 24

Slide 24 text

Store ● DomainごとにModule化 ● Actionsは持たない ● Observableな箱としての用途 ● 無理やり型付けしてます

Slide 25

Slide 25 text

Entity ● Interfaceの提供 ● Domainロジックの定義 ● Data Store Layerへの読み書きを許 容(through Vuex API)

Slide 26

Slide 26 text

Repository ● アプリケーション固有のDomainロ ジックを定義 ● Data Store Layerへアクセスを持つ (through Vuex API)

Slide 27

Slide 27 text

Container ● UIの表示単位 ● Atomic DesignでいうPages? ● ContainerごとにUse Caseと Presenterを持つ ● Containerを1つのドメインとみなした DucksなStore実装も可能

Slide 28

Slide 28 text

Use Case ● アプリケーションに必要な手続き を定義 ● DIされてはじめて動く

Slide 29

Slide 29 text

Presenter ● 表示要件に必要なデータを Storeから抽出・整形 ● 純粋関数として定義し、 Computed プロパティにマッピ ング

Slide 30

Slide 30 text

Container View ● Presenterの値をUI Componentに注入 ● Use Caseに依存性を注入する(Domain Injection) ● 現状Controllerも含まれてしまっている

Slide 31

Slide 31 text

Container Controller Use Case Repository Store Entity Presenter UI Components Query Command

Slide 32

Slide 32 text

Testing ● UIコンポーネント - Presenterの写像なので再現が簡単 ● Repositories - Data Store LayerへのRead & Write APIをテスト ● Use Cases - Given ConditionとしてRepositoryとServiceのモックをDIするだけ ● Entities- Use Casesと同様

Slide 33

Slide 33 text

まとめ: ● いたずらにレイヤーを増やせば良いというわけではない ● 依存の方向性を意識することで変更に強いアプリケーションに近づく ● Vuexと周辺のテストツールを信用しきるならデフォルトの API叩く方が楽(今は Gatewayを使っていない) ● Clean Architectureの導入コストは高いので見極めが大事

Slide 34

Slide 34 text

これってVueじゃなくてもできるのでは?

Slide 35

Slide 35 text

We Are Hiring!!

Slide 36

Slide 36 text

参考: ● https://qiita.com/kondei/items/41c28674c1bfd4156186 ● https://speakerdeck.com/takasek/10fen-tezhen-rifan-rusohutoueaakitekutiyafalseli-shi-2017 ● http://embryo.hatenadiary.com/entry/2016/12/16/011446 ● https://github.com/azu/large-scale-javascript ● https://qiita.com/Tueno@github/items/705360b357c2a00c9532