数字电路模拟程序 4~6 作业集阶段性总结

前言
我围绕数字电路模拟程序完成作业集 4、作业集 5、作业集 6 三个递进式开发任务,三次作业难度逐步抬升,从基础封装实体建模,过渡到抽象类、继承多态实现基础逻辑门,最终拓展接口、集合排序、多类型元件迭代开发组合电路,完整走完一套工程化迭代开发流程,每一次迭代都对上一版代码进行扩展,逐步理解面向对象设计在大型项目中的作用
三次作业为分层递进设计:
1、作业集 4:基础封装训练,完成引脚、基础门电路实体类封装,练习构造方法、访问修饰符、方法重载;
2、作业集 5:数字电路模拟程序 1,实现与、或、非、异或、同或 5 种基础逻辑门,依托抽象父类统一封装公共属性,使用多态实现统一运算调度;
3、作业集 6:数字电路模拟程序 2,在版本 1 代码无大幅修改的前提下扩展新增三态门、译码器、数据选择器、数据分配器四类组合元件,新增控制引脚、多输出引脚、差异化输出规则,自定义集合排序规则,完成复杂级联电路迭代求值逻辑。
为客观量化三次作业代码质量,我使用 SourceMonitor 工具导出每版代码度量报表,同时通过 PowerDesigner 绘制各阶段 UML 类图,结合报表数据、类图结构、测试用例运行结果完成本次源码分析、踩坑复盘与优化思考。通过三次完整迭代,我理清了抽象类、继承、接口、集合容器的落地场景,也梳理了开发过程中暴露的编码短板,为后续时序电路、子电路迭代开发打下基础。

设计与分析
第4次作业:
题目要求:实现引脚、基础逻辑门实体类,完成数据封装,提供 getter/setter、构造方法、方法重载,完成简单输入输出测试。
题量:6 道基础小题 + 1 道实体建模大题
难度:基础
核心训练目标:建立封装思维,区分成员变量与局部变量,禁止全局变量,规范实体类代码结构。
整体实现方式
我一共分了 5 个类来写,每个类只负责自己的功能,完全遵守单一职责原则。
1、Pin 类
存储引脚名称、引脚电平信号,只提供私有成员的 get/set 获取数据的方法,不做运算逻辑。
2、BaseGate 基础门类
存储元件名称、输入引脚总数,仅封装拼接引脚标识的通用方法,不实现电路运算。
3、AndGate 与门类
仅实现与门的信号校验、逻辑运算,只处理与门专属判断逻辑。
4、OrGate 或门类
仅实现或门的信号校验、逻辑运算,只处理或门专属判断逻辑。
5、Main 类
程序入口,处理控制台输入、实例化各类实体、调用运算方法、输出结果,所有流程调度都在这里完成
代码规模
227c19700038cc8c791fecd9ec8dc989
类图
9db2bde3d14499a25445cd8b8b571eb6
Bug 分析
公测
自己测试的时候,发现没有抽象父类,重复代码导致修改同步遗漏。
AndGate、OrGate 两类各自独立编写引脚读取、信号校验逻辑,修改引脚拼接规则元件名-引脚号时,仅修改与门类,忘记同步或门类,输入测试样例后,或门全部读取不到引脚信号,无输出结果。
原因是两类重复实现相同底层逻辑,无公共父类统一管理,一处修改需要同步全部同类文件,极易出现遗漏。
解决办法:新建 BaseGate 基础父类,将引脚拼接、信号读取、引脚遍历校验等公共逻辑全部移入父类,子类仅继承并保留专属运算判断,后续修改公共规则仅改动父类一处即可。
互测
和同学互相测试时,发现构造方法未做参数校验,传入负数引脚号程序直接崩溃。
手动输入引脚编号 - 1 时,Pin 类构造方法直接赋值负数,后续循环遍历引脚触发数组下标越界异常,程序终止运行。
原因是实体封装时没有对入参做合法性校验,未限制引脚编号范围为正整数。
解决办法:在 Pin、BaseGate 构造方法内增加判断,若引脚编号小于等于 0,直接抛出提示或默认重置为合法引脚值,拦截非法参数。
测试方法
本次作业采用手动黑盒测试,自行设计多组基础输入样例,同时和室友互换代码互测,重点检查实体封装、输入边界、类方法调用逻辑,提前暴露重复代码、参数校验缺失等问题。

