ども、いつもブログが長いと定評のあるバスクリンです。
今回は、前回少し出てきた「依存性」について業務に役立ちそうな話をしてみたいと思います。
依存性とは?
辞書で調べると「他のものによりかかり、それによって成り立つもの」とあります。 ではプログラムの世界でいう依存性とはどんなものがあるでしょうか?
まずは下の図を見てください。
AはBに依存しています。
AやBをクラスと考えるとBのインスタンスを使っていればBに依存していると言えます。 AとBが関数で、Bを呼び出している場合もBに依存していると言えます。 Aが関数でBという引数を外部から渡されて使っている場合もBに依存しています。
依存には色々な依存があります。
依存性があると・・・
例えば先ほどの図のBを変更してみます。すると今まで正常に動いていたはずのAまで影響を受けてしまう場合があります。
例えば業務アプリなどでデータベースを使用している場合は、データのベースの操作にライブラリを使っていると思います。このライブラリにバグがあって使えなくなったらどうでしょう?システム全般に影響が出ると思います。
また、下図のように複雑な依存関係があるプログラムにバグがあった場合はどうでしょうか?
1か所修正するだけですが、依存関係を全て調査しないと修正できません。 このくらいの依存関係なら、一般的なシステムなら十分にありえる複雑度です。今、私が担当しているシステムは80万行のC++のシステムなので、1か所修正するのも慎重に調査が必要になります。
また、複雑に絡み合った依存性があると、ユニットテストする際に依存関係が邪魔になってテストできない場合もあります。これが依存性の大きなデメリットです。
依存性を減らすには?
依存性を減らすためのテクニックは色々あります。
基本的な考え方は
- 疎結合にする
- 小さなクラス、コンポーネントによる部品化
- クラスの持つ責務を正しく設計する
- 依存による制御より、制約による制御
などがあります。
よくある依存性のパターンを考えてみる
よくある業務パターンで考えてみましょう。
よくある登録画面です。「登録」ボタンを押下するとデータをチェックして登録します。
ここで重要なのは、チェックの処理を画面に依存させないようにすることです。
「チェックして、整合性のとれたデータなら登録する」という業務要件は、社員情報登録画面だけのものではないからです。チェック(検証)はインターフェースにしてしまいます。個々のチェックはクラスにしてしまいましょう。
登録処理も毎回登録とは限りません。「チェックが完了すれば削除」かもしれませんし、Web系なら「チェックが完了すれば画面遷移」かもしれません。
ここは抽象クラスを作成して、実行する処理は継承先のクラスに移譲してしまうと汎用的になります。
チェックに失敗した場合は、エラーメッセージを表示するのか、ログに出力するのか、ステータスバーに表示するのかなども、システムに依存する部分です。
このようにインターフェースや抽象クラスを使用して設計していれば、仕様変更に強いプログラムになります。
「○○商事の商品だけは単価チェックはしないで欲しい」
「管理者でログインした場合は、削除前の△チェックは廃止して欲しい」
「システム全体の◇◇チェックは、仕様を変えて欲しい」
「△チェックの前に□チェックをして欲しい」
仕様変更大歓迎です(‘ω’)
さらに言えば、「チェックして処理」の部分は1回のテストで完了です。個々のチェックはそのチェックだけ意識してテストすれば問題ありません。
このように、お決まりの業務パターンなどはどんどん依存性を排除して、疎結合にしてしまうのが堅牢かつ仕様変更に強いシステムになります。
依存性について参考になる書籍など
依存関係について興味がある方は、下記の書籍が参考になると思います。
【新装版 リファクタリング―既存のコードを安全に改善する―】
Martin Fowler (著), 児玉 公信 (翻訳)、出版社: オーム社; 新装版 (2014/7/26)
ISBN-10: 427405019X、ISBN-13: 978-4274050190
マーチン・ファウラー著の定番の一冊です。
依存関係ががんじがらめなシステムをいかに安全にリファクタしていくか、その分類と手法が満載です。 既存システムの保守案件に入ったけど、何から手をつけていいかわからない方は読んでみてください。
【レガシーコード改善ガイド】
マイケル・C・フェザーズ (著), ウルシステムズ株式会社 (監修, 監修),、出版社: 翔泳社 (2009/7/14)
ISBN-10: 4798116831、ISBN-13: 978-4798116839
こちらも既存システムの依存性に真っ向から立ち向かわなければならない人向けの一冊。レガシーコードとはテストコードが一切ないシステムを指します。 リファクタをする前にはテストが必要! このテストのないシステムを、いかに依存性を排除しながらテスト可能な領域まで持っていくか。そんな実務レベルの改善方法が満載です。
まとめ
いかがでしたでしょうか?今回は実務観点から依存性について考えてみました。良いシステムやプログラムを作るためには、依存性はとても重要な要素になります。
依存の少ない疎結合なプログラムが書けるようになれば、コードの量もぐっと減ってバグの少ない高品質なプログラムにすることができます。設計をしている方は、部品化やDIによる依存性の注入、メッセージパッシングやプロトコルによるコラボレーション重視の設計など、依存性を改善する手法は色々あるので勉強してみるのも良いと思います。