oo面向对象--规格化设计

时间:2022-10-28 12:21:18

oo面向对象--规格化设计

规格化设计与抽象

要了解规格化设计首先要了解抽象化的程序设计,两者是密不可分的。

抽象化(Abstraction)

抽象化是将数据与程序,用语义呈现他们的外观,但是隐藏起它的实现细节。

抽象的过程可以看做多对一的映射,让我们忽略个体信息,将不同事物当做相同的事物对待,能够减少程序的复杂度,使得程序员可以专注在处理少数重要的部分。

发展

近几年来,程序员对已经产生的抽象水平产生不满,甚至不满足于在高级语言程序中普遍实现的抽象水平,解决这个问题的方法在于创造“更高级的语言”,用相对固定的数据结构以及有很强功能的原始类型来实现,但是这种方法的缺陷在于嘉定编程语言的设计者在设计语言的时候将大多数用户需要的抽象设计引进设计语言中,包含如此众多的内置抽象的编程语言可能笨拙的很难使用。

另一种可取代的方法是设计一种语言机制,允许程序员在需要的时候构建自己的抽象方法。通常的机制是使用过程(procedure)。编程语言包含了两种重要的抽象方法:参数化抽象(abstraction by parameterization)和规格化抽象(abstraction by specification)。其中:

  • 参数化抽象是用参数替换数据特征来进行抽象。这样能够归纳出模块,从而使其可以用于更多的情况。例如,可以定义一个排序抽象,既能够实现对实数数组的排序,又能够实现对整型数组的排序,或者甚至对数组类型这类一般结构都有用。
  • 规格化抽象是将运行细节(即模块如何实现)抽象为用户所需求的行为(即模块做什么)。这是从具体实现中抽象出模块,需要的仅仅是模块的实现能够匹配我们所依赖的表述形式。

程序设计中,抽象类别包括下列4类:

1:过程抽象:能够引入一些新的操作;

2:数据抽象:能够引入新的数据对象类型;

3:反复运算抽象:能够反复运算遍历在集合中的元素,而不必显示如何获得元素的细节;

4:类型层次:能够从多个单独的数据类型中抽象成几组相关的类型。

规格

抽象用于将一个程序分解为多个模块,然而抽象是无形的,没有描述,我们就无法知道如何将它与其实现的抽象区分。规格描述了服务的提供者和用户之间的协定,提供者同意编写一个属于规格满足集的模块。

规格是对一个方法/类/程序的外部可感知行文的抽象表示,它的目的是为了定义抽象的行为。

如果一个实现提供了所描述的行为,这个实现就满足了一个规格。

规格的含义是满足其所有程序的集合,这个集合称为规格满足集。

作业中的规格bug

此处为自己统计的bug,由于报告的jsf个数有限,自己重新看了一次还是发现了许多bug和不规范的地方。

bug类别 Requires不完整 Modifies不完整 Effects不完整 Requires逻辑错误 Modifies逻辑错误 Effects逻辑错误 Effects内容为实现算法 不符合JSF
个数 7 3 5 0 0 2 0 0
方法行数 3,5,5,13,22,20,4 5,7,7 20,30,15,17,15 30,15

BU*生原因

1、有些方法或者类的JSF遗漏

比如自己写的Exception类里面忘记写JSF,一些信息存储的类里面的构造方法有时候也会忘记写,还是自己不够细心。

2、没有按照标准格式书写

Effects之后的内容应该为布尔表达式。像是代码中出现的(\result = str),这种里面的=应该写成==

3、程序里面一些传入对象的方法,对应的Requires有的没写。

有传入还是应该写明有Requires的要求,比如传入对象不等于null,或者对象的repOK 为ture之类。

4、某些过程会有附加的隐式输入,例如读入文件和在System.out写信息,这些也属于过程的输入

5、还是偷了很多懒。。

JSF不规范的写法及改进

有些例子前置条件和后置条件一起修改了。

1、前置与后置条件:

    public int getDirection(Coordinate now, Coordinate next){
/**
* @REQUIRES: None;
* @MODIFIES: None;
* @EFFECTS: (next.getX()-now.getX()==1&&next.getY()-now.getY()==0)==>(\result = 0);
(next.getX()-now.getX() == -1 && next.getY()-now.getY()==0)==>(\result = 1);
(next.getX()-now.getX() == 0 && next.getY()-now.getY()==1)==>(\result = 2);
(next.getX()-now.getX()== 0 &&next.getY()-now.getY() == -1)==>(\result = 3);
* @THREAD_REQUIRES:
* @THREAD_EFFECTS:
*/
}

