自分が「プログラマが知るべき97のこと」のエッセイを読んで、気づきと学びがあったなと思ったことの「その2」です。
今回のポイント
こちらはプログラミングをテーマにしたエッセイ集です。
xn--97-273ae6a4irb6e2hsoiozc2g4b8082p.com
97のこと・・と言いながら、107個ものエッセイがあります。
読んでいると色々な気づきがあります。
今回は、自分が学んだこと「その2」で
DRYとSRPの両原則を守りつつも共通化は慎重に
にというキーワードで引っ掛かったポイントを引用しつつ書こうと思います。
DRY原則
DRY(Don’t Repeat Yourself :同じことを繰り返すな)原則は、Andy HuntとDave Thomasが書籍「達人プログラマー―システム開発の職人から名匠への道」で提唱したソフトウェア開発原則なのです。
DRY原則の説明を引用すると。
1つのシステムの中で同じものが重複することがあってはならないという原則です。
言い換えれば、1つの知識に対応する実装は必ず1つにする、ということです。
ということです。
このDRY原則を破ったら。
異星人のコンピュータのようにプログラムは矛盾につまづくことになるのです。
これはあなたが覚えていられるかどうかという問題なのではありません。
これはあなたが忘れてしまった時の問題なのです。
こういうことになるのも、よーーーく、わかります。
同じことを複数個所に書いていた場合、「片方を変更するのであれば、もう片方も変更しなければならない」わけですが、これを完璧に行うのは、ほぼ不可能です。
一度、運用にはいったアプリケーションは、下手すれば数十年使われ続け、プログラムをメンテナンスする人間もころころ変わることもありますから。
これは「あなたが忘れてしまった時の問題」とは、まさに言いえて妙です。
SRP原則
単一責任 (Single Responsibility Principle :SRP)原則」も重要です。
これは。
変更する理由が同じものは集める、変更する理由が違うものは分ける。
という原則です。
もう少し具体的には
1つのサブシステムやモジュール、クラス、関数などに、変更する理由が2つ以上あるようではいけない、ということです。
とか。
良いシステムデザインとは、システムのコンポーネントがそれぞれ独立してデプロイできるようになっているデザインのことです。
独立してデプロイできるというのは、あるコンポーネントに変更を加えたからといって、別のコンポーネントの再デプロイは不要であるという意味です。
と説明されています。
エッセイで取り上げられている例は以下のようなクラスです。
Employeeクラスに
- calculatePayメソッド:給与計算に関わるビジネスルール
- reportHoursメソッド:レポートを出力する
- saveメソッド:データベースに保存する
という3つのメソッドが定義されているわけです。
一見問題なさそうに見えますが、SRP原則を破っています。
理由を引用すると
問題なのは、3つのメソッドがまったく違った理由によって変更される可能性があるということです。
calculatePayメソッドには、給与計算に関わるビジネスルールが変わる度に、変更を加える必要があります。
reportHoursメソッドには、レポートのフォーマットが変わる度に、変更を加える必要があります。
saveメソッドには、DBAがデータベーススキーマを変更する度に、変更を加える必要があります。
3つも変更理由があるEmployeeクラスは、非常に不安定な存在と言えます。
となっています。
SRP原則を忘れると、様々な理由で頻繁に修正されて運用のネックになるプログラムになるリスクがあります。
そして、そういうプログラムは運用上重要なものだったりするわけです。
開発側にとっても、過大なメンテナンス負荷という形で降りかかってきます。
DRY原則ほどわかりやすくない、サイレントキラーのような原則だなと思います。
共通化はやりすぎると駄目
もちろん、「ソースの共通化」を行って記述量を減らすのは良い事です。
良いことなんだけど、やりすぎ注意・・ということです。
でも、やりすぎてしまうと
私は思い知らされることになります。
コードの再利用を容易に促進すると、かえってひんしゅくを買ってしまうのだ、ということを。
というエッセイ作者みたいなことになるようです。
問題なのは。
共通部分を使うソースコードの間に生まれる依存関係です。
狭い範囲でならいいんですけど
広範囲での依存関係が生じると、システムの様々な部分がそれに巻き込まれることになり、ライブラリのコード自体は良く出来ていても、デメリットのほうが大きくなります。
なんてことになります。
そりゃあ、そうですよね。
後でライブラリをちょっと直しただけで、広範囲のコードの調査やテストに莫大な工数がかかってしまう・・みたいなことが起きます。
エッセイでは
私は今では、システム全体の構造がわからないうちは、コードの共有を容易に進めたりはしません。
まずはぶぶんどうしの関係をよく見て、どこをライブラリ化すべきかを慎重に考えます。
という教えがかかれています。
そうだよな。
自分も肝に銘じないといけないな・・などと思ったわけです。
YAGNI プラクティス
もうひとつ大事なこと。
それは「YAGNI (You Ain’t Gonna Need It :それは多分、必要ない)」です。
本当に必要なコード以外は書くべきではない・・という原則です。
余計かもしれないが、面白そうだと思えた
とか
将来必要になるかもしれないと思った。
とか
必裂かどうか判断に迷った。
とか。
迷った時に「とりあえず書いておこう」とか、「余計かもしれないけど、面白いから実装しておこう」はやめましょう・・ということです。
でないと。
一部のタスクの実行に時間がかかりすぎるという問題が起きたことがありました。
本来は、ほぼ瞬時に完了するはずの簡単なタスクです。
原因は、実装をやりすぎていたことにありました。
ベルやホイッスルなどといった余分な付属機能を加えすぎていたのです。
作った時にはステキなアイデアに思えたのですが、結局は無駄でした。
などということが発生して、本来必要のない苦労をさせられることになるわけです。
なるほどですね。
これもつい忘れがちなので、時々、意識しなおさないと・・です。
今回はエッセイの中で頻繁にでてくる4つのポイントについて整理してみました。
今回はこんなところで。
ではでは。