2020.05.15
STAFF BLOG
スタッフブログ
TECHNICAL
テクログ

どうも!先月に入社二年目を迎え、とうとうパイセンと化したわいです。
自粛期間中ということで、かなり暇なので長編に挑みます。
暇な人はぜひ最後まで読んでみてください。
「うわあ、暇だあ…」ってより実感すると思います。
今回、またもやプログラミングを他の概念にこじつけるシリーズです。
この一年間、新人プログラマーとしていろいろ苦戦しました。
その中のひとつが、『オブジェクト指向とは』の理解です。
オブジェクト指向に関する記事はたくさんあります。
それこそ、「オブジェクト指向はもう古い」とされていたりします。
ただ温故知新という言葉があるように、オブジェクト指向について学ぶことは決して意味のないことではないと思います。
むしろ、プログラミングをする上での基本的な考え方が詰まっているように思えます。
詳しく、そして正確に知りたい場合は、他の記事をおすすめします。
今回はオブジェクト指向のイメージを掴むために少しでもお役に立てればと思い、あえて変な角度からアプローチしてみます。
その名も、「オブジェクト指向は因数分解だ!!」です。
因数分解とは、「足し算・引き算で表されている数式をかけ算の形に変形する」ことです。
例えば、cx^2+acx+bcx+abc = (x+a)(x+b)c となります。(中学数学でやりましたね?)
ここで、下図のようなWebページについて考えてみましょう。
(私自身、最初に車の例えを見たときピンとこなかったので…)
犬の情報は、売られている犬がリストで表示されているとします。猫も同様です。
店舗の情報は、住所、電話番号などが表示されているとしましょう。
(ちなみに、私はペットショップに行くと悲しい気持ちになるので、基本的に中には入りません)
かなり簡略化しているのでわかりやすいと思いますが、
ペットショップのWebサイト = 犬の情報 × 猫の情報 × 店舗の情報
という式が成り立つはずです。
複雑なWebサイトでもこのように各パーツの組み合わせで成り立っています。
これを先ほどの因数分解と合わせて考えてみます。
ペットショップのWebサイト
= cx^2+acx+bcx+abc (一見複雑だが…)
= (x+a) × (x+b) × c
= 犬の情報 × 猫の情報 × 店舗の情報
このようにWebサイトを因数分解することができました。
「だから、なんだ?」という話なのですが、ここでオブジェクト指向について考えたいと思います。
なぜわざわざ小難しいオブジェクト指向で書くかというと、それは変更に対して柔軟に対応するためです。
どういうことかというと、「爬虫類も売ることにしたから、サイトに爬虫類の情報も表示したい」や、「犬を売るのをやめて、鳥を売ることにしたから変えてくれ」などという要望に、瞬時にそしてバグを出すことなく対応することがオブジェクト指向を用いると容易になるということです。
適切にオブジェクト指向を使えば、似たような機能の追加が容易になり(再利用性)、たった一か所の変更のために他のパーツにバグが出ていないかページ全体をテストし直す必要がありません(疎結合性)。
しかし、このオブジェクト指向の難しいところはどのように機能(クラス)を分割するかというところにあると思います。
大雑把に分割しても効力は発揮しないし、かといって細かすぎても保守が大変になります。
ここで、今回私が提案するのは「因数分解のように考えてみたら意外と上手くいくんじゃね?w」ってやつです。
まず、「犬の情報」を「鳥の情報」に変えるということを因数分解で見てみましょう。
これは、仮に a → d とすることで実現するとします。
そうすると、
ペットショップのWebサイト
= (x+d) × (x+b) × c
= 鳥の情報 × 猫の情報 × 店舗の情報
となり、(x+b)やc の値に何ら影響を与えることなく変更することが出来ました。
ここで勘のいい人は、「おめえさん、x を変えたら『猫の情報 (x+b)』に影響を与えるだら?」と思うかもしれません。
そうです。そして、この x がオブジェクト指向の要です。
「犬の情報」も「猫の情報」も、『売られている動物がリストで表示される』という共通点があります。
この共通点を規格として、インターフェースや抽象クラスにまとめ上げることで再利用性が高まり、さらに各々のクラスの役割がはっきりします。
そして、ここで注意しないといけないのがなんでもかんでもこの x にまとめてしまうことです。
各ペットの情報欄に年齢や性別のほかに、仮に「1日に〇回散歩に行かないといけない」という項目があったとします。
これを x にまとめてしまうと『犬の情報 (x+a)』ではいいんですが、関係のない『猫の情報 (x+b)』に影響を与えてしまいます。
だから、この場合は各ペットの情報欄の項目までは共通化せず、『売られている動物がリストで表示される』という根本機能だけを共通化することがいいように思えます。(犬と猫だけだと差異がわかりにくいですが、変わった動物を追加するとなると変な項目も増えそうです)
かといって、ペットショップのWebサイトということなので、『売られている動物がリストで表示される』という機能の共通化を疑う必要はないでしょう。それだと、オブジェクト指向の意味がなくなります。
次に、f(a) = x+a とすると、
ペットショップのWebサイト
= f(a) × f(b) × c
= 犬の情報 × 猫の情報 × 店舗の情報
となり、 犬(a) や 猫(b) を f に与えるだけで欲しい情報が得られるということです。
この f こそが、『売られている動物をリストで表示する』という機能であり、インターフェースです。
この『動物』という抽象に対してプログラミングしていくことが、ポリモーフィズムです。
最後に、カプセル化について考えます。
f はインターフェースや抽象クラスで、 f(a) は『売られている犬をリストで表示する』という具象クラスです。
実際にペットショップのWebサイトを構築する際は、この f(a) を使います。
そして、この f(a) を利用するとき、『売られている犬をリストで表示する』という具象クラスであるということだけを知っていればよくて、f(a) = x+a だという具体的な中身を知っている必要は全くありません。
実は、『売られている犬を「人気順に」リストで表示する』ということをやっていて、中身が f(a) = 3x+1+a と多少複雑になっているかもしれません。
ただ、このように具体的な中身を知らずとも、 f(a) を使えばWebサイトは構築できます。
クラスを外部から利用するとき、 f(a) のような簡素な見た目で提供し、影響範囲をクラス内にとどめておくことをカプセル化といいます。
いかがでしたか?
「オブジェクト指向は因数分解だ!!」理論は。
あなたのソース、c(x^2+ax+bx+ab) や x^2(1+a/x)(1+b/x)c になっていないでしょうか?
「うわあ、暇だあ…」
最後まで読んでくださり、私としてはうれしい限りですが、相当お暇なんですね。
なにか自粛期間にできる趣味をお探しになることをお勧めします。
以上、わいでした。
健闘を祈る!!