7. モジュール化設計 内容 : モジュールの定義モジュールの強度又は結合力モジュール連結モジュールの間の交信
7.1 モジュールの定義 プログラムモジュールとは 次の特徴を持つプログラムの単位である モジュールは 一定の機能を提供する 例えば 入力によって ある出力を出す モジュールは 同じ機能仕様を実装しているほかのモジュールに置き換えられる この変化によって プログラム全体に影響をあまり与えない モジュール化設計の基本アイデアは 他の製品の生産プロセスと同じように考える
具体的には モジュールは 次のプログラム単位に 解釈できる : A procedure in Pascal. A function in C. An operation in general. A process in DFDs. A method in Java. A unit that groups operations. A class (e.g., a Java class). 操作レベルのモジュール 高いレベルのモジュール
事例 (1) 操作レベルのモジュール : Java メソッド : class ExampleModule { int x, y; int Swap() { int a = 0; //local variable declaration a = x; x = y; y = a; //statement-1 //statement-2 //statement-3
(2) 高いレベルのモジュール : module A; variable declarations; operation-1; operation-2; operation-3; operation-n end-module 幾つかの操作をグループする
高いレベルのモジュール : Java クラス class Calculator { int reg; public Calculator() { initialize reg; //constructor of the class public int Add(int i) { reg = reg + i; public int Subtract(int i) { reg = reg i; public int Multiply(int i) { reg = reg * i;
7.2 モジュールの強度又は結合度 下の議論には 操作レベルのモジュールを使う 定義 : モジュールの強度 (strength) 又は結合度 ( cohesion) は 文又は操作が同じモジュールに所属する程度を測る尺度である
一般原則 同じタスクを完成するために必要な文又は操作が 同じモジュールに所属する訳である
モジュール設計の指針 一つのタスクを完成するためにモジュールを作成する 例えば 計算機 Calculator クラスの中で 定義されている操作 Add, Subtract, および Multiply それぞれ操作は モジュールとして見られる 関係が薄い幾つかのタスクがひとつのモジュールに置くことができる ただし これらのタスクが プログラムの中で同じ時間で実行されるため 同じモジュールに置く 例えば 幾つかの変数らを初期化する文を同じモジュールに置く ひとつ以上の関係があるタスクを実装する文を同じモジュールに置くこともできる 例えば プログラムの実行の最後に データをファイルに書き込む文を同じモジュールに置く
7.3 モジュール連結 (coupling) 定義 : モジュール連結は プログラムモジュール間の独立性の程度を測る基準である 一般的に モジュール連結は 強くなればなるほど 一つのモジュールがほかのモジュールへの影響を与える可能性が高くなる 例えば 大家族と小家族と比べて 大家族の成員の間の影響は小家族より相互影響力が高い 一般的には 引数を通じてモジュール連結する場合はグローバル変数を通じてモジュール連結する場合より モジュール連結を弱める
事例 class Calculator { int reg; void Calculator() { initialize reg; //constructor of the class int Add(int i) { reg = reg + i; int Subtract(int i) { reg = reg i; int Multiply(int i) { reg = reg * i; Use the same global variable reg. Use no common global variable class Calculator { void Calculator() { //constructor of the class int Add(int reg, int i) { return reg + i; int Subtract(int reg, int i) { return reg i; int Multiply(int reg, int i) { return reg * i;
7.4 モジュールの間の交信 プログラムは 一般的に幾つかのモジュールから構成される プログラムの機能を提供するため モジュールの間に交信することが必要である モジュールの間の関係を モジュールの呼び出しによって作られる 一つのモジュールから もう一つのモジュールを呼び出すときに 必要なデータ項目を提供することが必要である それらのデータ項目が 引数またはグローバル変数によってできる
交信手段 引数によって交信する グローバル変数によって交信する
次の二つのプログラムを通じて モジュール連結の 概念を説明する 問題 : プログラムは 10 個の 0 ではない違う整数を入力して 二つの数字を出力する (1) 10 個の整数の平均値より大きい整数の数 (2) 10 個の整数の平均値より小さい整数の数 例えば 入力 : 5, 78, 56, 89, 12, 24, 75, 98, 34, 68 (average = 539 / 10 = 53.9); 出力 : count1 = 6 ( 大きい整数 : 78, 56, 89, 75, 98, 68) count2 = 4 ( 小さい整数 : 5, 12, 24, 34)
二つの Java- 擬似コード プログラム 1: import java.io.*; public class CountNumbers { //there is no global variables here public static void main(string args[]) { int numbers[] = new int[10]; int count1 = 0, count2 = 0; double average = 0.0; for (int i = 0; i < numbers.length; i++) INPUT numbers[i]; average = CalculateAverage(numbers); count1 = CountGreater(average, numbers); count2 = CountSmaller(average, numbers); OUTPUT count1 and count2;
double CalculateAverage(int a[]) //obtain average { int total = 0; double ave = 0.0; for (int j = 0; j < a.length; j++) total = total + a[j]; ave = total / 10; return ave;
int CountGreater(double ave, int a[]) { int count1 = 0; for (int k = 0; k < a.length; k++) if (a[k] > ave) count1 = count1 + 1; return count1; int CountSmaller(double ave, int a[]) { int count2 = 0; for (int k = 0; k < a.length; k++) if (a[k] < ave) count2 = count2 + 1; return count2;
プログラム 2: import java.io.*; public class CountNumbers { //there are four global variables here static int numbers[] = new int[10]; static double average = 0.0; static int count1 = 0, count2 = 0; public static void main(string args[]) { for (int i = 0; i < numbers.length; i++) INPUT numbers[i]; CalculateAverage(); CountGreaterSmaller(); //compute count1 and count2 System.out.println("Count1:" + count1); System.out.println("Count2:" + count2);
static void CalculateAverage() { // Obtain average int total = 0; for (int j = 0; j < numbers.length; j++) total = total + numbers[j]; average = total / 10; static void CountGreaterSmaller() { for (int k = 0; k < numbers.length; k++) if (numbers[k] > average) count1 = count1 + 1; else count2 = count2 + 1;
利点と弱点 グローバル変数を通じで交信の場合は モジュール連結を強め モジュールの独立性を弱める このような交信方法は モジュール化設計の立場から見ると よくない方法である グローバル変数を通じてモジュールの間の通信の場合は プログラムの実行する効率が高くなる
引数によって交信する場合は モジュールの独立性を強める しかし プログラムの効率が減らす可能性が高い