这里输入的两个坐标分别是当前坐标和下一步的坐标,这两个坐标需要满足的条件是在地图上是相邻的,由于可能出现道路突然断开的状况,所以两个坐标的连接状态未知,当时想着在代码里面处理了这种异常状况所以没有写requires,但是其实也能在requires中体现,然后在代码中处理这种情况,抛出异常或者返回等操作,如果不写的话也要加入两个坐标不为空,有输入最好要限制其内容,什么都不写不是一种好的习惯。

这里的effects书写也不规范,要用双等号。

修改版本:

public int getDirection(Coordinate now, Coordinate next){
/**
* @REQUIRES: now.getX()>=0 && now.getX() < 80
* && now.getY() >= 0 && now.getY() < 80 && next.getX()>=0
* && next.getX() < 80 && next.getY() >= 0 && next.getY() < 80
* && graph[now.getX()*80+now.getY()][next.getX()*80+next.getY()] == 1;
* @MODIFIES: None;
* @EFFECTS:
* (next.getX()-now.getX()==1&&next.getY()-now.getY()==0)==>(\result = 0);
* (next.getX()-now.getX() == -1 && next.getY()-now.getY()==0)==>(\result == 1);
* (next.getX()-now.getX() == 0 && next.getY()-now.getY()==1)==>(\result == 2);
* (next.getX()-now.getX() == 0 &&next.getY()-now.getY() == -1)==>(\result == 3);
*/
}

2、后置条件:

    public void servingHandler() throws InterruptedException{
/**管理出租车服务状态
* @REQUIRES: None;
* @MODIFIES: this.newtime;this.state;this.coordinate;this.schedulerInfo;
* * this.info;
* @EFFECTS: 对本线程的状态和参数进行改变
* @THREAD_REQUIRES:
* @THREAD_EFFECTS: \locked(trackingInfo);
*/ }

这个方法实现的过程有些复杂,当时直接用自然语言瞎写了一下,没有规范化表述。不过在此函数中调用了其他函数,现在不知道如何将调用其他函数的effects写清楚。。

    public void servingHandler() throws InterruptedException{
/**
* @REQUIRES: None;
* @MODIFIES:\this.newtime;\this.state;
* \this.coordinate;\this.schedulerInfo;\this.info;\System.out;
* InfoQueue;
* @EFFECTS:
* desMove(currentRequest.getDestination());
* this.credit.addAndGet(3);
* InfoQueue.contains(schedulerInfo);
* schedulerInfo.contains(info);
* System.out!=null;
* @THREAD_REQUIRES:None;
* @THREAD_EFFECTS: \locked(trackingInfo);
*/ }

3、前置条件和后置条件:

    @Override
public void desMove(Coordinate destination) throws InterruptedException {
/**出租车找最短路径行驶,找最小流量的边
* @REQUIRES: (\all Coordinate a,b;map;graph[a][b] == 1)
* @MODIFIES: this.coordinate;this.Info;newtime;
* @EFFECTS: this.coordinate == destination;
* @THREAD_REQUIRES:
* @THREAD_EFFECTS:
*/
}

这个函数是移动出租车到目标点,requires没有限制destination的范围,后置条件写的过于简略,没有将移动过程写清楚。

    @Override
public void desMove(Coordinate destination) throws InterruptedException {
/**出租车找最短路径行驶,找最小流量的边
* @REQUIRES: now.getX()>=0 && now.getX() < 80 && now.getY() >= 0
* && now.getY() < 80
* &&(\all Coordinate a,b;a.getX()>=0 && a.getX() < 80 && a.getY() >= 0 && a.getY() < 80 && b.getX()>=0 && b.getX() < 80 && b.getY() >= 0 && b.getY() < 80;graph[a.getX()*80+a.getY()][b.getX()*80+b.getY()] == 1)
* //保证地图连通
* @MODIFIES: this.coordinate;this.Info;newtime;
* @EFFECTS:pathway == TaxiGUI.getInstance().getShortestPath(destination))==>(\all Coordinate a;pathway;this.info.contains(a))
* && (\all int i,int j;j < pathway.size()&&i == j * 5;info.contains(i))
* && \this.coordinate == pathway.get(pathway.size()-1)
* && \this.newtime == newtime + waitime + 5*pathway.size()&&info.contains(newtime);
*/
}

4、前置条件和后置条件:


public static boolean judegeValid(Coordinate a, Coordinate b){
/**
* @REQUIRES: None;
* @MODIFIES: None;
* @EFFECTS: 判断是否符合坐标输入条件
*/ }

由于有输入参数,应该对参数范围加以规范和约束。

