モジュール設計

このページでは、STS分割・TR分割・ジャクソン法などのモジュール分割技法、モジュール結合度と強度の順番、制御領域と影響領域、コード設計がわかります。

  • 一言で言うと:
    • プログラムをどう小分け(モジュール分割)するかと、その小分けがうまくできているかをどう評価するかの話
    • 良いモジュールは、「他とのつながりは弱く(結合度が弱い)、中のまとまりは強い(強度が強い)」

どう分けるか(分割技法)→ うまく分けられたか(分割の評価)→ コードの付け方(コード設計)

覚え方の軸

  • 分割技法は「データの流れ」か「データの構造」かで2つに分かれる
    • 流れに注目するのは、STS分割(入力 → 変換 → 出力の3つに分ける)、TR分割(データの種類で枝分かれさせる)、共通機能分割(共通の機能を1つにまとめる)
    • 構造に注目するのは、ジャクソン法(出力のデータ構造から)、ワーニエ法(入力のデータ構造から、「いつ、どこで、何回」)
  • 評価の物差しは2つで、向きが逆
    • 結合度(モジュールの外とのつながり)は、弱いほど良い
    • 強度(モジュールの中のまとまり)は、強いほど良い
    • どちらも、良い方向に行くほど独立性が高い
  • 一番良いものと一番悪いものを押さえる
    • 結合度は、一番良いのがデータ結合、一番悪いのが内容結合
    • 強度は、一番良いのが機能的強度、一番悪いのが暗合的強度
  • 橋渡しの1組
    • 引数で機能を選ばせるモジュールは、強度では論理的強度、結合度では制御結合にあたる
  • 領域評価は「制御領域 ≧ 影響領域」なら良い
    • 自分の決定の影響が、自分の手下(制御領域)の中に収まっていればよい

モジュール分割技法:どう小分けにするか(★)

  • モジュール分割技法の2分類:
    • データの流れに着目した分割技法と、データの構造に着目した分割技法の2つに大きく分かれる
着目点 技法 一言で
データの流れ STS分割 入力・変換・出力の3つに分ける
データの流れ TR分割 入力データの種類ごとに、処理を枝分かれさせる
データの流れ 共通機能分割 共通する機能を、1つの共通モジュールにまとめる
データの構造 ジャクソン法 出力データの構造から、プログラム構造を作る
データの構造 ワーニエ法 入力データの構造から、「いつ、どこで、何回」で展開する

① STS分割:入力・変換・出力の3つに分ける

  • STS分割:
    • データの流れに着目した分割技法
    • 基本的なプログラムは「入力・処理(変換)・出力」という構造を持つことに注目する
    • プログラムを、入力処理機能(源泉:Source)、変換処理機能(変換:Transform)、出力処理機能(吸収:Sink)の3つのモジュールに分ける
    • 頭文字を取って、S・T・S
  • 分割の基準:
    • どの点で分けるかが重要
  • 最大抽象入力点:
    • もはや入力とはいえない点。つまり、これ以降は入力データが発生しない点
  • 最大抽象出力点:
    • はじめて出力データといえる点
  • 制御モジュール:
    • STSの3つのモジュールに分けたあと、モジュールの階層構造図を作る
    • このとき、3つのモジュールを制御する制御モジュールを定義する必要がある
  • 例(郵便番号から住所を表示するプログラム):
    • 流れは、「郵便番号を読み取る」→(最大抽象入力点)→「住所データベースを検索する」→「住所を得る」→(最大抽象出力点)→「住所を画面に表示する」
    • 源泉モジュール(S)は「郵便番号を読み取る」
    • 変換モジュール(T)は「住所データベースから住所を得る」
    • 吸収モジュール(S)は「住所を画面に表示する」
    • その上に、3つをまとめる制御モジュールを置く
  • STS分割の例え:
    • 料理なら、「食材を受け取る」(源泉)→「調理する」(変換)→「盛り付けて出す」(吸収)に分け、料理長(制御モジュール)が全体を指示する

② TR分割:データの種類で枝分かれさせる

  • TR分割(トランザクション分割):
    • データの流れに着目した分割技法
    • 入力トランザクションの種類によって、実行する処理が違う場合に有効
    • データが種類によって分岐していく点に注目して分割する
  • 例(在庫ファイルの更新):
    • 入庫・出庫・返品の伝票を個別に入力し、在庫ファイルを更新するプログラム
    • 「伝票入力処理」(入力モジュール)→「伝票の種類で振り分ける」(振分けモジュール)→「入庫の処理」「出庫の処理」「返品の処理」(処理ごとのモジュール)→「在庫ファイル更新」
  • TR分割の例え:
    • 郵便局の窓口。届いた用件(トランザクション)が「送る」「受け取る」「振り込む」のどれかで、担当の窓口に振り分ける