第5次作业:
题目要求:解析电路输入文本,存储全局引脚信号池,实现 5 种基础逻辑门运算,循环迭代计算级联电路电平,按指定顺序排序并输出有效元件。
题量:4 道小题 + 综合大题 7-1 数字电路模拟 1
难度:中等偏难
核心训练目标:掌握抽象类、继承、方法重写、运行时多态,使用 List、Map 集合管理元件与信号,自定义 Comparator 实现多条件排序。
整体实现方式
我一共分了 8 个类来写,每个类只负责自己的功能,完全遵守单一职责原则。
1、Able 接口类
统一约束所有电路元件的对外规范,定义getOutputPin()获取输出引脚、calc()运算电平两个抽象方法,不包含任何业务实现。
2、Base 抽象父类
存储元件类型、元件编号、完整元件名、输入引脚总数,封装全局静态信号池 signalMap、全部 getter 读取方法,声明抽象 calc () 方法强制子类重写运算逻辑,所有公共逻辑统一放在这里。
3、Yu 与门类
继承 Base 抽象类,仅重写 calc () 实现与门逻辑,只处理多输入全 1 才输出 1 的判断,不做其他公共操作。
4、Huo 或门类
继承 Base 抽象类,仅重写 calc () 实现或门逻辑,只处理存在 1 就输出 1 的判断,不做其他公共操作。
5、Fei 非门类
继承 Base 抽象类,仅重写 calc () 实现非门逻辑,单输入取反运算。
6、Yi 异或门类
继承 Base 抽象类,仅重写 calc () 实现异或逻辑,两输入不一致输出 1。
7、Tong 同或门类
继承 Base 抽象类,仅重写 calc () 实现同或逻辑,两输入一致输出 1。
8、Main 主类
程序入口,处理全部文本输入解析、元件实例化、循环迭代求值、自定义排序、结果打印,统一调度所有元件对象,是整个程序的流程调度中心。
代码规模
51e730c4ec2d27d01e092b322b37ce1a
类图
26fb8b92d0001045f7f28411815ac52c
bug分析
公测
自己测试的时候,发现单次遍历求值无法处理多级级联电路,后级元件丢失输出。
测试三级级联样例 4(与门→非门→或门)时,单次遍历会先读取非门、或门,此时前级与门输出还未计算存入信号池,非门 calc () 直接返回无效值 - 1 被过滤,最终只打印与门输出,缺失两行结果。
原因是电路存在信号前后依赖关系,线性单次遍历无法完成全部电平推导,前级输出未生成就访问后级元件。
解决办法:引入 do-while 循环搭配 update 标记,一轮遍历产生新电平信号则再次遍历集合,直到一轮无新增信号,保证后级电路能读取前一级运算结果。
互测
和同学互相测试时,发现自定义比较器排序优先级颠倒,元件输出顺序不符合题目规范。
最初编写 Comparator 时先比较元件编号,再判断元件类型,同类型 A (2) 2、A (2) 1 顺序颠倒;同时类型排序字符串写错为 AOXYN,非门输出位置错误。
原因是多条件排序未区分判断优先级,手写固定顺序字符串时字符排列失误。
解决办法:调整比较逻辑,优先对比元件类型下标,类型相同时再对比编号;固定常量字符串 "AONXY" 锁定输出先后顺序。
测试方法
本次作业采用分层黑盒测试,单独测试每个门电路运算逻辑,再搭建多级级联电路完整测试,和同学互测核对输出顺序、级联计算结果,校验输入缺失元件过滤逻辑。

