面嚮對象程序設計第四單元博客作業——終極Boss

2019面向对象程序设计第四次博客

  终于写到了最后一次博客作业,心里有点五味杂陈的感觉。在进入正文之前写一段前言。

  面向对象是当今程式设计的非常重要的思想之一(我感觉应该更严谨一点,针对软件程式设计),也是主流的设计思想。面向对象在不熟悉的人眼里显得非常抽象,解释了许多也常常“丈二和尚——摸不着头脑”。经过一番思考,我个人认为面向对象对于程序设计的指导,如同哲学对于生活和科学的指导,它是方法论一样的高层的东西,而绝非拿来直接能够上手的简单操作。因此唯有多实践,才能将方法论转换为指导操作的具体实现。

  我了解过一点其他学院/学校的面向对象这门课。举我校另一个专业为例,他们的课程放在大一下学期,相比思想上的训练,更多侧重语言的应用;以某道口高等技工学校的课程为参考,他们的课程设置在大一的暑期学期,更多像一门对于以前学期知识的实践练习,掌握更多实际操作(当然他们的学生都很强,或许不需要很强的训练自己也能悟出来许多);建墙的学生学习这门课程的时候,主要的精力是画出各种UML图,在理论层面上着重训练,期中期末也就考这些个;再举一个国外的例子,多伦多大学——他们没有这门课,电子与计算机工程系。孰优孰劣,我不做评论。

 

一、两次作业的结构设计总结

  如同第三单元的作业,本次作业也采取了首先存储数据并构建数据关系之后对数据进行查询的考察方式。不过必须说,这次没有数据的随意变动,确实是福音之一。

  作业的重点应该是设计合理的层次架构并提供实现。在数据存储方面,由于数据之间有高度的相关性,必须设计好相应的数据存储容器。数据容器当中的数据结构,或者说某些类的实现对象,应该具备良好的对外接口提供查询并设置必要的缓存以保留修改信息,采取“以空间换时间”的方法,为查询缩短时间;数据容器类应当采用可以快速定位的容器如HashMap,但是必须承担的风险是它的遍历效率很低,如果可能的话可以设置一个配套的存储数组,遍历速度很快。

  举MyUMLClass为例,它保存了如接口实现、操作、属性和继承的内容。visMap用以缓存各个Visibility,实现一次查询,全部记录的功能,再次查询就能节省时间。

1     private ArrayList<UmlInterfaceRealization> interfaces; // realized interface
2     private ArrayList<MyUmlOperation> operation;
3     private HashMap<String, MyUmlOperation> diffOperation; // may be same names
4     private HashMap<OperationQueryType, Integer> typeOp; // different operation
5     private HashMap<String, UmlAttribute> attributes; // Id to Attributes
6     private HashMap<String, ArrayList<String>> attributeNum; //naToId attribute
7     private HashMap<String, HashMap<Visibility, Integer>> visMap;
8     private ArrayList<UmlGeneralization> generalizations;
9     private HashSet<String> realization; // generation and realization

 

 

 

1     private HashMap<String, ArrayList<String>> classNameToId; // name to Id
2     private HashMap<String, MyUmlClass> idToClass; // Id is the unique symbol
3     private HashMap<String, ArrayList<String>> interfaceToId; // name to Id
4     private HashMap<String, MyUmlInterface> idToInterface;
5     private HashMap<String, UmlAssociationEnd> associationsEnd;
6     private HashMap<String, UmlElement> allElements;
7     private ArrayList<UmlAssociation> associations;

  MyUMLClass的容器,保存了Class的信息(从id到class,从name到id)、Interface的信息和Association相关的内容。由于Association的挂靠处不定(既可以挂在classA,也可以挂在classB),因而采用在MyUMLClass外存储的方法。

  在方法的实现上,高层实现更加抽象的方法,处理一些外围事件,将核心处理交由底层实现,但是必须为底层提供良好的实现环境。这样体现出了层次化的设计,也使得设计更加清晰(如同计算机网络将网络划分成为了5/7个层级,目的是为了缩小每一个层级的任务,使得从而方便研究)。

1     public Map<Visibility, Integer> getClassOperationVisibility(
2             String className, String operationName)
3             throws ClassNotFoundException, ClassDuplicatedException {
4         classError(className);
5         String s = classNameToId.get(className).get(0);
6         return idToClass.get(s).getOpVisibility(operationName);
7     }
View Code

  第二次的作业的实现相比起第一次作业,在查询工作上工作量轻松不少,但是结构层次与第一次作业查询UMLClass的形式类似。在正确性的检查上,尽量用一些下层类的自身的容易实现的方法的特性,从而减轻上层的工作,使得层次清晰。

 

