こんがらがったシステムの保守開発で苦労した経験から新規開発では「シンプルな構成・シンプルな実装にしよう」という話が出る。
目指す方向としては間違って無いように思えるのに、それだけだとうまく行かない。
「保守しやすい構造」とはそれなりに多くの知識が必要なので、これらの知識を持たず単純に「シンプルな構成・シンプルな実装」を目指すと失敗する。
「保守しやすい構造」を作るには「どういう構造が保守しやすいのか?」を学ぶ必要がある。
これについて書く。
「シンプル」を目指したつもりが複雑になって失敗する例
まずは、ありがちな失敗例を示す。
実装する処理を減らしてシンプルにしたら複雑化した
コードの複雑さを減らすため、実装する機能を絞った。
コード量が減ったのでシンプルになった。
しかしここで削られた機能の処理は結局はどこかでやる必要があった為、後日別の場所(連携する別システム側など)に実装された。
やるべき所でやってないのでデータの受け渡し等の必要性が発生しコードが複雑化した。
テーブル数を少なくしてシンプルにしたら複雑化した
テーブル数は少ないほうがread / wrightのコードがシンプルになる。
また、1テーブルを見ればどういうデータが入ってるか解るので、パッと見で理解しやすくシンプルであると思えた。
しかし、データ不整合が発生するので、それを防止するための処理コードが実装された。 また、どこか一部の処理がこの防止処理を通していなかったようで、すでに不整合なデータがテーブルに入ってしまい、データも信用できない状態になってしまった。。
・・・
これらは「局所的にシンプル(簡単)にできたが、全体としては複雑化してしまった例」である。
保守しやすくするためにシンプルを目指したのに、真逆の結果になってしまった。
シンプルな方が保守しやすいとは限らない
上記失敗例でも見て取れるように「シンプルにする」をとにかく実行すれば保守しやすい構造になっていくわけではない。
「シンプルにする」は複雑性を下げる為の1要素ではあるが、それだけでは駄目だという事だ。
例えば、DIやDIコンテナはシステムにある程度の「複雑性」を持ち込む事になるが、コードを単体テストしやすくなったり、依存度が下がったりして保守性があがる。
つまり、複雑になったのに保守しやすい構造になることもある。
「局所的なシンプル」ではなく「全体としてのシンプル」を目指すために、ある程度の複雑性を取捨選択しながら計画的に構造を構築する必要がある。
にわか知識で構造に手を出すと痛い目にあう
こちらの動画を見てほしい。
クソコード動画「共通化の罠」 pic.twitter.com/MM750CNXc2
— ミノ駆動 (@MinoDriven) May 12, 2019
クソコード動画「Managerクラス」#すえなみチャンス暑気払い pic.twitter.com/3FSQDkXfHu
— ミノ駆動 (@MinoDriven) August 3, 2019
これはミノ駆動さんの「クソコード動画シリーズ」。
面白いのでたまに繰り返し見てます。
注目してほしいのは、最初この登場人物は別に「複雑にしてやろう」とか思って無い所だ。
良かれと思ってやったことが結果的にどうしようもない構造を作り出してしまっている。
上記の失敗例も同じく、みんな良かれと思ってやっている。
過去の自分もやってしまったことがあるし、既存コードにそういう部分を見かけるのは「あるある」ではなかろうか?
保守しやすい構造にするにはそのための知識が必要だ。
知識が無い状態でオレオレ構造を作ると失敗する危険性が大きい。
保守しやすい構造に必要なものを既存知識から学ぶ
話がズレるが「ランダムな値を返す関数」が必要になった時、自分で実装することはしない。
既に存在する関数を使う。
なぜなら、それは専門家により多くの時間をかけて設計・実装された関数なので、自分で作るものよりもはるかに信頼できるからだ。
「保守しやすい構造」についても同じく、既に偉い人々が考えて指針を出してくれている。
我々入門者が改めて、オリジナルな独自の視点で「どういう構造が良いか」についてあーだこーだと議論するのは「車輪の再開発」と同じ種類のものだと思う。
指針も色々あるが「プリンシプル オブ プログラミング」に一通り記載されていてわかりやすかった。
一部だけ引用すると以下
- KISS(シンプルにしておけ)
- DRY(コピペするな)
- YAGNI(それはきっと必要にならない)
- PIE(意図を表現してプログラミングせよ)
- SLAP(抽象化レベルの統一)
- OCP(拡張に対し開き、修正に対して閉じている)
- ...他にも色々ある
もちろん、この本以外にもこれら重要な指針は様々な書籍で繰り返し出てくる。
つまり「保守しやすいシステム構造」を作るための指針は「シンプルに実装する」だけでは全然足りないという事だ。
こういった指針等を知識として吸収して初めて目指すことができる。
「保守しやすい構造」について議論する時、単に自分が思った意見を投げ合うのではなく「これらの指針を満たしているのでこういう構造はどうか?」のように、指針ベースで議論しないと雰囲気だけで誤った結論に導かれてしまう可能性が大きい。
(補足)保守しやすいテーブル設計には正規化が必要
テーブル設計では正規化することが重要。 IPA基本情報技術者試験(※応用ではない!基本!)の試験範囲にもなっている。
IPA 独立行政法人 情報処理推進機構:試験要綱・シラバス など
データベース設計
【目標】
・データの分析,データベースの設計の考え方を理解し,担当する事項に適用する。
・データの正規化の目的,手順を理解し,担当する事項に適用する。
・データベースの物理設計における留意事項を理解し,担当する事項に適用する。
このあたりの書籍がよかった。
理論から学ぶデータベース実践入門 ~リレーショナルモデルによる効率的なSQL (WEB+DB PRESS plus)
- 作者:奥野 幹也
- 発売日: 2015/03/10
- メディア: 単行本(ソフトカバー)
保守しやすい構造の例としてアーキテクチャを学ぶ
KISSやDRYやOCPのような指針を理解したならば、原理的にはそれを満たすようにシステム構造を組み立てれば保守しやすい構造になるはず。
次に「では具体的にどういう構造にすればよいのか?」という問題にぶつかるのだが、これも偉い人が検討して色々案(デザインパターン・クリーンアーキテクチャ・DDDなど)を出してくれているので、まずはそれらを学ぶのが手っ取り早い。
Clean Architecture 達人に学ぶソフトウェアの構造と設計 (アスキードワンゴ)
- 作者:Robert C.Martin,角 征典,高木 正弘
- 発売日: 2018/08/01
- メディア: Kindle版
- 作者:ヴォーン・ヴァーノン
- 発売日: 2015/03/19
- メディア: Kindle版
これらの本もなかなか抽象的な話が多くて「結局どういうコードにすれば良いのだ??」という悩みが尽きなかったが、nrsさんがコードベースでの説明をたくさんしてくれていて非常に参考になる。
これらをベースにして、もし自分のプロジェクトに合わない部分があればその部分だけをフィットするようにカスタマイズするのが良い。
ただし、本当に理解した上でカスタマイズしないと、そこが負債になってしまう危険性はあるので注意。
まとめ
「保守しやすい構造」を作るには「どういう構造が保守しやすいのか?」を学ぶ必要がある。