# DRY原則と密結合について初心者向けに解説

> エンジニアの概念とされるDRY（Don't Repeat Yourself）原則が密結合にどのように影響するかを解説し、DRYだが密結合なコードの具体例とそのリファクタリング方法についても紹介します。

- 公開日: 2024-12-04
- 更新日: 2024-12-05
- 著者: Matsu
- タグ: エンジニア概念マップ
- URL: https://tech.anycloud.co.jp/articles/dry-tightly-coupled

---

## はじめに

今回の記事を読むにあたり、以下の記事が前提となってきますので、まだ読まれていない方はこちらお読みください。

<div class="link-card-wrap"><a class="link-card" href="/articles/loose-coupling-tightly-coupled/" target="_blank" rel="noopener noreferrer"><span class="link-card-body"><span class="link-card-title">密結合と疎結合を分かりやすく解説</span><span class="link-card-description">「密結合」と「疎結合」の概念を解説し、それぞれのメリット・デメリット、具体例を挙げて、理想的なコード設計におけるバランスの重要性について解説しています。</span><span class="link-card-meta"><img class="link-card-favicon" src="./linkcard-01-favicon.ico" alt=""><span class="link-card-domain">tech.anycloud.co.jp</span></span></span><img class="link-card-image" src="./linkcard-01-image.webp" alt=""></a></div>

「DRY原則」と「密結合」は、どちらもコードの品質に大きく関係する概念ですが、誤って適用するとかえってコードが複雑になり、メンテナンスが難しくなることがあります。

この記事では、以下のポイントについて、Flutterの具体例を交えて解説していきます。

1.  誤ったDRYが密結合に繋がる理由
2.  DRYだが密結合なコードの具体例
3.  DRYだが密結合・低凝集なコードを疎結合・高凝集なコードにリファクタする方法

それではさっそく見ていきましょう。

## 誤ったDRYが密結合に繋がる理由

一見正しいDRYの適用でも、無理にまとめすぎると以下のような問題が発生します。

### **1.コードの密結合**

まとめたコードに複数の箇所が強く依存してしまい、一部を変更するだけで他の部分に影響が及んでしまう。

### **2.低凝集**

1つのクラスやモジュールが複数の責任を持ち、特定の目的に集中していない状態。

本来異なる目的の処理が一箇所に詰め込まれることで、コードが読みにくくなり、再利用もしにくくなる。

## DRYだが密結合なコードの具体例

以下のコードは、Flutterでボタンを作成する際にDRYを意識したコードの例です。

```dart
import 'package:flutter/material.dart';

class SharedButton extends StatelessWidget {
  final String buttonText;
  final Function onPressed;
  final bool isPrimary; // ボタンの種類を切り替えるフラグ

  SharedButton({
    required this.buttonText,
    required this.onPressed,
    this.isPrimary = true,
  });

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () => onPressed(),
      style: ElevatedButton.styleFrom(
        backgroundColor: isPrimary ? Colors.blue : Colors.grey,
        padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
      ),
      child: Text(buttonText),
    );
  }
}
```

一見、何の問題もないように見えますが、上記は密結合・低凝集になってしまっています。

### **密結合**

このボタンは、スタイルや機能をまとめていますが、`isPrimary`フラグの切り替えに全て依存しており、他の画面や用途に合わせたカスタマイズが難しいです。

例えば、特定の画面でボタンに別の色を追加したい場合などに柔軟に対応できません。

### **低凝集**

ボタンのスタイルとロジックが1つのクラスに詰め込まれており、中途半端になってしまっています。

## DRYだが密結合なコードを疎結合・高凝集にリファクタする

密結合なコードをリファクタリングするには、単一責任の原則（Single Responsibility Principle）を意識して、それぞれの要素が1つの目的に集中するように設計することが望ましいです。

### リファクタリング後のコード例

```dart
import 'package:flutter/material.dart';

// ボタンのスタイルを担当
class ButtonStyles {
  static final ButtonStyle primary = ElevatedButton.styleFrom(
    backgroundColor: Colors.blue,
    padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
  );

  static final ButtonStyle secondary = ElevatedButton.styleFrom(
    backgroundColor: Colors.grey,
    padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
  );
}

class CustomButton extends StatelessWidget {
  final String text;
  final VoidCallback onPressed;
  final ButtonStyle style;

  CustomButton({
    required this.text,
    required this.onPressed,
    required this.style,
  });

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: onPressed,
      style: style,
      child: Text(text),
    );
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('リファクタ後')),
      body: Column(
        children: [
          CustomButton(
            text: 'Primary Button',
            onPressed: () {
              print('Primary Button Clicked');
            },
            style: ButtonStyles.primary,
          ),
          CustomButton(
            text: 'Secondary Button',
            onPressed: () {
              print('Secondary Button Clicked');
            },
            style: ButtonStyles.secondary,
          ),
        ],
      ),
    );
  }
}
```

上記のように改善することで、疎結合・高凝集にリファクタすることができました。

### **疎結合**

スタイル（`ButtonStyles`）とウィジェット（`CustomButton`）が分離されており、それぞれ独立して変更可能になった。

### **高凝集**

プログラムの1つのクラスやモジュールが、単一の責任や目的に集中している状態で、読みやすく再利用しやすい設計になっている。

## まとめ

DRY原則を守るときも、「疎結合・高凝集」を意識して設計することが重要だとわかりました。

リファクタリングのポイントとして、責務を分離し、各部分が独立して動作するよう設計することで、柔軟性と保守性を高められます。

こうした設計の工夫がコードの質を大きく向上させるので、ぜひ実務でも活用していきたいです。