第6次作业:
题目要求:兼容版本 1 全部输入规则,新增 9 类电路元件,新增控制引脚、多输出引脚、差异化输出格式,过滤高阻、输入缺失等无效元件输出。
题量:3 道小题 + 综合大题 7-1 数字电路模拟 2
难度:困难
核心训练目标:理解软件开闭原则,在原有代码基础上扩展功能,适配多态差异化返回值,完善边界校验逻辑。
整体实现方式
我在作业集 5 原有 8 个类基础上新增 4 个扩展门类,总计 12 个类,每个类只负责自己的功能,完全遵守单一职责原则。
原有 8 个类(Able、Base、Yu、Huo、Fei、Yi、Tong、Main)全部保留,无修改,新增 4 个扩展元件类:
1、SanTai 三态门类
继承 Base 抽象类,仅重写 calc () 实现三态门逻辑,区分控制引脚电平,高阻态返回无效值 - 1,只处理三态门专属判断。
2、YiMa 译码门类
继承 Base 抽象类,仅重写 calc () 实现译码器逻辑,校验控制引脚有效性,返回输出 0 的引脚编号,专属译码运算。
3、XuanZe 数据选择器类
继承 Base 抽象类,仅重写 calc () 实现多路选择逻辑,根据控制引脚编码选取对应输入电平。
4、FenPei 数据分配器类
继承 Base 抽象类,仅重写 calc () 实现多路分配逻辑,返回存储全部输出引脚状态的 int 数组。
代码规模
86219d6586f365931e32806359d4c4e4
类图
c71f47d9dd1d130e90b4300ca93d6a00
bug分析
公测
自己测试的时候,calc () 返回值类型不统一,运行时触发类型转换异常。
新增译码器、数据分配器后,最初将 calc () 固定返回 Integer,打印译码器时强制转换 int 数组抛出 ClassCastException,程序直接终止;分配器无效值 - 1 未替换为字符 '-',输出格式与样例不符。
原因是未考虑不同元件差异化返回结果,统一强转单一类型,未做类型判断分支处理。
解决办法:将 Able 接口 calc () 返回值修改为 Object,打印流程使用 instanceof 区分返回类型,分分支处理单电平、编号、数组三种输出格式;遍历分配器数组,将 - 1 替换为 '-' 拼接字符串输出。
互测
和同学互相测试时,发现引脚完整性校验逻辑遗漏,输入不全的元件未被过滤。
测试样例 6 中 X2 仅接入 1 号引脚、缺失 2 号引脚,程序依旧正常计算并打印 X2 输出,违反题目输入不全则忽略元件的要求。
原因是运算底层未校验元件全部输入引脚是否都存在有效信号,仅读取现有引脚直接运算,边界校验逻辑缺失。
解决办法:每个子类 calc () 内部遍历该元件规定的全部输入引脚,统计有效信号数量,数量与总引脚数不一致直接返回 - 1,打印流程统一过滤返回值为 - 1 的元件。
测试方法
本次作业在原有单类、级联测试基础上,新增控制引脚、多输出元件专项测试,和室友互换代码做全样例互测,核对输出格式、元件排序、无效元件过滤三类核心规则,覆盖全部新增组合电路边界场景。

