ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf ·...

27
ソフトウェア工学1 5設計(22017523中島 1

Upload: others

Post on 04-Nov-2019

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

ソフトウェア工学1第5回 設計(2)

2017年5月23日

中島

1

Page 2: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

授業内容

• 前編– 設計とは

– 設計プロセス

– 設計で重要なこと

• アーキテクチャ記述

• 抽象データ型

• 後編– 手法

– パターン

2

Page 3: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

設計プロセス: 2つのプロセス(おさらい)

抽象から詳細へ、論理から物理へ

ソフトウェア要求仕様書

ソフトウェア外部設計 ソフトウェアの方式的記述

・アーキテクチャ・コンポーネント・外部インタフェース・コンポーネント間インタフェース・データ

プログラムの仕様記述・モジュール構成・モジュール仕様・データ構造とアルゴリズム

ソフトウェア内部設計

ソフトウェア外部設計書

ソフトウェア内部設計書

3

Page 4: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

良い設計を行うためには

設計知識を利用する

– 設計手法に則ること

• 記述法: 作るものの記述法

• 手順: 作るためのステップ

• 品質基準: 各ステップでの確認事項

– パターンを使うこと

• 課題: 解決すべき問題

• 前提: 問題の背景、前提事項、制約

• 解決策: 問題解決の核心的アイデア

4

Page 5: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

設計プロセスと設計知識

2つの設計段階と設計知識

ソフトウェア要求仕様

ソフトウェアの方式的記述

ソフトウェア外部設計

プログラム仕様

ソフトウェア内部設計

アーキテクチャコンポーネント

モジュール

設計手法

パターン

モジュール化手順

モジュール化基準

アーキテクチャパターン

デザインパターン イディオム

抽象データ型アーキテクチャ記述

抽象データ型カタログ

問題非依存

問題依存

言語知識依存

記述法

品質基準

手順

5

Page 6: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

設計手法に則ること: 設計手法例で説明

複合/構造化設計: G. J. Myers データフロー図を使い,段階的に機能の詳細化を行い,プログラムモジュールまで展開する設計手法

記述法: データフロー図モジュール構成図

手順: STS分解

TR分解

品質基準: モジュール強度

モジュール間結合度

6

Page 7: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

複合/構造化設計: 記述法

モジュール構成図データフロー図

処理A処理B

処理C

データストア

データa

データbデータc

モジュールA

モジュールB

モジュールC モジュールD

モジュールE モジュールF

7

• データフロー図: 機能の分解に用いる図

• モジュール構成図: モジュールの呼び出し関係図

Page 8: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

複合/構造化設計:手順1 (1)

STS分解

A B入力A 出力B

入力部 処理部 出力部

処理 A処理 B

処理 C

データストア

データ a

入力Aデータ c

出力B

入力Aの最大抽象点

モジュールA.1

モジュールA.2

モジュールA.3 モジュール

A.1モジュール

A.2モジュール

A.3

モジュールA

出力Bの最大抽象点

入力A

A’ B’出力B

A’ B’

機能をデータの変換過程と捉え、機能を入力(Source)、処理(Transform)、出力(Sink) 3つの機能に分解する方法

8

Page 9: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

複合/構造化設計:手順1 (2)

TR (Transaction) 分解

入力データに応じて処理が変わる場

合に用いるモジュール分割方法

C<0

C=0

C>0

処理 A処理 B

処理C

データストア

データ a

入力Aデータ c

出力B

データC

処理1

処理2

処理3

モジュールC.1

モジュールC.2

モジュールC.3

データD

モジュールC.1

モジュールC.2

モジュールC.3

モジュールC

データDデータD

データD

9

Page 10: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

複合/構造化設計: 品質基準その1

モジュール間結合度: 2つのモジュール間の結合の強さ

①データ結合(引数直接渡し)

②スタンプ結合(構造体渡し)

③制御結合(制御変数を渡す)

④外部結合(外部データを参照)

⑤共有結合(共有データ領域を参照)

⑥内容結合

必要なデータが明示的に渡される

10

Page 11: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

データ結合(引数直接渡し)の例

#include <stdio.h>

struct student {char name[40];char id[8];char birthday[9];char school;

};

void make_initial(char* name, char* initial) // 直接処理に使うデータのみ渡す{

char first[20], last[20];sscanf(name, "%s %s", first, last);sprintf(initial, "%c%c", first[0], last[0]);

}

int main(void) {struct student s = {"Taro Shibaura", "AL15126", "19960331", 'L'};char initial[3];

make_initial(s.name, initial);printf("%s's initial is %s¥n", s.name, initial);printf("%s's initial is %s¥n", s.name, to_lower(initial));

return 0;}

11

関数A 関数B

直接必要なデータを渡す

必要

Page 12: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

スタンプ結合(構造体渡し)の例

#include <stdio.h>

struct student {char name[40];char id[8];char birthday[9];char school;

};

