デザインパターン学習の必要性は受験数学で例えると分かりやすい【必須】
プログラミングのObject-Oriented Programming (OOP) の学習中。今はfactoryパターンを学習中。この章は長い。あと2日はかかりそうだ。
だがだんだんとデザインパターンを学ぶメリットが分かってきた気がする。
(約 4,600文字の記事です。)
【誤解】OOPはプロシージャルより優れている?
まずこれは初心者の大いなる誤解(私の誤解)。OOPは手法であって、コードスタイルの違いでしかない。なので記法の違いで何かしらの優劣を付けるというのは、結構乱暴な話。
みんなが通るHello world、プロシージャル・プログラミング
処理手順を考えた順に実装できる
分かりやすいし考えやすい。創意工夫しやすい。
場合によってはモジュールに分けてメインの処理と、繰り返し使われるようなサブの関数処理の記載位置を変えてスッキリさせる(可読性の向上)
グローバル、ローカルな引数が入り乱れ始める
モジュラープログラミング特有の「引数の受け渡し」の多発
スパゲッティーコードに向かって発展・進化していく運命(さだめ)
取っつきやすいし分かりやすい。思考の過程をコードに起こしていく楽しさがある。知恵の分だけコードを拡張して便利にできる。なのでみんなが通るプロシージャル・プログラミング。何にも悪いことはないじゃないか!と思うのだが、規模の大きい、複雑なソフトを作ろうとすると大きな壁にぶつかる。
OOPは何か凄いらしいが、なるほど分からん
んで、プロシージャルの逆の結果、これがOOPの特徴になる。
処理手順は既に「どのパターンを選ぶか」というコード設計時点でほぼ決まっている。考え出す部分ではない。
理解するまでの学習量がかなり必要。そして実は「創意工夫する要素はない」というかそれは最終手段なのだ。
モジュール分けに相当するようなクラス設計、メソッド設置も、実はパターンを決めた時点でほぼ機械的に決まる。考え出す部分ではない。
デザインパターンを用いることで自動的に疎結合になるので引数の要り乱れは起こらない
パターンの原理・原則を守って拡張する分にはスパゲティにならない(原則を破れば少しずつ壊れる=スパゲッティーへの迷路の入り口)
OOPの場合、実は創意工夫や「パターンに何かしらの新たな要素を加えること」は不要なのだ。むしろやってはいけない。それができるレベルに達しているならばOOPの原則を体得しているはずなので、それができるレベルに達するまではOOPの型を破ってはいけない。スパゲッティーの入り口。
学んでも学んでも、出口の見えない学習量
創意工夫の余地がない、あるにはあるが今はそのレベルにないので手足すら出せない
さっきのパターンの知識が次のパターンの学習で「少ししか」役に立たない(OOPの原理原則しか使えない。そりゃそうだ、似たパターンは淘汰されて優れたパターンだけが生き残った「その結果」だけを学んでいるわけだから、学習教材で重複領域が少ないのは当たり前。むしろ学習効率化のための優良教材を選んだとも言える。)
ちょっとやそっとのパターンを理解したところで「それって結局何に使えるの?」という疑問がいつもわき上がる
だがHead First本を4分の1ほど進めて理解した時点で、ちょっとだがOOPのメリットが分かるようになった。
学問として探求するのか?受験科目として学ぶのか?
多分この感覚が一番しっくりくると思う。例えば数学。学問として探求するために数学を学ぶのか?あるいは高校受験、大学受験で合格点を取るために数学を学ぶのか?
この両者のアプローチはまったく異なる。目的が異なる。例えば受験数学の場合、定理の深い理解よりも、結論の公式を暗記していることの方が重要だったりする。例えば三平方の定理が導かれた経緯なんか知らなくても、
x^2 + y^2 = z^2
つまりは水平の2乗+垂直の2乗=斜辺の2乗ってことなわけで、それを問う設問でこの数式を「どう使えば答えに辿り着けるか」を知っていることが受験数学では重要。
もっと言えば「こういう設問ではこういうふうに解く」というパターン学習が重要だったりする。
もう分かったかな?
そう、OOPのデザインパターン学習も、実はそれ。パターン学習こそがその使いこなしの真理だったのだ。
受験数学ではなくて現実問題の課題への対処
それが受験数学ではなくて、現実問題としての「ソフトウェアが解決すべき課題」に置き換わっただけ。そしてその最短の解決手法として、先人プログラマ達が試行錯誤した結果、残ったエッセンス、つまりは「問題の解き方」これがOOPにおけるデザインパターンだったのだ😍
受験数学が現実問題のユーザーストーリーズ(顧客のニーズ)へ
問題の解法の学習がデザインパターンの学習へ
設問に対する解法の選択がOOPのデザインパターンの選択へ
これらが置き換わっただけなのだ。
プロシージャルでプログラミングの自由の翼を得て自由にやりたい放題できるようになったあとで、また、再び受験勉強のようなデザインパターンに戻りたくないってのは、よく分かる。
だがここで思い直してほしい。受験の設問には解法パターンがあり、それを「出題率の高い問題にフォーカスしてその解法パターンを使って答えに近づける(実効性を高める)」ことで満点に近づく。ならば「現実問題の課題」に対して、もし解法パターンがあるとすれば、それを選ばない理由はナンダ?
受験で三平方の定理を原理から解説していたら時間も記入枠も足りない。そしてそんなことをしない。つまりは現実問題での顧客のリクエストに対して、それをソフトウェアで実現させるための「最適な解法パターン」があるとすれば、それを選ばない理由はナンダ?ということになる。
そしてプロに限らず、プログラマがデザインパターンを学んだあとのメリット、これについてはもう言わずもがな。
圧倒的な「問題への対処力の差」に繋がる。
具体的にはOOPを用いた設計結果そのものが、まったく異なる。一方は「その問題への対処方法」を反復して学んでいるため、その問題については適切なデザインパターンを適用してスマートに解決できているのに対し、他方は「人生で初めて出くわしたような課題」についてこねくり回して、挙げ句に答えを間違うという結果になるかもしれない。あるいは完成時点で既にスパゲッティーとか、有り得る。
【結論】プログラミングを学問したいのか?ツールとして問題解決に使いたいのか?
多分、OOPとデザインパターンの学習の必要性は、これに尽きると思う。プログラミングとして色んなことを探求したいならば、別にOOPもデザインパターンも不要だろう。緻密な引数の受け渡しについてじっくり検討すれば、スパゲッティーにはならない。
個人プログラマが全部自分でソースコードをメンテするならば、実はその方向性もありだと思っている。誰にも迷惑をかけないならば、自由にやっていい。むしろ楽しい活動時間ですらあると思う。プロシージャル・プログラミングは本質的に楽しい経験なのだ😊
だが逆に職業プログラマ、要するに納期という制約がありつつ、他者協業もある状況で、他者プログラマにも優しい可読性の高いコードを納品したいプロのプログラマだったら、そういう芸術作品作りはしていられない。
そして出てくるのが、デザインパターンという武器。受験生が常識として備えている解法パターンの知識であるのと同様に、職業プログラマが常識として身につけていて当然の知識が「OOP+デザインパターン」なのだろう、と予感した。
要するに問題解決に即効性のある手段がデザインパターンなのだが
とはいえ、ここで矛盾もある。その即効性を「有効」にするための長い修行期間が必要だと言うこと。
これについても受験数学を考えればスッキリ分かる。例えば試験時間1時間の間に効率よく6問を解く、たったそれだけのために3年掛けて数百時間も勉強するのが受験勉強なわけだ。これ、デザインパターン学習にもそっくりそのまま当てはまる。納期までの数十時間で問題解決するために、デザインパターンを数百時間かけて学ぶのだ。
だがそれができるようになればスキルになる。受験は終わればそこで全部が無意味になるが、デザインパターンによるソフトウェアでの問題解決スキルは、次の問題解決に生かせる。
なので私が数日前にデザインパターンが受験勉強に似ている、と感じたことは「間違いない直感」だったのだ。だがその後の影響力が受験数学とは異なる。プログラミングでのデザインパターンの理解は、必ず次に繋がると確信している。
少なくともプログラミングの「実践的なレベルアップ」を目指す人は必ず体得しなければならない必須スキルだと、今日確信しました。もちろん、なくても何とかなるけど、身につけていれば圧倒的な差に繋がる、分かりやすいスキルだと思います。
とりあえず個人的にはHead First本が面白く、楽しく学べるようになっただけでもかなり楽になりました😊
今回の創作活動は約1時間(累積 約3,922時間)
(1,165回目のnote更新)