Object-Oriented Conference 2024 (OOC2024)が3/24(日)に開催されたんだけど、そのときの動画がアップされてきてる。
それらの中からいくつか気になるものをピックアップして感想とか補足を書いてみたい。
まず取り上げたいのはミノ駆動さんの『クソコード動画「カプセル化 Mk-II」で考える、上手くカプセル化できない理由』。
「目的」と「手段」
動画が相変わらずオモロイんだけど、発表の肝になってるのは動画そのものではなく、「目的」と「手段」について言及して、その関係について議論しているところだと思う。
プログラミングというのは手段を提供するものなので、目的について考えなかったり、目的と手段をごっちゃにしがち。 そうすると「間違ったDRY」で「手段が同じなんだからコードを共通化しよう」みたいになって、動画のように「複数の目的があるのに手段が1つしか提供されてない」状況が発生して、カプセル化が壊れる、と。 目的が違うなら手段も分けた方がよくて、そうするとカプセル化が壊れにくい、と。
元々の「カプセル化」の動画は「属性をプライベートにしてgetterとsetterを作るのがカプセル化と勘違いしてる人がいるよね」という内容だった。
クソコード動画「カプセル化」 pic.twitter.com/kAhXCEHYVT
— ミノ駆動 (@MinoDriven) 2019年6月23日
今回の動画は「カプセル化するとして、そのときに間違ったDRYしないようにしよう」という内容と言えそう。 なので裏のテーマは「間違ったDRY」な気がする。
DRYはよく言われる原則だけど、間違って使ってしまうことが多い原則でもある。 目的が違うのに現状の実装が同じだからと共通化してしまうと、あとで苦労することが多いのよね。 DRYするときは「目的が同じか」に気をつけた方がいい。 これはカプセル化と関係なく言えることだったりする。
What(何をやるのか:目的)とHow(どうやるのか:手段)を区別するといいんよね。Howが同じでもWhatが違うなら別物なので共通化すると危ない。なぜならHowは変化するから。一方、Whatは変化しにくい。
— やまいも (@yappy0625) 2023年8月24日
で、WhatをInterfaceにしていくという話に繋がったりする。 https://t.co/6baW9ADrDd
「インタフェース」と「実装」
この「『目的』と『手段』をちゃんと分けて考えよう」というのは「『インタフェース』と『実装』をちゃんと分けて考えよう」という話につながってくる。
「インタフェース」というのはモジュールを外から眺めた姿で、そのモジュールが「何(What)を提供するのか」という「目的」を規定するものとなっている。 一方、「実装」はモジュールを内側から眺めた姿で、そのモジュールが「どうやって(How)目的を達成するのか」という「手段」を提供するものとなっている。
そう考えると「目的」と「手段」の「N対N対応」についても分かりやすい。
動画では「複数の目的に対して1つの手段で頑張るのはよくない」と言ってたわけだけど、これは複数のインタフェースに対する実装を1つのコードで頑張ろうとしてるわけだから、そりゃ大変となる。 そして「目的ごとに手段を用意しよう」というのは、インタフェースごとに実装を用意しようということになるので、素直な実装と言える。 さらに動画では言及されなかったけど、「1つの目的に対して複数の手段を用意する」というのも可能で、そうするとコードの柔軟性がぐっと上がることになる。 これがさらに進むと依存性の注入の話になってくる。
実装の再利用をどうするか
ところで、間違ったDRYはよくないものの、実装を再利用したいというのはよくある話で、そういったときにどうしたらいいのかも知っておくといい。
これは目的をより小さな目的に分割し、小さな目的に使える実装を提供して、処理を委譲する。 目的は小さく分けると汎用的な目的になるので、それを提供する実装も汎用的になり、再利用しやすくなる。
たとえば電子レンジの例を考えてみると、「食べ物を温める」という機能自体は電子レンジが提供するものの、そのためには「時間を測る」「電圧を上げる」「電磁波を発生させる」といったサブの機能が必要で、それらはモジュール化された機器を使うことになる。 そういったモジュール化された機器は電子レンジ以外の家電にも使えるわけよね。 さらにそういったモジュールもさらに小さなモジュールの集まりで構成されてるわけで。
そんな感じで、単純だけどちゃんと動く部品をまず作り、それらを段階的に組み合わせて創発的に機能を作っていくといいんよね。 まさにオブジェクト指向という感じ。
今日はここまで!