③ 共通機能分割:共通の機能を1つにまとめる

  • 共通機能分割:
    • STS分割やTR分割で分けたモジュールの中に共通する機能があったり、プログラム全体で共通して必要な機能があったりする場合
    • その機能を1か所にまとめ、共通モジュールとして独立させる方法
  • 共通機能分割の効果:
    • 開発効率や、保守・拡張性を高められる
  • 例:
    • 注文を登録するモジュールP、注文を取り消すモジュールQに、処理の前に「利用者の権限をチェックする」機能を追加する
    • 各モジュールに実装するのではなく、共通モジュールR(権限をチェックする)を作り、PからもQからも呼び出して使う
  • アスペクト指向プログラミング(AOP:Aspect Oriented Programming):
    • 注目されているプログラミング技法の1つ
    • 共通モジュールRの呼出処理を各モジュールに書くのではなく、「権限チェック」をアスペクト(横断的関心事)として、呼び出し方などを宣言する
    • そうすると、すべてのモジュールに「権限チェック」を織り込むことができる
  • アスペクト:
    • いろいろな場所で実行することがある共通処理(横断的関心事)のこと
  • AOPのイメージ:
    • 別の場所に「注文を操作する前にモジュールRを呼び出す」と宣言しておく
    • モジュールP、Qには「注文を登録する」「注文を取り消す」とだけ書けばよく、Rを呼び出す処理は書かない
  • 共通機能分割とAOPの例え:
    • 共通機能分割は、各部屋に「出るときは電気を消す」と貼り紙をする(各モジュールに呼出しを書く)
    • AOPは、家全体に人感センサーを付けて、部屋を出たら自動で消えるようにする(呼出しを書かずに織り込む)

④ ジャクソン法:出力のデータ構造から作る

  • ジャクソン法(JSP:Jackson Structured Programming):
    • データ構造に基づいて分割を進める構造化設計技法
    • 「プログラムの構造は、入力と出力のデータ構造から必然的に決まる」という考え方
    • 入力と出力のそれぞれの構造を、基本・連続・繰返し・選択の4つの要素を組み合わせた階層的な木構造(JSP木)で表し、対応させる
    • そのうえで、出力データ構造を基本形としてプログラム構造を作る
要素 書き方 意味
基本 Aだけ それ以上分けない要素
連続 Aの下にB、C BとCが(順に)実行される
繰返し Aの下にB* Bが0回以上繰り返される
選択 Aの下にB°、C° BとCのどちらかが選ばれる
  • 記号の覚え方:
    • *(アスタリスク)は繰返し、°(小さな丸)は選択
  • 入力の木:
    • 入力データ構造を表したJSP木
  • 出力の木:
    • 出力データ構造を表したJSP木
  • プログラムの木:
    • 入力の木と出力の木を対応させて作る、プログラム構造を表したJSP木

⑤ ワーニエ法:入力のデータ構造から作る

  • ワーニエ法:
    • 集合論に基づく構造化設計技法
    • 入力データ構造をもとに、「いつ、どこで、何回」という考え方で、プログラム全体をブレイクダウン(展開)していく
  • ジャクソン法との違い(ひっかけ注意):
    • ジャクソン法は、主に出力データ構造をもとにする
    • ワーニエ法は、入力データ構造をもとにする
  • プログラムの基本論理構造:
    • 「スタート部」「処理部」「エンド部」の部分集合でできている
  • 構造の例:
    • プログラム(全体集合)は、スタート部(1回)、処理部1(n回)、エンド部(1回)でできている
    • 処理部1の中は、さらに処理スタート部(1回)、処理部2(m回)、処理エンド部(1回)に分かれる
    • 例えば、売上集計なら、スタート部で「合計を0にする」(1回)、処理部で「1件ずつ足す」(n回)、エンド部で「合計を印刷する」(1回)

モジュール分割の評価:うまく分けられたか(★試験によく出る)

  • 評価の3つの観点:
    • 構造上の評価(大きさ、インタフェース)
    • 独立性の評価(モジュール結合度、モジュール強度)
    • 領域評価(制御領域と影響領域)

