0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C言語におけるモジュール結合度

Posted at

C言語におけるモジュール結合度を弱いものから強いものまで、コード例を交えて説明します。

1. データ結合(最も弱い結合)

データ結合は、モジュール間で単純なデータ(基本型)のみをパラメータとして渡す方法です。

// モジュールA
int calculate_area(int width, int height) {
    return width * height;
}

// モジュールB
void main() {
    int w = 5;
    int h = 10;
    int area = calculate_area(w, h);
    printf("Area: %d\n", area);
}

この例では、単純な整数値のみを引数として渡しており、モジュール間の依存関係が最小限です。

2. スタンプ結合

スタンプ結合は、構造体などの複合データ型を介して通信する方式です。

// 共有構造体
typedef struct {
    char name[50];
    int age;
    float salary;
} Employee;

// モジュールA
void print_employee_details(Employee emp) {
    printf("Name: %s, Age: %d, Salary: %.2f\n", emp.name, emp.age, emp.salary);
}

// モジュールB
void main() {
    Employee emp = {"John Doe", 30, 50000.0};
    print_employee_details(emp);
}

この例では、Employee構造体を通じてデータを共有していますが、モジュールAは構造体のフィールドにのみアクセスし、変更はしていません。

3. 制御結合

制御結合は、あるモジュールが他のモジュールの内部ロジックに影響を与える場合に発生します。

// モジュールA
void process_data(int data[], int size, int mode) {
    if (mode == 0) {
        // 合計を計算
        int sum = 0;
        for (int i = 0; i < size; i++) {
            sum += data[i];
        }
        printf("Sum: %d\n", sum);
    } else if (mode == 1) {
        // 平均を計算
        int sum = 0;
        for (int i = 0; i < size; i++) {
            sum += data[i];
        }
        printf("Average: %.2f\n", (float)sum / size);
    }
}

// モジュールB
void main() {
    int data[] = {1, 2, 3, 4, 5};
    process_data(data, 5, 0); // 合計モード
    process_data(data, 5, 1); // 平均モード
}

この例では、モジュールBがモードフラグを通じてモジュールAの動作を制御しています。これにより、モジュール間の結合度が高まります。

4. 外部結合

外部結合は、複数のモジュールが同じグローバルデータを参照・変更する場合に発生します。

// グローバル変数
int g_counter = 0;

// モジュールA
void increment_counter() {
    g_counter++;
    printf("Counter incremented to: %d\n", g_counter);
}

// モジュールB
void reset_counter() {
    g_counter = 0;
    printf("Counter reset to: %d\n", g_counter);
}

// モジュールC
void main() {
    increment_counter();
    increment_counter();
    reset_counter();
    increment_counter();
}

この例では、複数のモジュールがグローバル変数g_counterにアクセスして変更しています。

5. 共通結合

共通結合は、複数のモジュールが共有メモリ領域にアクセスする場合に発生します。

// 共有メモリ領域
typedef struct {
    int status;
    char message[100];
    float values[10];
} SharedData;

SharedData shared_memory;

// モジュールA
void update_status(int new_status) {
    shared_memory.status = new_status;
}

// モジュールB
void update_message(const char* new_message) {
    strcpy(shared_memory.message, new_message);
}

// モジュールC
void update_values(float new_values[], int size) {
    for (int i = 0; i < size && i < 10; i++) {
        shared_memory.values[i] = new_values[i];
    }
}

// モジュールD
void main() {
    update_status(1);
    update_message("Processing");
    float vals[] = {1.1, 2.2, 3.3};
    update_values(vals, 3);
}

6. 内容結合(最も強い結合)

内容結合は、あるモジュールが他のモジュールの内部実装に直接アクセスする場合に発生します。

// モジュールA
void process_array() {
    static int internal_array[100];
    static int count = 0;
    
    // 内部配列に値を追加
    internal_array[count++] = count;
    printf("Added value: %d\n", count);
}

// モジュールB - 内部実装に不正にアクセス
extern int internal_array[];
extern int count;

void hack_module_a() {
    // モジュールAの内部変数に直接アクセス
    internal_array[count] = 9999;
    count += 10;
    printf("Hacked internal state!\n");
}

void main() {
    process_array();
    hack_module_a();
    process_array();
}

この例では、モジュールBがモジュールAの内部実装詳細(静的変数)に直接アクセスしています。これは非常に強い結合であり、モジュールAの実装変更がモジュールBに即座に影響を与えるため、避けるべきです。
各種結合度は、上から下に向かうにつれて強くなり、コードの保守性や再利用性が低下します。良いプログラム設計では、できるだけ弱い結合(データ結合やスタンプ結合)を目指すべきです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?