by しんぺい a.k.a. 猫型蓄音機あの日見たM V WhateverのModelを僕たちはまだ知らない
View Slide
自己紹介• しんぺい a.k.a. 猫型蓄音機• Scala Ruby Perl Swift• 妻の夫で息子の父親
息子紹介
宣伝
M V Whatever?
MVW• M V C(ontroller)• M V P(resenter)• M V V(iew)M(odel)• etc.
FAQ:何が違うの?
どこが同じでどこが違うの?• MVWは全て、PresentationDomain Separationの実現のためのパターン• 実現の仕方が細かく言うといろいろ違う
PDS?• http://martinfowler.com/bliki/PresentationDomainSeparation.html
PDS?• separation between thepresentation aspects of aprogram (the user interface)and the rest of thefunctionalityIUUQNBSUJOGPXMFSDPNCMJLJ1SFTFOUBUJPO%PNBJO4FQBSBUJPOIUNM
PDS?• その名の通り、プレゼンテーションとドメインの分離
PDS• This principle is the mostprominent part of Model ViewController (MVC)IUUQNBSUJOGPXMFSDPNCMJLJ1SFTFOUBUJPO%PNBJO4FQBSBUJPOIUNM
PDS?• 「Domain?あっDDDでやったところだ!!!!」<=頻出する間違いです• DDDで言うDomainModelとPDSの言うDomainの関係は、無関係という関係
じゃあPDSで言うところのDomainってなあに?
MVWのMのことです
じゃあMVWで言うところのModelってなあに?
よくある説明• Model:ビジネスロジック• View:見た目• Whatever:ModelとViewをつなぐもの
ビジネスロジックとは一体(哲学)
わからないときはわかりやすいところから考えよう
Viewはわかりやすい• iOSならUIView• AndroidにもViewクラスがありますね• WebAppならばHTML(DOM)+CSSですね• WebAPIならJSONとか
Wもわかりやすい• iOSならViewController• androidならActivity• RailsならController• ViewをレンダリングしたりViewを変更したり• 入力を受け取ったり
PDSふたたび• separation between thepresentation aspects of aprogram (the user interface)and the rest of thefunctionality
Presentation =View + Whatever入力を受け取る見た目を作る
ではM = Domainの部分はなんなのか
PDSみたび• separation between thepresentation aspects of aprogram (the user interface)and the rest of thefunctionality
Domain =the restプレゼンテーション以外全部です
MVWはModelの設計方針を何一つ語っていない!!!!MVWはModelの設計方針を何一つ語っていない!!!!
アバンパート終了
あの日見たM V WhateverのModelを僕たちはまだ知らない
Modelのアーキテクチャ例• ActiveRecordPattern• TransactionScript• LayeredArchitecture
ActiveRecordPattern
ActiveRecordPattern• テーブルとクラスが1:1• rowとインスタンスが1:1• テーブルに対する操作をクラスメソッドに書く• rowに対する操作をインスタンスメソッドに書く
ARパターン適用前
ARパターン適用後
• Rack経由せずにテストできるようになった!• rake タスクとかからも呼べるよね〜
よくある課題• 複数のテーブルにまたがるロジックどうするの?• トランザクションどこで制御すんの?
ActiveRecordPattern再訪• Patterns of Enterprise ApplicationArchitecture で紹介されたパターンのうちのひとつ• テーブルとクラスが1:1• 実践DDD says:「単なるCRUDアプリケーションならばRuby On Railsで十分だろう」
ARパターンだけで全てが解決できると思ってはいけない
ちなみに• RoRのARはARパターンをベースにしたライブラリだけど、さらに拡張が加えられている• RoRではARベースで問題を解決しようとするアプローチもあるっぽいがうまく行ってるという話はあまり聞かない[要出典]
TransactionScript
TransactionScript• ユースケースと1:1のメソッド• ユースケースに対応する手続きをそのメソッドに書いていく• まさに「script:台本」
TS適用
• ARだけでは実現できなかった、複数の関心にまたがるユースケースを実現できた• トランザクションもばっちり
よくある課題• コピペ地獄• 1メソッドの長さが100000000行• 1メソッド読み終えるのに5億年かかる
ちなみに• とはいえ、WebApplicationやWebAPIではトランザクションスクリプトで問題ないケースは結構あると思う
LayeredArchitecture
Layered ArchitecturePresentationApplicationServiceDomainModelInfrastructure• VとW• Pが叩く窓口• これ以外すべて• DBアクセスとか
in DomainModel
in Infrastructure
in ApplicationService
• 一枚岩のスクリプトだったのが責務分散された• 複雑化しすぎたTransactionScriptはテスタビリティが悪化する• テスタビリティを取り戻した• DomainはDBなしでテストできる
よくある課題• 難しい• 「これどこに書けばいいの?」• ちゃんとOOPで設計できないプログラマにとってはTSの手続き型のほうがわかりやすい。というかOOはやっぱり難しいですよ• ドメイン層、やっていくしかない
とはいえ• われわれはそもそも複雑な問題を解決するためにこのパターンにたどり着いた• たとえ難しくてもやっていく価値はある• OOPやDDDを頑張って学ぼう
FAQ• Q.これって要するにDDDのこと?• A.惜しいです。• LayeredArchitectureはDDDで触れられるパターンのうちのひとつ。DDDはLAのほかにもユビキタス言語とか境界付けられたコンテキストとかいろいろ含む
Aパート終了
アイキャッチあの日見たM V WhateverのModelを僕たちはまだ知らない
BパートGUIで実践編
連打マシーンを作る• 連打された数が表示されるカウンターと連打用ボタンが置いてある• ボタンを押すとカウントが +1 される• 自分だけじゃなくてネットワーク越しにみんなで連打しまくる
実装方針• クライアントで連打数をバッファリングして一定時間おきにサーバーにflush• ただし、タップしたらすぐに見た目上のカウンターの数が増えるようにする• サーバーから定期的に「現在の総連打数」が送られてくるので、そのときはカウンターをupdateする
意外と複雑!
まずはModelを考えてみる
in Domain
アプリケーションの挙動はモデリングできた
Presentation層
ViewController
Presentation層からイベントを受けてApplicationをinvokeするところまでできた
しかしこのままではViewが描き変わらない
Counterの状態が変わったらUILabelを書き換えたい
Xの状態が変わったらYを書き換えたい
Observerパターンでやったところだ!
CounterをObservableに
VCでObserve
完成や!!!
• ドメインは一切プレゼンテーションに依存していない• テスタブルだし、CocoaTouchに依存してないから「わかりやすい」
PDS!IUUQNBSUJOGPXMFSDPNCMJLJ1SFTFOUBUJPO%PNBJO4FQBSBUJPOIUNM
yudetamago,STAR ZERO andYOU感動のエンドロール
感動のエンドロール
いきなり数字が< 飛ぶぞ!!!!これはバグだ!
UIの問題なのでPresentationの領域で解決しましょう
CounterLabel
VCも変更
• UIの変更がPのみでできた• Dは一切いじってない
そして設計沼へ……• 今回ServerからのpushをハンドルしてくれるくんをModelに置いたけど、本当にこれでいいのか?• Serverからのpush = アプリケーションへの入力では?• 本質的にはタイマーイベントと一緒なのでは?
• PにActionProviderという層があってもいいかもしれない• タイマーイベントを発行する君• サーバーからのpushを受け取ってイベント発行する君• VCがこれらのイベントを監視してApplicationServiceをinvokeするそして設計沼へ……
• このObserverパターン素朴すぎる• Observerパターンはオブジェクトのmutationが前提• immutableな設計と相性悪い• API呼び出しはInfrastructureに置いてDIするべきではそして設計沼へ……
• RepositoryとQueryの相性めっちゃわるい• ARにはあまりなかったRDBとOOのインピーダンスミスマッチがここにきて問題にそして設計沼へ……
• Fluxアーキテクチャとの統合…?• CQRS…?• EventSourcing…?そして設計沼へ……
ここから先は君自身の目でたしかめよう!▲▲▲
まとめ• PDSを心がけよう• MVWはプレゼンテーション層の作り方のパターン• Mの設計はまた別にちゃんと考える必要あり• トライフォースの力とともに進もう
宣伝• 株式会社リラクでは、一緒に最高の設計を追求したいプログラマを募集しています• 声かけてください!