オブジェクト指向設計実践ガイド読書会 - 第36回 === ###### tags: `オブジェクト指向設計実践ガイド読書会` # 開催概要 * 日程: 2022/09/24 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 # 読書メモ ## 7.1_ロールを理解する_責任を管理する_p.182_184 ### discord開始地点 https://discord.com/channels/432531367427964929/898843794101911622/1028187693290627072 ### 感想 >  この実装は、単純で明確な改善を強く求めています。どんな改善が必要かはコードのパターン からわかります。ほかのクラスの詳細を知るのではなく、Scheduleはほかのクラスにメッセージ を送るべきなのです。 - p.184 - 「整備士の役職によって、休息期間が違う」「自転車の種類によって〜」「自動車の車種によって〜」とか、「リードタイムが一定にならない」という事態になるケースを色々考えてみたりすると、Scheduleクラスにリードタイムを埋め込むのは一層骨が折れることがはっきりしてくる :+1: :+1: - 「リードタイムが一定にならない」ということは、「個別の事情によってリードタイムが可変になる」ということなので、「一箇所で一律定義するのではなく、個別のオブジェクトごとに必要なリードタイムを計算させて申告させる = メッセージ経由にする」という圧力がより一層強くなる - さらに「他に整備士がたくさんいるときはリードタイムが長めになる」「整備士が全然残っていないときはリードタイムが短くなる」みたいなケース = 個別のオブジェクト単独では決定できないケースも考えてみたが、それでも「標準のリードタイム」みたいなものは個別のオブジェクトごとに計算させた方が良さげ - その上で、「リードタイム調整」みたいなまた別のルールを定義して、そこを経由して最終的なリードタイムを決定する、という仕組みにしそう - 「Scheduleはほかのクラスにメッセージを送るべき」という結論に「多分そうだね」と思いつつ、その結論をひっくり返すような例は無いかといろいろ考えた結果、「ほぼ確実にそうだね」という結論に回帰してしまった :zany_face: :zany_face: :+1: - p.182「自転車と自動車はメンテナ ンスを受けなければなりません」とあるように自動車整備士も必要になるが、一人でなく複数人で対処しなければならないとしたら、個々のオブジェクトだけでなくオブジェクトのグループを考慮する必要も出てきそう。自動車整備をできる者のうち、少なくとも N人を確保、みたいな。 - Compositeパターン的な、「整備士のように振る舞う整備士集団」みたいなものを仮想すると、いい塩梅に組み込めたりするだろうか? - と想定しているけど、どちらかというと固有の問題が追加で生じるだろうか、というところの方に興味が引かれた。 :+1: :+1: :+1: :thinking_face: ```plantuml interface 整備士 整備士 <|.. 個人整備士 整備士 <|.. 整備士チーム 整備士チーム o--> "n" 整備士 ``` - 自転車整備と自動車整備の両方をできる人がいた場合、別々のリソースとして並行稼働できないので、直列的に作業する者としてスケジュールを確保する、みたいなケースだと、単純にそれぞれの役割のオブジェクトとしての同一人物に対して問い合わせるだけで大丈夫だろうか、みたいなこともちょっと気になった。 ### 疑問 ## 7.1_ロールを理解する_不必要な依存を取り除く_p.184_187 ### discord開始地点 https://discord.com/channels/432531367427964929/898843794101911622/1028200059436802080 ### 感想 > オブジェクトは自身を管理すべき > 自身の振る舞いは自身で持つべきなのです > オブジェクトBに関心があるときに、オブジェクトBを知りたいがためにオブジェクトAの知識が求められるようなことがあってはいけません > Aの知識を使わずともBについて知れるべきです - Don't Ask, Tell 大事 - 意外とこれがまったく守れていない手続き的なコードが世の中には多い。。。 :innocent: - 一方、あくまで「一般的な規則」なので例外もありそう? - それがどんな場合なのかうまく言語化できない : - https://discord.com/channels/432531367427964929/898843794101911622/1028196074768310292 で書かれている「それら以外に考慮するコンテキスト情報が発生した場合」とか、一例になるかなと :+1: - より具体的には「他に整備士がたくさんいるときはリードタイムが長めになる」「整備士が全然残っていないときはリードタイムが短くなる」みたいなケースとか - ref: https://discord.com/channels/432531367427964929/898843794101911622/1028196435109367849 - ↑あ、naruhodo :soreda: :point_left: :+1: :innocent: > 図7.2のシーケンス図はこの規則を破っています。開始オブジェクトは、targetオブジェクト がスケジュール可能かを確かめようとしていますが、残念なことに、質問はtarget自身に聞いて いません。代わりに、第三者であるScheduleに聞いています。 - p.186 - 状況次第ではScheduleが「スケジュール調整」のFacadeとして機能する場合もあるので、この評価はやや短絡的にすぎるという印象. :+1: - そもそもとして「スケジュールを知っているオブジェクトに直接問い合わせてないからダメ」とは言うが、そこを経由しないということは「調整対象と直接結合する」ということでもあり、「調整対象と結合していることで、対象単体で完結しないルールを差し込む余地が失われている」という評価もできる - 自分だったら、こうしたスケジュール関連の問い合わせを一箇所でしかしておらず、かつ他に考慮すべき事項も無いなら直接問い合わせても良いと思うが、そうではない(以下のケースなど)なら、Scheduleを経由させるか、少なくとも経由させることを検討すると思う - https://discord.com/channels/432531367427964929/898843794101911622/1028196074768310292 で書かれている「それら以外に考慮するコンテキスト情報が発生した場合」 - スケジュール可否の判断がtarget単体では完結しない - スケジュール問い合わせが複数箇所から行われている場合 - 直接対象に問い合わせると、後からルールが変わったときの影響範囲が広大になる - スケジュール問い合わせのルールが暫定的で、今後変更の可能性がある - 後から別軸のルールを差し込める余地を作っておくために、Scheduleを経由 > 文字列が empty? に応答し、 自身について語れるのとまったく同じように、target は schedulable?に応答するべきです。このschedulable?メソッドはSchedulableロールのイン ターフェースに追加されるべきでしょう - p.187 - 「target は schedulable?に応答するべき」というのは特に異論無く、ただそれは「target.scheduleable? を直接利用するべき」を直ちに導出しない(ので、先の「Scheduleは不要」という結論を導くための根拠としては不十分) :+1: :point_left: - 「targetはschedulable?にyesと回答するんだけど、諸般の都合で全体としてはnoという扱いになる」みたいなケース、逆に 「targetはschedulable?にnoと回答するんだけど、諸般の都合で全体としてはyesという扱いになる("うるせぇ働け")」みたいなケースが存在しえない、あるいは排除できるなら、それでも良いが... > p.185: schedulable? - 異義語になっているので、名称がミスリードする例になっていそう。 - Schedule#schedulable? は、そのプランが全体としてスケジュール可能か - 整備士#schedulable? は、その整備士が手が空いているか - ある整備士が手が空いているとしても、条件下で「作業が可能か」というのも schedulable? にされそうだけど、別の処置なので別のメソッドであるべき。 ### 疑問 ## 7.1_ロールを理解する_具体的なコードを書く_p.187_ ### discord開始地点 https://discord.com/channels/432531367427964929/898843794101911622/1028210043033755689 ### 感想 - 当初は「旅行の」スケジュールだった Schedule が、いつの間にか「個々のリソースの」スケジュールに責務が変化している。都合のいいように誘導しているような感じがして、不信感が募る。 :point_right: :sorena: - 責務が変わったら名称変えよう、みたいなことをどこかで主張していなかったっけ? 他の本だったかなぁ。 - :male-police-officer: < シレッと言葉の意味や使い方をすり替えるのはやめろ署の方から参りました ### 疑問 > @schdule = args[:schedule] || Scheduler.new - 引数で :schedule が指定されるということは、どういう状態を意味しているのだろう - 新しい自転車が用意された時点でスケジュールが決まっている、というのは実際あるのだろうか - とか思いつつ、まあスケジュール登録済みの自転車オブジェクトをDBから再構築したりすると、こうなるだろうなとも思いつつ - でもまあ、それだったらoptionalじゃなくて必須扱いでも良いよね、とか思ったり. - 自分だったら、コンストラクタとは別に新規作成用のFactory methodを用意するかなあとか - `def new_bycicle; new(Schedule.new); end` みたいなの --- # ふりかえり - 感想/次回の課題それぞれで5分 - 要望に応じて :okawari: ## 感想 https://hackmd.io/E0HZBN9OS9GBAtnsYXjDsw#%E6%84%9F%E6%83%B3 ### 気づいたこと、気になったこと - 前々からわかっていたことではあるが、全体的に議論の詰めが甘いので、読むときは注意が必要な箇所が多々 - それはそれとして、要素要素としてはまっとうな話も含んでいるしその箇所も少なくないので、扱いがなやましい - というのを再確認する範囲だった - 「嘘は事実の中にちょっとだけ含めるのが効果的」というのを考えると、(嘘とまでは言わないけれど、怪しげな飛躍がちょこっとこっそり混じっているのは) なにげに害悪度が高いような気もする。 :point_left: :ne: - 「7.1_ロールを理解する_責任を管理する」までは良かったけど、その後の二節が続けてだいぶアレな議論の仕方でアレ :skull: :array: - 「オブジェクトの詳細を基準にあれこれするのではなく、オブジェクト自身に語らせよう」という話自体は、汎用性高い(が、オブジェクト自身では完結しないケースも多いので「自身に語らせれば済む」という話でもない) :point_left: ### 疑問点 ### 仕事に活用してみたいこと ## 次回の課題 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/rxY1uFNYQWyDGsPUQ9jH2Q?both