Web Analytics Made Easy - StatCounter

工業大学生ももやまのうさぎ塾

うさぎでもわかるをモットーに大学レベルの数学・情報科目をわかりやすく解説! 数式が読み込まれない場合は1回再読み込みしてみてください。

【基本情報対策】うさぎでもわかるソフトウェア工学 Part09 モジュール分割とモジュール独立度(強度、結合度)

こんにちは、ももやまです。

今回はプログラム設計(ソフトウェア詳細設計)の際に行われるモジュール分割と、モジュールの独立度(モジュール強度、結合度)についてまとめを書きました。


特にモジュール独立の関する

  • モジュール強度
  • モジュール結合度

については基本情報で頻出するため、基本情報を受ける人は必ず確認しておきましょう。

前回のソフトウェア工学の記事はこちら!

www.momoyama-usagi.com

UMLの振る舞いを表すユースケース図、シーケンス図、アクティビティ図についての説明です!

1.モジュール分割のメリット

内部設計(プログラム方式設計)されたプログラムは、プログラム設計(ソフトウェア詳細設計)の際にモジュールと呼ばれる単位に分割を行います。

f:id:momoyama1192:20200802213952g:plain

モジュール単位に分割することで、モジュール単位で作成、テストを行えるため、並行して複数の作業を行うことができます。

また、モジュール単位で問題が起こった位置の特定、デバッグが行えるため、保守性に優れたプログラムを作ることができます。

2.2つのモジュール分割技法

モジュール分割技法にはデータの流れに着目する方法3種類データの構造に注目する方法2種類の合計5種類があります。

f:id:momoyama1192:20200802214025j:plain

人名がついている分割技法はデータの構造に注目する方法、人名がついていない分割技法はデータの流れに注目する方法と頭にいれておきましょう。

この方法で頭に入れておけば、試験のときに「あれ、この手法ってデータの流れと構造どっちに注目するんだっけ?」となるのを防ぐことができます。


では、それぞれの分割手法の特徴を下でおさえましょう。

(1) データの流れに着目する分割技法

データの流れに着目する方法には、STS分割法、トランザクション(TR)分割法、共通機能分割法の3つがあります。

f:id:momoyama1192:20200802231726j:plain

(i) STS分割法

STSでは、プログラムを入力処理(Source)、メイン処理(Transform)、出力処理(Sink)の3つに分割する方法です。

f:id:momoyama1192:20200802213957g:plain

なお、STSは、Source(源泉), Transform(変換), Sink(九州)の3つの頭文字を表したものです。

(ii) トランザクション分割法(TR分割法)

プログラムを処理内容ごとにトランザクションと呼ばれるグループに分け、トランザクションごとにモジュールを分割する方法です。

f:id:momoyama1192:20200802214003g:plain

(iii) 共通機能分割法

プログラム中にある共通な機能を1つにまとめて、共通モジュールとして独立、分割する方法です。

f:id:momoyama1192:20200802214009g:plain

(2) データの構造に注目する分割手法

データの構造に注目する分割手法では、ジャクソン法とワーニエ法の2つがあります。

f:id:momoyama1192:20200802214020j:plain


ジャクソン法は入力、出力両方のデータ構造に着目して分割しますが、ワーニエ法では入力のデータ構造のみに注目して分割するのが特徴です。

3.モジュールの独立度

モジュール分割を行う際には、それぞれのモジュールの設計を切り離して行うために、「それぞれのモジュールが独立するような分割方法」、具体的には、

  • それぞれのモジュールが明確である
  • 入出力データが明確である

の2点を満たすようにモジュールを分割する必要があります。


そこで、どれくらいモジュールが独立しているか(モジュールの独立性)を測る尺度として、

  • モジュール強度
  • モジュール結合度

の2つが使われるようになりました。

(1) モジュール強度

モジュール内にある機能の関連の強さを表す基準となるのがモジュール強度です。

具体的に言うと、モジュールがどれくらい単一の機能に特化して設計されているかの度合いを表します。