二、四个单元OO设计的架构演变和方法理解

  面向对象的重要思想:抽象和封装。越高层次抽象越高,数据和操作全部封装在类当中由其管理。

  如同人类任何科学的发展历程一样,面向对象也会经历由具体到抽象、由特殊到一般的发展过程。最开始实现任务的时候,很容易陷入到细节当中不能自拔,有时是捺下葫芦又起了瓢。在程式设计的过程当中,功能实现的内容和逻辑是更加重要的。如同计算机基础学科的关系一般:计算机体系结构——>计算机组成——>计算机实现,是从功能设计到逻辑设计再到物理实现;在工程化程度愈加升高的今天,如果最开始仍是考虑如何从最底层的物理上实现一台新的计算机,恐怕大概率是要失败的。OO涉及到时候,也应当先对功能进行划分,任何一个方法都应当有其实现的内容和意义所在,从高层的抽象的方法,逐渐往下细分各个类和方法应当实现的内容。

  第一单元的作业可以说非常“面向过程”了。如同人类的发展是有阶段性的,程序思维的转变也是有阶段性的。最开始设计的各个类,基本是按照流程执行顺序的。比如处理输入一个类,该类的对象实现完功能之后将数据传递给求导的类。如此种种,便可以看出最开始真的很面向过程,尽管使用了各种类,新建了不少对象,但是颇有“身在曹营心在汉”的感觉。然后这种“顽疾”几乎持续了一整个单元,第三次作业由于形势所迫,做出了一些调整。毕竟开始尝试,没有什么一蹴而就的方法。

  第二单元在实现起来相比较上个单元有所进步,也是采用了一些课上所讲的设计方法,把整个任务划分给了输入处理、调度和执行机构模块分别处理。由于多线程的存在性,使得程序无法再面向过程(无法预测什么时候会有输入需要处理),不可能采用类似程序查询的方式来检查是否有输入出现,否则将极大消耗CPU性能。然而,这单元存在的问题是功能划分不足够明确,更多是实现了任务就好的感觉,一部分代码的执行显得不明所以。

  第三单元由于必须要承接接口,因此相当于课程组在帮助我们建立良好的结构,从更高的角度看待方法的实现,采用结构化的手段迫使你不得不重新考虑自己的设计。不过不得不说,实现了好久,结果再CPU执行时间上卡了很多问题。容器的使用还是需要加强。本次作业封装性得到了一定的加强。

  第四单元的实现层次更高。平心而论,一上来看到这回作业顿时就想吐槽:什么玩意?完全看不懂!不过当我看了讨论区大佬们的精彩解说之后,还是一头雾水。只好和同学一起讨论,方才明白了作业的任务目标。然而不得不说,本次作业确实帮助实现层次化和抽象化比较好,就有非常明确和清晰的层次关系和实现逻辑。在明确每个层次的功能上,对于设计实现的目标更加清晰。数据封装很有意思。印象之前的作业会有很多对外提供内部数据的方法,在后续的升级当中,每个单元对外提供获取内部数据的方法在减少,换言之,类对自己的保护性更强,数据管理能力也更强。

  算是接触到了一点面向对象的皮毛了。不过如果想学好,还是要更多的投入后续的时间才行。要是单单只靠学校一门课就能完成所有培训,如果不是天方夜谭,就是这个东西实在是太简单了。

 

三、测试理解和实践演进

  作为初级的学生,必须要自己构造设计测试集。当然最开始的测试还是仅限于想到哪里测到哪里,没有一套方法论一样的东西支持。

  不得不说,我的测试不算很好,因为只是基于自己对于测试样例的理解,尽可能全方面地构造测试集。因而前两单元会有少量的自己未发现的bug。第三单元的时间複雜度真的很想吐槽,真的不知道使用什么样的方法比较好。第四单元的测试主要依靠弱侧和中测发现自己的问题(如果说找个理由,只想说烤漆好忙啊,不想学新的东西了)。

  在实践过程中,确实也能发现自己的代码的设计和实现能力在增强。这不是一个很量化的东西,不是很好测评。

 

