Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Application Design 勉強会 #3
Search
k-kohey
July 12, 2019
Programming
0
88
Application Design 勉強会 #3
k-kohey
July 12, 2019
Tweet
Share
More Decks by k-kohey
See All by k-kohey
ゲームボーイアドバンスでSwiftを動かそう
k_koheyi
0
760
Swift Package Mangerのバグを直した話
k_koheyi
2
1.3k
swift-async-algorithms...? へえ…面白そうじゃん…?
k_koheyi
3
1.4k
[社内勉強会]Parchment-swiftの実装説明
k_koheyi
0
110
[社内勉強会]Combineの説明
k_koheyi
0
27
あるインスタンスの取る値が 何パターンあるか数えてみるンゴ!
k_koheyi
1
140
Tuistを用いた Xcode Project管理の紹介
k_koheyi
0
170
SwiftでわかるSOLID原則 iOSDC 2020
k_koheyi
3
2.6k
Visitorパターン
k_koheyi
0
130
Other Decks in Programming
See All in Programming
Make Impossible States Impossibleを 意識してReactのPropsを設計しよう
ikumatadokoro
0
170
シェーダーで魅せるMapLibreの動的ラスタータイル
satoshi7190
1
480
ActiveSupport::Notifications supporting instrumentation of Rails apps with OpenTelemetry
ymtdzzz
1
230
광고 소재 심사 과정에 AI를 도입하여 광고 서비스 생산성 향상시키기
kakao
PRO
0
170
TypeScriptでライブラリとの依存を限定的にする方法
tutinoko
2
670
初めてDefinitelyTypedにPRを出した話
syumai
0
410
Flutterを言い訳にしない!アプリの使い心地改善テクニック5選🔥
kno3a87
1
170
CSC509 Lecture 11
javiergs
PRO
0
180
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
0
110
Arm移行タイムアタック
qnighy
0
320
距離関数を極める! / SESSIONS 2024
gam0022
0
280
2024/11/8 関西Kaggler会 2024 #3 / Kaggle Kernel で Gemma 2 × vLLM を動かす。
kohecchi
5
920
Featured
See All Featured
Writing Fast Ruby
sferik
627
61k
What's in a price? How to price your products and services
michaelherold
243
12k
Facilitating Awesome Meetings
lara
50
6.1k
The Pragmatic Product Professional
lauravandoore
31
6.3k
Reflections from 52 weeks, 52 projects
jeffersonlam
346
20k
A better future with KSS
kneath
238
17k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
6.9k
How to Ace a Technical Interview
jacobian
276
23k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
We Have a Design System, Now What?
morganepeng
50
7.2k
Fashionably flexible responsive web design (full day workshop)
malarkey
405
65k
Transcript
"QQMJDBUJPO%FTJHO ษڧձ ষ ஜେֶ ใϝσΟΞֶྨ ޱ ߤฏ 1
Ϧείϑͷஔݪଇʢ-41ʣ 2
Ϧείϑஔͷݪଇʢ-41ʣ 「派⽣型はその基本型と置換可能でなければならない.」 この原則に反すると,OCPにも反することとなりプログラムが脆くなる. - 関数fがある基本クラスAをその引数に取り - Aの派⽣クラスCを関数fに渡した際において異常を起こした…とする - この場合にクラスCはLSPに従わないという LSPはOCPを有効にする⼿段の1つであり
あるモジュールに修正を施さずに拡張する⽅法として,基本型と派⽣型の置換性という形で表している 3
Ϧείϑஔͷݪଇͷྫ • 「派⽣型はその基本型と置換可能でなければならない.」 • この原則に反すると,OCPにも反することとなりプログラムが脆くなる. 4 • UserやBookがEntityの代わりとして扱えないことに よって,LSP違反が起きている. •
Entityがidentifierを持つことを担保すればこの問題 は起きない • また,Entityの種類が増えると分岐が増えるので OCP違反をしている. • LSP違反は⾃然にOCP違反を引き起こす.
Ϧείϑஔͷݪଇʢ-41ʣ • 「派⽣型はその基本型と置換可能でなければならない.」 • この原則に反すると,OCPにも反することとなりプログラムが脆くなる. 5 • UserやBookがEntityの代わりとして扱えないことに よって,LSP違反が起きている. •
Entityがidentifierを持つことを担保すればこの問題 は起きない • また,Entityの種類が増えると分岐が増えるので OCP違反をしている. • LSP違反は⾃然にOCP違反を引き起こす. この例では,単なる継承によって解決する. 継承によってLSPを満たせない場合はあるのか?
ܧঝʹΑͬͯෳࡶԽ͞Εͨ-41ҧͷྫ • この⻑⽅形を表すRectangleViewに加えて正⽅形を表すSquareViewを追加する必要が出てきたケース. • 継承はIS-A(「である」)の関係であるといわれている. • 正⽅形は⻑⽅形であるのでSquareはRectanbleのサブクラスになりそうだ. 6
ܧঝʹΑͬͯෳࡶԽ͞Εͨ-41ҧͷྫ • 本来⼀辺を設定できれば良いが,継承によって不要なメソッドを受け継いでしまった. • したがって,下記のように両辺の⻑さが等しいことを担保した. • 結果,Squareの性質を担保することが出来た! 7
ܧঝʹΑͬͯෳࡶԽ͞Εͨ-41ҧͷྫ • 結果,Squareの性質を担保することが出来が…… • クライアントによっては下記のコードのような間違いが起きる. 8 関数fにSquareViewを与えたときに,assertでエラーが発⽣する. SquareViewはIS-Aの関係を満たしており正⽅形本来の性質も満たしている. じゃあ,このコードには正当性があり,間違っているのはクライアント?
ܧঝʹΑͬͯෳࡶԽ͞Εͨ-41ҧͷྫ • 結果,Squareの性質を担保することが出来が…… • クライアントによっては下記のコードのような間違いが起きる. 9 関数fにSquareViewを与えたときに,assertでエラーが発⽣する. SquareViewはIS-Aの関係を満たしており正⽅形本来の性質も満たしている. じゃあ正当なのか? このコードが間違っているのだろうか?
LSPに準拠するためにはIS-Aの関係では不⼗分. 「振る舞い」の同等性も必要! 誰もが合理的だと思う振る舞いをIS-Aに持たせる.
ܖʹΑΔઃܭ • 合理的な仮定を明確にするテクニック. • あるメソッドについての事前条件と事後条件を決めておくことによって,そのメソッドを利⽤する⼈が 必要としている振る舞いを知る事ができる. • 事前条件: そのメソッドを実⾏する前に成⽴していなければいけない条件 •
事後条件: メソッドが終了したときに成⽴していなければならない条件 • 基本クラスをインタフェースにした場合に,クライアントが理解しているのは基本クラスの事後条件と 事前条件のみ • 派⽣クラスの事前条件は基本クラスに課せられている事前条件より強くしてはいけない. • 派⽣クラスの事後条件は基本クラスの事後条件より弱くしてはいけない. Square::setWidthはRectanbleより事後条件が弱い.よって設計契約に反する. -> 振る舞いの同等性が担保されていない 10
ܦݧଇʹґΔ͓खܰ-41ҧνΣοΫ • Overrideによって関数の機能が劣化しているケース • 基本クラス以下のことしか出来ないのであれば置換は不可能. • 基本クラスでは投げない例外を派⽣クラスによって投げられているケース • 基本クラスの利⽤者がその例外を期待していないのでれば,置換不可能. •
= 事前条件が強まってる?? 11
ґଘੑٯసͷݪଇʢ%*1ʣ 12
ґଘੑٯసͷݪଇʢ%*1ʣ 上位のモジュールは下位のモジュールに依存してはならない. どちらのモジュールも抽象に依存すべきである. 抽象は実装の詳細に依存してはならない.実装の詳細が抽象に依存すべきである. • 悪しき⼿続き型プログラミングでは⽅針が実装に依存する • 抽象と実装の詳細を完全に切り分けることによって変更に強くなる • 再利⽤性も⾼まる
13
%*1ͷϞνϕʔγϣϯ • アプリケーションの⽅針といったビジネスモデルを含む上位モジュールが下位のモジュールに依存する と,下位のモジュールの変更が上位モジュールに影響する. • それは本来逆であるべき.⾃分たちが使いたいのは上位のモジュールであるはず. 14 ґଘੑͷٯస 下位モジュールから上位モジュールへの
%*1ʹΑͬͯӨڹ͕ൖ͠ʹ͍͘֊ߏΛ࡞Δ • オブジェクト指向の⾔語では明確に定義付けられた階層を持つ • 上位のモジュールがインタフェースを持つことによって,下位のモジュールは上位のモジュールに依存 する. • インタフェースによって詳細の実装を隠蔽されているため上位のモジュールは下位のモジュールに依存 しない. 15
本書p165より転載 本書p165より転載
%*1ҧͷྫ 16 Button Lamp
%*1ద߹ͷྫ 17 Button SwifthableServer Lamp
%*1ద߹ͷྫ 18 Button SwifthableServer Lamp Buttonによって制御されるオブジェクトは全てButtonServerに準拠しなくてはいけない,というの は問題.Switchなどを操作することもある. ー> 命名を⼀般的にすることによって解決
நʹґଘͤΑ • DIPは抽象に依存せよ,という経験則とも⾔える. • 具体的なクラスへのポインタやリファレンスを保持するような変数があってはならない • 具体的なクラスから派⽣するクラスがあってはならない • 基本クラスで実装されているメソッドを上書きするようなメソッドがあってはならない. 19
Πϯλϑʔεͷݪଇʢ*41ʣ 20
ΠϯλϑΣʔεͷݪଇ • 太ったクラスはそれを利⽤するクライアント同⼠で良くない問題を起こす. • 例えば,あるクライラントが依存先のクラスに変更を要求すると,別のクラスに変更の影響が伝搬する 可能性がある(OCP違反) • クライアントごと(もしくはクライアントのグループ)に必要なメソッドを切り出したインタフェース を作成することによって,この問題は解決できる. •
結果,クライアントは⾃⾝が利⽤しないメソッドとの依存関係を切り捨てられる. 21 ΠϯλϑΣʔεͷ クライアントに⾃⾝が利⽤しないメソッドへの依存を強要してはならない
ΠϯλϑΣʔεͷྫ • これらの定義を⽤いて⻑時間ドアが空いているとロックされるTimedDoorを実装する. 22
ΠϯλϑΣʔεͷྫ • よくある⼿法(らしい) • この⼿法ではTimerDoor⾃体がタイムアウトの通知を 受けられる利点がある⼀⽅でDoorがTimerDoorに依存 してしまう問題がある. • これはインタフェースを太らすインタフェースの汚染 である.
• また,この⼿法はLSPに違反する. 23 • これらの定義を⽤いて⻑時間ドアが空いているとロックされるTimedDoorを実装する.
ΠϯλϑΣʔεͷྫ • よくある⼿法(らしい) • この⼿法ではTimerDoor⾃体がタイムアウトの通知を 受けられる利点がある⼀⽅でDoorがTimerDoorに依存 してしまう問題がある. • これはインタフェースを太らすインタフェースの汚染 である.
• また,この⼿法はLSPに違反する. 24 • これらの定義を⽤いて⻑時間ドアが空いているとロックされるTimedDoorを実装する. インタフェースの分離=クライアントの分離 DoorとTimeClientは異なるクライアントにインタフェースを 提供する.ならばインタフェースを分離させるべき.
ΠϯλϑΣʔεͷྫ 25 Adapterパターンを⽤いた⽅法 多重継承を⽤いた⽅法
Ҿ༻ • ロバート・C・マーチンほか.アジャイルソフトウェア開発の奥義 第 2版 オブジェクト指向開発の神髄と匠の技. SBクリエイティブ, 2008 26