结对编程
结对成员:马汉虎
结对编程的优点是效率高,结对编程也是一个相互督促,相互学习,相互磨合的过程。
结对编程的缺点是团队内部很容易起矛盾,还有就是要做到团队的合理分工合作很困难,两个人之间没有默契。
和我结对的马汉虎的优点是比较有礼貌,但是缺点是不负责任,基础差,经常找不到他人,对项目也不怎么关心。
Information Hiding:
信息隐藏是结构化设计与面向对象设计的基础。在结构化中函数的概念和面向对象的封装思想都来源于信息隐藏。
David Parnas在1972年最早提出信息隐藏的观点。他在其论文中指出:代码模块应该采用定义良好的接口来封装,这些模块的内部结构应该是程序员的私有财产,外部是不可见的。
关于信息隐藏的原则有:
• 多层设计中的层与层之间加入接口层。
• 所有类与类之间都通过接口类访问。
• 类的所有数据成员都是private,所有访问都是通过访问函数实现的。在面向对象的语言中,信息隐藏主要通过类的封装来实现。添加一些控制访问的权限,例如用private,public,protected等修饰类的属性和方法。
interface design:
接口设计能给程序提供一个好的框架。
• 用户接口
用来说明将向用户提供的命令和它们的语法结构,以及软件的回答信息。
• 外部接口
用来说明本系统同外界的所有接口的安排包括软件与硬件之间的接口、本系统与各支持软件之间的接口关系。
• 内部接口
用来说明本系统之内的各个系统元素之间的接口的安排
loose coupling:
类与类之间的互相调用,这两个类之间就会有比较高的耦合程度,降低类与类之间的耦合程度,可以通过接口实现。
关于契约式设计:
一个简单的契约设计,就是约束了某个方法调用的要求、以及返回的承诺。比如:
Code highlighting produced by Actipro CodeHighlighter (freeware)
{
public void Info(string message)
{
//do something here
}
}
如果我要调用Log.Info的方法,前提必须满足message非空。否则这个方法不能保证返回需要的结果。
那么根据经典的计算机原则:在正确的输入下,能够得到正确的输出。我只要保证了我所有调用方法的前提要求,我的代码就是 0 bug。这个就是契约设计。
以往我们会通过各种判断去检测输入,这种设计模式叫做:防范式设计(请看code complete 2,里面有详细介绍)。防范式设计的前提就是:我们会假设调用这个方法是恶意的,因此要对所有可能出错的输入进行检测。
在这种设计模式下,就会导致了各种与业务逻辑无关的代码充斥着我们的程序,维护困难,看起来也恶心。因此契约设计是非常反对的。
在我们的代码中,对于模块间使用了契约的思想,保证双方地位的平等。调用者的传入参数必须是正确的,否则责任不在被调用者,而在传入者。
然而契约式编程并未被标准化,因此项目之间的定义和修改各不一样,给代码造成很大混乱,这正是很少在实际中看到契约式编程应用的原因。
实际检测时,思路就是,查看当前方法体内所有使用了的方法是否存在了契约的约束,如果存在了但是没有被履行,那么就认为契约无效。
单元测试
单元测试的基本方法是调用被测代码的函数,输入函数的参数值,获取返回结果,然后与预期测试结果进行比较,如果相等则认为测试通过,否则认为测试不通过。
1、常用的Assert类的使用
Assert.Inconclusive() 表示一个未验证的测试;
Assert.AreEqual() 测试指定的值是否相等,如果相等,则测试通过;
AreSame() 用于验证指定的两个对象变量是指向相同的对象,否则认为是错误
AreNotSame() 用于验证指定的两个对象变量是指向不同的对象,否则认为是错误
Assert.IsTrue() 测试指定的条件是否为True,如果为True,则测试通过;
Assert.IsFalse() 测试指定的条件是否为False,如果为False,则测试通过;
Assert.IsNull() 测试指定的对象是否为空引用,如果为空,则测试通过;
Assert.IsNotNull() 测试指定的对象是否为非空,如果不为空,则测试通过;
例如:
Assert.AreEqual("3",c1.count("1 + 2"));
Assert.AreEqual("-1", c1.count("1 - 2"));
Assert.AreEqual("1'2/3", c1.count("1 + 2/3"));
有关问题:
图表上的From1类是我设计的用户界面,它的块数是最多的,但是实际怎样测试我不是很清楚,也不知道是否有必要进行测试。。。
UML
算法的实现
用户界面
算法由三个部分组成:生成器,比较器和计算器。
生成器用来生成指定条件的算法,比较器用来比较数据结果并输出到指定文件上,计算器用来计算表达式的值。最后由Core类通过一个API借口来和其他模块交流。