モジュール強度には、以下の7段階があります。

f:id:momoyama1192:20200802214029g:plain

基本的に、

  • 単一の機能をモジュールにしたのか、複数の機能をモジュールにしたのか
  • 複数の機能をモジュールにしている場合、順番が関係あるのかないのか
  • モジュールの入力、出力データは共通なのか機能ごとに独立しているか

の3つを基準に強度が決定します。

基本情報などの情報処理試験に超頻出するので必ず頭に入れておきましょう。


ということで、それぞれの強度が具体的にどのような状態なのかを強い順に見ていきましょう。

機能的強度

単一の機能を実行するモジュールです。

シンプルでわかりやく、強度が高いため、非常に独立性が高いです。

f:id:momoyama1192:20200802214039g:plain

情報的強度

同じデータ構造を扱う機能をまとめたモジュールです。

イメージはオブジェクト指向のカプセル化です。

f:id:momoyama1192:20200802214043g:plain

連絡的強度(通信的強度)

複数の機能が順番に実行されるモジュールです。

ただし、それぞれの機能の入出力として共通のデータを参照します。

f:id:momoyama1192:20200802214047g:plain

手順的強度

連絡的強度と同じく、複数の機能が順番に実行されるモジュールです。

ただし、連絡的強度と違う点としてそれぞれの機能の入出力は別々のデータとなっている点があります。

f:id:momoyama1192:20200802214053g:plain

時間的強度

初期化処理、終了処理などの特定のタイミングで必要になる処理をまとめたモジュールです。

f:id:momoyama1192:20200802214059g:plain

ここまでくるとだいぶ強度が弱くなってきます。

論理的強度

関連のあるいくつかの機能まとめたモジュールです。

どの機能を実行するかは「入力パラメータ」によって決まります。

f:id:momoyama1192:20200802214103g:plain

暗号的強度

関連のないいくつかの機能をまとめたモジュールです。

とりあえず複数のモジュールをまとめてみました、って感じですね。

(2) モジュール結合度

モジュール間の結合(関連)の度合いを表す基準となるのがモジュール結合度です。

具体的には、モジュール同士がどれだけ独立に or 関連して設計されたかの度合いを表します。


モジュール結合度には、以下の6段階があります。

f:id:momoyama1192:20200802214034g:plain

基本的に、

  • 変数を渡す際に引数で渡すのか、それとも外部宣言されたデータ(グローバル変数、大域変数)を参照するか
  • 引数として渡したのは単一のデータ(int型, double型)なのか構造体として渡したか
  • 制御パラメータを用いてモジュールの実行順序を制御するか

の3つを基準に結合度、独立性が決定します。

(結合度はどれくらい依存しているかを表しているため、結合度と独立性は反比例する点に要注意*1!)

こちらも基本情報などの情報処理試験に超頻出するので必ず頭に入れておきましょう。


ということで、それぞれの結合度が具体的にどのような状態なのかを強い順にプログラムとセットで見ていきましょう。

データ結合

モジュールで必要なデータ項目だけを引数として渡します。

[データ結合の例]

「英語の成績」、「国語の成績」、「数学の成績」の3つを引数から3教科の平均点を求める。

double dataBinding(int eng, int math, int jpn) {
    return (eng + math + jpn) / 3.0;
}

最も独立度が強く、結合度が弱いモジュールです。

スタンプ結合

モジュールで必要なデータ構造を引数として渡します。

[スタンプ結合の例]

3教科の点数が入った構造体から3教科の平均点を求める。

typedef struct score {  
    int id; // 受験番号
    char name[50]; // 名前
    int eng;  // 英語のの点数
    int math; // 数学の点数 
    int jpn;  // 国語の点数
} SCORE;

double stampBinding(SCORE my_score) {
    return (my_score.eng + my_score.math + my_score.jpn) / 3.0;
}