① 構造上の評価

  • 構造上の評価:
    • 複雑なプログラムは、複数のモジュールに分けると、わかりやすく保守しやすくなる
    • しかし、1つのモジュールに機能が多すぎたり、モジュール間インタフェースが複雑だったりすると、効果が薄れる
    • そのような観点から、モジュールが適切に分けられているかを評価する
  • モジュールの大きさ:
    • 原則として論理的な単位で分け、できるだけ1つの機能を持った独立性の高いものにする
    • ただし、小さすぎると管理が煩雑になるので、その場合は下位モジュールを上位モジュールなどに組み込むことを考える
  • モジュール間インタフェース:
    • 上位モジュールと下位モジュールのインタフェースは、必要最小限に抑えるなどして、モジュール結合度を弱くする
    • 下位(上位)モジュールの変更が、上位(下位)モジュールに影響しないようにする
  • モジュール構造図の形:
    • 「モジュール構造図は、ピラミッド型を経てモスク(回教寺院)型になる」という、形による評価基準もある
    • モスク型は、下のほうに共通モジュールがあり、複数の上位モジュールから呼ばれて、下が少しすぼまった形になる

② 独立性の評価

  • 独立性:
    • 互いに関連し合うモジュールどうしが、相手のモジュールの影響をできるだけ受けないという特性
  • 独立性が高いと良いこと:
    • 関連するモジュールが修正されても、影響が少なくて済む
    • 保守の効率化と、保守コストの削減につながる
    • プログラム開発(製造)でも、並行作業がしやすくなる
  • 独立性を評価する尺度:
    • モジュール間の関連の強さを示すモジュール結合度
    • モジュール内の構成要素間の関連の強さを示すモジュール強度(結束性)

モジュール結合度(6種類。弱いほど独立性が高い)

順位 結合度 中身 例え
強い(悪い) 内容結合 絶対番地を使って直接相手モジュールを参照したり、JUMP命令で相手モジュールに直接分岐したりする 他人の家に勝手に上がり込んで、冷蔵庫を開ける
↓ 共通結合 大域領域に定義されたデータを参照する 町内の共有掲示板を、誰でも書き換えられる
↓ 外部結合 大域領域に必要なデータだけを外部宣言し、他のモジュールからの参照を許して共有する 掲示板のうち、決めた項目だけを共有する
↓ 制御結合 機能コードなど、モジュールを制御する要素を引数で渡し、相手のモジュール内の機能や実行を制御する。モジュール強度の論理的強度にあたる 「今日は1番の仕事をして」と、相手の仕事内容まで指図する
↓ スタンプ結合 相手が構造体データ(レコード)の一部しか使わない場合でも、構造体データをすべて引数で渡す 住所だけ知りたい人に、住民票をまるごと渡す
弱い(良い) データ結合 相手モジュールをブラックボックスとして扱い、必要なデータだけを引数で渡す 住所だけ知りたい人に、住所だけを伝える
  • 大域領域:
    • どのモジュールからでも共通に参照できる領域
    • グローバル領域、共通領域ともいう
  • 試験での出方(試験):
    • モジュール結合度が最も弱い(独立性が最も高い)のはデータ結合、が問われる
  • 結合度の順番の覚え方:
    • 強い順に「内容・共通・外部・制御・スタンプ・データ」
    • 「ない(内)きょう(共)、がい(外)せい(制)、スタンプ、データ」と唱える
    • 相手の中身に直接触る(内容)→ みんなの領域を共有する(共通・外部)→ 引数で相手を操る(制御)→ 引数で余計なものまで渡す(スタンプ)→ 引数で必要なものだけ渡す(データ)

モジュール強度(結束性)(7種類。強いほど独立性が高い)

