第二次Blog作业

前言

一、知识点

程序1:Java 面向对象基础封装、类与对象、HashMap/ArrayList集合框架、正则表达式文本解析、五种基础逻辑门(与 / 或 / 非 / 异或 / 同或)电平运算、多级串联电路信号循环迭代刷新、元件分类排序输出规则。

程序2:多引脚分层建模,区分控制引脚、输入引脚、输出引脚;新增译码器、多路数据选择器等复合组合元件;扩充元件命名、引脚编号正则匹配规则,拓展多类型元件独立运算逻辑。

程序4:GoF 组合模式实现子电路封装与复用,子电路独立局部信号隔离域;支持多层嵌套子电路跨模块信号传递;五级优先级输入异常校验、输入引脚多源冲突检测;统一规范错误输出格式,实现多模块低耦合分层设计。

二、题量与难度

程序1:中等难度。核心难点为自定义输入文本正则解析、多级串联电路循环迭代计算,仅基础面向对象建模;
程序2:中高难度。新增多类复合元件、多引脚区分逻辑,正则匹配规则大幅扩充,分支判断复杂度显著上升;
程序3:困难级。引入组合模式、独立子电路信号域、五级优先级异常校验,同时兼容前两次全部功能需求,约束条件严苛。

设计与分析

一、类图

image

整个程序分为四层结构:顶层抽象接口CircuitComponent、叶子类Gate、容器类Module、入口调度类Main。

CircuitComponent(顶层接口)

统一定义calcSignal()、getAllGateList()、getComponentId()三个通用方法,约束所有电路单元的行为,实现统一遍历、计算,适配子电路嵌套场景。

Gate(叶子节点,基础逻辑门)

实现顶层接口,代表不可拆分的与 / 或 / 非 / 异或 / 同或门。
属性:存储元件类型、编号、引脚电平、所属子电路;
方法:isAllReady()判断引脚是否全部接入信号,各类calcXxx()完成电平运算;
关系:被Module聚合,一个子电路可以包含多个逻辑门。

Module(容器节点,子电路 / 主电路)

实现顶层接口,用来封装一整个子电路,自带独立局部信号空间,隔离主电路与子电路的信号,避免同名元件冲突。
属性:子电路编号、输入输出标签、内部连线、本地信号缓存、内部门集合;
方法:getOrCreateGate()自动创建、复用门元件;

Main(程序入口)

依赖 Gate 与 Module,只负责读取输入、流程调度、异常检测、最终输出;核心工具方法checkConnError()校验输入异常、parseMainConn()解析连线信号。

二、复杂度分析

image

全部代码共 3 个文件、915 行,拆分 17 个自定义类,平均每个类 4 个方法,单个方法平均 7.84 行,类和方法粒度拆分合理,没有超长巨型方法。

缺陷数据:
注释占比 0,代码无说明,可读性差;
最高圈复杂度 38,对应异常校验方法,多层 if-else 嵌套,逻辑臃肿;
最大代码嵌套深度 9 层,调试、阅读困难。

踩坑心得

问题1:

作业 6 初次提交后,30 条子电路相关测试用例全部 0 分,无任何子电路元件输出。打印调试信息发现子电路内部Gate.isAllReady()永久返回 false,所有门电路输入引脚没有任何电平赋值。
解决:读取并解析所有主电路连接语句,完成子电路输入标签Cx-Tag的全局信号赋值。全部主电路信号填充完成后,再循环迭代计算所有子电路内部电平。刷新主电路内部逻辑门信号。

问题2:

子电路内部门可以正常算出输出电平,但主电路引用C1-C这类子电路输出标签时读取不到数值,多层嵌套子电路(C2 调用 C1 输出)全部评测判错。
解决:在Module迭代计算逻辑中新增findSubOutSignal()方法:每次子电路刷新电平后,遍历自身subOutputs输出标签,匹配连线绑定的电平,同步写入全局信号池。

问题3:

连接语句[A A(2)1-1](多个空格分隔),使用split(" ")分割会生成空字符串数组元素,程序误判这条连线无输出,抛出错误异常。
解决:全部文本解析统一替换为split("\s+"),正则匹配任意数量空白字符,兼容单个空格、多空格、制表符等不规范输入格式。

问题4:

6 级串联逻辑门电路,循环迭代上限仅设置 10 次,中间两级门输出电平始终无法更新,评测输出缺失部分元件。
解决:将全局信号迭代循环上限调整至 200 次,保证超长串联、多层嵌套子电路有充足迭代次数刷新全部电平。
调整后所有多级串联、嵌套子电路测试用例输出完整无缺失。

心得:

完成三次数字电路迭代作业后,结合 SourceMonitor 代码度量报表、UML 组合模式类图与四十余组评测测试用例的踩坑经历,我收获了完整的工程化开发经验。
在这三次作业中遇见的问题很多,更加体现了我对java基础知识内容的掌握不牢固,要加强编码能力,增强处理复杂问题的能力。我从本次开发懂得先架构设计,合理拆分代码,重视边界与流程,减少 BUG。
整体而言,三次增量迭代作业让我摆脱了 “只实现样例功能即可” 的过程式编程思维,真正理解面向对象、分层架构、设计模式在工程开发中的实际价值。后续开发复杂程序时,我会先完成 UML 建模、梳理执行流程图,严格拆分长分支方法,控制单方法圈复杂度,同时补充完整注释提升代码可维护性,从源头规避各类边界逻辑 BUG。

改进建议

架构分层优化,实现长期可扩展

拆分输入解析、信号仿真、输出打印为独立工具类,Main 仅保留流程调度,严格遵循单一职责。

算法性能优化,适配大规模电路

替换循环迭代刷新信号的方式,改用拓扑排序计算电平,按依赖顺序一次性仿真,大幅减少循环次数,提升大型多子电路仿真效率。

代码可维护性优化,方便迭代修改

增加本地 JUnit 单元测试,单独校验五种逻辑门、五类异常、子电路输入输出,不用反复提交 OJ 调试边界用例。

输入容错拓展,增强程序健壮性

增加非法元件名、空输入段、多余换行等异常容错逻辑,对不规范输入输出标准化错误提示,兼容各类不标准输入文本,拓展程序适用场景。

总结

经过三次数字电路仿真迭代作业的完整实践,我收获了一套完整的小型工程开发能力。基础层面吃透了 Java 面向对象核心思想,熟练运用封装、聚合、接口实现分层解耦;同时落地了组合设计模式;还掌握了正则自定义文本解析、多级依赖信号迭代仿真、多优先级业务异常校验等核心业务逻辑。此外我学会借助 SourceMonitor 度量代码、PowerDesigner 绘制 UML 类图,能用量化数据、类结构图客观评估代码优劣,跳出了只靠肉眼读代码的低效复盘方式。但是仍然有许多地方需要加深学习,比如各类设计模式搭配运用不熟练,电路仿真拓扑优化算法、标准化单元测试、代码重构技巧等,在后续的学习中,我会特地多花时间学习这些,来弥补技术上的不足,为以后就业打好基础。

posted @ 2026-06-24 23:46  邹诗颖  阅读(2)  评论(0)    收藏  举报