オブジェクト指向設計実践ガイド読書会 - 第38回 === ###### tags: `オブジェクト指向設計実践ガイド読書会` # 開催概要 * 日程: 2022/10/29 Sat 21:00〜 * 会場: https://discord.com/channels/432531367427964929/898843794101911622 * [README](https://hackmd.io/sSmTRzcQSCuvqiO7uDUkFg) * [タイムキーバー用テンプレート](https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw) ## 課題図書 『オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方』(Sandi Metz 著, 髙山泰基 訳, 技術評論社) - 技術評論社, pdf版あり - https://gihyo.jp/book/2016/978-4-7741-8361-9 - Amazon - https://www.amazon.co.jp/dp/B01L8SEVYI ## 実施要領 - 事前読書なし。都度その場で読んで、感想を書いて、議論する、を繰り返す。 - 参加スタイルは自由形。チャットでも音声でもご自由に。 - 主催はチャット参加です。 ## タイマーについて 時間管理はタイマーbotで行います。 VCチャンネルに入っている人を対象にメンションが飛ぶので、VCチャンネルへの参加をお願いします。 また、タイマーは終了時に **音声がなる** ので、ご注意ください。 ## 当日までの準備 1. 課題図書を手元に用意する - 買う、借りる、etc(?) 2. 当日までに読んだり読まなかったりする - 当日その場で読むので、事前に読んでおく必要は無し - 気になったら事前に読んでおいても良し --- # 当日の進行 ## 進行フロー https://hackmd.io/sSmTRzcQSCuvqiO7uDUkFg?view#%E9%80%B2%E8%A1%8C%E3%83%95%E3%83%AD%E3%83%BC ## :goti: or :okawari: について - 各パートごとに :goti: or :okawari: を投票する. - :okawari: が1つでも有れば、パートを続行する. ## 開催コール https://1.bp.blogspot.com/-YrhlmWQ4uIQ/UrlmxoUdDeI/AAAAAAAAcLw/M6VFUKHnTos/s400/text_start.png ## タイムキーパー募集 https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%AD%E3%83%BC%E3%83%91%E3%83%BC%E5%8B%9F%E9%9B%86 ## 読書パート https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E8%AA%AD%E6%9B%B8%E3%83%91%E3%83%BC%E3%83%88 ## 投票パート https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E6%8A%95%E7%A5%A8%E3%83%91%E3%83%BC%E3%83%88 ## トークパート ### 議論(:thinking_face:)パート https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E8%AD%B0%E8%AB%96%E3%83%91%E3%83%BC%E3%83%88 ### 任意トーク(:+1:)パート https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E4%BB%BB%E6%84%8F%E3%83%88%E3%83%BC%E3%82%AF%E3%83%91%E3%83%BC%E3%83%88 ### 次回繰越(:eyes:)パート https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E6%AC%A1%E5%9B%9E%E7%B9%B0%E8%B6%8A%E3%83%91%E3%83%BC%E3%83%88 ## 終了コール http://3.bp.blogspot.com/-zgTNWF_hBmI/UZYlh9RhuDI/AAAAAAAATQ8/dymPl5P4eAs/s500/undoukai_relay_animal.png # 読書メモ ## 7.1_ロールを理解する_メソッド探索の仕組み_ほぼ完全な説明_ロールの振る舞いを継承する_p.197_199 ### discord開始地点 https://discord.com/channels/432531367427964929/898843794101911622/1035888014636888064 ### 感想 > 複数のモジュールを1つのクラスにインクルードすると、モジュールはインクルードされた ときとは逆順でメソッド探索パスに配置されます。したがって、最後にインクルードされたモ ジュールのメソッドは、探索パスの先頭に来ます。 - p.197 - ~~あんまりちゃんと調べたことなかった(そもそもインクルードの順序が気になる使い方をしたことがなかった)けど、この説明からすると include は先勝ちなのね~~ 誤読 :zany_face: :+1: - 「逆順に配置される」ので、最後に追加したものが最初に検索対象になる後勝ちなのでは? Rubyのよくある説明では、継承ツリーを「遡る」。 - あ、確かにこれは誤読ですね……「最後にインクルードされたメソッドが探索パスの先頭にくる」=「最後にインクルードされたモジュールでメソッド定義が見つかったら探索終了するので先にインクルードされたモジュールは無視」= 後勝ちですね (^^; - (ですよね) :man-bowing: :ok: - ~~先勝ちだと外部のGemとかフレームワークに先に取られたりして面倒な事にならないのだろうか~~ > しかし、Rubyのextendキーワードを使うと、オブジェクト1つだけにモジュールのメソッド を追加することもできます。 - p.197 - Ruby触りはじめのころ、Javaのextendとまるっきり意味が違う & Rubyにおける「特異」を理解していない & 「クラスもオブジェクト」という発想がゼロ のあわせ技で混乱したおもひで :aruaru: - まあ今になって改めて見ると、Rubyにおけるextendは「オブジェクトそのものの拡張(extend)」だし、includeは「メソッド探索パスに含める(include)」でしかないわけで、(Javaの語法を引きずらなければ)別に奇っ怪な表現でもない - 自分も、最初の頃はしばしば、include と extend の違いが分からなくて、混乱して使い間違えて、あれ?ってなってた。 - (1年以上Ruby触ってるのにいまだに Interface でいいじゃん勢 - 実装の継承を mixin で実現したいような用途なので、interface だと力不足 :+1: - 静的型付け言語であっても、Interfaceで基本I/Fは定義しつつ、mixinやtraitで実装を共有する、というかたちで「両方あって初めてやりたいことが実現できる」というケースはありますね - 今のJavaだとInterfaceにデフォルト実装持てるようになったので「Interfaceだけで完結する」と言えば言えるけど、これはJava固有であって、Interface一般の話ではない - C# やってた頃はデフォルト実装付き Interface 欲しかった記憶ある(今はあったりするんかしら - 正直なところ、デフォルト実装付き interfece は、C++ の純粋抽象クラスと何がちがうん、という気持ちがわいてしまう。 :point_left: - たしかにこのケースはあるなあ - コンストラクタで委譲すれば良いと言えばいいけど、まあそれは面倒だったり可読性の低下を招く場合もあるからな~~ - 手間暇の問題のみならず、プログラマー側の意図の表現という観点でも委譲ではなくmixinやtraitによる実装の共有 = 全く同じ挙動を取ることを担保したいこともしばしば :+1: - (「同じことをする」と「同じXを保持する」とでは、表現内容が微妙にズレる) - つまり自分は module とは別に inteface もください勢という事だった :+1: - module に inteface の真似事させるのほんと辛い... :point_left: - そのあたりはたぶん今後は rbs かなぁ - rbs はよ - Rubyコミッタ勢(というより、Matz?)的には「moduleでinterfaceのエミュしようとするな」という回答にたぶんなる :point_left: - これはそう - なんだけど現実的には必要なんだよ大規模開発で規律を保つためには・・・ - まあ動的型付け言語で大規模開発しようとしてるのがそもそも無理あるんだけども - 動的言語のアプローチ自体が(Smalltalkの頃から)規律や制約より自由と柔軟さなので、規律を最優先したいなら動的言語を使うなという結論になってしまうのは、それはそう :+1: :+1: :+1: - このあたりかな( https://twitter.com/yukihiro_matz/status/1066980158429552640?s=20&t=GkucpgILF6dUigPeL0UtOA ) - > Rubyでは、型やインターフェースはあなたの心の中にあるのです。 > まあ、抽象クラスやインターフェースの代わりにmoduleが使えますが、使いすぎるとRubyっぽくなくなるので、ほどほどに。 - 全員100%心の中で同じものを簡単に想像できるスキル持ちならそれでいいんすけどねー - 現実は非情。 - 人類はニュータイプにはまだ進化できていない :innocent: - 採用時に人類の選別が始まる(不穏) - (いまあなたの心に語り掛けています・・・) に反応したら入社 - 最近(といっても2系初期だから何年前だ :sweat: )は prepend というものもありけり - https://docs.ruby-lang.org/ja/3.1/method/Module/i/prepend.html - 1.4.3 辺りから使っていた勢としては最近( ### 疑問 ## 7.2_継承可能なコードを書く_アンチパターン_契約を守る_p.199_201 ### discord開始地点 https://discord.com/channels/432531367427964929/898843794101911622/1035902452207190037 ### 感想 > p.199: 1 つ目は、オブジェクトが type や category という変数名を使い、どんなメッセージを self に送 るかを決めているパターンです。(中略) このようなコードは、クラスによる継承を使うように再構成できます。 - 概念的な関係では無く、振る舞いの、というかコードの類似性に基づく、よくない継承を生みそうで、あやうい。 - これどういうコードなんだろうイマイチ想像できてない - 本書p.145の `Bicycle#spares` とか :naruhodo: - if文で種別ごとの処理を書き始めたら負けといういつものアレかー :+1: :+1: > サブクラスは「契約」に同意します。スーパークラスと置換できることを約束するのです。置換 できる場合は限られています。(...)サブクラス はスーパークラスのインターフェースに含まれるどのメッセージが来ても応えられるべきであ り、同じ種類の入力を取り、同じ種類の出力を行わなければなりません。 - p.201 - ~~もしかして~~ もしかしなくても: https://ja.wikipedia.org/wiki/%E3%83%AA%E3%82%B9%E3%82%B3%E3%83%95%E3%81%AE%E7%BD%AE%E6%8F%9B%E5%8E%9F%E5%89%87 - 実は次ページのコラムがリスコフの置換原則なのだ :+1: :+1: - あっ。。。 (∩゚д゚)アーアーキコエナイ :yoshi!: - リスコフの置換原則、すごく大切だけど世の中には違反しているコードがすごく多い悲しみ :point_left: :point_left: - オブジェクト指向初心者の頃はリスコフの置換原則をきちんと理解できてなくて違反しているコードを書いてしまうこともありがちなので仕方ないところもある :aruaru: ### 疑問 ## 7.2_継承可能なコードを書く_テンプレートメソッドパターンを使う_まとめ_p.202_204 ### discord開始地点 https://discord.com/channels/432531367427964929/898843794101911622/1035907881784057896 ### 感想 > p.202: リスコフの置換原則 (LSP) - LSP は、SOLID等の中では、満たすのがベター/状況によっては優先しなくていい、のと違って、クラス階層を型階層と同一視する向きには必須の大前提である、というところで性質が違うやつなのよね。 - 「テンプレートメソッドを使おう」「superを呼び出さないようにしよう」と前範囲の「抽象スーパークラス内のコードを使わないサブクラスがあってはなりません」が整合するのか?というのが一瞬引っかかった - が、原文を見ると `All of the code in an abstract superclass should apply to every class that inherits it.` で、多分これは日本語訳があまり良くない - なぜ、否定形に置き換えて訳した……? - 「抽象クラスのコードは、それを継承する全てのクラスへ適用されるべき」ぐらいが素直な訳 - で、ここで言う「全てのクラスへ適用されるべき」は「サブクラスで抽象クラスのコードが一部無効化(ex. not implementedでオーバーライド)されたり、「一部のサブクラスにとって全く関係しないコードが抽象クラスにある」ということが無いようにせよ、という話 - そう理解すれば全体として特に不整合は起きないし、おそらくそう理解するのが妥当 :+1: > 継承する側でsuperを呼び出すようなコードを書くのは避けましょう。代わりにフックメッ セージを使います。そうすれば、抽象クラスのアルゴリズムを知っておく責任からは解放されながらも、アルゴリズムに加わることはできます。 - p.202 - 6.5(p.167-177)でも取り扱われたテーマ - super(ないし、親クラスのメソッドやプロパティを参照する任意のコード)を使う = 親クラスとの結合が強まるというのは、わすれないようにしておきたい - まさに最近、「あ、super使おうとしてたけど、これ結合強くなっちゃうな……」と気づいて実装変更するタイミングがあった(結合してよい/すべき箇所ならして良いけれど、その時はむしろしたくないケースだった) :clap: > p.203-204: 階層構造は浅くする - 階層構造が深くて大変な負債になっていた事例 - 継承とメタプログラミング満載なアプリケーションコードでもアクションとフィルタに悩まないための Gem を作った話 / makicamel - 動画: https://youtu.be/fTesufhojAU - スライド: https://speakerdeck.com/makicamel/lets-enjoy-creating-gems - この辺から https://speakerdeck.com/makicamel/lets-enjoy-creating-gems?slide=3 - ちなみにこれに関しては makicamel さんがこの負債を返しきったという話が今年の Kaigi on Rails であった(偉業 & いい話) - https://kaigionrails.org/2022/talks/makicamel/ - 2020 の発表からの続きもの(動画は今後公開予定) - 負債を返すのは大変なので、必要のない負債は負わないようにしたいし、負った負債は返済計画を立てておかないとあぶない。ご利用は計画的に。 :point_left: - 「p.200 抽象に固執する」と悪魔合体して曲解された結果、振る舞いの差分ごとに中間クラスが作られ、無意味に深い継承階層が爆誕していたのを目にして、うっ、ってなったおもひでがぴろぴろ。ぴぴるぴるぴるぴぴるぴー(謎) :aruaru: :hammer: :angel: - ??「でーもそれって、ぼくの愛なのー」 > 7.2 継承可能なコードを書く - 「継承可能なコードを書く」という題だったが、全体としては「継承に適したコードを書く」「適切に継承を使う」みたいな話だった印象 - なお原文は `Writing Inheritable Code` 。とくにかわりない(^^; - いやでも、「継承可能なコードを書く」という目的を実現するために「テンプレートメソッドパターンを使おう」とか「フックメッセージで疎結合にしよう(親に依存させない)」とかのテクニックが紹介されているわけだから、良いのか(^^; - (いままでがいままでだったのもあり)やや疑りすぎた感。 :kusa: ### 疑問 --- # ふりかえり - 感想/次回の課題それぞれで5分 - 要望に応じて :okawari: ## 感想 https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E6%84%9F%E6%83%B3 ### 気づいたこと、気になったこと - 7章全体で、本書における「ロール」という概念の取り扱い方や説明の仕方には疑問の有る点も多かった(無理やりボトムアップの観点からだけで説明しようとした結果か)が、個々別々のテクニックについてはよくまとまっていた印象 - テクニックを語らせると悪くないけれど、コンセプトを語らせると途端に怪しいところが噴出する本書 :ne: - 叩き上げの経験値を蓄積するかたちで技能を得た感じ?の人なのだろうか。理論的な部分の整理・解説に不安がある。一方で個別具体的な技法についてはよくまとまっているし、メリット/デメリットの解説も丁寧。 - 時々、枝葉末節に誌面を費やすこともなきにしもあらず ^^; - レビュアーがそれスルーしたらいかんでしょレベルの内容もあって万人にはお勧めしづらい・・ :sorena: - 久しぶりに参加できただけで :100: - :100: - :100: - 時間変更により、一部の方々が参加しやすくなったかも。 ### 疑問点 ### 仕事に活用してみたいこと ## 次回の課題 https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E6%AC%A1%E5%9B%9E%E4%BB%A5%E9%99%8D%E3%81%AE%E8%AA%B2%E9%A1%8C [まとめ用mdに追記](https://hackmd.io/wfDfaf4nRQuPG1BYtcy_jA) # 次回 https://hackmd.io/tfVMl52_QJ2WczF7zFTtSQ?both
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up