软件构造学习心得之设计规约

目录

1 沟通

2 规约(Specification)

2.1 行为等价性

2.2 前置条件pre-condition(requires)和后置条件post-condition(effects)

2.3 分类规约

2.4 规约的强度判断

2.5 图表规约(Diagramming specifications)

2.6 设计良好规约

 3 知识图谱


1 沟通

沟通在日常生产生活中是最重要的一环,只有进行有效合理的沟通才能高效正确的完成某项任务。在软件开发的过程中,沟通同样十分重要。但要注意,在软件开发过程的过程中的沟通包括两个主要方向:1.开发者和编译器,计算机之间的沟通。 2.开发者与开发者之间,开发者与客户端之间的沟通。

诚然,作为程序的实现者,计算机是工具,只有做好与计算机的沟通,才能有效正确的完成设计,实现功能。实际上,我们在编写程序的过程中使用的int,public,private等等,都是在与机器进行沟通,告诉他如何实现并完成我们的设计。这部分大家都应该很熟悉了,不再详细解释。

在实际的软件开发的过程中,很多情况下都是很多开发者共同完成一个软件的设计与实现。同样,软件开发后一定会与客户进行交互,所以人与人之间的交流与沟通同样至关重要。

为了规范化,高效化人与人之间的沟通,同时,提高与机器间的沟通,我们采取在编写程序文档来确保沟通的高效准确的进行。规约(Specification)是Java文档的一个重要部分,用来描述方法的功能与接口。

2 规约(Specification

规约的重要性:

  1. 没规约,没法分派任务,无法写程序;即使写出来,也不 知道对错
  2. 程序与客户端之间达成的一致
  3. Spec给“供需双 方”都确定了责任,在调用的时候双方都要遵守
  4. 没有规约 ,难以定位错误
  5. 客户端无需阅读被调用函数的代码,只需理解spec即可

规约的作用:

  1. 规约可以隔离“变化”,无需通知客户端
  2. 规约也可以提高编码效率
  3. 规约:扮演“防火墙”角色,客户端不需要知道实现,实现者不需要知道如何被使用

规约的格式:

/**
*XX
*@param XX
*@return XX
*/
方法签名

示例:

    /**
     * Add, change, or remove a weighted directed edge in this graph.
     * If weight is nonzero, add an edge or update the weight of that edge;
     * vertices with the given labels are added to the graph if they do not
     * already exist.
     * If weight is zero, remove the edge if it exists (the graph is not
     * otherwise modified).
     * 
     * @param source label of the source vertex
     * @param target label of the target vertex
     * @param weight nonnegative weight of the edge
     * @return the previous weight of the edge, or zero if there was no such
     *         edge
     */
    public int set(L source, L target, int weight);

2.1 行为等价性

行为等价性是指,根据client和implmentation共同判断,两个规约是否描述的是同一种行为。单纯的看实现代码,并 不足以判定不同的 implmentation是否是 “行为等价的”,需要根据代码的spec (开发者与client之间 形成的contract)判定 行为等价性,在编写代码之前,需要 弄清楚spec如何协商形 成、如何撰写。

2.2 前置条件pre-condition(requires)和后置条件post-condition(effects)

前置条件(pre-condition):对client的约束,程序注释使用@param。

后置条件post-condition(effects):对开发者的约束,程序中使用@return

注意:如果前置条件满足则后置条件必须满足;反过来,如果前置条件不被满足,则方法可以任意。虽然. 当前置条件被违反时,说明客户端有bug, 尽管实现者没有义务提醒,但可通过快速失败使bug更容易被找到和修复。

在这里,我们面临一个重要的问题:是否应该使用前置条件?在方法正式执行之前,是否要检查前置条件已被满足? 

 对此我们可以按照如下规则来操作:如果判断特殊输入的代价较大,那就把他写进前置条件中,把责任交给client,如果代价不大,可以采用check来检测是否合理。  如果决定内部处理,则要使用check从错误根源上寻找,防止错误大规模扩散,如果交给client,可以使用throw抛出错误即可。判断有两点:1.代价 2.方法使用范围如果方法是在类的内部使用,private,可以采用check,如果是public,最好是抛出错误。

2.3 分类规约

根据规约的表述性质,可以对规约进行分类,分类的依据性质如下:

  • 确定性:规约是否是确定的,输出值是单一的,还是在一组合法输出中进行选择
  • 陈述性:规约只是描述了输出应该是什么还是明确的说明了该如何计算输出
  • 强度:该规范的合法实现是小范围的,还是大范围的

2.4 规约的强度判断

如果规约S2>=S1,则需要同时满足:

  1. S2的前置条件不强于S1
  2. S2的后置条件不弱于S1

注意:前件条件强是指要求多,后件条件强是指承诺多。后置条件的强弱判断需要在相同的输入下进行比较,如果  前置条件变弱了,需要在前置条件较强的那个输入下来比较后置条件的强弱!!
 如果两个条件变化不同步,前置减弱,后置减弱,或者前置增强,后置减弱,则属于无法判断,不能进行替换。

2.5 图表规约(Diagramming specifications)

  • 用点作为方法
  • 用圈来表示规约覆盖的方法
  • 更强的规约面积约小,包含方法也越少

示例:

图1 规约图表

2.6 设计良好规约

  • 内聚的coherent:减少嵌套,判断,标记等,即:spec描述的功能单一,简单易理解。当一个方法实现多个目标时,最好将其拆分成多个方法。
  • 信息丰富的informative:避免输入或返回值情况出现歧义,即每一个输入或者返回值都有明确的对应信息,对于确定输入有确定的处理信息,对于一个返回值能确定的判断对应何种情况。核心:不能让client产生歧义。
  • 足够强的strong enough:加强后置条件,给出更高承诺,对于一些特殊输入要在后置条件中给出足够的处理措施,太弱的规约client使用起来不放心。
  • 足够弱的weak enough:太强的规约在特殊情况下难以达到,极大增加了开发者难度。
  • 使用抽象类型use abstract types:在spec中使用抽象类型有利于实现和client更大的自由度。

 3 知识图谱

图2 知识图谱

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值