话不多说!先上图!!!!看看我和小伙伴认真学习的照片(你懂得
左:13061212赖彦谕 右:13061203徐丞
首先按照要求分析一下自己的优缺点!
赖彦谕:
优点:服从安排合作 愿意提出想法 敢于接受任务
缺点:拖延症晚期 手癌晚期 代码能力并不是很强大
徐丞:
优点:编程能力还可以,对C++掌握比较好;细致认真,查到好多bug;逻辑严密
缺点:面向过程的编程思想比较严重,函数体一般比较长,而且有大量的if-else逻辑判断
1.结对编程的优点和缺点:
优点:
(1)从结对编程的这一个词语的分析来看就知道,结对编程比较考验大家的配合,合作能力。有一定的机会锻炼大家的团队协作能力
(2)提高了个人学习能力,因为有机会向对方学习编程的一些技巧。
(3)有助于编程过程中的注意力集中,因为结对编程可以在一定程度上督促对方进行程序的阅读和理解。
缺点:
(1)性格差异,导致合作会有些问题
(2)有时候难分工作量的大小,因为都不好意思推脱任务。
2.说明怎样利用好这些设计:
Information hiding:顾名思义,信息隐藏就是将我们的数据进行封装,以保证一定的安全性,也就是说外部不能够对我们内部的数据进行修改,以此完成数据的封装。在数据隐藏的过程中,我们也为外部提供了接口,让外部可以直接使用这个提供的接口,然后达到不改变内部数据就能够使用的目的。这就好比之前我们所学过的面向对象编程,在面向对象的编程的过程中,数据的封装,安全性都是一个很重要的地方,在类间的调用中,我们需要保证外部不会修改我们内部的数据造成我们的数据不安全,所以通过数据隐藏的这样的方法,来确保类各自的安全性并且也保证了方便调用的可能。
Interface design:借口在编程时,一般都是定义了一种行为,对于这种行为,需要类去实现这个借口,然后我们就可以使用这个统一的标准,这在很大程度上减轻了代码的复杂度,因为我们使用时不需要考虑具体的实现。
Loose coupling:首先我们在编写代码的时候应当让每个模块都少些依赖性,因为这符合松耦合的原则,我们在松耦合的原则看到,要求的是供应者与用户之间其中一个发生了问题时都应该不影响到另一方,并且在相关模块进行修改的时候,不会影响到其他模块的正常运行,然后通过提供API来供外部调用,利用接口的实现调用,降低各个模块的依赖性。
3.Design by Contract&&Code Contract
契约式编程的构成是前置条件与后置条件还有不变式组成的,契约可以在代码实现前建立好,并且保证之后的代码时符合条件的。
优势:在一定程度上保证了代码的可靠性,因为我们所契约的操作都是一致的,前后的状态以及不变时都能够帮助我们清楚我们程序在调用什么后会出现什么样的结果。也提高了代码的依赖性、复用性和替换性,也让程序的结构变得更加清晰。
劣势:契约的构成中,如果有遗漏,没有遵守契约的情况,会带来更多的工作量和任务。
Formula,StuCaluator还有Operand都是我们这次编程设计的三个类,并且我们也实现了借口,是在StuCalulator的类中提供的。就是提到封装后,通过接口的调用就无需担心内部的数据被改变,更好的封装了内部的变量和实现细节,并且通过这样的设计方法,我们实现了calc和Generate还有check三个接口。
4.单元测试
我们的程序有三个类Formula,Operand,StuCalculator,我们对每个类都有测试文件进行测试,一共使用了90个单元测试用力。
在我们的测试中也发现了许多BUG,然后按照老师的要求,我们也给出了我们的代码覆盖率-95.23%,在我们分析的过程中发现我们没有达到100%的主要原因就是我们生成表达式的时候采用的是随机算法,并且种子不唯一,在生成的过程中,随机数会有不一样的分支进入,我们没法控制这一点,所以导致最后的覆盖不能全满。下面我们也给出了我们的代码覆盖率的截图。
5.UML图
6.算法说明:
1.生成表达式算法的整体思路:首先对操作数进行随机生成,对运算符进行随机生成,最后将生成的操作数和运算符拼到一起形成一个前缀表达式,再转换为中缀表达式输出。之所以先生成前缀表达式,是因为要检测生成的表达式是否满足需求,需要进行一步步计算,这里因为我们直接生成了前缀表达式,所以可以直接进行计算。对于去重的检测,我们放弃了检测这一思路,我们的想法是生成的表达式绝不会出现交换重复的情况。为实现这一点,当发现生成的表达式中有‘+’或‘*’时,我们会对操作数做一次排序,就是说是操作数符合有序性,因为交换重复会打破有序性,这样我们保证操作数一定是有序的那么就不会有重复。(这里有一点例外,就是生成的操作数有相同的,所以我们再加一条限制,就是操作数排完序后不允许出现连续三个数相等的情况),操作数有序的做法不能避免产生一模一样的表达式,所以采用哈希值来记录生成的表达式,若出现重复的哈希值则说明生成了一模一样的表达式,则重新生成。
2.对于不同参数组合的支持:这里我们确立了一条规定:允许有负数,就一定允许有括号;不允许有括号,就一定不允许有负数。因为负数输出时都是加括号输出的,所以我们的逻辑导致必须有这条规定。由于我们是随机产生操作数,对于不同的参数就在随机生成的时候根据不同的条件随机生成即可。对于不允许有括号的情况,只要规定随机产生的运算符有序就不需要括号了。
3.对中缀表达式的计算算法:这个没什么创新点,就是两个栈,通过弹栈压栈实现运算即可。