BUAA-OO-Unit4

武彬煦-21373267 学生 2023-06-20 19:35:12

第四单元博客

hw13

  正向建模与开发是指先利用建模工具进行需求分析设计,在依照设计编写代码、进行测试。整体看来像是先画图纸,再按照图纸去生成建筑物。其实之前几个单元,我也都是先构思,但仅限于在脑中构思,或者是用笔画一些草图。本单元我使用了StarUML工具进行建模,先后绘制了UML类图、状态图、顺序图。
  首先来看类图,下图是我在第十三次作业中绘制的。本次作业模拟了图书馆系统,我将其总体上分为了三部分。一是BookOwner,也就是能够储存书的人/物,这包含了借书的学生、存书的书架、扣留书的管理员或者机器等等。由于他们有一个共同的抽象行为,能够储存书,给出和收入书,因此我建立了一个父类BookOwner,其余各种Manager都是继承他的子类。然后为每一本书实例化一个对象,借书的时候就将这个对象在不同的类实例化出来的对象之间相互传递,从而达到模拟借书的效果。

img

  从上图也能大概看出,左侧是图书馆一方,右侧是学生一方,书通过中间四个管理者流动(走了类图中的曲线部分),因此他们之间会有关联关系。BookOwner通过下面两个方法进行书籍的放入和取出,同时维护三个ArrayList来储存不同种类的书。

public void putInBook(Book book) {
    ArrayList<Book> books = findType(book.getType());
    books.add(book);
}

public Book takeOutBook(String type, String serial) {
    ArrayList<Book> books = findType(type);
    for (int i = 0; i < books.size(); i++) {
        Book book = books.get(i);
        if (book.getSerial().compareTo(serial) == 0) {
            books.remove(book);
            return book;
        }
    }
    return null;
}

  因此借书的时候只需要从学生端发送请求,书籍从书架转移到借还管理员,如果不符合要求就扣留在此,反之借出给学生。这样就满足了hw13的基本要求。
  我在本次作业中是先画的UML类图后写的代码,总体感觉是我能够绘制出大概类图的样子,但是至于谁与谁之间是否一定有关联关系却不一定分得清,细化到每个类的方法个数、功能就更加困难。因此总体上我是依照类图写代码,但是也会有细节上的更改。

hw14 & 15

  由于第14次和第15次作业差异不大,主要是第十四次作业的迭代,因此我将后两次放在一起梳理。在这次迭代中主要是增加了图书借阅的逻辑,增加了校际借阅,而并没有增加管理员本身的功能。因此我的做法就是在之前的基础上多实例化了几个Controller和其对应的BookShelf以及*Manager,分别代表不同学校的图书管理系统。在借阅时增加Controller的处理逻辑,就可以完成要求的功能。最终第十五次作业类图如下

img

  整体差异与第十三次并不大,说明最开始设计的架构比较合理,能够顺利迭代。此外,本单元还在后续两次作业中首先绘制了状态转移图如下:

状态转移图

img

  代码与UML图的追踪关系,其中类图已经在hw13中详细介绍。对于状态转移图,我们可以结合类图来看。在我设计的状态中,能够存储书的只有书架和学生两个,还有一个状态是卡车(通过校际借阅在运输路上的书)。其意义也十分明显,书架代表着书被归还给了图书馆,或者从未借出。Studente则代表目前书籍被借给了学生,而如果学生调查了该书的状态却发现已有书目不符合再借阅条件,则会导致书的状态再书架上原地踏步。之所以没有设计各个管理员的状态是因为那样设计过于复杂,需要将A类B类C类书分类讨论放进不同的类别转换条件中,不利于展示总体状态转移的形态。此外,我也专门设立了一个类用以输出状态转移关系,使得状态转移图与方法对应的更加清晰:

public void shelfToTruck(LocalDate date, String type, String serial) {
        System.out.println("(State) [" + date + "] "  + type
                + "-" + serial + " transfers from bookShelf to truck");
    }

    public void truckToShelf(LocalDate date, String type, String serial) {
        System.out.println("(State) [" + date + "] " + type
                + "-" + serial + " transfers from truck to bookShelf");
    }

    public void shelfToStu(Book book, LocalDate date) {
        System.out.println("(State) [" + date + "] " + book.getType()
                + "-" + book.getSerial() + " transfers from bookShelf to student");
        System.out.println("(Sequence) [" + date +
                "] Student sends a message to StateTransfer");
    }

    public void stuToShelf(Book book, LocalDate date) {
        System.out.println("(State) [" + date + "] " + book.getType()
                + "-" + book.getSerial() + " transfers from student to bookShelf");
    }

    public void shelfToShelf(Book book, LocalDate date) {
        System.out.println("(State) [" + date + "] " + book.getType()
                + "-" + book.getSerial() + " transfers from bookShelf to bookShelf");
    }
顺序图

img

  接下来就是顺序图的绘制。这里因为评测原因,我也是单独建立了StateTransfer来输出消息传递信息(不过最后好像并没有对此进行评测)主体看来消息传递就是从学生发出结束请求,通过控制台Controller转发至图书馆,分别对应了代码中的dealBorrowBookqueryBook。这之后进行相应回复,这包括拒绝和同意两种情况。分别对应了图中5和7的的shelfToShelf(拒绝),和shelfToStu(同意)的借书结果。

  通过本单元正向建模开发,我感觉到了UML图带来的清晰感,通过一个类图、状态图或是顺序图就能够理解代码的主题逻辑。但是自己先写UML图再写代码却显得有些别扭,总是要在两头来回调整更改保持其一致性,这也是我需要进一步提升的地方。

