#前言
随着期末的到来,对于面向对象程序设计课程的学习也迎来了尾声。在最后一个月的从课程中,笔者对于面向对象程序规格实现层面的单元测试、正确性论证以及使用UML图描述程序的设计进行了深入的学习。通过对类和方法进行规格实现进行单元测试以及论证,检查并确认实现的正确性,使得相应代码拥有更高的可靠性。通过使用UML类图、时序图、状态图对系统的功能、结构、行为等层面进行描述,使面向对象程序具有更清晰的结构设计,提高程序的质量。本文通过对相关知识进行调研,就电梯调度系统这一案例绘制UML图并作分析。在本文的最后笔者还会对本学期所学的面向对象程序设计知识进行总结。
##正确性论证与测试
-
单元测试:
在作业中,笔者就已经以电梯调度系统为案例进行了全覆盖的单元测试。运用JUnit4为每个类中的每个方法设计单元测试样例。通过覆盖方法中每行代码与每个分支,设置测试点,从而检测方法运行的正确性。这一环节能够对方法进行比较全面的检测,检查代码运行结果是否符合预期。笔者也在单元测试的过程中,发现了方法中选择分支设置上的问题。 -
正确性论证:
在最近的一次作业,笔者对于电梯调度系统每个类和方法进行了实现层面的正确性论证。从抽象对象实现的有效性、对象有效性、方法实现有效性三个方面对系统实现层面有效性进行了逻辑证明。在抽象对象层面,论证类的抽象对象对于数据管理的有效性;在对象有效性层面,论证所有由类生成的对象都恒符合类的不变式;在方法实现层面,根据方法的规格对输入与输出进行划分,并根据具体代码实现匹配输入-输出对,论证方法实现符合规格。当然,需要以规格设计的正确性作为前提。 -
正确性论证 vs 测试
- 正确性论证能够从类规格以及方法过程规格出发,对于代码实现进行逻辑上的证明。理论上,拥有正确而全面的论证过程的程序的正确性与可靠性是有保障的。
- 单元测试是通过运行大量的测试样例来覆盖运行代码的每个分支,从而对程序的每个部分进行运行正确性的检测。从效果上来看,测试所达到的效果与正确性论证的效果相近,都能达到规格中的所有匹配情况。但从数学的角度来看,测试类似于试根,即通过输入某些特值来得到某些结论。这在证伪时,相当有说服力,但在证明时就显得缺乏严谨性。类似的,单元测试在寻找程序问题时,相当有效,但无法向像正确性证明一样全面的论证程序的正确性。
- 正确性论证能够覆盖类实现、对象有效性以及方法实现多个方面,而测试仅能覆盖方法正确性一个方面。
##OCL语言调研
- OCL语言,又名对象约束语言(Object Constraint Language),作为图形符号(UML)的补充,对建模元素的有关细节进行说明。如前置条件、后置条件,约束等。
- UML图一般不够精细,缺乏与规范相关的描述,导致使用自然语言产生歧义。OCL便是为填补这一空白研制出来的,是一种保留了易读易写的形式语言。
- OCL语言是在UML基础之上形成的用于描述规格的语言,保留了大量的自然语言的词汇,使用一定的标识符,达到对规格的描述效果。其结构较为复杂,描述能力较强。
- JSF语言(课程内介绍)是在命题逻辑的基础上形成的。通过将条件和约束的描述转化为逻辑表达式,运用蕴含关系,描述方法的规格。运用于具体情况时,将条件转化为逻辑表达式的难度加大,描述能力不足。
##UML图案例分析
-
UML类图:https://images2018.cnblogs.com/blog/1346407/201806/1346407-20180625133725679-1772023560.png
-
UML时序图:https://images2018.cnblogs.com/blog/1346407/201806/1346407-20180625133758807-401882250.jpg
-
UML状态图:https://images2018.cnblogs.com/blog/1346407/201806/1346407-20180625133805915-1446813532.jpg
#总结
- 在本学期中,笔者对于面向对象程序设计进行了基础性学习以及大量的实践。根据知识点的聚合情况,大致分为以下几个方面:
- 对象化编程;
- 多线程程序设计;
- 抽象设计与程序规格;
- 程序测试与正确性论证。
————————分割线————————
- 对象化编程:
在学习编写面向对象程序之前,笔者主要编写的是面向过程程序(C程序)。在这一部分,笔者初次尝试进行面向对象编程:与面向过程程序相对比的同时,学习对象的基础知识、属性与方法,并进行了多项式、电梯调度系统和Als电梯调度系统(可稍带)三次练习。这一部分内容比较简单,但对与后期的学习起到基础性作用。对象化编程需要设计者对程序需要描述的数据进行对象化,根据其特性进行划分,并为之设计相关的方法。这一思想也是程序抽象设计的重要一部分。 - 多线程程序设计:
在这一部分,笔者对于多线程程序的理论基础、线程间协调、线程安全类等要点进行了学习。相较于上一单元,这一单元的难度有了较大的提高。主要是体现在多线程程序运行的不确定上。共享资源的保护、线程间协调以及调试难度较高等因素都增加了这一部分的难度。 多线程程序是将上一单元所学的单线程程序并行化。通过对程序中各部分功能进行分解,将能够并行的功能块并行以增加程序的效率~~(虽然增加不了多少)~~。由于多线程并行,就会存在线程之间的数据交互,即产生了数据共享。对于共享数据,不同的线程运行次序往往会导致不同的结果。于是便引入了锁机制以及线程安全类,通过限制共享对象的入口,来达到互斥的效果。 - 设计与规格:
面向对象设计思想是对象化设计思想的升华与提炼。其中的核心便是SOLID[^1]五项设计原则。在设计环节对于系统的交互关系、内部结构、数据组织等方面进行逐层抽象,在实现环节遵从面向对象设计原则才能编写出复用性、鲁棒性高的代码。
规格是对程序实现后功能的设计。在设计环节对程序内部进行数据抽象、过程抽象,分别归纳出类规格与方法规格。类规格通过不变式和抽象函数规定了对于数据的管理以及操作。方法规格从前置条件、后置条件、对象修改三个方面描述了方法实现后所能达到的功能。在设计环节使用规格,能够提高程序的质量,同时也为后期的测试以及正确性论证提供了依据。 - 程序测试与正确性论证:
在程序设计与实现后就需要进行检查。测试与正确性论证则是从两个角度对程序实现后的正确性进行检测。程序测试通过输入大量测试样例,试图观察程序在不同的环境下的运行情况,并将其与预期效果(规格)进行对比,从而达到检查的效果。正确性论证则是从设计规格出发,从类实现有效性、对象有效性、方法实现有效性三方面开展论证,从而得到程序实现正确的结论。对于实现的程序,这两个环节是程序在投入使用前必要的环节。
————————分割线————————
- 通过连续的11次编程实践,笔者设计与编写面向对象程序的能力得到了明显的提高。其中主要体现在以下几个方面:
- 面向对象程序设计能力提高:在面向对象程序设计的过程中,最重要的部分常是前期的设计环节。经过这几次的编程练习,笔者基本掌握了面向对象程序设计的要点与原则。通过需求分析、数据抽象、过程抽象、规格设计等设计流程,对于将要编写的程序进行全面的设计。这对于程序结构化以及鲁棒性有着巨大的作用。
- 初尝工程化程序设计:本学期的11次编程练习都有这严格时间期限。周末发布作业指导书,deadline设置在周三下午。无论作业的难度高低,都必须在限定的时间内完成。这在实际的工程程序设计中是司空见惯的。在这有限的时间内需要完成程序的设计、实现及测试整个流程,最后在时间期限前完成提交。此外,在本学期的练习中有两次系列练习(继承前一次作业),这就要求设计时注重工程设计原则,使用各种方法让程序有更好的可延展性,为之后可能遇到的新需求做准备。
- 学习相关的工具使用:在完成编程练习的过程中,笔者对于如git、jUnit、starUML、jprofiler等工具进行了一定学习。结合这些辅助工具,对程序设计、测试等都有着不错的效果。
————————分割线————————
经过了这学期的学习,笔者对于面向对象程序设计以及工程化程序设计有了比较深入的认识;通过大量的实践,编程能力也得到了不少的提升。一学期虽短,知识量却很大,笔者也将在以后用更多的时间与精力对面向对象程序设计以及工程化程序设计进行更加深入的学习与实践。 在本文的最后由衷地感谢本学期老师与助教们在课程中的辛勤付出。
来源:oschina
链接:https://my.oschina.net/u/4381341/blog/3927665