301
社区成员
发帖
与我相关
我的任务
分享正向建模与开发通常指的是一种软件开发方法或过程,主要关注从需求分析开始,逐步构建和开发软件系统的过程。本单元涉及到的UML和U3中的JML作用相似,都是为了给之后的开发提供了一种规范,让项目的结构更清晰、代码更具有可读性。在我看来正向建模开发与逆向开发最大的区别就是正向建模开发注从总体到局部,而逆向开发的关注点主要集中于局部。
从本单元来看,正向建模与开发可以主要分成以下3个步骤:1.根据需求进行UML建模(类图、状态图和顺序图) -> 2.根据UML建模编写代码 -> 3.对程序进行测试和调试。但在实际的执行过程中我并没有严格遵守上述三个步骤的顺序,尤其是步骤1和2。对于这种单人设计、开发的项目来说,我们很难在一开始就确定一些细节,比如类属性的个数,方法的个数、返回值等。因此笔者在实际的开发过程中先确定类的个数、类需要包含哪些信息以及不同类的对象之间需要进行怎样的交互。在编写代码的过程中再对一些细节进行完善。不过对于一些需要多人协调、协作的大项目来说,严格遵守正向建模与开发的规则可能会是一个不错的选择。


本单元作业中,笔者通过MainClass进行输入处理并调用实例化的Library类对象的方法来实现图书馆中的各种操作。其中几个关键的位置BookCollection、AppointmentOffice、DriftingCorner和BorrowReturnOffice都被抽象为Library类的属性来辅助图书馆的运转。
BookCollection类是书架。提供了取书、还书的功能,同时还具备整理时将借还处以及预约处的图书整理至书架的功能。
AppointmentOffice类是借还处。包含了已经成功(取到目标书)的预约以及未成功(还没有取到目标书)的预约。提供了接受预约、查询预约的功能,同时还具备整理时将书架上的书整理至借还处的功能。
DriftingCorner类是图书漂流角。包含了漂流图书、捐赠图书所对应的捐赠人以及漂流图书被借阅的次数。提供了还书、取书、查询书籍借阅次数、查询剩余书籍、查询捐赠人的功能,同时还具备整理时将借还处书籍整理至图书漂流角的功能。
Appointment类是预约,被预约处中的容器统一管理。包含了预约书的ID、预约人的名字以及该预约的截止日期。提供了设置截止日期、查询截止日期、查询图书ID以及查询预约人名字的功能。
Record类是借书记录,可以理解为来借书的用户,由Library中的容器统一管理。包含了该用户所拥有的所有图书以及该用户的信用分。提供了查询是否拥有某书、取书、还书、查询信用分以及更新信用分的功能。
最终的代码设计和UML模型设计之间的追踪关系:
对于类图,保证代码与类图属性、方法以及类之间的关系相对应。
对于状态图,表示调用不同方法后图书状态的变化(图书的位置代表其状态),通过@Trigger来检查状态图中导致状态转移方法的功能是否与代码中一致。
对于顺序图,描述图书系统中多个对象之间的交互顺序,通过时间线从上到下展示消息传递的顺序。交互所涉及到的对象方法要与代码中对应。
第一单元的设计思维是层次化设计,为我们展示如何恰当使用接口进行层次化设计。
所涉及到的“递归下降”算法就是所谓层次化设计的一个具体实现。层次化设计可以通过将系统分解为更小、更易管理的模块或层次,使代码结构更加清晰并简化了复杂系统的管理和维护。
第二单元是多线程编程,这是笔者第一次接触多线程。
这个单元使用了生产者-消费者模式来实现电梯接客的功能,其核心是线程通信与线程安全。通过进行上锁来解决线程间的同步互斥问题同时还要保证不会发生死锁的情况。本单元还涉及到怎样合理地开启和结束线程、电梯的调度算法、怎样提高电梯的性能以及SOLID原则。
第三单元是规格化编程,学习了契约式编程的思想。
JML使代码需要实现的功能变得非常明确、严谨,编写的过程也不需要加入很多自己的思考。虽然要遵守契约,但编程的过程也要灵活一些,这便涉及到了规格与实现分离。规格可以告诉我们怎样写能够满足正确性,但对性能和实现方式都没有限制。这使得开发者可以在满足要求的基础上去优化其性能,测试者只需根据规格编写测试程序检验实现是否正确。
第四单元是正向建模设计。
之前几个单元中,在编写代码之前多少会在纸上画一画所要实现层次结构的草图来从整体上确认设计方向。而这次作业则是直接让同学们体验从整体到局部的正向设计过程,同时还会对UML图与代码的一致性进行检测。
总的来说,四个单元间的设计逻辑是从了解面向对象的设计方法到合理利用一些工具来辅助我们设计架构。
第一和第四单元主要是使用黑箱测试。
规模较小的数据很难发现代码中潜藏的问题,因此需要通过随机生成规模较大的数据来检验程序的行为是否正确。当然这里的“随机”也是要加入一些的特定限制来增强数据的强度。
第二单元在黑箱测试的基础上还采用手动构造极端数据的方法(主要应对互测)。
由于同学们的调度算法不同,可以通过手动构造极端数据的方法来测住一些有着明显缺陷的调度算法。
第三单元不仅要检测程序正确性,还要保证在极端情况下程序运行不超时以及程序的实现符合JML的要求。
这个单元再次用到了Junit,其主要作用是检测程序的实现是否复合JML的要求。由于本地与评测机运行时间差距过大,很难通过黑箱测试发现问题,故性能是本单元的最大难点。因此我们也可以利用Junit构造一些极端数据来进行压力测试(Junit可以反馈程序的运行时间)。
每周一次的开发迭代增强了我的编程能力,并且学会了很多新知识。
通过反复实践,逐渐养成了面向对象的思维方式,能够更自然地将现实世界的对象和关系在代码中进行抽象和使用。
学会了如何合理地对代码进行封装,使得模块各司其职,代码层次结构更加清晰。
学习了多种常用的设计模式,如生产者-消费者模式、单例模式、工厂模式、观察者模式等。理解了这些设计模式的适用场景和实现方法,能够在项目中识别并应用适当的设计模式,提高代码的可复用性和可维护性。理解了SOLID设计原则。
周而复始调试代码和debug的过程固然艰辛,但通过自己的努力收获满意的分数是一件很有成就感的事情
感谢OO课程组老师助教们的辛苦付出与陪伴 :)