课程总结

  至此,本学期OO课程也告一段落了,下面进行学期总结,通过四个单元学习过程中我再架构设计思维、测试思维两方面主要谈谈我的体会。

Unit1

  第一单元是迎头痛击的一个单元,在未掌握java语法的情况下需要在一周内学会递归下降法来解析表达式。这无疑是非常困难的,但是经过不断尝试,我也对此留下了深刻的印象。通过表达式与因子的行为抽象,(表达式) ≈ 因子我们用一个parser的三方法循环解析了一个复杂嵌套的表达式,每一级只需要考虑其输入与输出,不再需要管别的。例如parserExper只需要识别加减号,然后调用parserTerm即可,不再需要考虑多余的事情,这就是递归下降最核心的思想。
  后面的拆括号工作,我使用了MonoPoly类来处理,我们要做的事把一个表达式转化为Poly再去输出即可,同样用递归下降法去思考这件事,一个Exper变成Poly需要将其中的Term变成Poly后加起来,一个Term变成Poly需要将其中的Factor变成Poly后乘起来。同样是递归下降,同样是行为抽象,而这是我在第一单元学到的最深刻的思想。

Unit2

  第二单元多线程编程,架构设计同样比较重要。我在第一单元经历过重构后,格外小心的设计了本单元的架构。这个电梯调度程序采用了一个多线程的架构,通过一个详细的类图设计来进行模块划分。我们把任务拆成了几个部分,包括一个储存请求的Queue类、用于请求输入和储存等待请求的InputHandler类、负责请求分发的Schedule类、一个处理电梯运行和捎带请求的ElevatorRun类和Elevator类、管理电梯状态和乘客信息的Operation类、以及提供现实策略的Strategy类。这些模块各自独立,通过三级流水线的框架相互协作,完成电梯调度的功能。整体代码的可读性更高,且易于扩展和维护,大大提高了系统的可靠性。因此我也在两次迭代过程中较为轻松且高质量的完成了本单元的任务。
  在测试方面,由于第一单元的时候我都没时间写完代码,所以测试极少。第二单元多线程测试,主要使用了讨论区的多线程评测机,以及自己少量数据的构造,并不算十分强的数据。这也导致我在后两次迭代中出现了两个比较低级的错误,并不是难de的死锁或者轮询。这很明显是可以通过增加测试来避免的。

Unit3

  第三单元是JML语言,在这里我们不需要设计架构,因此这里以程序测试为主。在第三单元我第一次自己写了评测机,大量生成数据来测试对拍,效果非常好。我主要进行的是单元测试和黑盒测试,即写完一个对应的方法就测试其功能,以及最后完成代码后测试整体程序的正确性进行测试。数据生成方面比较有讲究,我在随机生成的过程中,控制好personId的范围,就能够间接控制图的密度和复杂度,从而能够高强度测试程序的正确性。
  本单元还引入了OK测试,这是用于检测代码是否符合给定规格要求的测试方法。我们通过编写测试用例来执行OK测试,验证代码在各种情况下是否符合预期。在OK测试中,使用JML编写规格,多个ensures语句与OKTest返回值对应。这是一种很严谨的测试方法,但是保证我的OKtest正确也很复杂,尤其是在hw14中的20多种错误返回值的情况下,稍有不慎便会导致OK测试出现问题。
  总体来讲,本单元我的进步主要在于自己评测水平的增大和了解了更多测试的方法和技巧。

Unit4

  最后一个单元就在刚刚已经写过我的架构。测试方面,由于借阅流程的复杂度很高,常常出现不合法的数据,因此本单元测试以手造为主。通常我使用的方法是写完一个借阅逻辑就对其进行测试,类似于单元测试的思想,以防后患。
  整个学期看下来,我在编程方面变化巨大。架构方面,我的设计架构早已不再是大一时的见到题目就动手写代码,而是会先去考虑以后可能会有什么新需求等着我迭代,从而实现更好的架构。此外,每次代码风格的调整,也让我有了很好的缩进、命名习惯。在程序测试方面,我也搭建了属于自己的评测机,不再依靠多次提交系统评测来无脑debug,而是学会用更少的次数去AC。
  总体来讲,OO课带给我的知识是无比丰富的,经历也是坎坷的。每周一次迭代的强度确实很高,但我也从中获得了不少的成就感。虽然hw14作业迭代任务量的不合理也曾遭到了同学们的吐槽和反馈,但是我能看到的时助教团队和老师对此积极的调节和付出。另外,我感觉最后课程组设置的颁奖环节也非常暖心,为各个方面努力并且有突出表现的同学都给予了鼓励,这让我们有更多动力去继续前进。最后,希望本课程能够吸取往日不足,
在未来不断进步。

...全文
80 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

444

社区成员

发帖
与我相关
我的任务
社区描述
2023年北京航空航天大学《面向对象设计与构造》课程博客
java 高校 北京·海淀区
社区管理员
  • 被Taylor淹没的一条鱼
  • 0逝者如斯夫0
  • Mr.Lin30
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