面向对象设计与构造:OO课程总结

第一部分:UML单元架构设计

第一次作业


UML图

  • MyUmlInteraction类实现接口方法,ClassUnitInterfaceUnit管理UML图中的类和数据单元
  • MyUmlInteraction类整合UML类图中的所有数据元素,并用Map建立相应的Id到UmlElement的映射
  • ClassUnit除了记录自身的属性,关联和实现接口外,采用All-XXX的形式记录来自父类的上述元素继承自身的上述元素
  • InterfaceUnit分别记录了自身继承的父类接口继承的所有父类接口

递归回溯

需要查询和记录父类的信息时,采用了递归回溯的思想,下面以getAllAttribute方法为例

    //MyUmlInteraction.javaprivate Set<String> getAllAttribute(String classId) {ClassUnit target = getClassUnitById(classId);if (target.getId().equals(target.getFather())) {return target.getAttributes();}if (target.getAllAttributes() == null) {ClassUnit father = getClassUnitById(target.getFather());target.setAllAttributes(getAllAttribute(father.getId()));}return target.getAllAttributes();}//ClassUnit.javaprivate Set<String> attributes = new HashSet<>();private Set<String> allAttributes = null;...public void setAllAttributes(Set<String> attributes) {allAttributes = new HashSet<>();allAttributes.addAll(attributes);allAttributes.addAll(this.attributes);}public Set<String> getAllAttributes() {return allAttributes;}
  • 该方法完成的功能:返回Id为classId的类所包含的所有属性
  • 第一个if语句判断此时classId对应的类是否为顶层类(在ClassUnit中fatherClass的Id全部初始化为自身的Id)
  • 如果该类不是顶层类,需要找到所有父类包含的所有属性。allAttributes如果为null表示查询该类所有属性的操作还未进行,需要递归查找父类的所有属性,并添加进allAttributes数据结构中;allAttributes不为null说明已经记录好了该类所有属性,直接返回数据结构即可

第二次作业


架构与代码实现

说实话我感觉第二次作业工程量巨大,为了保证扩展性,要维护大量的数据结构

