Lecture5

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;
Use the
}
same
int Subtract(int i) {
global
variable
reg = reg – i;
reg.
}
int Multiply(int i) {
reg = reg * i;
}
}
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;
}
}
利点と弱点
グローバル変数を通じで交信の場合は、モジュール連
結を強め、モジュールの独立性を弱める。このような交
信方法は、モジュール化設計の立場から見ると、よくな
い方法である。
グローバル変数を通じてモジュールの間の通信の場合
は、プログラムの実行する効率が高くなる。
引数によって交信する場合は、モジュールの独
立性を強める。しかし、プログラムの効率が減ら
す可能性が高い。