オブジェクト指向設計実践ガイド読書会 - 第34回 === ###### tags: `オブジェクト指向設計実践ガイド読書会` # 開催概要 * 日程: 2022/09/03 Sat 15:00〜17: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 # 読書メモ ## 6.4_抽象を見つける_すべてのテンプレートメソッドを実装する_p.165_167 ### discord開始地点 https://discord.com/channels/432531367427964929/898843794101911622/1015504133689716767 ### 感想 > 痛い目にあう可能性がある世界であっても、前もって、かんたんなルールに従うことで痛みを 和らげることができます。それは、テンプレートメソッドパターンを使うどのクラスも、その送信するメッセージのすべてに、必ず実装を用意するようにすることです。 - p.165-166 - OOP・OODやや関係なくなっている話題だけれど、 abstract みたいな(どこかでオーバーライドされるべきであることを明示する)何かは、キーワードでもメソッドでも良いけど、言語レベルで欲しかった気がする - 似たようなことを思っている人も多いのか、rubygemsで"abstract"で検索するとワラワラ出てくる - まあ基本的には対症療法 - このレベルのこと(オーバーライドされるべきものがされていない)は、動的言語であっても、何らかの静的解析で事前検出したい気がする - RBS「呼んだ? :point_left: :+1: - ほい https://pocke.hatenablog.com/entry/2021/01/02/175940 - ちなみに sorbet はこれ :+1: - https://sorbet.org/docs/abstract ### 疑問 ## 6.5_スーパークラスとサブクラス間の結合度を管理する_結合度を理解する_p.167_172 ### discord開始地点 https://discord.com/channels/432531367427964929/898843794101911622/1015510069691035660 ### 感想 > p.167: この spares のスーパークラスでの実装は、さまざまな方法で書けます。これらの違いは、どれ ほど強固にサブクラスとスーパークラスを結合するかにあります。結合度を管理することは重要 です。 - この観点を持たないと、なんでも委譲にすべし、というようなベストプラクティスの行き過ぎた適用をしてしまうことにつながる。気を付けたいところ。 :+1: :point_left: - なぜ「継承より委譲」なんて言い出したのかと言えば結合度を下げるためのはずなのに、「継承より委譲だ、だから全てのメソッドコールを別のオブジェクトに委譲するね」と結合度を跳ね上げることを厭わないスタイル、しばしば出くわす…… - リファクタリングの「仲介人の除去」あたりの話ですかね :eyes: > 次のコードは、そのトラップを説明したものです。仮に、だれかがサブクラスを新しくつくり、 そのinitializeメソッド内でsuperを送り忘れると、このような問題に直面します。 - p.171 - このあたりは言語依存の話題ではある。Javaあたりだと、コンストラクタの先頭で親のコンストラクタを呼ばないとエラーになったりするし。 ### 疑問 ---- ## 6.5_スーパークラスとサブクラス間の結合度を管理する_フックメッセージを使ってサブクラスを疎結合にする_p.172_177 ### discord開始地点 https://discord.com/channels/432531367427964929/898843794101911622/1015520744098250753 ### 感想 > これらの問題はすべて、最後のリファクタリングを1つ加えれば回避できます。サブクラスに アルゴリズムを知ることを許し、superを送るよう求めるのではなく、スーパークラスが代わり に「フック」メッセージを送るようにすることができます。 - p.172 - フレームワークでよく見る(使わされる)手法 :+1: :+1: - rails とかのコールバックもこの類 - ruby じゃないけど vue とか react のライフサイクル系もこれかな - ですね。最近仕事の都合でVue2のソースコード読む羽目になって、途中でcreatedメソッド呼ばれている箇所にも遭遇しました。まさに初期化フローの中でVueから呼び出されてます。 :+1: - この種のフックメッセージ、増えれば増えるほど逆に覚えることが増えて学習コストが増えるのは辛いところ :+1: - vue とか rails とかその他 DSL 関連 > RoadBikeは、自身が「何を」初期化する必要があるかについての責任をまだ負っています。しかし、「いつ」初期化が行われるかには責任がありません。この変更によって、RoadBikeのBicycleに ついての知識はより少なくできます。 - p.173 - コンストラクタの部分どうするのかなと気になってたけど、この発想は無かった。よくよく考えると、フレームワークを使う時はよくやらされるのに。。。 - 常に使うかはともかくとして、コンストラクタといった言語仕様レベルの箇所ですらも疎結合にできるのだ、というのを確認できたのは収穫 :+1: :+1: - ミニフレームワークを作るとか、そこまでいかなくても構造だけつくって実装は別の人にやってもらう、という場面でもこのテクニックは有効 - 通常のメソッドならしばしばやるのに、コンストラクタだと発想に出てこなかったのは、我ながら不思議。「言語組み込みの箇所」という要素で目がくらんでいたかも。 - 多分、この種のフックメソッドを「拡張点を作る」という意味でしか捉えてなくて、「結合度を下げる」という観点で見たことが全く無かったのが気づかなかった原因な気がしてきた。 - これを仕組みレベルで汎用のポイントカット (フック可能点) を定義しておいて、別の関心事との結合度を下げる技術が AOP、とかなんとか。 - 昔、フレームワークとライブラリがどう違うのかで混乱していた時に「自分のコードから直接使うのがライブラリ、自分のコードを使わせるのがフレームワーク」みたいな感じの説明受けたことを思い出した > p.173: def post_initialize - この場合、「子クラスで initialize を実装してはならない」もしくは「親クラスの initialize を上書きしても問題が生じないようにしなければならない」というルールを徹底する必要もあり……。依存度が下がったからといって、まだ油断してはならない。 :+1: - CakePHPは `function initialize` というフックメソッドを使ってControllerの初期化をするけど、コンストラクタ(`function __construct`)を直接上書きして「動かない」と言っていた人が実際いたのを思い出した :aruaru: - Javaであれば、コンストラクタにfinalつけるまでやればなんとかなりそうではある。「オーバーライドの可否」を指定できない言語だと…… - **post**_initialize という命名は post をどういう意味合いで使っているのかちょっと気になった - 接頭辞のpostだと思います。「ポストモダン」とか「ポスト構造主義」とかの「ポスト」。意味としては「〜の後」。 :naruhodo: - post initialization ではなく、post initialize というのは、文法的にはどうなのかしら、とは思った。まぁ意味も意図も分かるのでスルーするところではあるけれど。 - 「initialize メソッド」の後、と考えると良さそうに見えるかも? :duck: - 細かいこというと initialize メソッドの中で呼ばれるので initialize メソッドの後ではないのよね ^^; - ↓。。。とか。。。どう。。。でしょう、、、? ^^; - ナルホド? ^^;; ```ruby= def self.build(arg={}) new(arg).post_initialize(arg) end def initialize(args={}) ... end ``` ### 疑問 --- # ふりかえり - 感想/次回の課題それぞれで5分 - 要望に応じて :okawari: ## 感想 https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E6%84%9F%E6%83%B3 ### 気づいたこと、気になったこと - 継承における「結合度の管理」という話題から、「継承より委譲」主義がどう問題になるのか、というのを改めて言語化できたのは収穫 - フックメソッド自体は使ったこともつくったこともあったけれど、「フックメソッドによって結合度を下げる」という発想は今まで無かった ### 疑問点 ### 仕事に活用してみたいこと - [ダジャレで返す](https://discord.com/channels/432531367427964929/898843794101911622/1015517545647841330) ## 次回の課題 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/2YTuvTxdRoCvDbMh9vv8Sw?edit