データ結合に比べ、構造体の内容に依存してしまうため、モジュール独立度が弱く(モジュール結合度が強く)なってしまいます

制御結合

引数として制御パラメータを渡すことでモジュールの実行順序を制御します。

他の引数は単一のデータ項目でもデータ構造でもOKです。

[制御結合の例]

名前や3教科の点数が入った構造体から3教科の合計点を表示する。ただし、男性の場合と男性以外の場合で表示が微妙に変わる。

typedef struct score {  
    int id; // 受験番号
    char name[50]; // 名前
    int eng;  // 英語のの点数
    int math; // 数学の点数 
    int jpn;  // 国語の点数
} SCORE;

void controlBinding(SCORE my_score, int gender) {
    int total = my_score.eng + my_score.math + my_score.jpn;
    // 男性(1)か男性以外で分岐
    if(gender == 1) { 
        printf("%sくんの合計点は%3d/300です!\n",my_score.name,total);
    }
    else {
        printf("%sさんの合計点は%3d/300です!\n",my_score.name,total);
    }
}
外部結合

外部宣言された変数(グローバル変数)を参照するモジュールです。

ただし、参照するグローバル変数は単一の変数です。

[外部結合の例]

引数で与えられた「英語の成績」、「国語の成績」、「数学の成績」のうち、どれか1つでも外部変数で与えられる基準値を下回っていれば0(不合格)、それ以外(全部基準点以上)なら1を出力するプログラム(モジュール)。

int border = 60;
int externalBinding(int eng, int math, int jpn) {
    if(eng < border || math < border || jpn < border) {
        return 0; // 3教科のうち1つでも基準点に満たなければ不合格
    }
    else {
        return 1; // 合格
    }
}
共通結合

外部結合と同じく、外部宣言された変数(グローバル変数)を参照するモジュールです。

ただし、参照するグローバル変数が単一データではない(構造体など)のが外部結合と違うポイントです。

(共通域に定義したデータを参照するモジュールと書かれている参考書も多くあります。)

[共通結合の例]

共通域に定義されている配列の平均値を返すモジュール(プログラム)。

int data[5] = {55,66,22,77,44};
int n = 5;
double commonBinding(void) {
    int sum = 0;
    for(int i = 0; i < n; i += 1) {
        sum += data[i];
    }

    return sum * 1.0 / n;
}
内容結合

ほかのモジュール内のデータを直接参照するモジュールです。

ほかのモジュールに依存してしまっているため、結合度が大変強く、独立性が大変低いです。

4.練習問題

では、4問ほど基本情報、応用情報、高度情報の問題で練習してみましょう。

練習1

モジュール強度が最も高いものはどれか。

[基本情報技術者平成19年春期 午前問43]

ア:あるデータを対象として逐次的に複数の機能を実行するモジュール
イ:異なる入力媒体からのデータを処理するモジュール
ウ:単一の機能を実行するモジュール
エ:特定の時点で必要とされる作業のすべてを含んでいるモジュール

練習2

モジュールの独立性を高めるには、モジュール結合度を低くする必要がある。モジュール間の情報の受渡し方法のうち、モジュール結合度が最も低いものはどれか。

[基本情報技術者平成28年春期 午前問47]

ア:共通域に定義したデータを関係するモジュールが参照する。
イ:制御パラメタを引数として渡し、モジュールの実行順序を制御する。
ウ:データ項目だけをモジュール間の引数として渡す。
エ:必要なデータを外部宣言して共有する。

練習3

プログラムの構造化設計におけるモジュール分割技法の説明のうち、適切なものはどれか。

[システムアーキテクト平成22年度秋期 午前Ⅱ問5]

ア:STS分割は、プログラムをデータの流れに着目して分割する技法であり、入力データの処理、入力から出力への変換及び出力データの処理の三つの部分で構成することで、モジュールの独立性が高まる。
イ:TR分割は、プログラムをデータの構造に着目して分割する技法であり、オンラインリアルタイム処理のように、入力トランザクションの種類に応じて処理が異なる場合に有効である。
ウ:共通機能分割は、プログラムをデータの構造に着目して分割する技法であり、共通な処理を一つにまとめ、共通モジュールとする。
エ:ジャクソン法は、プログラムをデータの流れに着目して分割する技法であり、バッチ処理プログラムの分割に適している。

