301
社区成员
发帖
与我相关
我的任务
分享正向建模是一种用于描述和分析系统或过程的建模方法。它从系统的需求和功能出发,明确系统中各个模块及其相互关系,进行系统的设计和实现。
在本单元涉及的 UML 图中,与代码架构最贴近的是 UML 类图,大致使用流程如下:首先,对系统进行需求分析,识别出系统中的关键模块,作为 UML 类画入类图,并初步为每个类定义属性和方法,确定类之间的继承、关联等关系,最后根据 UML 类图编写代码,并对 UML 类图中的细节进行完善修正。而 UML 状态图和时序图则展现了对象在系统运行时的状态变化和行为逻辑,以及各个类之间如何相互协作共同完成对一件任务的处理,这些逻辑很难在代码层面直观展现,但却可以在 UML 状态图和时序图中简洁清晰地表示出来。



本单元架构基本按照书的状态进行设计,为书可能存在的每个位置建一个类。
在编写过程中,感觉较为困难的部分是如何协调多个类共同完成一件任务,即确定任务完成的各个步骤、各个步骤分别应该放到哪个类中进行处理以及处理时消息传递的流程。如用户借阅流程中,检查书籍是否有余本在架和是否为 A 类书籍显然放到 Bookshelf 类中处理最合适,而检查是否符合借阅数量限制则放在 User 类中,并且由 BorrowAndReturnOffice 类向 User 类传递消息进行借阅数量限制的检查。编写时想到的另一种可行的方法是由 Main 类依次向 Bookshelf 类、User 类传递消息,检查书籍是否可借阅,但这样设计还需要 Main 类在不符合借阅数量限制的情况下向 BorrowAndReturnOffice 类传递一次消息,不如前文设计的消息传递流程简洁。
对于图中唯一多设计出的 WareHouse 类,本意是想将其作为 Bookshelf 类和 BookDriftCorner 类的接口,这样在一些流程(比如 query, borrow, return)中,无需繁琐地判断消息接收的类应该是 Bookshelf 类还是 BookDriftCorner 类。但写了一部分后发现由于除了 User 类之外所有类的属性和方法均设计为了静态属性和方法,难以支持接口和继承,故只好将 WareHouse 类改装为类似 Controller 的消息分发类,根据书的类别号判断应该将消息传递到哪个类中。本人认为,使用单例模式而不是将所有属性方法定义为静态应该可以避免这种问题的出现 ,但是写都写了,懒得改了。
在第一单元中,我主要沿用了 OOpre 的知识,通过面向对象的编程思想进行各个类的构建,完成了表达式解析与化简这项复杂而庞大的任务。在仅用“类”这一个概念就顺利完成复杂项目的过程中,我逐渐领悟到面向对象编程思维在大型工程领域的重要意义。
在第二单元中,我首次接触了多线程设计,花费了大量时间在死锁、线程退出条件等问题上踩坑,并逐渐认识到了多线程编程中的一些关键点,如 Distributer 类的设计和及时释放不需要的锁的设计原则。另外,在这次作业中,我进一步掌握了面向对象编程的各种方法,开始在编程中熟练使用接口、继承等特性,弥补了第一次作业的不足。
在第三单元中,我首次领悟到 JML 这类形式化语言在实际生活中的作用。这次作业中涉及自行涉及架构的部分较少,仅在必要时添加辅助类即可。
在第四单元中,我首次接触了使用 UML 进行正向建模的设计方法。在架构设计上,有了先前的经验,我在潜意识中开始更多考虑架构设计的合理性,而不是仅追求功能上的实现,使迭代时几乎无需改动先前原有的方法,增量开发即可。
在四个单元中,我基本都尝试了手动构造极端数据和评测机大规模数据测试两种测试方法。手动构造数据主要观察程序在极端情况下的稳定性和性能,如第三单元中测试程序在全是时间复杂度较高的指令时是否超时,这是评测机的随机生成所做不到的;而评测机随机生成的数据可以弥补手动构造数据时考虑不周产生的漏洞,与手动测试相辅相成。在第三单元中,我还特别学习了如何根据 JML 的约束条件构造样例以及检查结果的正确性,收获颇丰。
回顾整个课程,我认为收获最多的部分来自第二单元的多线程内容,其中很大一部分原因来自我之前并未深入接触过多线程编程,即使曾经在程序中创建过多个线程,也只是各个线程各司其职,做着相对独立的工作,而在多线程中,各个线程间的数据共享和协作其实才是要点所在。其次是第三单元的 JML 规格和第四单元的 UML 建模,这两个单元的内容虽然不会直接影响架构设计与代码编写,但都是面向对象设计过程中的强有力工具。前者可以让我们精准无误地理解他人编写的方法,而后者可以使我们自己的设计思路直观形象地表示出来。最后就是对上学期 OOpre 知识的强化与拓展。无论如何,本学期的 OO 经历都将转化为过硬的知识储备和编程素养,成为今后人生中一笔宝贵的财富。