順位 強度 中身 例え
弱い(悪い) 暗合的強度 プログラムを単純に分割しただけで、モジュールの機能を定義できない。または、複数の機能を持つが、機能間にまったく関連はない 引き出しに、文房具・薬・電池をごちゃまぜに入れる
↓ 論理的強度 関連した複数の機能を持ち、呼び出すときの引数(機能コード)で、モジュール内の1つの機能が選ばれて実行される。モジュール結合度の制御結合にあたる 番号を押すと、お茶かコーヒーかジュースが出る自販機
↓ 時間的強度 初期設定や終了設定モジュールのように、特定の時期に実行する機能をまとめたもの。機能間にはあまり関連はない 朝にやることリスト(歯みがき、天気を見る、ゴミ出し)
↓ 手順的強度 順番に(逐次的に)実行する複数の機能をまとめたもの 掃除の手順:机を拭く → 床を掃く → ゴミを捨てる(順番は決まっているが、同じデータを受け渡してはいない)
↓ 連絡的強度 手順的強度のうち、モジュール内の機能間にデータの関連性があるもの 計算した結果を、すぐ次の処理で使う
↓ 情報的強度 同一のデータ構造や資源を扱う機能を1つにまとめ、機能ごとに入口点と出力点を持つもの 「口座」に対する入金・出金・残高照会を、1つにまとめる(オブジェクトに近い)
強い(良い) 機能的強度 1つの機能だけからなるもの 「消費税を計算する」だけをする
  • データの関連性がある:
    • 同じデータを参照するという意味
  • 試験での出方(試験):
    • それぞれのモジュール強度について、具体的なモジュールのイメージができるようにしておく
  • 強度の順番の覚え方:
    • 弱い順に「暗合的・論理的・時間的・手順的・連絡的・情報的・機能的」
    • 「暗(あん)い論(ろん)理の時(じ)間に、手(て)順を連(れん)絡、情(じょう)報で機(き)能する」と覚える
    • 関係ない(暗合的)→ 似た仲間を引数で選ぶ(論理的)→ 同じ時期(時間的)→ 順番(手順的)→ 順番+同じデータ(連絡的)→ 同じデータ構造(情報的)→ 1つの機能(機能的)
  • 補足:
    • 暗合的強度は、「偶発的強度」と呼ばれることもある

例:2つのモジュールを比べる

  • ファイル操作モジュール:
    • 「読み込む」「書き込む」の2つの機能を1つにまとめ、引数でどちらの機能を使うかを指定する
    • 論理的強度(モジュール結合度では制御結合)
  • 成績集計モジュール:
    • 必ず「合計を計算する」→「平均を計算する」の順に実行され、しかも合計の結果を平均の計算で使う、2つの機能を1つにまとめる
    • 連絡的強度
  • 比べると:
    • 連絡的強度のほうが強いので、成績集計モジュールのほうが独立性が高い
  • 例題(結合度):
    • ①顧客レコードをまるごと渡し、相手は郵便番号だけを使う
    • ②「1なら新規登録、2なら削除」という機能コードを引数で渡す
    • ③税抜価格だけを引数で渡し、税込価格を返してもらう
    • それぞれ何結合か。また、独立性が一番高いのはどれか
  • 例題の答え:
    • ①はスタンプ結合、②は制御結合、③はデータ結合
    • 独立性が一番高いのは、結合度が一番弱い③データ結合

③ 領域評価

  • 領域評価:
    • モジュールの制御領域と影響領域を評価すること
  • 制御領域:
    • そのモジュールが制御する範囲
    • モジュール自身と、それに従属する(下にぶら下がる)モジュール
  • 影響領域:
    • あるモジュールの中での決定が影響を及ぼす範囲
  • 例:
    • モジュールPの下にQ、R、Tがあり、Qの下にU、Rの下にSがある
    • Rの制御領域は、R自身と、従属するS
    • R内で決定した判断をPに渡し、PがTを実行するかどうかを制御する場合、Rの決定の影響領域はP、Tに及ぶ
    • 影響が制御領域の外にはみ出しているので、「制御領域<影響領域」になっている
  • 良い・悪いの判断:
    • 「制御領域 ≧ 影響領域」なら良い
    • 「制御領域<影響領域」なら、モジュールの独立性が低くなっているので、改善が必要
  • 領域評価の例え:
    • 係長(R)が自分の部下(S)に指示を出すのは問題ない
    • しかし、係長の判断で、部長(P)が別の課(T)の仕事を止めるかどうかが決まるのは、権限の外まで影響が及んでいて良くない

コード設計(時々出る)

  • コード設計:
    • 処理効率の向上とデータの体系化のために、使う目的に合ったコード体系を設計すること
    • 外部設計の重要な作業の1つ
    • 例えば、商品コード、社員番号、顧客番号の付け方を決めること
  • コード設計の大まかな流れ:
    1. コード化する対象を選び、コード化の目的をはっきりさせる
    2. 使用期間とデータ件数を予測する
    3. コード体系を決める
    4. コード化作業をして、コード表を作る
    5. コードファイルを作る
