第五章 总体设计

发表于 2022-08-20 18:12:12 阅读 (66) 分类:软件工程

5.1为每种类型的模块耦合举一个具体的例子。

答:耦合式对一个软件结构内不同模块之间互联程度的度量。耦合强弱取决于接口的复杂度,进入或访问某一模块的点,以及通过接口的数据。一般模块之间的可能的连接方式有七种,构成耦合的七种类型,它们的关系为:

低                                   耦合性                                 高

 

非直接耦合

数据耦合

特征耦合

控制耦合

外部耦合

公共耦合

内容耦合

 

强                                   独立性                                 弱

下面举例说明以上耦合:

A. 非直接耦合:两个模块没有直接的关系(模块1和模块2),独立性最强

001.png

B.数据耦合:即一个模块访问另一个模块的时候,彼此之间是通过数据参数来交换输入、输出信息的,这种耦合为数据耦合。这种耦合较为松散,模块间独立性较强。

002.png

C.特征耦合:即一组模块通过参数传递记录信息,用户情况是个数据结构,图中模块都与此有关,“计算水费”和“计算电费”本没有关系,由于引用了此数据结构产生了依赖关系

003.png

D.控制耦合:即如果一个模块通过传送开关、标志、名字等控制信息,明显地控制选择另一模块的功能,就是控制耦合

004.png

E.外部耦合:一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,则称之为外部耦合。

005.png

F.公共耦合: 若一组模块都访问同一个公共数据环境,则它们之间的耦合就称为公共耦合。

006.png

G.内容耦合:如果出现以下情况之一,两个模块就发生了内容耦合

① 一个模块访问另一个模块的内部数据。

② 一个模块不通过正常入口儿转到另一个模块的内部

③ 两个模块有一部分程序代码重叠(只可能发生在汇编程序中)

一个模块有多个入口(这意味着一个模块有几种功能)

Sub   AA(….)

Goto L

End sub

Sub  BB(..)

L: …

End  sub


5.2为每种类型的模块内聚举一个例子

答:内聚标志着一个模块内各个元素之间彼此结合的紧密程度,它是信息隐藏和局部化概念的自然扩展。

低内聚:

A. 偶然内聚:如果一个模块完成一组任务,这些任务彼此间即使有关系,关系也是很松散的。这就叫做偶然内聚

偶然内聚的例子:在模块T 中有A,B,C三条语句,至少从表面上看来这三条语句没什么联系,只是因为D,E,F,G中都有这三条语句,为了节省空间才把这三条语句作为一个模板放在一起。

B. 逻辑内聚:如果一个模块完成的任务在逻辑上属于相同或相似的一类(例如一个模块产生各种类型的全部输出),称为逻辑内聚

逻辑内聚的例子:某一个模块将打印,年,月,日,具体打印什么,将由传入的控制标志所决定。

C. 时间内聚:一个模块包含的任务必须在同一段时间内执行(例如,模块完成各种初始化工作),称为时间内聚

时间内聚的例子:将多个变量的初始化放在同一个模块中实现。

中内聚:

A. 过程内聚:如果一个模块内的处理元素是相关的,而且必须以特定次序执行,称为过程内聚

过程内聚的例子:一个子程序,将开始读取学生的学号,然后是姓名,最后将读取分数,是由于特定的顺序而将这些操作组合在一起的

B. 通讯内聚:如果模块中所有的元素都使用同一个输入数据和(或)产生同一个输出数据,则称为通讯内聚

通讯内聚的例子:有一个子程序,它将打印实验报告,并且在完成后重新初始化传进来的实验数据。这个程序具有通讯内聚性。因为这两个操作由于使用同一个数据源联系在了一起。

高内聚:

A. 顺序内聚:如果一个模块内的处理元素和同一个功能密切相关,而且这些处理必须顺序执行(通常一个处理元素的输出数据作为下一个处理元素的输入数据),则称为顺序内聚。

顺序内聚的例子:有一个子程序,通过给出的生日,先计算出年龄。再根据年龄算出退休的时间,则这个程序具有顺序内聚性。