void make_initial(struct student *s, char* initial) // 構造体を丸ごと渡す{

char first[20], last[20];sscanf(s->name, "%s %s", first, last);sprintf(initial, "%c%c", first[0], last[0]);

}

int main(void) {struct student s = {"Taro Shibaura", "AL15126", "19960331", 'L'};char initial[3];

make_initial(&s, initial);printf("%s's initial is %s¥n", s.name, initial);

return 0;}

12

関数A 関数B

構造体丸ごとデータを渡す必要

不要

Page 13: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

外部結合(外部データを参照)の例

#include <stdio.h>

struct student {char name[40];char id[8];char birthday[9];char school;

} s = {“Taro Shibaura”, “AL15126”, “19960331”, ‘L’}; // 外部変数の定義(関数外)

void make_initial(char* initial){

extern struct student s; // 外部変数の参照宣言char first[20], last[20];sscanf(s.name, "%s %s", first, last);sprintf(initial, "%c%c", first[0], last[0]);

}

int main(void) {extern struct student s; // 外部変数の参照宣言char initial[3];

make_initial(initial);printf("%s's initial is %s¥n", s.name, initial);

return 0;}

13

関数A 関数B

外部変数 外部データで渡す

Page 14: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

共有結合(共有データ領域を参照)の例

#include <stdio.h>

char s[100]; // 共有データ領域の定義

void make_initial(){

sscanf(&s[0], “%s %s”, &s[61], &s[81]); // 決められた番地にアクセス!sprintf(&s[58], "%c%c", s[61], s[81]);

}

int main(void) {sprintf(&s[0], "Taro Shibaura");sprintf(&s[40],"AL15126");sprintf(&s[48],"1996331");s[57] = 'L';

make_initial();printf("%s's initial is %s¥n", &s[0], &s[58]);

return 0;}

14

関数A 関数B

共有データ領域

Page 15: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

制御結合例

#include <stdio.h>#include <ctype.h>

struct student { char name[40]; char id[8]; char birthday[9]; char school };

void make_initial(char* name, char* initial, int lflag) // 制御指令をフラグで渡す!

{char first[20], last[20];sscanf(name, "%s %s", first, last);if (lflag == 1)

sprintf(initial, "%c%c", tolower(first[0]), tolower(last[0]));else

sprintf(initial, "%c%c", first[0], last[0]);}

int main(void) {struct student s = {"Taro Shibaura", "AL15126", "19960331", 'L'};char initial[3];

make_initial(s.name, initial, 0);printf("%s's initial is %s¥n", s.name, initial);make_initial(s.name, initial, 1);printf("%s's initial is %s¥n", s.name, initial);

return 0;} 15

Page 16: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

プログラムにおける主な依存関係

• 関数間: 呼び出し関係

• 関数ー変数間: 外部変数参照

• クラス間(C++,Java): 継承関係

• ファイル間: インクルード関係

16

参照を追加するのは簡単だが・・・

→ 複雑になると、修正の影響が思わぬところ発生する場合がある

⇒ しっかり設計しよう!

Page 17: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

複合/構造化設計: 品質基準その2

モジュール強度: モジュール内の機能間の関連性

①情報的強度

②機能的強度

③連絡的強度(手順的強度+データ依存のあるもの)

④手順的強度(手順として起動する機能群)

⑤時間的強度(ある特定のタイミングに起動する機能群)

⑥論理的強度(制御フラグで機能選択される機能群)

⑦暗号的強度(独立した機能の寄せ集め)

単機能であること

カプセル化していること優劣はない

17

Page 18: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

情報強度例: double型のキュー

#ifndef _MYQUEUE#define _MYQUEUE

// Double型のキューの仕様を記述

extern double queueGet(void); // キューからデータを取り出す

extern int queuePut(double); // キューにデータを入れる

//(-1:オーバーフロー, 0:正常)

extern int isQueueEmpty(void); // キューが空かどうかを調べる

// (1:True, 0:false)

#endif

18

抽象データ型「キュー」の仕様 myqueue.h

Page 19: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

情報強度例: double型のキュー

double queueGet(void){

double value = 0;// 頭が縮みデータを取り出すif (isQueueEmpty() == 0) {

value = queue[head];head = (head + 1) % MY_QUEUE_SIZE;

}return value;

}

int isQueueEmpty(void){

return (head == tail) ? 1 : 0;}

19

抽象データ型「キュー」の実装 myqueue.c#include "myqueue.h"#define MY_QUEUE_SIZE 100

// 配列を循環的に使うことによるキューの実現static double queue[MY_QUEUE_SIZE];static int tail = 0; // キューの最後尾static int head = 0; // キューの最前列

int queuePut(double d){

int stat = 0;// 尾が伸びてデータが入るif ((tail + 1) % MY_QUEUE_SIZE == head) {

stat = -1;}else {

queue[tail] = d;tail = (tail + 1) % MY_QUEUE_SIZE;

}return stat;

}

