「直接の友達とだけ話すこと」というプログラミングのお約束です。
社員、部署、会社というオブジェクトがあったとします。
class Employee {
String id;
String name;
Depertment dept;
}
class Depertment {
String id;
String name;
Company company;
}
class Company {
String id;
String name;
}
社員の会社名を取り出すときに、社員から”直接の友達”じゃない会社にアクセスしてはダメという話です。 こういうのはダメです。
employee.dept.name
じゃ、Employee に getter を追加したらいいのか?
class Employee {
String id;
String name;
Depertment dept;
String getCompanyName() {
return dept.name;
}
}
これも正解ではない。というか、何も解決してない。 問題は、社員、部署、会社という3つのオブジェクトに関与してしまっていることです。 依存が大きくて、ほかのオブジェクトの影響を受けやすいです。
これのテストコードを書くことを想像してください。テストデータとして、3つのオブジェクトのテストデータを作らないといけないです。 ユニットテストのコードの大部分は、テストデータとモックなので、依存するオブジェクトが多いと、ユニットテストのコード量も肥大していきます。
ではどうするのか? 解決策は、専用のクラスを作って、責任範囲をそのクラスに限定することです。 "社員の会社名を出力する" とき、このオブジェクトのことだけ知ってればよくて、3つのオブジェクトを知る必要はない。それらのオブジェクトの事情に影響をうけることもない。
class CompanyEmployeeName {
String employeeId;
String employeeName;
String companyName;
}
また、クラスは、多重継承よりも、コンポジットの方がよいのだけど、さらに、プロパティは、できるだけフラットに設計するのが、よいとされてます。 専用クラスを作って、データを移し替えることで、フラットにすることを検討しましょう。
これだけで、テスタビリティは、ものすごく改善します。テストデータは、1つだけだから、テストコードもスッキリします。 とりあえず、なんらかの処理を書くときは、ほかの処理で使っているオブジェクトを使いまわすんじゃなくて、 いったん、必要な項目だけの専用の入れ物を作って、移し替えて、結合の依存をできるだけ薄い状態にして、処理を書くようにする。 これを徹底することで、ユニットテストの作業負荷を小さくしていきましょう。
デメテルの法則、覚えておきましょう。
関連記事
- 2024/01/25 TypeScriptで名前付き引数っぽい実装をする TypeScriptでPythonのように関数呼び出し時に引数名を使って「名前=値」の形式で引数を指定するOptions Objectパターンという技を紹介します。
- 2023/10/17 コードの品質を測定する方法 コードの品質を測定する方法が紹介されていました。計測の自動化に向けて、少しまとめてみました。
- 2020/06/15 PySparkの分散される処理単位であるクロージャと共有変数の仕組み Spark では、処理が分散されて、複数のノードやスレッドで実行されますが、分散される処理の塊を、どう配信しているのか?加えて、複数のタスク間でのデータの共有とか、集約するための仕組みがどうなっているのか?少しだけ説明します。
- 2019/09/24 「オブジェクト指向エクササイズ」でクセの強いコードを矯正しよう よくできたコードは、パッと見で、”なんか違う”と感じさせるところがあり、あぁ、このコードを書いた人はデキるって思わせるものですが、そんなコードを書くためには、どうしたらよいんでしょうか?そのヒントが「オブジェクト指向エクササイズ」にあります。
- 2018/07/18 全文検索を自社サイト・社内サーバーに構築したいクライアントのための留意点 システム開発における「全文検索」の実装方式・コスト・性能に関して、クライアント企業の方にも腹落ち頂けるようまとめました。grep型と索引型の違いに関する平易な解説を記載しているので、これらをクライアントに解説されたい開発者にもオススメです。