B. 功能内聚:如果模块内所有的元素属于一个整体完成一个单一的功能,则成为功能内聚。

功能内聚的例子:一个程序中所有的操作都是为了算出一个人的年龄


5.3用面向数据流的方法设计下列系统的软件结构

①储蓄系统

001.png

②机票预订系统

002.png

③患者监护系统

003.png


5.4 美国某大学有 200 名教师,校方与教师工会刚刚签订一项协议。按照协议,所有年工资超过$26000(含$26000 )的教师工资将保持不变,年工资少于$26000的教师将增加工资,所增加工资数额按下述方法计算:给每位教师所赡养的人(包括教师本人)每年补助$100,此外,教师有一年工龄每年再多补助¥50,但是,增加后的年工资总额不能多于$26000。

教师工资档案存储在行政办公室的磁带上,档案中有目前的年工资、赡养的人数、雇佣日期等信息。需要写一个程序计算并印出每名教师的原工资和调整后的新工资。

要求:

(1)画出此系统的数据流图;

(2)写出需求说明;

(3)设计上述的工资调整程序(要求用 HIPO 图描绘设计结果),设计时分别采

用两种算法,并比较两种算法的优缺点:

(a)搜索工资档案数据,找出年工资少于$26000 的人,计算新工资,校核是

否超过$26000,存储新工资,印出新旧工资对照表;

(b)把工资档案数据按工资从最低到最高的次序排序,当工资数额超过$26000

时即停止排序,计算新工资,校核是否超过限额,存储新工资,印出结果。

(4)你所画出的数据流图适应用那种算法?

解:(1)数据流图:

001.png

分解后:

002.png

(2)需求说明:

1. 功能需求:可以输入调资的标准,输入教师档案,经调资给出新的教师档案,

需要存储档案

2. 性能需求:软件的响应时间应小于0.5s,更新处理要快

3. 灵活需求:当需求发生某些变化时,该软件应该能够适应这些变化

4. 故障处理要求:出现错误时,应给予警告或提示

(3)

A

003.png

B

004.png

(a)比较耗时,因为它要检索所有的档案,(b)从速度上看比较快,但是(b)

需要排序算法,比较复杂,(a)对于设计来讲比较简单 .

(4)画出的数据流图比较适合(A)的算法 


5.5下面将给出两个人玩的扑克牌游戏的一种玩法,试设计一个模拟程序,它的基本功能是:

(1)发两手牌(利用随机数产生器)。
(2)确定赢者和赢牌的类型。
(3)模拟N次游戏,计算每种类型牌赢或平局的概率。要求用HIPO图描绘设计结果并且画出高层控制流程图。
扑克牌游戏规则如下:
(1)有两个人玩分别为A和B。
(2)一副扑克牌有52张牌,4种花色(黑桃、红桃、梅花、方块),每种花色的牌的点数按升序排列有2,3,4,.........,10,J,Q,K,A等13种。
(3)给每个人发三张牌,牌面向上,赢者立即可以确定。
(4)最高等级的一手牌成为同花,即3张牌均为同一种花色,最大的同花是同一种花色的Q,K,A。
(6)第三等级的牌是同点,即点数相同的三张牌,最大的同点是AAA。
(7)第四等级的牌是对子,即3张牌中有两张点数相同,最大的对子是A,A,K。
(8)第五等级的牌是杂牌,即除去上列4等之外的任何一手牌,最大的杂牌是不同花色的A.K,J。
(9)若两个人的牌类型不同,则等级高者胜;若等级相同,则点数高者胜;若点数也相同,则为平局。

程序:#include "stdio.h"

int rabl(int a,int b,int *r)

{

int l,k,m,i,p;

k=b-a+1;

l=2;

while(i<=1)

{

k=k+k+k+k+k;

k=k%m;

l=k/4+a;

if(l<=b)  {p=l;i=i+1;}

}

*r=k;

return(p);

}

int max(int T[10][10])

