BUAA_OO_UNIT4 总结

OO_unit4 架构设计

文件结构

- src // 代码根目录
	- base	//	存放基类,所有的模型继承自此处
		- MyUml		//	uml模型基类
		- MyLink	//	链接关系的基类
	- classes	//	类图相关文件
		- MyClass
		- MyInterface
		- MyAttribute
		- MyParameter
		- MyOperation
		- MyAssociationEnd
	- collaboration	//	顺序图相关文件
		- MyCollaboration
		- MyInteraction
		- MyInteractionItem
		- MyMessage
	- main	//	主类包
		- Database	//	数据库模型
		- MainClass
		- MyImplementation
	- state	//	状态图相关文件
		- MyEvent
		- MyRegion
		- MyState
		- MyStateMachine
		- MyTransition

UML类图

classes

image

collaboration

image

state

image

架构总结

整体思路

其实整体思路很简单,就是根据题目需求,在原来模型的基础上,简化、去掉部分属性或方法,将其抽离出来,按照自己的方式,形成另一套模型,并加入自己的逻辑。

模型关联

每一个模型都继承自基类MyUml或者MyLinkMyUml定义了最基础的只读属性idnameparentIdvisibility以及获取他们的方法。MyLink定义了最基础的关联关系,由一个source的Uml对象指向另一个target对象,用于两个对象形成关联或者交互。

代码可读性维护

值得一提的是,在三次作业的逐次扩展、迭代开发中,代码量越来越大,单个文件代码行数也呈爆发式增长,为了不影响代码可读性(其实是checkStyle逼出来的),我将各个文件进行了分包处理,这样会使得整个文件层次更加清晰;同时,引入Database数据库模型,将数据存储与生成单独分离出来,并使之成为MyImplementation的一个属性,需要获取某个数据时,直接调用数据库的getter方法即可。

逐层封装

将某些通用的方法进行单独封装。比如,在MyImplementation层次,通过名称获取类的对象:

public MyClass getClassByName(String s)
            throws ClassNotFoundException, ClassDuplicatedException {
        HashMap<String, MyClass> classMap = database.getClassMap();
        MyClass myClass = null;
        for (MyClass classItem: classMap.values()) {
            if (classItem.getName().equals(s)) {
                if (myClass == null) {
                    myClass = classItem;
                }
                else {
                    throw new ClassDuplicatedException(s);
                }
            }
        }
        if (myClass == null) {
            throw new ClassNotFoundException(s);
        }
        return myClass;
    }

再比如,在MyClass的层次,通过方法名,获取该类的方法:

    public List<MyOperation> getOperationByName(String s)
            throws MethodWrongTypeException, MethodDuplicatedException {
        List<MyOperation> operations = new ArrayList<>();
        for (MyOperation myOperation: operationList) {
            if (myOperation.getName().equals(s)) {
                if (!checkOperationValid(myOperation)) {
                    throw new MethodWrongTypeException(getName(),s);
                }
                operations.add(myOperation);
            }
        }
        for (int i = 0; i < operations.size() - 1;i++) {
            MyOperation myOperation1 = operations.get(i);
            for (int j = i + 1; j < operations.size(); j++) {
                MyOperation myOperation2 = operations.get(j);
                if (checkOperationDuplicated(myOperation1,myOperation2)) {
                    throw new MethodDuplicatedException(getName(),s);
                }
            }
        }
        return operations;
    }

隐藏实现,暴露接口。比如实现getClassSubClassCount时,将需要的方法封装置于MyClass中,在获取了MyClass对象后直接从MyClass对象调用实现。

    @Override
    public int getClassSubClassCount(String s)
            throws ClassNotFoundException, ClassDuplicatedException {
        return getClassByName(s).getNumOfSubClass();
    }
    public int getNumOfSubClass() {
        return subClassCount;
    }

通过逐层封装,不仅能够减少单个文件、单个方法的代码量,使整个项目可读性提高,增加各个类的独立性,降低类之间的关联程度,符合“高内聚,低耦合”的设计理念。

OO课程学期总结

架构设计思维及OO方法理解的演进

因为大一从事过游戏项目的开发工作,对面向对象有一定的理解基础,因此在一开始接触OO课程的时候就有意去分析需求,抽象模型,打磨架构,在电梯单元的体现尤为明显:从一张架构设计图到整个项目的千行代码,程序开发本身就应该是先有图后有码的过程。如今,经过OO课程的训练,我对抽象与架构有了更深层次的认识,熟练度也有了质的飞跃。

对测试的理解与实践的演进

程序开发过程,很难保证不会出现bug,所以需要对程序进行全方位测试。
第一单元,嵌套括号的拆分是一个递归的过程,那么数据生成中又何尝不是呢。在此基础上,我进行数据的生成,而正确性校验采取标准答案对比的方式。
第二单元,数据生成时,将各个乘客需求进行时间先后的序列化,采用纯随机方式生成即可。正确性校验则采用分点校验,如乘客最终是否出电梯并到达目的地,电梯有无超载等。
第三单元,数据生成采用半随机方式,重点针对边界条件进行测试。正确性校验采用多人对拍的方式进行。
第四单元,未进行测试。

课程收获

知识层面,深入学习并实践了面向对象的编程思想,个人代码力也有很大的提高,从课程单元作业架构到评测机搭建,处处都在学习并实践着OO这一编程思想,对程序开发有了更深层次的体悟。
协同方面,增进了与他人合作开发的能力(开发评测机),提升了自己的团队协作能力,与他人协作开发一个工程的经历让我甚是感念,甚是激动,甚是自豪。

课程建议

  1. bug修复模块的限制过于严苛,改bug一次改5行以内的规则有时候会很恼人,让人无从下手。
  2. 增加课程趣味性、实际应用性。像第二单元这样充满实际应用感的作业就一个单元,其他单元感觉都是在与抽象的理论打交道,多少让人少了一点“码”的动力。
  3. OO指导书有些部分讲述不够清晰,模棱两可,容易产生误导,建议教学团队加强对OO指导书的规范工作。
posted @ 2022-06-28 23:59  不怕事学渣扛把子势力  阅读(30)  评论(0编辑  收藏  举报