はじめに
ソフトウェア設計におけるモジュール結合について学んでおり、
その中で表題のパターンについて知ったので、今回はこれを記事にしてみたいと思います。
スタンプ結合とは
モジュールがデータ構造を丸ごと受け取っている一方、
処理においてはその一部を使うのみになっている、
と言うモジュール結合のことをスタンプ結合と言います。
何らかの振る舞いを表現するために処理を実装するとして、
そのために不必要な知識までを必要としている、
言い換えると、そう言った不要な知識までもが、本来カプセル化されていなければならないにもかかわらず、
内部実装と言う知識(情報)として漏れ出してしまっている状態になっている、
それを引き起こすようなデータ構造の利用のあり方になっている状態を指しています。
共通結合との違い
データ構造に関係するモジュール結合というと共通結合も挙げられます。
この両者はデータ結合に関するモジュール結合という点では似ていますが、内実は大きく異なっています。
両者の違いは、
- 共通結合のデータ構造はグローバルで可変な状態で共有されているが、スタンプ結合ではそうではなく、メソッド呼び出しの場面などに限定される
- 上記の違いにより、共通結合のデータ構造とその値はさまざまなところで参照・更新され得るために追跡や管理が難しいが、スタンプ結合ではそのデータを呼び出すモジュールに管理が限定化されており、参照される程度なために追跡や管理が容易
- それにより、共通結合ではその利用の並行性の制御や値の検証が必要になるが、スタンプ結合ではその必要がない
こういったところにあります。
モジュール利用における知識、情報、状態の漏れがシステム全体に及ぶ影響力の点で大きく異なっているのです。
具体例
言葉だけだとイメージが湧きにくいので、ここで以下のコードを紹介いたします。
class Order {
final String id;
final int totalPrice;
final String shippingAddress;
final DateTime orderedAt;
Order({
required this.id,
required this.totalPrice,
required this.shippingAddress,
required this.orderedAt,
});
}
String generateReceiptText(Order order) {
return 'お買い上げ金額は: ¥${order.totalPrice} です。';
}
void main() {
final myOrder = Order(
id: 'ORD-123',
totalPrice: 5500,
shippingAddress: '福岡県博多区...',
orderedAt: DateTime.now(),
);
final receipt = generateReceiptText(myOrder);
print(receipt);
}
上記generateReceiptText関数はお買い上げ金額をテキストとして返すためにOrderというデータ構造を介して、
その内部のtotalPriceを呼び出しています。
実際のプロダクト開発においてはこういった書き方はよく見られるものかと思われますが、
こういった、「自身の関心事、目的、役割、責務を達成するために必要となる情報をデータ構造を介して利用する」、
といった状態をスタンプ結合と言います。
今回はメソッドチェインが最少なのでそこまで問題が目立っていませんが、これが長大化した場合は問題が出てきます。
こういった設計は「デメテルの法則」にも反しており、その具体例と解消法については、僭越ながら、以下の記事をご参照ください。
参考