effects书写也不符合规范。


public static boolean judegeValid(Coordinate a, Coordinate b){
/**
* @REQUIRES: a instanceof Coordinate && b instanceof Coordinate && a! = null && b!=null;
* @MODIFIES: None;
* @EFFECTS:(a.isOutOfBound()||b.isOutOfBound()||a.equals(b))==> \result == false;
*!(a.isOutOfBound()||b.isOutOfBound()||a.equals(b))==> \result == true;
*/ }

5、前置条件和后置条件:

    public void RoadStatusHandler(String cmd){
/**
* @REQUIRES:
* @MODIFIES: TaxiGUI;
* @EFFECTS: 改变道路开关;
*/
}

String cmd不能是null,虽然也在代码中有处理,effects没写清楚。。

    public void RoadStatusHandler(String cmd){
/**
* @REQUIRES: str instanceof String;str!=null;
* @MODIFIES: TaxiGUI;System.out;
* @EFFECTS: !cmd.isValid()==>System.out == "#set Status Format Error";
* cmd.matches(this.m)&&cmd.isValid()&&m.group(5).equals("OPEN")==>TaxiGUI.getInstance().graph[m.group(1)*80+m.group(2)][m.group(3)*80+m.group(4)]==1;
* cmd.matches(this.m)&&cmd.isValid()&&m.group(5).equals("CLOSE")==>TaxiGUI.getInstance().graph[m.group(1)*80+m.group(2)][m.group(3)*80+m.group(4)]==0;
*/
}

6、前置条件和后置条件

    public void RequestHandler(String cmd) throws RequestFormatErrorException,InterruptedException{
/**
* @REQUIRES:
* @MODIFIES: rcv;
* @EFFECTS: 请求读入
*/
}

没有写异常情况,requires不完整,effects不完整

    public void RequestHandler(String cmd) throws RequestFormatErrorException,InterruptedException{
/**
* @REQUIRES:cmd instanceof String && cmd! = null;
* @MODIFIES: rcv;System.out;
* @EFFECTS: cmd.isValid()==>\this.rcv.contains(new PassengerRequest request);
* !cmd.isValid()==>e == exceptional_behavior(RequestFromatErrorException)&&System.out == e.getMessage(); */
}

功能bug和规格bug在方法上的聚集关系

方法名 功能bug数目 规格bug数目
public void input() 2 1
public void SetRoadStatus(Coordinate a1,Coordiante a2) 1 0
public void randomMove() 1 1

我的功能bug主要在代码实现上面有问题,其实和规格的bug联系并没有很大。

规格设计思路及体会

老师在课上强调,要先写出规格再开始写代码。也就是要先抽象出这个类或者方法的功能,输入输出再进行代码的书写,写出来的内容要符合规格的叙述。所以构思抽象规格是放在首位的,关注的是行为,而不是实现行为的细节。

一个规格的语义包含三部分:需求(Requires),修改(Modifies),结果(Effects)。

1、requires:规格需要有足够的限制性来排除其抽象的用户不可接受的任何实现,这就需要在requires里面明确指出来。一个局部的过程规格总是包含了一个requires格式,有些时候编程应该检查requires中的约束条件,如果不满足就跑出一个异常。

2、modifies:列出了被修改的所有输入名称,做到不遗漏。

3、effects:所有为被requires格式排除的输入描述了过程的行为,必须定义产生了何种输出,同时必须定义被列在modifies格式中的输入做的修改所产生的结果。在本课程中需要用到规范化的表达,实际工程上也有用到简洁的自然语言表达,但是一定要表述清楚,并且符合逻辑。

4、线程类的requires和effects需要书写,但一般不要给使用者限制requires.

实际上因尽可能避免使用requires格式,因为如果输入产生了不满足requires的格式的时候,规格并没有给出相应的操作。所以设计抽象的时候要设计成满足最小限度的受限,对过程行为的细节仅仅做必要的限制,给实现者更多的*,可以进行更加有效的编程。