踩坑心得
第一次作业是作业集 4 基础封装阶段,踩的都是基础实体、语法相关的坑,最让我头疼的就是无抽象分层带来的大量重复代码问题。一开始直接独立编写 AndGate、OrGate 两个门类,引脚读取、信号完整性校验逻辑完全重复,修改引脚拼接规则元件名-引脚号时,只修改了与门类,忘记同步或门类,测试时或门全部读取不到引脚信号,无任何输出结果,调试很久才定位到重复代码不同步的问题。另一个坑是实体构造没有入参校验,手动传入负数引脚号时,Pin 类直接赋值非法数值,循环遍历引脚触发数组下标越界,程序直接崩溃。这次作业让我明白,实体封装不能只简单私有化成员变量,开发前一定要梳理所有对象的公共特征,提取父类复用逻辑,同时构造方法必须拦截非法参数,写完代码要主动构造边界用例测试,不能只依赖正常样例。
第二次作业是作业集 5 数字电路模拟程序 1,在封装基础上增加继承、抽象类、集合多态,踩的坑偏向调度逻辑、集合排序。最主要的坑是多级级联电路单次遍历求值失效,测试三级级联样例时,线性单次遍历会先读取后级非门、或门,此时前级与门输出信号还未计算存入信号池,后级元件直接返回无效值被过滤,输出结果缺失多行。还有一个典型坑是自定义比较器排序优先级颠倒,最开始先判断元件编号再判断类型顺序,同类型元件编号顺序颠倒,同时手写排序字符串写错顺序,输出元件排布完全不符合题目规范。另外,初期没有完整校验输入引脚完整性,仅读取现有引脚直接运算,若元件缺少输入引脚也会正常输出,违反过滤规则。这次作业让我意识到,业务调度逻辑要贴合实际业务依赖关系,不能只用简单线性遍历;多条件排序必须固定判断优先级,用常量字符串存储固定顺序;运算底层必须做好完整的业务边界校验,不能只依靠上层打印过滤。
第三次作业是作业集 6 数字电路模拟程序 2 迭代扩展,新增多类组合电路、差异化输出规则,踩的坑集中在多态兼容、类型转换、扩展兼容层面。第一个大坑是 calc () 返回值类型不统一,最初强制所有元件返回 Integer,新增译码器、数据分配器后,打印分配器时强制转换数组抛出ClassCastException,程序直接终止,同时分配器无效值 - 1 没有替换为字符-,输出格式与样例不符。第二个坑是迭代扩展时修改原有稳定代码,初期曾直接改动 Base 抽象类内部逻辑,导致 5 个基础门类全部运算异常,大量原有测试样例失效。还有一个细节坑是新增控制引脚校验逻辑遗漏,三态门控制引脚缺失时没有返回无效标记,程序依旧输出电平,不符合高阻态忽略输出的要求。

改进建议
通过三次作业的编写,我也发现自身代码存在多处可优化的地方,总结四点改进方向:
第一,代码注释数量不足,抽象类、核心运算 calc ()、循环求值、排序工具方法缺少功能注释,后期回看或调试时理解成本较高,后续编码会为核心类、关键逻辑添加简洁清晰的注释,提升代码可读性。
第二,边界条件与异常处理覆盖不全,当前程序默认输入完全合法,非法元件名、引脚多源连接、负电平、缺失控制引脚等场景没有统一校验,后续会增加全局合法性判断、自定义业务异常,捕获解析、运算阶段的各类错误,仅过滤无效元件不中断整体程序。
第三,重复代码未完全工具化,引脚拼接、信号池查询、输出格式化等逻辑存在多处重复,可提取独立工具类封装通用方法,简化主类代码结构,降低修改同步成本。
第四,类之间耦合度偏高,Base 类静态全局 signalMap 造成所有子类强依赖,Main 主类同时承担输入解析、求值、排序、打印全部流程,职责臃肿。后续设计会拆分输入解析、电路计算、结果打印三大独立工具类,移除全局静态信号池,通过传参注入信号池,降低类之间耦合,方便单独单元测试。
第五,扩展分支过多,元件创建、输出格式化存在大量 if 判断,后续引入工厂模式、策略模式消除多分支,新增时序电路、子电路时无需修改原有调度代码。

总结
通过这三次数字电路模拟程序的编程练习,我从基础类封装、实体建模,逐步过渡到抽象类继承、接口多态、集合容器、项目迭代扩展,完整完成了从单一基础逻辑门到九类组合电路的分层系统开发。
三次作业难度层层递进,我不仅熟练掌握了类的封装、单一职责原则、继承与抽象类、List/Map 集合、自定义 Comparator 排序等核心知识点,还学会了处理输入边界、多级依赖业务调度、多态差异化返回兼容、项目迭代扩展等工程化开发思路。在不断手动黑盒测试、和同学互测排查 bug 的过程中,改掉了编码粗心、逻辑考虑不全的问题,深刻理解了前期分层设计、规范代码结构对后期调试、扩展的重要意义。
同时我也清晰意识到自身存在的不足:代码注释偏少、异常处理体系不完善、代码复用性不强、不会使用设计模式简化多分支逻辑、缺少自动化单元测试。后续我会持续养成规范的编程习惯,写代码前梳理完整分层逻辑,写完后多组边界、异常用例测试,系统学习设计模式、JUnit 单元测试、Java 异常机制,提升代码健壮性与可维护性,为之后更复杂的大型迭代项目开发打好基础。

posted @ 2026-06-24 18:50  王润  阅读(2)  评论(0)    收藏  举报