有向图图查询

  • addEdge:有向图加边,传入的两个String为类或接口的Id,nodeMap建立Id到node编号映射

        public void addEdge(String fromId, String toId) {if (!nodeMap.containsKey(fromId)) {nodeMap.put(fromId, nodeCount++);}if (!nodeMap.containsKey(toId)) {nodeMap.put(toId, nodeCount++);}map[nodeMap.get(fromId)][nodeMap.get(toId)] = 1;}
  • floyed:图更新算法

  • getReachableNodeCount:寻找该结点后续可达结点

        public int getReachableNodeCount(String id) {if (!nodeMap.containsKey(id)) { return 0; //未加入有向图中说明id对应的类或接口无继承或被继承关系}if (!finished) {  //finish为graph的全局变量,因为图建立好以后只需跑一次floyed算法floyed();finished = true;}int nodeId = nodeMap.get(id);if (reachableCount[nodeId] != maxValue) { //如果已经统计过一次直接返回结果return reachableCount[nodeId];}int answer = 0;for (int i = 0; i < nodeCount; i++) {if (map[nodeId][i] != maxValue) { //map[i][j]均初始化为maxValueanswer++;}}reachableCount[nodeId] = answer;return answer;}
  • isCircle:是否存在自身到自身的循环。这里主要看map[id][id]是否为maxValue,如果不是则存在自环

时序图和状态图

  • 记录数据结构,提供查询接口即可
  • 状态图中的getSubsequentStateCount方法实现采用了有向图查询类
类图

  • 保留第一次作业实现的功能

  • 重复继承的检查

        public void checkForUml009() throws UmlRule009Exception {Set<UmlClassOrInterface> answer = new HashSet<>();//检查类是否重复实现接口for (String i : classList.keySet()) {ArrayList<String> temp1 = getAllImplementedInterfaces(i);Set<String> temp2 = new HashSet<>(temp1);if (temp1.size() != temp2.size()) {answer.add(classList.get(i));//类实现的所有接口列表中存在重复元素}}//检查接口是否重复继承接口for (String i : interfaceList.keySet()) {ArrayList<String> temp1 = getAllInterfaceFathers(i);Set<String> temp2 = new HashSet<>(temp1);if (temp1.size() != temp2.size()) {answer.add(interfaceList.get(i));//接口继承的所有接口列表中存在重复元素}}if (answer.size() != 0) {throw new UmlRule009Exception(answer);}}
    • 主要的思路是使用Arraylist和Set去查重,getAll-XXX方法均返回Arraylist<String>
  • 循环继承的检查采用有向图的自环检查即可

第二部分:课程收获

本来觉得,这十五次作业我只是在一味地设计与编码,并没有将某次架构深入极致或收获颇丰。但回过头来想想,我发现这更像是一种体验,好像自己的设计能力是比无头苍蝇好一点了,代码也敲得快了,各种工具也会用了,JML和UML也会写会画了。虽然不知道影响多大,但也算熬过了本次巅峰体验

架构


  • 表达式求导,规格和UML单元在我看来,更多的是在做数据结构的事情:如何封装数据,如何解析数据,如何设计查询和修改的接口。所以对于实际问题,我的思路逐渐成型:

    • 明确需要管理和维护的数据,封装成类并提供相应查询和修改接口
    • 根据对数据的操作是否具有共性,确定在类内部实现还是抽象为操作类(如UML作业中的循环继承和后继状态实际上可抽象为有向图的解析,而对于寻找类所有属性实际上为数据内容的集合,在类中实现即可)
  • 电梯单元在我看来,更多的是在维护线程安全,因此我的做法是:

    • 画流程图(非常重要,甚至涉及架构的正确性)

      • 流程图实质上是状态图,所以要求状态的完备性,确保所有的输入对应到的所有后继状态
      • 在流程图找到可能会起冲突的临界区,用矩形框圈起来标识
      • 分析冲突区域,找到起冲突的数据单元,隔离相应的增删查改操作

  • 划分数据单元,将线程相关与数据相关进行隔离(通俗地说,维护数据的类就不要有run方法)

关于OO方法理解的进演


什么,oo方法?肝!

重提SOLID原则

  • SRP(单一责任原则):避免类的功能重合和一个类做太多事

    • 什么是类的功能重合?调度器类在根据当前状态分配任务,电梯类自身调度任务干什么?
    • 一个有效代码超过300行的类,实则是类的层次划分不够明晰,该抽象抽象,该写包写包(譬如UML单元作业,ClassUnit单元可以写在MyUmlInteraction类里面,但没有必要)
  • OCP(开放封闭原则):对扩展开放,对修改封闭
    • 上一次的架构要考虑扩展性,已经写好的代码没有特殊需求就不要改变(譬如UML第一次作业getAllAttributes方法返回类型为Set<String>,第二次作业改为ArrayList<String>才实现了重复继承的检查。这个例子实际上说明了一个问题:应保留原始数据,在具体的对外查询接口内再处理
    • 基于扩展中的继承问题,直接在类里添加代码实现新功能创建子类实现新功能视功能的复杂度而定
  • LSP(里氏替换原则):所有引用基类的地方必须能透明地使用其子类的对象
    • 子类可以扩展父类的功能,但不能改变父类原有的功能。我们用继承不就是用父类中的重复代码吗?
    • 子类在替换掉父类后必须不能影响到原程序的运行状态。这里就涉及到多态的问题了
  • ISP(接口分离原则):避免接口的责任重合和一个接口做太多事情

    • 接口分离的难点在于对方法的抽象,遗憾的是我们的作业大多是根据官方接口去实现程序
  • DIP(依赖倒置原则):模块之间尽可能依赖于抽象实现

    • 简而言之,多采用基于抽象类的代码设计模式,其实我们的作业设计也差不多采用这种模式
    • 本学期课程我很少用设计模式去进行架构,看来需要更多的实践才行啊 ~

测试


愿以后的工作没有互测,不做社畜,少受社会的毒打,不用霸王洗发水

生成测试数据

  • 从功能说明入手。例如JML单元,查询最短路构造自环等情况
  • 从架构细节入手。主要是检查架构的完备性,以及架构各部分的逻辑正确性

测试实践


  • IDEA源代码打包jar→测试数据in.txt→输出结果out.txt→脚本对拍(fc对比文件差异)
  • jprofiler:查看CPU占用,线程生命周期,堆栈使用情况。分析程序的性能

  • JML检查工具系列:针对规格化程序设计的规格语言测试,生成测试样例

  • Junit:单元测试,针对某一方法进行单独测试

第三部分:课程建议

一,精简理论课内容,从架构难点深入讲解

  • 理论课的PPT实在是缺少场景例子,尤其涉及架构的理论知识冗余,各种名词晦涩难懂
  • 一遇到具体如何架构的地方感觉就会浅尝则止,庞大的代码工作量无法预留更多时间进行架构上的探索
  • 理论课的内容完全可以收录许多精品贴(比如对各种UMLElement元素的解析)

二,实验上机后放出实验内容,给出标程

  • 实验上机的内容实属良品,尤其是画UML图等很考察我们在短时间内进行初步架构设计的能力
  • 不放标程,不让我们回头寻思一番,实验分数没有意义

三,指导书需要更加明确,对有争议的地方及时更新

  • 重点在刚刚结束的第十四次作业,指导书的质量在逐渐下滑(就事论事)
  • 这里说的及时更新应该是在周六晚前解决大部分疑问,重点是不影响架构设计的进程

四,建立良好的测试数据库机制(下届)

  • 测试数据库的准入前提应是你为数据库的贡献可量化,测试数据的抓取应做到随机与限量
  • 建议单独开设如何构造覆盖性更优的测试数据讨论专栏

转载于:https://www.cnblogs.com/Red-Revolution/p/11070777.html

面向对象设计与构造:oo课程总结相关推荐

  1. 【面向对象设计与构造】第一次博客作业

    [面向对象设计与构造]第一次博客作业 一.程序结构分析 1. 第一次作业 类图 由于第一次作业难度较低,实现起来也不需要很复杂的算法,因此在编写程序的时候只建立了两个类,Main类主要负责多项式的读入 ...

  2. 面向对象设计与构造第一次总结作业

    第一次作业--多项式计算 ---结构分析 第一次作业我只使用了两个类,正像下面的类图所表示的那样,分别是Poly和ComputePoly.Poly类是不可变的,能保存一个多项式,可以进行加.减运算.C ...

  3. iOS 开发之 OOA (面向对象分析) OOD (面向对象设计) OOP (面向对象编程)

    OOA OOA 基本概念 OOA 全称 Object-Oriented Analysis 面向对象分析 指的是在一个系统的开发过程中进行了系统业务调查以后,按照面向对象的思想来分析问题.OOA 与结构 ...

  4. 【设计模式系列】之OO面向对象设计七大原则

    1  概述 本章叙述面向向对象设计的七大原则,七大原则分为:单一职责原则.开闭原则.里氏替换原则.依赖倒置原则.接口隔离原则.合成/聚合复用原则.迪米特法则. 2  七大OO面向对象设计 2.1 单一 ...

  5. 面向对象程序设计(Java)课程设计——五子棋小游戏

    目录 一.团队成员及任务 二.项目简介 三.功能设计图 四.运行结果截图 五.核心源码 六.课程设计感想与展望 一.团队成员及任务 队长:管俊杰  计科(智能)22-1 202203200037 负责 ...

  6. 面向对象程序设计(Java) 课程设计——三少五子棋(Final)

    背景:设计五子棋游戏背景, 初步猜想: ① 设计一个五子棋小游戏,实现人机对战和双人对战两功能. ② 设计五子棋小游戏,使用Java Swing设计可视化操作界面,并使用GraPhic 2D技术设计图 ...

  7. 面向对象简称 OO(Object Oriented),20 世纪 80 年代以后,有了面向对象分析(OOA)、 面向对象设计(OOD)

    面向对象简称 OO(Object Oriented),20 世纪 80 年代以后,有了面向对象分析(OOA). 面向对象设计(OOD).面向对象程序设计(OOP)等新的系统开发方式模型的研究. 对象的 ...

  8. 面向对象设计原则OO

    面向对象设计原则是OOPS(Object-Oriented Programming System,面向对象的程序设计系统)编程的核心,但大多数Java程序员追逐像Singleton.Decorator ...

  9. 【OO学习】OO第四单元作业总结及OO课程总结

    [OO学习]OO第四单元作业总结及OO课程总结 第四单元作业架构设计 第十三次作业 第十四次作业 总结 这两次作业架构思路上是一样的. 通过将需要使用的UmlElement,封装成Element的子类 ...

最新文章

  1. 架构设计之分布式文件系统
  2. python二叉树深度 判断平衡树
  3. How To: Team Build 自定义版本号
  4. 通用前端监控采集脚本
  5. MySQL 常用账户管理及授权操作
  6. LeetCode题库第888题 公平的糖果棒交换
  7. SAP CRM IPC and configuration page debugs
  8. 平台系统表怎么修改为普通表
  9. telnet发送socket报文_简单讲解一下Socket网络编程
  10. git clone出错
  11. 手把手教你一个321MB的视频,如何压缩到300MB以内?
  12. 死亡时间推断MATLAB,AGU 本周精选文章:火星陨石坑;气候敏感性;水资源压力;洪水灾害建模...
  13. ES9,ES10,ES11知识点
  14. 8K播放网络全终端播放器H5播放器网页直播/点播播放器EasyPlayer和vlc播放RTSP流地址不兼容问题排查解决
  15. java 反编译软件
  16. sony android mp3播放器,入手一年,详细聊聊 索尼ZX505、艾利和SR15 两款安卓播放器的使用体验...
  17. html隐藏链接跳转,HTML 链接
  18. Android镂空字体,TextvView实现镂空字体效果
  19. ssh 无密登录(两行命令即可)
  20. Linux常用基本命令之二

热门文章

  1. android键盘多线程bug,按键精灵多线程运用,检测卡死线程,短信api调用,通知功能...
  2. 测试linux mongodb数据库开启,安装配置MongoDB数据库
  3. SpringBoot使用netty
  4. WebSocket使用sendObject(Object arg0)向页面方法发送对象
  5. 数据库中复合主键与联合主键
  6. springboot 文件上传 设置文件大小配置
  7. Android开发笔记(二十七)对象序列化
  8. eclipse配置tomcat运行时访问路径不要项目名称
  9. Xcode9 2 编译在iOS8 1 系统上图片显示异常
  10. 谈谈分布式事务之一:SOA需要怎样的事务控制方式