5.練習問題の答え

解答1

解答:ウ

モジュール強度を高くするには

  • なるべく単一の機能を実行するようにする
  • 複数の機能を実行するのであれば機能を順番ごとに対応づける
  • 入出力データを共通にする

などがありましたね。

選択肢を見ていくと、圧倒的に結合度が強い「単一の機能を実行するモジュール」があるので、答えはウとなります。

[他の選択肢]

ア:あるデータを対象として逐次的に複数の機能を実行するモジュール
→ 手順的強度 or 連絡的強度(2番目に強い)

イ:異なる入力媒体からのデータを処理するモジュール
→ 論理的強度(4番目に強い)

ウ:単一の機能を実行するモジュール
→ 機能的強度。最強。選択肢の中だと1番強い。

エ:特定の時点で必要とされる作業のすべてを含んでいるモジュール
→ 時間的強度(3番目に強い)

解答2

解答:ウ

モジュール結合度を弱くする方法には、

  • データ項目を外部宣言された変数(グローバル変数)を使うのではなく、引数として渡す
  • 引数にデータ構造ではなく、単一のデータ項目を使う
  • 制御パラメータで実行順序を制御しない

の3つがあります。

ア:共通域に定義したデータを関係するモジュールが参照する。
→ 共通域に定義したデータを使ってしまうと大域変数に依存することになるため、モジュール結合度は強くなってしまいます。(共通結合)

イ:制御パラメタを引数として渡し、モジュールの実行順序を制御する。
→ 制御パラメータに依存することになるため、モジュール結合度は強くなってしまいます。(制御結合)

ウ:データ項目だけをモジュール間の引数として渡す。
→ データ項目を引数として渡すため、独立したモジュールとなり、モジュール結合度が弱くなります。(答え)

エ:必要なデータを外部宣言して共有する。
→ 外部宣言したデータを使っているため、モジュール結合度は強くなってしまいます。(外部結合)

解答3

解答:ア

データの流れに着目する分割技法は、

  • STS分割法
  • トランザクション(TR)分割
  • 共通機能分割法

の3つ、データ構造に着目する分割技法は、

  • ジャクソン法
  • ワーニエ法

の2つでしたね。

選択肢を見ると、

イ:TR分割は、プログラムをデータの構造に着目して分割する技法であり、オンラインリアルタイム処理のように、入力トランザクションの種類に応じて処理が異なる場合に有効である。
→ TR分割はデータの流れに着目して分割する技法なのでNG。

ウ:共通機能分割は、プログラムをデータの構造に着目して分割する技法であり、共通な処理を一つにまとめ、共通モジュールとする。
→ 共通機能分割はデータの流れに着目して分割する技法なのでNG。

エ:ジャクソン法は、プログラムをデータの流れに着目して分割する技法であり、バッチ処理プログラムの分割に適している。
→ ジャクソン法はデータの構造に着目して分割する技法なのでNG。

と「データの流れに着目」するか「データ構造に着目」するかで残りの3つの選択肢が消せてしまう。

よって残ったアが答え。

6.さいごに

今回は、ソフトウェア工学の分野の中でも

  • モジュール分割
  • モジュール独立度(モジュール強度・結合度)

の2つについてわかりやすく説明しました。

基本情報では、モジュール独立度についての出題が多いので、モジュール独立度に関するところ(モジュール強度、モジュール結合度)は必ず見直ししておきましょう!


次回はソフトウェア工学の「テスト」に関する部分について見ていきたいと思います!

*1:カップルでも依存すればするほど彼氏彼女単体で独立して行動するのが難しくなるよね~って覚えておけばたぶん忘れないと思います。