结对项目内容:http://www.cnblogs.com/jiel/p/4830912.html
结对成员:康家华1190,马腾跃1184(http://www.cnblogs.com/summerMTY)
关于结对编程
“在结对编程模式下,一对程序员肩并肩地、平等地、互补地进行开发工作。两个程序员并排坐在一台电脑前,面对同一个显示器,使用同一个键盘,同一个鼠标一起工作。他们一起分析,一起设计,一起写测试用例,一起编码,一起单元测试,一起集成测试,一起写文档等。”——《构建之法》
通过阅读教科书和网络上的参考资料,我总结了以下结对编程的优点和缺点。
结对编程的优点
结对编程的缺点
我的结对伙伴
我很幸运的是能够和同班同学组成结对,这样一来,两人合作的“萌芽阶段”和“磨合阶段”都可以省掉了。
我初次看完我的partner的代码后,我的内心是欣慰的,因为我们两个人在个人项目上的设计想法几乎是一致的,个人编程习惯和风格也十分相似,这就意味着我们在进行结对编程的时候能够很快地在编码规范上达成一致。同时,个人作业的设计相似也为我们在之后的结对项目中可能会有着更好的默契。
任务开始进行到现在,他一直表现得很积极,我们分配的任务他都会按时按点、保质保量地完成,和他合作真的不用担心在deadline之前完不成任务。他写的代码结构非常清晰,该有的注释一个都不少,在结对编程和团队编程中这点是十分宝贵的,因为清晰明了让人一看就懂的代码可以给团队省去很多不必要的时间。而且他还十分的谦虚,他不像那些在编程上有过一些经验就对别人指手画脚、说三道四的“老手”。不管你说的是对是错,他都耐心地听进去,之后再发表自己的意见和看法。跟他在一起编程,让人感觉很轻松,所以那些和他组团的同学们一定要让她在团队中发光发热!
当然没有人是十全十美的,若要在他的身上找些缺点,那我可能要在编程上面找了。他的代码虽然说结构清晰容易理解,但是有一点不足,那就是对于代码的优化方面还需努力。像数据结构上,能用简单的数据结构完成数据的存储是最好的;在一些库函数的巧妙运用要比自己再多写一个函数好更方便;代码上的简化等等。不过这都不是大问题,等经验多了,自然而然的就会养成这些习惯了。
一些设计原则和方法
信息隐藏(Information Hiding)原则
信息隐藏是结构化设计与面向对象设计的基础。在结构化中函数的概念和面向对象的封装思想都来源于信息隐藏。David Parnas在1972年最早提出信息隐藏的观点。他在其论文中指出:代码模块应该采用定义良好的接口来封装,这些模块的内部结构应该是程序员的私有财产,外部是不可见的。信息隐藏原则可以用于一下应用:多层设计中的层与层之间加入接口层;所有类与类之间都通过接口类访问;类的所有数据成员都是private,所有访问都是通过访问函数实现的,这样做确保了数据的安全性。(经过参考书籍和资料整理)
接口设计(Interface Design)
“接口”这个词泛指实体把自己提供给外界的一种抽象化物(可以为另一实体),用以由内部操作分离出外部沟通方法,使其能被修改内部而不影响外界其他实体与其交互的方式。人类与电脑等信息机器或人类与程序之间的接口称为用户界面。电脑等信息机器硬件组件间的接口叫硬件接口。电脑等信息机器软件组件间的接口叫软件接口。
对于这个Interface Design,我分成用户界面和软件接口两部分。
软件接口
计算机不同功能层之间的通信规则。搜索资料,找到以下接口设计原则:
(Source: http://www.cnblogs.com/zfc2201/p/3423370.html)
界面设计
经过查询资料,我找到了如下界面设计原则:
(Source: http://bokardo.com/principles-of-user-interface-design/)
对于我个人的理解,如果要实现界面设计,首先,要注重第一感觉,也就意味着我们设计的界面要在用户第一眼的时候就知道它的功能和使用方法;其次,实现人机交互,界面的设计要求各有所需,不允许残缺也更不允许冗余,不能让用户在使用的时候感到迷惑;然后,规划界面,包括布局、背景、字体等等,要想用户的喜好上靠拢;最后,检查整体性,没有设计缺陷。
松耦合(Loose Coupling)
一个软件是由多个子程序组装而成,而一个程序由多个模块(方法)构成。 而内聚就是指程序内的各个模块之间的关系紧密程度,耦合就是各个外部程度(子程序)之间的关系紧密程度。耦合是对某个元素与其他元素之间来凝结、感知、和依赖的度量,这里说的元素可以是功能、对象(类),也可以指系统、子系统、模块。它取决于每个模块之间的接口的复杂程度,调用模块的方式——即有哪些信息通过接口。
具体来说耦合就是:元素B是元素A的属性,或者元素A引用了元素B的实例(这包括元素A调用的某个方法,其参数中包含元素B);元素A调用了元素B的方法;元素A直接或间接成为元素B的子类;元素A是接口B的实现。
如何降低耦合:
(Source: http://jiadongkai-sina-com.iteye.com/blog/749439)
Design By Contract
契约式设计(Design By Contract)把类和它的客户程序之间的关系看作正式的协议,描述双方的权利和义务。Bertrand Meyer把它称作构建面向对象软件系统方法的核心。
契约式设计的提出,主要基于软件可靠性方面的考虑。可靠性包括正确性和健壮性,正确性指软件按照需求规格执行的能力,健壮性指软件对需求规格中未声明状况的处理能力。健壮性主要与异常处理机制相关 。正确性一方面包括对象元素内部运行的正确性,另一个重要方面是与其它对象元素交互时的正确性。
契约式设计其它的一些好处:
这就让我想起了上学期面向对象课程中的规格,包括“Required”“Modified”“Effect”,这种契约式的设计和JAVA中的规格如出一辙,均是面向对象过程中使用的可以保证可靠性的设计方法。
那么如何使用实现契约式设计呢?利用.NET Code Contracts实现运行时验证。.NET的Contract类库是Declarative Programming实践的一部分,可以对日常编程带来很多好处:
Contract类本身已经在.NET 4.0之后集成进了System.Diagnostics.Contracts命名空间,但如果想使用Contract方法实现运行时的验证,还需要单独安装一个VS插件(http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx)。具体的使用方法可以参考http://www.cnblogs.com/polymorphism/p/Using_Runtime_Contract_Checking_In_DotNet_Project.html
(Reference: http://www.cnblogs.com/RicCC/archive/2007/11/28/Design-By-Contract-DBC.html)
设计思想
从构造数据结构来存表达式开始,我们通过递归的方式来储存表达式,比如说(((-5) + (-49)) ÷ (-15)) ÷ 10这个表达式,如果把这个表达式看作是父表达式,那么他就有((-5) + (-49)) ÷ (-15)和10这两个子表达式,再接下去,((-5) + (-49)) ÷ (-15)就有(-5) + (-49)和(-15)这两个子表达式……于是就构成了一个树状的结构,这样一来就有利于存储了。所以我们设计了一个Expression的类来存储表达式。
表达式当中有很多中数字形式,包括整数,分数,带分数还有负数形式,那么如何存储这些数字呢?我们找到这些数字的共同之处,就是它们都能化成分数,所以我们设计了一个Number类,专门用来存储数组,它当中有三个属性:a, b, c(分别表示整数部分、分母和分子),这样一来就方便多了。
按照结对作业的要求,我们设计了三个功能:
我们将核心功能封装到Core类里,相对应的我们设计了四个接口:
Calculate(),输入的表达式string进行格式判断,错误则抛出异常。生成Expression,再调用Expression的Calculate函数计算。
Produce(),使用Setting()来设置参数,然后进行生成
Judge(),使用Produce()生成的文件格式的文件来进行答案检测,输入的精度x,允许待测答案和标准答案有[0, x]之间的误差。
Setting(),进行Produce()的参数设置,如果有参数错误的情况,则抛出异常。
总的来说,我觉得我们在数据存储和计算上面比较有特点。在进行查重的工作中我们将表达式按照规则化成字符串,然后和其他的表达式进行比较,如果相同那么就跳过,所以这部分我觉得也挺值得一提的。
使用VS的Unit Test
使用Unit Test来测试Core的接口
覆盖率如下,由于About、Helper和MainFrame是Windows窗体类,在测试的时候没有进行调用,所以未覆盖。Test类是用来启动程序的主类,也未被覆盖。
Core是核心,它的覆盖率是98.74%,Expression类和Number类的覆盖率也达到了99.70%和98.09%,可见我们的测试程序几乎覆盖了整个核心代码区域。
UML图
由于没有找到VS中代码生成UML类图的方法,所以通过使用VS中显示类图的方法生成一个UML图,再通过新建一个UML关系图,进行类的关系连接又生成一个。
结对编程进行中