{

int t=0;

if(T[0][0]>T[1][0])

t=T[0][0];

else t=T[1][0];

if(t<T[2][0])

t=T[2][0];

return t;

}

int E1(int T[10][10])

{

if(T[0][1]==T[1][1]&&T[1][1]==T[2][1])

return 1;

else  return 0;

}

int E2(int T[10][10])

{

int q=0;

if(((max(T[10][10])-1)==T[0][0]||(max(T[10][10])-1)==T[1][0]||(max(T[10][10])

-1)==T[2][0])&&((max(T[10][10])-2)==T[0][0]||(max(T[10][10])-2)==T[1][0]||

(max(T[10][10])-2)==T[2][0])) // if(q=max(T[][10]))

return 1;

else

return 0;

}

int E3(int T[10][10])

{

if(T[0][0]==T[1][0]==T[2][0])

return 1;

else return 0;

}

int E4(int T[10][10])

{

if(T[0][0]==T[1][0]&&T[0][0]!=T[2][0])

return 1;

else if(T[0][0]==T[2][0]&&T[0][0]!=T[1][0])

return 1;

else if(T[1][0]==T[2][0]&&T[1][0]!=T[0][0])

return 1;

else return 0;

}

void main()

{

int times=0,e1=0,e2=0,e3=0,e4=0,e5=0;

int A[10][10],B[10][10];

int r1=2,r2=3;

printf("请输入游戏的次数\n");

scanf("%d",×);

for(int j=0;j<times;j++)

{

for(int i=0;i<3;i++)

{

A[i][0]=rabl(1,13,&r1);

A[i][1]=rabl(14,17,&r2);

B[i][0]=rabl(1,13,&r1);

B[i][1]=rabl(14,17,&r2);

}

if(E1(A[][10])>E1(B[][10])){

e1++;

printf("A赢,同花顺\n");

}

else if(E1(A[][10])<E1(B[][10]))

{

e1++;

printf("B赢,同花顺\n");

}

else if(E1(A[][10])==E1(B[][10])&&E1(B[][10])==1)

{

e1++;

if(max(A[][10])>max(B[][10]))

printf("A赢,同花顺\n");

else

printf("B赢,同花顺\n");

}

else if(E2(A[][10])>E2(B[][10]))

{

e2++;     

printf("A赢,顺子\n");

}

else if(E2(A[][10])<E2(B[][10]))

{

e2++;

printf("B赢,顺子\n");

}

else if(E2(A[][10])==E2(B[][10])&&E2(B[][10])==1)

{

e2++;

if(max(A[][10])>max(B[][10]))

printf("A赢,顺子\n");

else

printf("B赢,顺子\n");

}

else if(E3(A[][10])>E3(B[][10]))

{

e3++;

printf("A赢,同点\n");

}

else if(E3(A[][10])<E3(B[][10]))

{

e3++;

printf("B赢,同点\n");

}

else if(E3(A[][10])==E3(B[][10])&&E3(B[][10])==1)

{

e3++;

if(max(A[][10])>max(B[][10]))

printf("A赢,同点\n");

else

printf("B赢,同点\n");

}

else if(E4(A[][10])>E4(B[][10])) {

e4++;

printf("A赢,对子\n");

}

else if(E4(A[][10])>E4(B[][10]))

{

e4++;

printf("B赢,对子\n");

}

else if(E4(A[][10])==E4(B[][10])&&E4(B[][10])==1) ;

{

e4++;

if(max(A[][10])>max(B[][10]))

printf("A赢,对子\n");

else

printf("B赢,对子\n");

}

else  

{

if(max(A[][10])>max(B[][10]))

printf("A赢,杂牌\n");

else

printf("B赢,杂牌\n");

}

}

printf("同花顺赢牌概率为%d,顺子赢牌概率为%d,同点赢牌概率为%d,对子赢牌概率为%d,杂牌赢牌概率为%d",e1/times,e2/times,e3/times,e4/times,e5/times);


控制流程图:

005.png