Page 20: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

パターンを用いること

パターン:

– 型、思考や行動の様式、見本

– ボキャブラリを提供すること (例: ゴシック様式)

– 繰返し使われること

– 問題ドメイン固有の知識の蓄積

• 要求

• 制約

• 解決策

20

Page 21: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

パターンの記述内容

名称: パターンを識別するための名称

前提: 課題が生じる文脈(利用可能な状況)や制約

課題: 前提下で繰り返し現れる要求

解決策: 課題に対する解決策。以下の側面から記述:

– 構造: 構成要素と構成要素間の関係

– ふるまい: 実行時のプログラムの構造と実行シナリオ

– 設計根拠:要求と制約が、解決策でどのように達成するか

– 具体的な適用例

21

Page 22: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

パターンの利用例

アーキテクチャパターンの例:

– 名称: Model-View-Controller (MVC)– 前提: 人間とコンピュータ間のインタフェースに柔軟性を

持たせた対話型アプリケーション

– 課題:

[課題1] 入力手段と表示手段を頻繁に変更したい

[課題2] 同一情報を異なる表示手段で表示したい

[課題3] データの変化を、即時に表示手段に反映したい

0

2 0

4 0

6 0

8 0

1 0 0

1 月 2 月 3 月 4 月

東京

名古屋

大阪

1 月 2 月 3 月 4 月東京 20.4 27.4 90 20.4名古屋 30.6 38.6 34.6 31.6大阪 45.9 46.9 45 43.9

入力手段表示手段

データ

データ処理

22

Page 23: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

Model-View-Controller (MVC)の例

解決策: コンポーネント間の静的な構造

Model

コアデータ

データ処理

データ

0

2 0

4 0

6 0

8 0

1 0 0

1 月 2 月 3 月 4 月

東京

名古屋

大阪

1 月 2 月 3 月 4 月東京 20.4 27.4 90 20.4名古屋 30.6 38.6 34.6 31.6大阪 45.9 46.9 45 43.9

処理(Model) - 出力(View) - 入力(Controller)の3つの部分に分割する

入力UI部品

出力UI部品

Controller

View表示データ

イベント-処理変換

*

*

23

Page 24: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

Model-View-Controller (MVC)の例

[課題1] 入力手段と表示手段を頻繁に変更したい

解決策: ユーザインタフェースを動的に切り替える– Modelから、ViewとControllerへの接続を、ユーザ操作で切り

替えできるようにする。

利点: ユーザインタフェース(入力と表示の形態)は頻繁に変更できる

0

2 0

4 0

6 0

8 0

1 0 0

1 月 2 月 3 月 4 月

東京

名古屋

大阪

1 月 2 月 3 月 4 月東京 20.4 27.4 90 20.4名古屋 30.6 38.6 34.6 31.6大阪 45.9 46.9 45 43.9

Model入力の変更

表示の変更

Controller1

View1

View2

Controller2購読者

操作者

データ

24

Page 25: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

Model-View-Controller (MVC)の例

[課題2] 同一情報を異なる表示手段で表示したい

解決策:表示用部品をデータの表示用として登録する

– Modelの購読者として、異なる種類のViewを複数個登録できる。

利点: 同一情報を異なる形式で表示できる

0

2 0

4 0

6 0

8 0

1 0 0

1 月 2 月 3 月 4 月

東京

名古屋

大阪

1 月 2 月 3 月 4 月東京 20.4 27.4 90 20.4名古屋 30.6 38.6 34.6 31.6大阪 45.9 46.9 45 43.9

同一データを2種類のViewで表示

Controller1

View1

View2

Model

購読者

登録

登録

グラフ

表データ

25

Page 26: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

Model-View-Controller (MVC)の例

[課題3] データの変化を、即時に表示手段に反映したい

解決策: 出力UI部品に変更を伝え、部品が表示更新する– Modelからデータを参照している部品(購読者)に向けてデータの

更新を連絡し、購読者のViewは自ら表示を更新する

利点: データが変更すると、それを直ちに表示に反映できる

Model

データ0

2 0

4 0

6 0

8 0

1 0 0

1 月 2 月 3 月 4 月

東京

名古屋

大阪

1 月 2 月 3 月 4 月東京 20.4 27.4 90 20.4名古屋 30.6 38.6 34.6 31.6大阪 45.9 46.9 45 43.9

Controller1

View1

View2

②データ更新通知

①データ更新

③表示更新

購読者

26

Page 27: ソフトウェア工学1 第5回設計(2tsnaka/lecture/se1/第5回 設計2.pdf · 設計プロセス:2つのプロセス(おさらい) 抽象から詳細へ、論理から物理へ

今日のまとめ

• 再利用可能な設計知識の2つの形

– 手法: 記述法、手順、品質基準

– パターン: 名称、課題、前提、解決策

27