oo面向对象--规格化设计的更多相关文章

  1. 规格化设计——OO第三单元总结

    规格化设计--OO第三单元总结 一.JML语言理论基础.应用工具链 1.1 JML语言 ​ JML(java modeling language)是一种描述代码行为的语言,包括前置条件.副作用等等.J ...

  2. 【设计模式系列】之OO面向对象设计七大原则

    1  概述 本章叙述面向向对象设计的七大原则,七大原则分为:单一职责原则.开闭原则.里氏替换原则.依赖倒置原则.接口隔离原则.合成/聚合复用原则.迪米特法则. 2  七大OO面向对象设计 2.1 单一 ...

  3. OO第三单元——JML规格化设计

    OO第三单元--JML规格化设计 JML语言的理论基础以及应用工具链情况 理论基础 JML是对JAVA程序进行规格化设计的一种表示语言,是一种行为接口规格语言.JML整合了Java和JAVAdoc,并 ...

  4. OO&lowbar;Unit 3 JML规格化设计总结

    OO_Unit 3 JML规格化设计总结 JML语言概述(Level 0) 概念定义   JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言.JML ...

  5. Atitit 基于sql编程语言的oo面向对象大规模应用解决方案attilax总结

    Atitit 基于sql编程语言的oo面向对象大规模应用解决方案attilax总结 1. Sql语言应该得到更大的范围的应用,1 1.1. 在小型系统项目中,很适合存储过程写业务逻辑2 1.2. 大型 ...

  6. Atitit usbQb212 oo 面向对象封装的标准化与规范解决方案java c&num; php js

    Atitit usbQb212 oo 面向对象封装的标准化与规范解决方案java c# php js 1.1. 封装性是面象对象编程中的三大特性之一  三个基本的特性:封装.继承与多态1 1.2. 魔 ...

  7. java 28 - 1 设计模式 之 面向对象思想设计原则和模版设计模式概述

    在之前的java 23 中,了解过设计模式的单例模式和工厂模式.在这里,介绍下设计模式 面向对象思想设计原则 在实际的开发中,我们要想更深入的了解面向对象思想,就必须熟悉前人总结过的面向对象的思想的设 ...

  8. OO面向对象第一单元总结

    OO面向对象第一单元总结(表达式求导) 写在前面: 魔鬼课程oo第一单元终于结束,当终究要落笔总结,竟不知从何写起…… 回首再去看第一次的作业,你会满足于那时的幸福,或许,这就是成长吧! 千言万语,一 ...

  9. Java面向对象课程设计——购物车

    Java面向对象课程设计——购物车 小组成员:余景胜.刘格铭.陈国雄.达瓦次仁 一.前期调查 流程 客人(Buyer)先在商城(Mall)中浏览商品(Commidity),将浏览的商品加入购物车(Sh ...

随机推荐

  1. 从红米手机经常发生UIM没有服务的一些猜想

    缘起:买了测试用的红米手机,安装电信卡,经常生UIM没有服务,大约两天1次. 我的解决办法:飞行模式切换一下就恢复正常. 之前这张卡用三星的信号是满格,红米断开挺经常的 上网搜索: 同样的现象,还好官 ...

  2. Codeforces GYM 100114 B&period; Island 水题

    B. Island Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Description O ...

  3. win7计划任务执行BAT文件问题

    今天下午做了一个调用java 可执行jar的程序,想通过win7的计划任务来调用 批处理命令: java -jar BIDropSyc.jar    或者 javaw -jar BIDropSyc.j ...

  4. mobile angualar ui的简单使用

    最近做一个微信App形式的业务平台,之前从别人的推荐文中知道了mobile angualar ui这个东西,这次纯做mobile Web就试用了一下,之前PCWeb中用过AngularJS,Hybri ...

  5. btcpool之StratumServer

    一.简介 StratumServer(简称sserver)接收JobMaker发送的stratumjob消息,从http api获取用户列表,对外部矿机提供服务. 二.处理stratumjob消息 s ...

  6. kafka工作原理介绍

    两张图读懂kafka应用: Kafka 中的术语   broker:中间的kafka cluster,存储消息,是由多个server组成的集群.  topic:kafka给消息提供的分类方式.brok ...

  7. javasript中var、let和const区别

    let和const都是es5,es6新版本的js语言规范出来的定义,在这以前定义一个变量只能用var.let和const都是为了弥补var的一些缺陷而新设计出来的. 简单来说是: let是修复了var ...

  8. LeetCode 657 Robot Return to Origin 解题报告

    题目要求 There is a robot starting at position (0, 0), the origin, on a 2D plane. Given a sequence of it ...

  9. JMeter出现&OpenCurlyDoubleQuote;the target server failed to respond&OpenCurlyDoubleQuote;的解决办法

    今天用jmeter压测执行过程中遇到一个报错如下: 解决方案如下: 1. 修改执行计划中,HTTP请求的Implementation为HttpClient4. 2. 保存执行计划 3. 修改JMete ...

  10. Java基础学习篇---------this、object的学习

    一.this的学习方法 1.使用this调用构造方法市一定放在构造方法的首行 2.使用this调用构造方法时一定流出调用的出口 public class MyClass { public MyClas ...