zoukankan      html  css  js  c++  java
  • 面向对象设计与构造2019 第二单元总结博客作业

    面向对象设计与构造2019 第二单元总结博客作业

    作业回顾

    • 2.1 单部傻瓜式调度电梯设计
    • 2.2 单部捎带式电梯设计
    • 2.3 多部智能型电梯设计

    一、三次作业的设计策略

    • 第一次作业只有正确性要求,没有性能要求,对于多线程的知识也没有过多涉及。所以我就无脑写了一个FAFS型,不含捎带的电梯。在正确性上有十分充足的保证,但是性能上很差劲,也没有什么可以说的策略。

    • 第二次作业加上了20分的性能分,但我并没有在性能上做出过多优化。我采用的策略是类似于磁盘扫描算法的LOOK算法,即模仿现实生活中电梯的算法。事实证明,这种调度策略在所有人的程序中并不算优秀。虽说我和其他部分人都是LOOK算法,但我在细节方面的实现非常粗糙,依然保留着上次作业的风格,并没有想尽可能多的去载人,而是尽可能让电梯路线不受牵制。这样,正确性虽好,但是性能分很低。

    • 第三次作业适当的扣除了性能分占比,让我们能更专注于正确性。我在写的时候,策略和第二次基本相同,所以正确性上没有很大问题。关于中转的问题上,我依然是选择牺牲性能来完善正确性。我将所有一部电梯无法送达的指令送到1层或15层(哪个近去哪),拆分成两条来处理。这样子正确性上有保证,但是效率依然不够。最后,我的性能分也并不理想。

    二、基于度量的分析

    1.时序图和类图

    • 时序图对于三次作业而言大同小异,多张图没有很大的参考价值,且占用空间。我在此放出第三次作业的时序图。可以看出,我采用的是生产者-消费者的模式,使用经典的生产者-消费者-容器三大类,对电梯运行进行有序处理。分发器采用notify的形式唤醒wait中的电梯,减少了CPU忙等待的时间。

    • 三次作业的类图也是大同小异,我在此一并放出。



    • 类图方面,可以看到类并不多,也没有建立过多类的必要。三次作业都以非常基本的设计模式构建。
    • 但是,就SOLID设计原则而言,我的程序做的并不够好。我的程序没有很高的复用性和广泛性,许多类的方法功能都写得比较死,是在面向对象的每个方法内尽情使用面向过程的思路进行编写。尤其是电梯的上下人开关门处理,一套过程性思路行云流水,却没有体现出对象之间的交互性。

    2.经典度量数据

    Type Name NOF NOPF NOM NOPM LOC WMC LCOM FANIN FANOUT
    Elevator 7 0 6 2 63 9 0 1 1
    Input 3 0 2 2 30 4 0 1 1
    Main 0 0 1 1 11 1 -1 0 3
    Switch 1 0 3 3 12 3 0 3 0
    Type Name NOF NOPF NOM NOPM LOC WMC LCOM FANIN FANOUT
    Elevator 11 0 16 2 223 57 0 2 2
    Main 1 0 2 1 44 6 0 1 3
    RequestList 3 0 5 5 25 6 0 2 0
    Type Name NOF NOPF NOM NOPM LOC WMC LCOM FANIN FANOUT
    Container 4 0 8 8 38 11 0.375 3 1
    Dispatcher 4 0 7 2 91 17 0 2 3
    Elevator 12 0 23 2 306 76 0 2 3
    Request 3 0 5 5 24 5 0 3 0
    TestMain 0 0 1 1 17 1 -1 0 3
    • 以上依次是我第一、第二、第三次作业的度量情况。可以看到,在代码行数(LOC)方面,电梯类Elevator一直是大头。三次作业中的电梯类代码行数占了总行数的50%以上,可以说将一切处理全部聚合在一个类中。这种设计并不算好的架构,但我本次作业又不知道如何去更好的拆分。
    • 第一次作业中,由于对生产者-消费者模型不熟悉,我甚至写了一个Switch类作为原子布尔型变量,作用是能够使得电梯线程停止工作。后面这种东西没有再出现。
    • 第三次作业中,程序的扇入扇出值较为合理,高扇入(FANIN),合理扇出(FANOUT),可以感觉到自己初步掌握了OO的设计诀窍。

    三、分析自己程序的bug

    • 三次作业中,我为了追求正确性从而牺牲了许多性能,后果是三次作业中我都没有被检测出bug。课下我使用自己的测评机进行大量数据反复测试,得到的结果也十分稳定。所以在这里,我没有很多可以分享的内容。
    • 助教曾经提到过,输出类TimeableOutput不是线程安全的。但是我在实际编写程序的时候,无论锁不锁输出,对结果都没有影响。虽然我锁了,但是我依然没有弄清楚不锁可能带来的问题。

    四、找别人bug的策略

    • 我坚信,越往后写,代码量越大,通过阅读他人代码的方式来找bug的行为会越发艰难。而且哪怕他人的代码有错,自己的思维也会非常容易被带入他人的错误写法中,从而导致一时间找不出错误。所以,我选择使用自动评测的方式,来寻找他人的bug。
    • 一台自动评测机器所需要的基本功能:
      • 随机数据生成功能
      • 编译运行、控制输入输出流的功能
      • 输出结果正确性判断功能
      • 判断结果可视化导出功能
    • 就这次的三次作业我自己写评测机的经验而言,难点在第二点,工程量大的重点在第三点。第二点是许多同学写出像样评测机的门槛,也就是定时输入的功能,给许多同学带来了困扰。这里我采用Python自带的subprocess模块来解决问题。此模块可以控制定时投放数据,也可以关闭输入流,非常方便。
    • 而输出结果的正确性判断,只是简单的逻辑问题。指导书中对于正确性判断说的十分清楚,我们只需要把助教的言语转化为代码就可以完成此功能,但是这个工程量未必比写一台电梯要小。所以大家可以量力而行。到第三次作业的时候我已经完全摸了,拿了第二次的程序改成三台电梯直接用了,没有实现特定楼层、超载判定等功能,有点可惜。

    五、三次作业的心得体会

    三次作业下来,我切实的体会到了OO思想和OO课程的特点。面向对象程序设计特有的设计模式,和多线程特有的设计模式,都超脱于之前学的所有知识,让我于困境之中发现了更多的惊喜。虽然电梯功能很简单,但是从其中学到的东西和面向对象的知识,远远超过之前的求导程序

    多线程的学习中,线程安全很重要。线程安全的设计要点,在此之前的程序设计中从来没有涉及。对于临界资源的操作要谨慎再谨慎,是多线程有风险而有魅力的点。另外,wait()和notify()的使用要比忙等待更加节省资源,也是多线程设计中非常智能的设计功能。

  • 相关阅读:
    跳出iframe
    leetcode 225. Implement Stack using Queues
    leetcode 206. Reverse Linked List
    leetcode 205. Isomorphic Strings
    leetcode 203. Remove Linked List Elements
    leetcode 198. House Robber
    leetcode 190. Reverse Bits
    leetcode leetcode 783. Minimum Distance Between BST Nodes
    leetcode 202. Happy Number
    leetcode 389. Find the Difference
  • 原文地址:https://www.cnblogs.com/sharinka0715/p/10753914.html
Copyright © 2011-2022 走看看