モジュールの分け方(強度と結合度)
モジュール強度(中のまとまり)と結合度(モジュール同士のつながり)の種類と強弱の順番を覚え、「どれが最も強い/弱いか」「望ましい設計はどれか」を選べるようになる。あわせて、リファクタリング、コーディング規約、階層構造のインタフェース数(N−1)の問題も解けるようにする。
結合度の強弱は免除試験も含めて18回出ており、このレッスンでいちばんよく出る知識です。中身は「直しやすいシステムはどう分けるか」という設計の常識で、API設計で「パラメータは必要最小限にする」「モード切替フラグで振る舞いを変えない」と言われる理由もここで説明できます。
このレッスンで稽古する(用語チェック・過去問)結論:強度は強く、結合度は弱く
モジュールは、プログラムを分けた1つの部品のことです(関数やクラスくらいの単位)。良い分け方は**「強度(中のまとまり)は強く、結合度(部品どうしのつながり)は弱く」です。こうすると、1か所を直したときに他の部品へ影響が広がりにくく、保守性(直しやすさ)と信頼性**(壊れにくさ)が上がります。
たとえるなら会社の部署です。良い部署は「経理なら経理だけ」と役割がはっきりしていて(強度が強い)、他の部署とは必要な書類だけをやりとりします(結合度が弱い)。
| 指標 | 何を見るか | 望ましい方向 |
|---|---|---|
| モジュール強度(結束性) | 1つのモジュールの中がどれだけ1つの目的にまとまっているか | 強く |
| モジュール結合度 | モジュールどうしがどれだけ依存しているか | 弱く |
「強度を強く・結合度を強く」のように、2つとも同じ向きにした選択肢がひっかけとして出ます。強度は強く、結合度は弱くと、向きが逆になる点を覚えてください。
モジュール結合度:6種類と強さの順番(最頻出)
結合度は6種類を強い順に並べられることがすべてです。いちばん弱い(=いちばん望ましい)のはデータ結合で、「必要なデータ項目だけを引数(呼び出すときに渡す値)で渡す」受け渡し方です。
| 強さ | 種類 | 受け渡しの方法 | 部署のたとえ |
|---|---|---|---|
| 最も強い(悪い) | 内容結合 | 相手のモジュール内部のデータや処理を直接参照・変更する | 他部署の机の引き出しを勝手に開けて書き換える |
| ↑ | 共通結合 | 共通域(グローバルなデータ領域)のデータ構造をみんなで共有する | 全社の共有フォルダを誰でも書き換えられる |
| ↑ | 外部結合 | 外部宣言した個々のデータ項目を共有する | 共有の掲示板の特定の欄だけを共有する |
| ↑ | 制御結合 | 相手の処理の流れを決める値(フラグ、処理コードなど)を引数で渡す | 「今日はAの手順でやれ」と相手の仕事の進め方まで指図する |
| ↓ | スタンプ結合 | データ構造(レコードなど)を丸ごと渡し、相手はその一部だけを使う | 必要な1枚のために書類ファイルを丸ごと渡す |
| 最も弱い(良い) | データ結合 | 必要なデータ項目だけを引数で渡す | 必要な書類1枚だけを渡す |
覚え方は、強い順の頭文字をとって**「内・共・外・制・ス・デ(ないきょうがいせいすで)」**です。API設計にあてはめると、必要なパラメータだけを受けるAPIがデータ結合、mode= のような値で中の処理を切り替えるAPIが制御結合に近いイメージです。
問われ方:選択肢は種類の名前ではなく、受け渡し方の説明文で出ることが多いです。「グローバルな領域」「共通域」→共通結合、「外部宣言して共有」→外部結合、「論理を制御する引数」「実行順序を制御するパラメタ」→制御結合と言い換えて読めば、残る「必要なデータ項目だけを引数で渡す」が正解(データ結合)です。
モジュール強度:7種類と強さの順番
強度は、モジュールの中にある機能がどんな理由でまとめられているかで分類します。いちばん強い(=望ましい)のは機能的強度で、1つのモジュールが1つの機能だけを実行します。
| 強さ | 種類 | まとめた理由 | 見分けるキーワード |
|---|---|---|---|
| 最も強い(良い) | 機能的強度 | 単一の機能だけを実行する | 「単一の機能」 |
| ↑ | 情報的強度 | 同じデータを扱う複数の機能をまとめ、機能ごとに入口点(呼び出せる場所)を設ける | 「同一の情報」「入口点」 |
| ↑ | 連絡的強度 | 同じデータを受け渡しながら、複数の機能を順番に実行する | 「あるデータを対象に逐次的に」 |
| ↑ | 手順的強度 | 実行の順番に関係がある機能をまとめる(扱うデータは別) | 「順序」 |
| ↓ | 時間的強度 | 同じタイミングで実行する処理をまとめる(初期処理など) | 「特定の時点で必要な作業」 |
| ↓ | 論理的強度 | 似た機能をまとめ、引数で1つを選んで実行する | 「処理コード」「パラメタで選択」 |
| 最も弱い(悪い) | 暗合的強度 | 特に関係のない機能がたまたま入っている | 「特別な関係はない」 |
覚え方は、強い順に**「機・情・連・手・時・論・暗」**です。論理的強度のモジュールは呼び出し側から処理コードを受け取るので、多くの場合、制御結合とセットになります。
問われ方:「処理コードが I なら挿入、U なら更新」のような設計書を見せて種類を当てさせます。「引数で機能を選ぶ」は論理的強度、「機能ごとに入口点がある」は情報的強度という違いが決め手です。改善策としては「機能ごとに分割する、または機能ごとの入口点を設ける」が正しい答えになります。
階層構造のインタフェース数は N−1
トップダウン(上から順に分ける)でN個のモジュールを木の形に分け、各モジュールが上位の1つとだけつながる場合、モジュール間のインタフェース(呼び出しのつながり)はN−1個です。一番上のモジュールだけは上位を持たないためです。
flowchart TD
M["メイン(上位なし)"] --> A["入力"]
M --> B["計算"]
M --> C["出力"]
B --> D["税計算"]
図ではモジュールが5個、矢印が4本で、5−1=4と一致します。全部のモジュールどうしをつなぐ組合せの数 N(N−1)/2 と取り違えるのが、この問題のひっかけです。
リファクタリング:外から見た動きは変えずに中を整理する
リファクタリングは、外部仕様(外から見た振る舞い)を変えずに、プログラムの内部構造を整理して保守性を高める活動です。アジャイル開発でも重視されています。部屋のたとえでいうと、住所や間取りは変えずに、収納の中だけを片付け直すような作業です。
試験では、ほかの開発手法の説明と並べて「どれがリファクタリングか」を選ばせます。下の表で区別できるようにしておいてください。
| 活動 | 中身 | 見分けるキーワード |
|---|---|---|
| リファクタリング | 外部仕様は変えずに、内部構造を改善する | 「外部仕様を変更することなく」「保守性」 |
| ペアプログラミング | 2人で1つのプログラムを書く | 「2人のプログラマ」 |
| テスト駆動開発 | テストケースを先に作り、それに合うようにコードを書く | 「テストケースを先に」 |
| プロトタイピング | 試作品を早く作り、利用者から意見をもらう | 「試作品」「フィードバック」 |
| リバースエンジニアリング | ソースコードから設計書を作り直す | 「ソースコードから設計書」 |
| リグレッションテスト(回帰テスト) | 修正が他の部分に影響していないかを確かめる | 「修正が他に影響していないか」 |
「外部仕様を変更して」と書かれていたらリファクタリングではありません。また、リファクタリングのあとに動作が変わっていないかを確かめる作業がリグレッションテストなので、この2つは混同しないようにしてください。
コーディング規約:書き方がばらばらなときの対策
「プログラムの書き方が統一されておらず保守しにくい」という問題には、コーディング規約(書き方のルール)を見直し、開発者に教育するのが正解です。セキュアプログラミング(安全なコードの書き方)、テストの網羅度を上げること、管理レビューへの参加は、書き方の統一とは直接関係しません。
N個のモジュールを木の形に分けたときのインタフェース数
ア N^2
イ N−1
ウ N(N−1)
エ N(N−1)/2
出典:基本情報技術者試験 科目A免除 修了試験 20110702 実施分 問49
解き方と答えを見る
- 条件を読む:下位のモジュールは上位のモジュールのうち1つだけとつながる。つまり全体は木の形(枝分かれだけで、輪にならない形)になる。
- 一番上のモジュールは上位を持たないので、上につながるインタフェースは0本。
- 残りの N−1 個のモジュールは、それぞれ上位と1本だけつながる。合計は (N−1) × 1 = N−1 本。
- 具体的な数で確かめる:N = 5 なら 5 − 1 = 4 本で、図の矢印4本と一致する。
- ひっかけを消す:N(N−1)/2 は全モジュールを総当たりでつないだ数で、N = 5 なら 5×4÷2 = 10 本になり、条件に合わない。N² や N(N−1) はさらに多い。
答え:イ:N−1
設計書の記述からモジュール強度を判定する
ア これは“暗合的強度”のモジュールである。モジュール内の機能間に特別な関係はなく,むしろ他のモジュールとの強い関係性をもつ可能性が高いので,モジュール分割をやり直した方がよい。
イ これは“情報的強度”のモジュールである。同一の情報を扱う複数の機能を,一つのモジュールにまとめている。モジュール内に各処理の入口点を設けているので,制御の結びつきがなく,これ以上のモジュール分割は不要である。
ウ これは“連絡的強度”のモジュールである。モジュール内でデータの受渡し又は参照を行いながら,複数の機能を逐次的に実行している。再度見直しを図り,必要に応じて更にモジュール分割を行った方がよい。
エ これは“論理的強度”のモジュールである。関連した幾つかの機能を含み,パラメタによっていずれかの機能を選択して実行している。現状では大きな問題となっていないとしても,仕様変更に伴うパラメタの変更による影響を最小限に抑えるために,機能ごとにモジュールを分割するか,機能ごとの入口点を設ける方がよい。
解き方と答えを見る
- 機能の数を数える:挿入・更新・削除の3つがあり、単一の機能ではないので機能的強度ではない。
- 機能の選び方を見る:上位から渡される処理コード(I/U/D)で1つを選んで実行している。これは論理的強度の特徴。
- 情報的強度と比べる:情報的強度なら機能ごとに入口点があり、処理コードで分岐はしない。このモジュールは入口が1つで、コードで分岐しているので違う。
- 連絡的強度と比べる:連絡的強度なら複数の機能を順番に全部実行する。このモジュールは1回に1つしか実行しないので違う。
- 改善策を確かめる:論理的強度は強度が弱いので、機能ごとに分割するか、機能ごとに入口点を設けるのがよい。エはこの判定と改善策の両方を正しく述べている。
答え:エ:論理的強度。機能ごとにモジュールを分割するか、入口点を設けるのがよい。
要点(試験直前に読む)
- 望ましい設計は「強度は強く、結合度は弱く」。向きが逆になる点に注意する。
- 結合度は強い順に「内容・共通・外部・制御・スタンプ・データ」。必要なデータ項目だけを引数で渡すデータ結合が最も弱い(最も良い)。
- 強度は強い順に「機能・情報・連絡・手順・時間・論理・暗合」。単一機能の機能的強度が最も強い。処理コードで機能を選ぶのは論理的強度。
- 階層構造(下位が上位の1つとだけつながる)でN個に分けると、インタフェースは N−1 個。
- リファクタリングは、外部仕様を変えずに内部構造を改善して保守性を高めること。
- 書き方がばらばらな問題への対策は、コーディング規約を見直して教育すること。
ひっかけ
- 「グローバルな領域」「共通域」「外部宣言」は弱い結合のように書かれるが、実際は共通結合・外部結合で強い。必要なデータ項目だけを引数で渡す選択肢が正解。
- 「論理を制御する引数」「実行順序を制御するパラメタ」は、引数で渡していてもデータ結合ではなく制御結合。
- 強度の問題では、連絡的強度(同じデータを対象に逐次実行)や時間的強度(特定の時点の作業をまとめる)がもっともらしく並ぶ。最も強いのは「単一の機能」だけ。
- 「処理コードで分岐する」のは論理的強度、「機能ごとに入口点がある」のは情報的強度。入口点の有無で見分ける。
- リファクタリングの選択肢には、ペアプロ(2人)、テスト駆動開発(テストを先に)、プロトタイピング(試作品)、リバースエンジニアリング(設計書を作り直す)、リグレッションテスト(影響を確かめる)が並ぶ。「外部仕様を変えずに内部構造を変える」を探す。
用語(22)
1つのモジュールの中にある機能が、どれだけ1つの目的にまとまっているかを表す尺度で、強いほど良い。
⚠ モジュール結合度は部品どうしのつながりを表し、弱いほど良い。望ましい向きが逆。
モジュールどうしがどれだけ依存し合っているかを表す尺度で、弱いほど良い。
⚠ モジュール強度(中のまとまり)と取り違えない。こちらは部品と部品の間の話。
1つのモジュールが単一の機能だけを実行する、最も強い(望ましい)強度。
⚠ 情報的強度は複数の機能を持つ(機能ごとに入口点がある)点が違う。
同じデータを扱う複数の機能をまとめ、機能ごとに入口点を設けたモジュールの強度。
⚠ 論理的強度は入口が1つで、引数で機能を選ぶ。入口点が機能ごとにあれば情報的強度。
同じデータを受け渡しながら、複数の機能を順番に実行するモジュールの強度。
⚠ 手順的強度も順番に実行するが、扱うデータは別々。同じデータを扱えば連絡的強度。
実行の順番に関係がある機能をまとめた強度で、扱うデータどうしには関係がない。
⚠ 連絡的強度との違いは、同じデータを扱うかどうか。
初期処理のように、同じタイミングで実行する処理をまとめたモジュールの強度。
⚠ 「特定の時点で必要な作業をすべて含む」と書かれていたら時間的強度。機能的強度ではない。
似た機能をまとめ、処理コードなどの引数で1つを選んで実行するモジュールの強度。
⚠ 情報的強度(機能ごとの入口点)と区別する。引数による選択は制御結合を生みやすい。
関係のない機能がたまたま1つのモジュールに入っている、最も弱い強度。
必要なデータ項目だけを引数で渡す、最も弱い(望ましい)結合。
⚠ スタンプ結合はデータ構造を丸ごと渡す。必要な項目だけならデータ結合。
レコードなどのデータ構造を丸ごと引数で渡し、受け取った側がその一部だけを使う結合。
⚠ データ結合より1段強い。不要な項目まで渡していればスタンプ結合。
呼び出し先の処理の流れを決めるフラグや処理コードを引数で渡す結合。
⚠ 引数で渡しているのでデータ結合と思いやすいが、渡す値が処理の流れを決めるなら制御結合。
外部宣言した個々のデータ項目を、複数のモジュールで共有する結合。
⚠ 共通結合はデータ構造(共通域)全体を共有する。個々の項目の外部宣言なら外部結合。
グローバルな共通域にあるデータ構造を、複数のモジュールで共有する結合。
⚠ 内容結合の次に強い。「グローバル」「共通域」と書かれていたら強い結合だと判断する。
他のモジュールの内部のデータや処理を直接参照・変更する、最も強い(最悪の)結合。
外から見た振る舞い(外部仕様)は変えずに、プログラムの内部構造を整理して保守性を高める活動。
⚠ リバースエンジニアリング(コードから設計書を作り直す)、リグレッションテスト(修正の影響を確かめる)と区別する。
2人のプログラマーが組んで、1つのプログラムを一緒に書く開発方法。
⚠ リファクタリングの選択肢と並べて出る。「2人」と書かれていればこちら。
先にテストケースを作り、それに合格するようにプログラムを書く開発方法。
⚠ 「テストケースを先に設定」と書かれていればこちら。リファクタリングではない。
試作品を早い段階で作り、利用者から意見をもらいながら開発を進める方法。
⚠ 「試作品」「フィードバック」と書かれていればこちら。
既存のソースコードなどを解析して、設計書や仕様を作り直すこと。
⚠ リファクタリングはコードそのものを書き直す。設計書を作るならリバースエンジニアリング。
プログラムを修正したあと、修正していない部分に悪い影響が出ていないかを確かめるテスト。
⚠ リファクタリングのあとに行うテストであり、リファクタリングそのものではない。
変数名の付け方や書式など、プログラムの書き方を統一するために決めておくルール。
⚠ セキュアプログラミングは安全なコードを書くための手法で、書き方の統一が目的ではない。
このレッスンの過去問
- モジュール強度の分類(論理的強度等)平成23年度 秋期 基本情報技術者試験 午前 問45
- モジュール結合度の強弱令和元年度 秋期 基本情報技術者試験 午前 問46
- モジュール強度と結合度の望ましい方向基本情報技術者試験 科目A免除 修了試験 20160724 実施分 問48
- 階層構造のモジュール間インタフェース数(N−1)基本情報技術者試験 科目A免除 修了試験 20110702 実施分 問49
- コーディング規約不統一問題への対策令和8年度 基本情報技術者試験 科目A 公開問題 問11
- リファクタリングの定義平成29年度 春期 基本情報技術者試験 午前 問50