どうも村上です。
今回はオライリーから発売されている「レガシーコードからの脱却」を読んだ直感的な感想と要約を記載いたします。
レガシーコード・・・古の改修が困難で影響力が大きいコード
レガシーコードについて
レガシーコードが与える影響は底がしれません。
なぜそこまでレガシーコードについて真剣に考えなければいけないかと言うと、プロジェクトの成功の判断になる「コスト」「納期」に非常に密接に関わってくるからです。
例えば機能を初めて追加するよりも、既存のコードを理解した上で改修を行うほうが時間・コストがかかってきます。
またレガシーコードがあることによって仕様が複雑になり人間の理解の範疇を超えてバグの温床となる可能性が高いです。
バグの修正作業は突発的であることが多く、プロジェクトをスケジュール的にも精神的にも苦しめていきます。
そのために私達プログラマーはレガシーコードをいかに生み出さないかが重要であり、日々考えていけない課題であるというのが、本書でも強く書かれていました。
レガシーコードによる負債
レガシーコードを生み出さないようにするためには、なぜレガシーコードが出てくるのかを理解する必要があります。
典型的なパターンとしては最初はしっかりとした設計をしていたとしても度重なる新規機能の追加などを繰り返すことによって、あっという間に機能拡張が難しくなり最初の設計が機能しなくなるレガシーコードが誕生いたします。
本書ではどちらかと言うと、そうなってしまったレガシーコードをどうするかよりも、レガシーコードを生み出さないためにはどうすれば良いかということに焦点を当てていました。
レガシーコードを生み出さないために、本書では9つのプラクティスを提唱していました。
- やり方より先に目的、理由、誰のためかを伝える
- 小さなバッチで作る
- 継続的に統合する
- 協力しあう
- 「CLEAN」コードを作る
- まずテストを書く
- テストでふるまいを明示する
- 設計は最後に行う
- レガシーコードをリファクタリングする
上記のプラクティスは必ずしもどのプロジェクトに当てはまるものではないとは思いますが、少なくとも取り入れられる部分は参考にすべきだと思います。
「CLEAN」コードを作る
プログラマーとして働いている方は様々な美的センスを持っていますが、プロジェクトをチーム単位で行っていく上でそれぞれが異なる美的センスを持っているとそれはすぐにコード上に現れ、扱いが難しいものとなっていきます。
そういった問題を防ぐために先人たちは様々な原則を定義いたしました。
そのうちの1つに本章第5章にある「CLEAN」であること、という原則が提唱されていました。
「CLEAN」とは
- Cohesive 凝縮性
- Loosely Coupled 疎結合
- Encapsulanted カプセル化
- Assertive 断定的
- Nonredundant 非冗長
上記のそれぞれの頭文字を取って「CLEAN」と言います。
1.凝縮性があるということはプログラムが正しくまとまっていることを示します。
必要な機能のプログラムがそれぞれまとまっているということで理解がしやすくなり、バグの混在を防ぐことが可能です。
2.疎結合であるというのは、機能と機能間の依存度が少ないということです。
システム間が独立していることで改修を容易にし、ユニットテスト可能な状態になりやすくなります。
3.カプセル化というのは、オブジェクト指向プログラミングでよく言われます。
実際のデータなどは外部から見えないようにし、データを扱う手続きなど必要なもののみ公開するという手法です。
メリットとしてはクラス内のデータ不整合を防ぐことが可能にになります。
4.断定的であるというのは、プログラムの状態は使われるその場で管理されているという意味になります。
これは凝集性があれば自然と断定的になりやすくなります。例えば不用意にグローバル変数が多用されているとコードを読む際に私達の脳内メモリーをかなり消費していきます。
5.非冗長はそのままで、同じ振る舞いをするプログラムを二度書かないということです。
上記の原則は基本的にプログラムやフレームワークの機能として提供されているのですが、使い手がその原則の背景を理解していないと扱われるプログラムはすぐに技術的な負債となっていきます。
原則を理解することによって、読み手に優しく改修可能なプログラムを作成していきたいですね。
テストで振る舞いを明示する
本書ではいかにしてテストが大事だということが提唱されていました。
テストにも、ユニットテスト、結合テスト、受け入れテストなど様々なテストがありますが、ここではユニットテストについて解説していきます。
「テストで振る舞い明示する」とは、ものすごく簡単に言うとテストをドキュメント代わりにするということです。
テストを読むことで設計書などを読まずともプログラムの動き方について理解ができるというのが理想の状態でしょう。
そのためにどうするかというと、「6.まずテストを書く」にも記載があるのですがテストファーストエンジニアとなるということです。
テストファーストエンジニアは名前の通りテストに重きを置くエンジニアです。
テストファーストになるための手法の一つにテスト駆動開発というものがあります。
ここではテスト駆動開発については深く掘りませんが、
- まずテストを書きプログラムの振る舞いを記述
- テストのコンパイルが通るようにメソッドを追加
- メソッドが返す代表的なパターンを記述
- メソッドに具体的な処理を追加
- メソッド、テストをリファクタリング
上記の5つのサイクルを繰り返して開発を進めるということです。
機能を作る前にテストを書くのは確かに気持ち悪いかもしれません。
しかしテストを先に書くことでプログラムはテスト可能なコードになるように独立され、さらに不必要な余分な実装をしにくくなります。
さらに自動テストがあることで改修時のバグ混在率は大幅に減少し、結果としてプロジェクトのコスト節約につながるというのが大事なポイントです。
ただの開発手法の一つとして捉えるものいいですが、運用コストを下げいかにプロジェクトを成功に導くかというのも、エンジニアにとって極めて大切な考え方だと思います。
まとめ
「アジャイルサムライ」にも記載されていましたが、アジャイルでは機能を細かい単位で考えた上で日々リファクタリングを実施する姿勢が大事であるということが書かれていました。
そしてテストが明確であること、テストを見ると機能が理解できること
いつでもリリースができて統合できていること
上記のようなことを当たり前で実施することによって、プロジェクトを成功へと導け、お客様との信頼関係を築ける土台が完成するのだと思いました。
まだまだソフトウェア開発業界は建築や物理学と比べると極めて未成熟で不安定な業界ですが、少しでも私達エンジニアが日々の課題を改善することで、お客様・私達の後ろの世代により良いものを届けれたらと思います。
コメント