欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

作业小结3

程序员文章站 2022-03-26 21:48:52
作业小结3 规格化设计的发展历史 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的指令和数据。简单来说,就是直接编写0和1的序列来代表程序语言。例如:使用0000代表加载(LOAD),0001代表存储(STORE)等。 面向机器的语言通常情况下被认为是一种“低级语言 ......

作业小结3

规格化设计的发展历史

最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的指令和数据。简单来说,就是直接编写0和1的序列来代表程序语言。例如:使用0000代表加载(LOAD),0001代表存储(STORE)等。

面向机器的语言通常情况下被认为是一种“低级语言”,为了解决面向机器的语言存在的问题,计算机科学的前辈们又创建了面向过程的语言。面向过程的语言被认为是一种“高级语言”,相比面向机器的语言来说,面向过程的语言已经不再关注机器本身的操作指令、存储等方面,而是关注如何一步一步的解决具体的问题,即:解决问题的过程,这应该也是面向过程说法的来由。

第一次软件危机:结构化程序设计。根本原因就是一些面向过程语言中的goto语句导致的面条式代码,极大的限制了程序的规模。结构化程序设计(英语:Structuredprogramming),一种编程范型。它采用子程序(函数就是一种子程序)、代码区块、for循环以及while循环等结构,来替换传统的goto。希望借此来改善计算机程序的明晰性、质量以及开发时间,并且避免写出面条式代码。

为了解决问题,在1968、1969年连续召开两次著名的NATO会议,会议正式创造了“软件危机”一词,并提出了针对性的解决方法“软件工程”。虽然“软件工程”提出之后也曾被视为软件领域的银弹,但后来事实证明,软件工程同样无法解决软件危机。

结构化程序设计的主要特点是抛弃goto语句,采取“自顶向下、逐步细化、模块化”的指导思想。结构化程序设计本质上还是一种面向过程的设计思想,但通过“自顶向下、逐步细化、模块化”的方法,将软件的复杂度控制在一定范围内,从而从整体上降低了软件开发的复杂度。结构化程序方法成为了1970年代软件开发的潮流。

规格化设计被重视的原因

  • 所有的程序开发手册都包含了各种规则。一些习惯*程序人员可能对这些规则很不适应,但是在多个开发人员共同协作的情况下,这些规则是必须的。这不仅仅是为了开发效率来考虑,也是为了后期维护考虑。

  • 代码规格化设计正是为了培养规范设计和编程,养成良好的习惯,增强软件产品的稳定,健壮,可靠性;同时也提高了软件的可读性,可以让程序员尽快而彻底地理解新的代码,使产品可维护性提高。

  • 此外,还有如下好处:
  1. 减少维护成本。一个软件的生命周期中,80%的花费在于维护,另一方面,几乎没有任何一个软件,在其整个生命周期中,均由最初的开发人员来维护,规范的编码减少人员变动带来的维护成本。
  2. 改善软件的可读性。可以让程序员尽快而彻底地理解新的代码。在一个团队中,代码也容易在程序员之间共享。
  3. 维护部门交付产品的规范形象。

规格bug的表格分析

规格bug类别 所对应方法的代码行数 产生原因
第九次作业公测->JSF检查->不符合JSF规范 4 测试者说REQUIRES必须是一个布尔表达式不能是自然语言
第九次作业公测->JSF检查->Modifies不完整 5 改了this但没写
第九次作业公测->JSF检查->Requires不完整 8 测试者说有参数必须写requires
第九次作业公测->JSF检查->Requires逻辑错误 4 测试者说有参数必须写requires
第十次作业公测->规格检查->方法规格检查->JSF不符合规范 7 测试者说我没使用布尔表达式
第十一次作业公测->规格检查->抽象对象有效性实现检查:Overview是否明确抽象对象 - 测试者说Overview过于简陋,仅是名字的翻译,未体现出数据抽象思想
第十一次作业公测->规格检查->抽象对象有效性实现检查:Overview是否明确抽象对象 - 测试者说您的Taxi类、Settings类、Light类等等,Overview都相当的“抽象”啊,仅仅将名字翻译过来,或者是名词,或者是动词短语,并没有体现其真正含义所在。
第十一次作业公测->规格检查->方法规格检查->JSF不符合规范 1 测试者说规范的表示是:\result==this.point0; 而你是* @EFFECTS: return this.point0;。

前置条件与后置条件案例