コードの種類 付け方 長所 短所
順番コード(連番コード、シーケンスコード) データの発生順、または一定の順に並べて、順番に番号を付ける 少ない桁数でコード化できる。発生順に付けるなら追加が簡単 件数が予想以上に増えると、桁数が足りなくなるおそれがある。分類がわからない
区分コード(分類コード) データをいくつかのグループに分け、グループごとに番号の範囲を割り当て、その中で連番を付ける 少ない桁数で多くのグループ分けができる データを追加する場合や件数が多い場合に不便
桁別コード データを大分類・中分類・小分類と階層化し、それぞれの層の中で連番を付ける 分類基準がはっきりしている。各桁が分類上の意味を持つのでわかりやすい 桁数が大きくなりやすい
表意コード(ニモニックコード) 商品の略称や記号などをコードにする コードの値から対象物を連想でき、覚えやすい 分類には不便
  • コードの例:
    • 順番コードは、「0001、0002、0003…」
    • 区分コードは、「001〜099は文房具、100〜199は食品」
    • 桁別コードは、「1-2-05」(1桁目が大分類、2桁目が中分類、残りが小分類)
    • 表意コードは、「TV-42-LCD」(42型の液晶テレビ)

混同しやすいペア

  • データの流れに着目 / データの構造に着目
    • データの流れに着目するのは、STS分割、TR分割、共通機能分割
    • データの構造に着目するのは、ジャクソン法、ワーニエ法
  • STS分割 / TR分割
    • STS分割は、入力・変換・出力の3つに分ける
    • TR分割は、入力トランザクションの種類で処理を枝分かれさせる
  • 最大抽象入力点 / 最大抽象出力点
    • 最大抽象入力点は、これ以降は入力データが発生しない点
    • 最大抽象出力点は、はじめて出力データといえる点
  • 源泉(Source) / 変換(Transform) / 吸収(Sink)
    • 源泉は、入力処理
    • 変換は、処理(変換)
    • 吸収は、出力処理
  • 共通機能分割 / アスペクト指向プログラミング(AOP)
    • 共通機能分割は、共通モジュールを作り、各モジュールから呼び出す処理を書く
    • AOPは、呼出し方を宣言して、呼出しを書かずに全モジュールに織り込む
  • ジャクソン法 / ワーニエ法
    • ジャクソン法は、出力データ構造をもとにする(JSP木:基本・連続・繰返し・選択)
    • ワーニエ法は、入力データ構造をもとに「いつ、どこで、何回」で展開する(集合論:スタート部・処理部・エンド部)
  • JSP木の繰返し / 選択
    • 繰返しは、*を付ける(0回以上)
    • 選択は、°を付ける(どちらか一方)
  • モジュール結合度 / モジュール強度
    • 結合度は、モジュール間の関連の強さ。弱いほど良い
    • 強度は、モジュール内の関連の強さ。強いほど良い
  • 内容結合 / データ結合
    • 内容結合は、絶対番地やJUMP命令で相手に直接触る。最も強く、最も悪い
    • データ結合は、必要なデータだけを引数で渡す。最も弱く、最も良い
  • 共通結合 / 外部結合
    • 共通結合は、大域領域のデータを参照する
    • 外部結合は、大域領域に必要なデータだけを外部宣言して共有する
  • スタンプ結合 / データ結合
    • スタンプ結合は、一部しか使わなくても構造体データをまるごと渡す
    • データ結合は、必要なデータだけを渡す
  • 制御結合 / 論理的強度
    • 制御結合は、結合度での呼び名(機能コードを引数で渡して制御する)
    • 論理的強度は、強度での呼び名(引数で機能を選んで実行する)
  • 時間的強度 / 手順的強度
    • 時間的強度は、同じ時期に実行する機能をまとめる(機能間にあまり関連はない)
    • 手順的強度は、順番に実行する機能をまとめる
  • 手順的強度 / 連絡的強度
    • 手順的強度は、順番に実行するだけ
    • 連絡的強度は、順番に実行し、さらに機能間にデータの関連性がある(同じデータを参照する)
  • 情報的強度 / 機能的強度
    • 情報的強度は、同じデータ構造を扱う機能をまとめ、機能ごとに入口点と出力点を持つ
    • 機能的強度は、1つの機能だけ。最も強く、最も良い
  • 制御領域 / 影響領域
    • 制御領域は、自分と、自分に従属するモジュールの範囲
    • 影響領域は、自分の決定が影響を及ぼす範囲
    • 制御領域 ≧ 影響領域なら良い
  • 順番コード / 区分コード
    • 順番コードは、全体に連番を付ける。分類がわからない
    • 区分コードは、グループごとに番号の範囲を割り当てて連番を付ける
  • 桁別コード / 表意コード
    • 桁別コードは、各桁が大・中・小分類の意味を持つ。桁数が大きくなりやすい
    • 表意コードは、略称や記号をコードにする。覚えやすいが分類には不便

← 09 開発技術の目次に戻る

タイトルとURLをコピーしました