四、课程收获

  课程最大的收获是:没有收获(开个玩笑)。如同张三丰传授张无忌技法的时候,等到张无忌全部忘记之后才让他上场挑战对手,则说明他掌握的不仅仅是武功的外在形式,更多的是其内涵击败对手的哲理。因此我在这里想传递的是:OO课带来的收获更大的层面不是基础的软件设计的知识和技巧,而是一种思维方法。而这种思维方法不光是应用在日后的软件设计当中,还可以用以指导生活领域和学习(不说太夸张,不可能全部用上,但是指不定在什么时候就能派上用场)。举例而言OS,现在OS功能非常全面,也很复杂,但是最基本的功能之一,是它对多线程的支持。尽管是人仿照人类世界的方式设计的操作系统,但是它确实可以反过来指导人的做事方式。任务排队,根据紧急性、重要性分类,分给时间片,现场保护和切换,还需要处理突发中断;我们的学习工作和生活中也有各种各样的任务,也会出现突发状况,如何响应便需要“操作系统——计划”来调度了。当然了,OS不会没事找事,也不会感到疲倦和烦躁;于是这些又要依靠人类自己克服了(其实挑战自我获得提升,不正是人存在的价值之一吗?)。说回我们的OO,以对象为例,每个人都是一个对象,一个小组就是这些对象的容器。小组有需要实现的任务目标,于是有方法把目标分为不同阶段和方向,将要实现的事情交给个人/对象;个人要做的事情就是其所管理的数据,其处理事情的行为就是数据处理的方法;最后还需要交互。简单来说就是这样:

 1 public class Group {
 2     private  List<Person> members;
 3     
 4     issueTask(Task task) {
 5         parttask = taskPartition(task);
 6         membersResult = members.deal(partTask);
 7         mergeResult(membersResult);
 8     }
 9 }
10 
11 public class Person {
12     private dataType data;
13 
14     Result deal(PartTask partTask) {
15     }
16 }

  除去思想之外,还有OO带来的抗压能力和自学能力。由于时间紧(好像高工大三不太该说这话),任务量大,又和分数直接挂钩,再加上北航这么一所大家都热爱学习学校所拥有的良好学风(没错,我是真心的),自然而然就被加压。不过如果大家去翻翻培养方案,会发现上面写着培养的学生具有面对现代社会的抗压能力。这种能力也不是说有就有天生俱来不可改变的,需要经过后天和训练。OO,就很好地、勇敢而一往无前地承担起了这一光荣而伟大的使命,冒着被同学们各种喷的风险,毅然决然地给同学们不断加压,终于成就了一代北航计算机人生命中难以挥去的一段记忆和后来者的传说(好吧我不说了)。此外,因为课上讲的东西比较抽象,真正想把课程内容转为代码还是需要自己动手实践,学习很多东西。不过好处在于,一些东西学了一遍就掌握了;即使长时间不用忘记了用法,至少知道有这些东西的存在,重学一遍很快。这些抽象的能力,看不见摸不着无法量化考察,不过确实真真实实存在于此。正所谓,“天将降大任于斯人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行拂乱其所为,所以动心忍性,增益其所不能”(好吧我真的不说了)。

  通过OO课还是能学到很多的,伴随着个人的成长。

  其实在这里要特别感谢老师们和助教团队,在给我们加压的同时其实也是再给自己加压,设计实验难度适中,又要符合课程内容,还要评测给分。在最后一次OO课程博客这里道一声:您各位辛苦了。

 

五、对课程的几点具体建议

  1. 老话说得好,万事开头难(然后中间难,然后最后难)。一般每个单元开始的作业都会有一些不知所措,有时还要面临新的工具。因此希望以后的课程当中对每个单元的第一次作业特别加一点帮助,纵使修行在个人,也还是需要师傅领进门。比如给一个往届好的代码架构参考(不是说给全部代码,给出代码中一些比较重要的信息,比如方法名和实现功能描述等即可,帮助大家快速理解,也好入个门)。

  2. 降低强测占比和提升中测难度。强测占的比重偏大,容易导致分数两极分化严重,建议从本版限定的75%下降到55%-65%,提升一定的中测占比,会让学生稍微轻松一点。其实有时强测丢分,自己没测出来是一部分,还有一部分原因是中测强度略显不足。电梯的例子很明显,中测的强度真的和弱侧没什么区别,跟强测之间的差距有些大。

  3. 实验课教学不足。有时确实有不清楚实验课要做什么的感觉,建议课上可以多做一点讲解。

转载于:https://www.cnblogs.com/runnan-shen/p/11067399.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值