foo() { double dSeta, dTan; ...... /* dSetaを設定する */ dTan = tan(dSeta); /* タンジェントを求める*/ }このように単純な変数による結合です。
typedef struct { long lEmployeeID; char szName[40]; char szAddress[100]; long lBirthDay; char szPhone[20]; } EMPLOYEETYPE; foo() { EMPLOYEETYPE Emp; /* Empに設定 */ ... PrintEmployeeData(Emp); /* EmployeeData全体を印刷 */ }このようにデータ構造を渡す結合です。
ところで…
foo2() { EMPLOYEETYPE Emp; /* Empに設定 */ ... PrintEmployeeName(Emp); /* EMPLOYEETYPEのszNameを印字 */ }こんな場合はどうでしょうか。これもデータ構造による結合をしています。
foo2_dash() { EMPLOYEETYPE Emp; /* Empに設定 */ ... PrintEmployeeName(Emp.szName); }こんなふうに、単純なデータによる結合に昇華(あえて昇華としたい)させましょう。
では、lEmployeeID以外の情報を使うルーチンがあったらどうしましょう?
単純データ結合でパラメータをたくさん並べる。
あるいは、データ構造による結合で、Emp全体を渡し、渡されたほうではlEmployeeID以外を使うようにする。
どちらも間違いではありません。
でも…
typedef struct { long lEmployeeID; struct tagEMPDATA { char szName[40]; char szAddress[100]; long lBirthDay; char szPhone[20]; } data; } EMPLOYEETYPE; foo3() { EMPLOYEETYPE Emp; /* Empに設定 */ ... PrintEmployeeData(Emp.data); }こんなふうに、データからなるサブストラクチャを作成するのがもっともスマートな解決法ですね。
foo() { DoProcess(1); DoProcess(2); } DoProcess(int flag) { if (flag == 1) { /* 月次報告書印刷処理 */ ... } if (flag == 2) { /* 四半期報告書印刷処理 */ ... } if (flag == 3) { /* エラー表示処理 */ ... } if (flag == 4) { /* メール送受信処理 */ ... } }
この結合は望ましくありません
まず名前がよくありません。DoProcess()?なにをするのでしょう?
フラグによる結合を行うと、このようによく解らないネーミングが増えます。
また、「何をする関数」かどうかの定義があいまいになり、グローバル変数を使用する機会が増えます。
ルーチン内で処理対象を切り替えるような作りは、望ましくありません。
typedef struct { long lEmployeeID; char szName[40]; char szAddress[100]; long lBirthDay; char szPhone[20]; } EMPLOYEETYPE; EMPLOYEETYPE EmpTbl[100]; foo () { EmpTbl[0].lEmployeeID = 1; /* EmployeeID(従業員コード)を設定する…つづく */ ... /* EmployeeID(従業員コード)を設定する…ここまで */ EmpTbl[99].lEmployeeID = 100; PrintEmployeeID(50) } PrintEmployeeId(int nTableIndex) { /* EmpTbl[nTableIndex].lEmployeeID を印刷する...*/ ... }この結合は望ましくありません
このような結合はプログラムの可読性、保守性を著しく害します。
ルーチンへ戻る | _ | Top of Site |