前置条件

  1. * @REQUIRES: other != null
    改进:* @REQUIRES: other instanceof TrackableTaxi && other != null
    说明:requires不够完整,对于某些方法应该更明确表明它的类型。
  2. * @REQUIRES: this != null
    改进:* @REQUIRES: None
    说明:一般情况下this是不会等于null的,这大概是一句废话。
  3. * @REQUIRES: None
    改进:* @REQUIRES: this.property > 0
    说明:该方法要求其它方法执行过后才能执行,而其它方法执行过后的当且仅当的标志是某个属性大于零。于是就这样子改了。
  4. * @REQUIRES: this.property != null
    改进:* @REQUIRES: None
    说明:类中有一个repOK的方法,要求property不是Null。而property属性在构造方法中已经保证了不是Null。因此这是废话。
  5. * @REQUIRES: x >=0 && x <= 79
    改进:* @REQUIRES: x >= 0 && x <= MAP_MAX_LENGTH
    说明:之前定义过常量MAP_MAX_LENGTH,这里就不适合写79了,不然以后要改地图尺寸时得改很多东西。其它所有常量同理。

后置条件

  1. * @EFFECTS: return this.property
    改进:* @EFFECTS: \result == this.property
    说明:常见的语法问题。感谢测试者帮我找到这个问题。
  2. * @EFFECTS: \result = this.property
    改进:* @EFFECTS: \result == this.property
    说明:常见的语法问题。感谢我舍友的测试者帮我舍友找到这个问题。
  3. * @EFFECTS: this != null
    改进:* @EFFECTS: this.property == value
    说明:构造方法不能写的过于简单。
  4. * @EFFECTS: 初始化该实例
    改进:* @EFFECTS: this.property == value
    说明:构造方法不能写的过于简单,即使使用自然语言。
  5. * @EFFECTS: linkedList.contains(request); 改进: * @EFFECTS: linkedList.contains(request) && linkedList.size = \old(linkedList).size + 1`
    说明:没有列出所有变化。

功能bug与规格bug的聚集关系

方法名 功能bug数 规格bug数
Line 0 1
Taxi 0 2
initTaxis 0 1
checkSameUser 0 1
getPoint0 0 1

看的出来,功能bug数跟规格bug数是相关的。如果一个方法连规格都写错了,那么它的功能是很难正确的。不论是构造方法还是普通的方法,都是这样子的。当然前提是写代码的人是根据规格来写的代码。

如果写规格的人和写代码的人不是同一个人,这个结论应该就很显然了。

我们常常做测试时,就对方法单独的测试,只要输入满足规格的requires,检查输出是否满足effects就好了。如果测试通过,且modifies正确,那么就较大概率没bug(因为并未进行完备的测试)。这样单独的方法对了,才是对的。

设计规格和撰写规格的思路和体会

先说体会吧!首先感谢课程组让我们训练设计和撰写规格。

老师课上总是强调设计规格的重要性,虽然大家写得很累,但是我觉得老师说得很对。设计规格确实是最重要的。尤其是在团队协作中。

所有的程序开发手册都包含了各种规则。我们可能对这些规则很不适应,但是在多个开发人员共同协作的情况下,这些规则是必须的。这不仅仅是为了开发效率来考虑,也是为了后期维护考虑。所以我觉得老师说的很对。

关于设计规格和撰写规格。我的思路如下:

首先,我们要根据设计需求,进行架构,做数据抽象,总结出几个类,弄清楚各个类的定义,弄清楚各个类之间如何交互,弄清楚各个类如何相互合作最终把这些设计需求来实现。

其次,根据数据抽象,弄清楚各个类需要哪些属性。

再然后,根据设计需求,弄清楚类需要哪些方法,而这些方法需要被哪个或哪些类调用。又或者它仅仅只是一个内部方法。弄清楚这个方法要实现什么样的功能。这里我想起来老师上课常常讲的话,就是写JSF时千万别去想算法。所以,这一步,先不考虑算法怎么实现,只考虑这个方法的功能。另外这一步要保证代码的逻辑是正确的。

再之后,开始写设计规格。根据上一布自己所想的,写好设计规格。注意require effect的正确性。

再之后,开始写代码,就实现那些方法。这里要注意算法的正确性,注意,如果有modify,可能还需要修改一下设计规格。

最后,测试程序,检查代码功能是否正确。如果功能错误,可能是在设计规格时逻辑错误,也可能是代码在具体实现时算法错误或者编码错误。要从这两个方向来找bug,最终得到正确的程序。

最后谢谢老师们谢谢助教们谢谢同学们!