第二次Blog作业
总述
面向对象程序设计课程的第四、五、六单元内容已经全部学完,这三个单元围绕数字逻辑电路仿真程序持续迭代升级,从单层过程式代码逐步优化为分层面向对象工程架构,在反复调试、重构、静态代码度量分析的过程中,我收获了诸多实用的编程与系统设计知识:
熟练掌握 Java 抽象类、继承、多态、工厂模式等核心面向对象开发语法;
建立起分层解耦、单一职责、开闭原则的标准化软件架构设计思维;
直观理解代码圈复杂度、类粒度、分支占比等度量指标,学会量化评估代码工程质量;
掌握文本正则解析、拓扑迭代仿真、模块化子电路封装、异常容错处理等综合开发能力;
积累大量线上评测调试经验,能够根据报错信息定位逻辑漏洞、修正输出格式与运算缺陷。
一、作业整体概述
本次程序设计实训依托三道递进式 PTA 编程题目完成迭代开发,三道作业编号依次为第四题、第五题、第六题,分别对应子电路模块化单层仿真、面向对象架构重构、全功能综合电路仿真三大开发阶段。整套程序基于原生 Java API 开发,未引入任何第三方依赖库,核心功能是解析自定义文本格式的数字电路拓扑、加载引脚初始电平、迭代模拟信号在电路中的传输过程,最终收敛至稳定电平并标准化输出所有逻辑器件运算结果。
为客观量化三次迭代的代码质量变化,我使用 SourceMonitor 工具对三套源码开展静态代码度量分析,分别统计代码行数、类数量、单类平均方法数、圈复杂度、分支占比、代码嵌套深度等软件工程核心指标。三组度量数据直观反映出从过程式编程到分层面向对象架构的优化全过程:第四题采用单层过程式开发,仅划分 2 个内部类,代码集中、方法体量庞大;第五题重构后拆分出 12 个独立类,职责拆分细化,平均圈复杂度显著下降;第六题整合前两者功能,拓展至 6 个核心业务类,兼顾模块化复用与分层解耦,同时兼容更多数字器件,是功能与代码质量平衡最优的最终版本。
这三次练习将数字逻辑硬件理论与 Java 软件编程深度结合,通过三轮迭代、静态代码度量对比、bug 调试优化,完整掌握代码重构、抽象多态、工厂模式、模块化拆分、稳态迭代仿真等核心知识点,既夯实了编程语法基础,也建立起标准化工程开发思维。
二、三次迭代作业需求与开发目标
2.1 第一次迭代:PTA 第四题
第四题是整套实训的起步迭代版本,核心需求是实现子电路自定义封装、多层级嵌套调用与电路拓扑语法校验。在硬件工程开发场景中,重复功能的电路模块会被封装为独立单元反复调用,单层无分层电路无法适配复杂设计场景,因此本版本重点实现 C1、C2 标识子模块的解析逻辑,区分主电路与子电路的输入输出端口,支持跨模块信号互连传输。
同时题目要求增加输入容错机制,能够识别连线无输入源、多输入冲突、端口顺序颠倒、引脚信号重复赋值冲突等非法格式,并输出对应错误提示。本版本整体采用传统过程式开发思路,全部业务逻辑封装在 Main 主类内,仅通过两个静态内部类划分连线、器件数据结构,没有做分层架构拆分。
类图:

配套 SourceMonitor 度量数据:总代码 307 行,有效执行语句 264 条,拆分出 12 个独立类,单类平均方法数仅 2.42,单方法平均语句压缩至 6.69 行,平均圈复杂度降至 2.97,最大圈复杂度 15,最大嵌套深度 6 层,分支语句占比下降至 18.9%。对比第四题数据可见,重构效果十分显著:类粒度拆分细化,每个方法承载逻辑变少,分支占比降低,整体圈复杂度大幅下降,代码可读性、可维护性、拓展性实现跨越式提升。虽然总代码行数略有减少,但代码分层清晰、逻辑分散,工程化质量显著优化。

一些错误:

该版本是早期过程化实现,调试阶段频繁出现运行异常,主要问题集中在全局数据管理与信号传递机制:
1.全局静态容器共享引发数据污染 所有引脚电平、器件对象全部存放在 Main 静态集合,多条连线同步修改同一引脚数据,电平数值反复被覆盖,每次运行输出结果随机变化,无法稳定复现正确答案。
2.引脚读取未做空值判断 访问未接入信号的引脚时,没有前置非空校验,程序运行中途抛出空指针异常,直接终止评测。
3.仅单次执行信号同步,无迭代更新逻辑 程序只会完成一轮信号赋值,多级串联电路下游元件无法拿到更新后的电平,电路永远无法收敛至稳定状态。
4.器件重复注册覆盖原有信息 解析多条连线时,同一门会多次触发创建方法,映射表内原有器件信息被覆盖,引脚参数丢失。
5.输出文本格式书写不统一 部分场景输出时省略-0标准输出引脚后缀,和平台要求的打印格式存在字符差异。
2.2 第二次迭代:PTA 第五题
第四题过程式代码的缺陷在调试过程中完全暴露:全局静态变量泛滥、数据存储与运算逻辑深度耦合、大量重复 if-else 分支、新增器件需要大规模修改主类代码,完全不符合软件工程规范。因此第五题核心开发目标是全架构重构,彻底抛弃单层过程式写法,采用抽象父类、多态、工厂模式、分层设计对系统进行解耦改造。
重构将整套系统拆分为五大独立模块:信号存储层统一管理所有引脚电平、抽象逻辑门层定义统一运算接口、工厂类负责器件实例化、电路解析层处理输入文本与拓扑连线、运算调度层统筹迭代仿真与结果输出。每个类严格遵循单一职责原则,新增逻辑门仅需创建子类,无需改动原有核心代码,满足开闭设计原则;同时删除全部全局静态变量,通过构造方法实现依赖注入,支持多组电路独立仿真,从根源杜绝数据污染问题。
类图:
对应 SourceMonitor 度量数据:总代码 345 行,有效执行语句 304 条,仅包含 2 个类,单类平均方法数高达 11.5,单方法平均语句 11.04 行,最大圈复杂度 15,平均圈复杂度 4.43,最大代码嵌套深度 4 层,分支语句占比 23.7%。从指标可以直观看出代码高度集中,单类、单方法承载大量业务逻辑,圈复杂度偏高,分支判断冗余,耦合程度高,后期拓展难度大。

一些错误:

从平台提交记录能看到,大部分基础逻辑门、简单串联电路测试用例都判定答案错误,仅少数极简单门样例拿到分数,整体失分范围广,根源集中在逻辑运算、数据遍历、输出规范三方面。
1.多输入逻辑门的引脚遍历边界设计出错 针对 A (n)、O (n) 这类支持多路输入的器件,编写循环读取引脚电平时,终止条件设置不合理,会漏掉最后一路输入信号。输入数据残缺后,与、或运算的最终数值自然和标准答案不符,所有多输入相关测试点全部失分项。
2.异或、同或的数值判断缺少前置空校验 程序在计算异或、同或结果时,没有先判断两路输入是否存在有效电平,直接进行数值对比。一旦某一路引脚无信号,运算逻辑会出现 0、1 数值颠倒的问题,混合逻辑电路全部无法通过。
3.器件输出排序规则不符合题目硬性要求 题目明确输出顺序必须是与门、或门、非门、异或门、同或门,同一类型器件按数字从小到大排列。代码只是按照对象创建先后顺序输出,没有基于编号做数值排序,在线评测逐行比对文本,直接判定输出不匹配。
4.未过滤输入不完整的器件输出 规则规定只要器件任意一路输入缺失,就不能打印该器件结果。原代码缺少完整输入判定,无效门仍会打印一行内容,输出文本行数和标准样例不一致,大量用例直接零分。
5.信号迭代循环次数设置偏少 多级串联电路中,信号需要多轮传递才能稳定。原程序迭代轮数不足,下游逻辑门始终读取旧电平,带多级级联的电路全部运算出错。
6.次要格式类漏洞 器件编号采用字符串比对而非数字对比,会出现 “10” 排在 “2” 前面的排序错误;打印结束存在多余空行,平台字符匹配失败。
2.3 第三次迭代:PTA 第六题
第六题为实训最终交付版本,整合第四题子电路模块化复用能力与第五题分层面向对象架构优势,完成功能全覆盖、逻辑优化、稳定性升级。本版本兼容九类数字器件,除基础与、或、非、异或、同或门外,拓展支持三态门、译码器、数据选择器、数据分配器等高级组合器件;优化信号迭代更新策略,设置最大迭代阈值避免电路信号震荡死循环,保证电路快速收敛至唯一稳态;同时规范输出排序规则,按照器件类型优先级、编号升序输出结果,完全匹配 PTA 在线评测格式要求。
类图:

在架构层面,第六题平衡了模块拆分粒度,保留分层解耦特性,同时合并部分细碎工具类,最终形成 6 个核心业务类,兼顾运行效率与代码简洁度。
对应 SourceMonitor 度量数据:总代码 391 行,有效执行语句 342 条,共 6 个核心类,单类平均方法数 3.00,单方法平均语句 16.39 行,最大圈复杂度 33,平均圈复杂度 7.33,最大嵌套深度 9 层以上,分支语句占比 26.6%。代码行数与执行语句数量为三套版本最高,原因是兼容九类器件、子电路嵌套、错误校验、迭代收敛等全套功能;类数量介于第四、五题之间,既避免第四题单类臃肿的问题,又不会出现第五题类划分过细、模块跳转繁琐的情况,是功能与架构平衡最优的成品代码。

一些错误:

整套子电路、多层嵌套相关测试用例全部答案错误,部分样例程序运行超时、异常退出,综合功能模块均存在逻辑漏洞,是三套代码缺陷最多的版本。
1.子电路输入输出端口映射顺序颠倒 定义子电路C1的输入为 A、B,输出为 C 时,主电路向 C1-B 传递信号,程序错误将数值赋值给第一个输入端口 A,子电路内部全部输入数据错乱,所有单模块测试无得分。
2.主、子电路共用一套器件索引表 子电路内部器件编号和主电路门编号重复时,映射表原有对象会被新数据覆盖,读取引脚参数时拿到错误器件,整体运算全部失效。
3.异常报错检测逻辑顺序不符合优先级规范 题目给定报错优先级:多条输入 > 无输入 > 端口顺序颠倒 > 引脚信号冲突,但代码校验判断顺序完全相反,高等级错误无法优先输出,所有语法校验样例全部失分。
4.仅校验主电路引脚冲突,忽略子模块端口 两套不同信号接入同一个子电路输入端口时,程序不会输出冲突提示,无法通过冲突检测类评测用例。
5.多层嵌套电路信号刷新顺序混乱 程序没有预先梳理子电路依赖关系,顶层子电路先执行运算,底层模块电平还未完成更新,多层嵌套电路无法算出稳定结果。
6.缺少迭代次数上限保护 存在反馈环路的电路会持续循环刷新电平,程序陷入死循环,评测显示运行超时、非 0 退出。
7.子电路输出文本拼接格式写错 标准打印格式为C1-A(2)1:0,代码把子电路标识放到器件编号后方,字符格式不匹配直接判错。
8.新增高级器件运算逻辑存在漏洞 三态门、译码器、多路选择、分配器的控制引脚、多路输出处理代码存在疏漏,包含复合器件的混合电路全部运算错误。
三、基于度量数据的架构迭代对比与优化分析
3.1 第四题过程式代码的缺陷
从 SourceMonitor 输出的量化指标可以清晰定位单层过程式代码的工程短板:
1.类粒度极度粗糙:仅 2 个内部类,绝大多数方法集中在 Main 主类,单类平均方法 11.5 个,单个方法平均包含 11 行执行语句,方法体量过大,阅读、调试、修改都十分繁琐;
2.分支逻辑冗余:分支语句占比 23.7%,大量 if-else 判断区分器件类型、端口类型、信号传输规则,圈复杂度均值 4.43,复杂分支容易产生逻辑漏洞,调试成本高;
3.耦合度无法量化但指标侧面体现:所有信号、连线、器件数据依靠全局静态集合存储,不同功能方法互相读写同一批全局变量,极易出现信号覆盖、数据污染 bug,无法实现多电路并行仿真;
4.拓展性差:若新增一类数字器件,需要新增全局集合、新增匹配正则、新增运算分支、新增输出逻辑,需要修改主类多处代码,违反开闭原则。
该版本仅适合快速实现基础功能,不具备长期维护、迭代拓展的工程价值,也是我开展第五题全面重构的核心动因。
3.2 第五题面向对象重构的优化成效
第五题重构后的度量数据,各项指标均呈现正向优化,完美解决第四题的全部短板:
1.细粒度类拆分:拆分至 12 个独立类,单类平均仅 2.42 个方法,每个类只负责一项独立功能,单一职责原则落地;单方法平均语句降至 6.69 行,方法逻辑精简,单一方法只完成一件小事,定位 bug、修改逻辑效率大幅提升;
2.分支占比与圈复杂度显著下降:分支语句占比从 23.7% 降至 18.9%,平均圈复杂度从 4.43 降至 2.97。核心原因是通过抽象父类 + 多态机制,消除了海量区分器件类型的 if-else 分支,不同器件的运算逻辑分散至各自子类中,主调度流程不再需要冗长条件判断;
3.彻底消除全局静态数据,所有依赖通过构造函数注入,支持多电路实例,不存在数据污染风险;
4.代码拓展性大幅提升:新增器件仅需要新建 LogicGateBase 子类,重写 calcResult 运算方法,工厂类自动识别创建,无需修改解析、调度、输出核心代码,完全符合开闭原则。
唯一小幅上升的指标是最大代码嵌套深度,从 4 层提升至 6 层,是分层调用带来的正常现象,不影响代码可读性与稳定性,属于可接受范围内的指标变化。
3.3 第六题综合版本的平衡设计思路
第六题作为整合最终版,功能体量是三套代码最大的,因此代码行数、执行语句、分支占比、平均圈复杂度、最大嵌套深度有所回升,但架构设计吸取前两版优势,做出折中优化:
1.类数量精简至 6 个核心业务类:摒弃第五题过度细碎的类拆分,合并部分仅提供工具方法的轻量工具类,减少类之间频繁跳转,降低代码阅读成本;同时维持分层架构,信号存储、器件、解析、调度模块边界清晰,不会回归第四题单类臃肿的问题;
2.指标回升属于功能拓展的正常代价:本版本兼容 9 类器件、子电路嵌套、完整错误校验、多层拓扑迭代收敛,业务逻辑量大幅增加,因此分支占比、圈复杂度、嵌套深度同步上升,最大圈复杂度 33 集中在器件匹配、拓扑更新的核心方法,其余普通方法复杂度维持在较低水平,不存在全代码高复杂度问题;
3.兼顾复用与简洁:保留第五题抽象多态、工厂创建的核心架构,同时复用第四题子电路拓扑解析逻辑,一套代码同时支持单层电路、多层嵌套子电路、九类数字器件混合仿真,是综合性能最优的交付版本。
四、核心模块工作原理详解
4.1 信号数据封装存储模块
第五、六题重构版本独立设计信号存储类,完全替代第四题全局静态 Map。类内部私有封装哈希映射集合,外部代码无法直接操作底层数据源,仅能通过对外公开的三个接口完成操作:存储引脚电平、查询引脚电平、判断引脚是否存在有效信号。
这种封装特性可以从根源避免跨方法、跨类随意修改电平数据导致的信号错乱问题,保证整套仿真系统中引脚电平数据统一、一致、无脏数据写入。对比第四题直接操作全局静态集合的写法,封装后的代码数据安全性更高,也为多电路实例并行仿真提供底层支撑。
4.2 抽象逻辑门与多态运算机制
重构版本设计统一 LogicGateBase 抽象父类,统一定义所有数字器件的通用属性:器件标识字符串、器件编号、输入引脚集合、输出引脚名称,同时声明抽象 calcResult 运算方法,强制所有器件子类重写专属逻辑运算。
与门、或门、非门、异或门、同或门、三态门、译码器等器件分别创建独立子类,根据自身硬件逻辑重写运算函数。程序运行时统一使用抽象父类引用接收所有器件实例,依靠多态机制自动匹配对应器件的运算逻辑,直接删除第四题中数十行区分器件类型的 if-else 分支代码,大幅降低分支占比与整体圈复杂度,也是第五题度量指标大幅优化的核心技术手段。
4.3 工厂模式器件自动创建模块
为统一管理各类器件的实例化流程,重构版本引入 GateBuilder 工厂类,内置预编译正则表达式,精准匹配每一类器件的标准命名格式,自动解析器件类型、输入引脚数量、器件编号,动态生成对应子类对象。
工厂模式将所有对象创建逻辑集中封装,上层解析代码无需关心器件实例化细节,仅传入器件名称字符串即可获得运算对象,实现对象创建逻辑与业务仿真逻辑完全解耦,进一步简化上层代码,降低分支判断数量。
4.4 电路拓扑解析与信号迭代传播
解析模块逐行读取控制台输入文本,区分初始电平配置、子电路定义、拓扑连线三类文本,分别完成数据解析与结构化存储。程序内部封装连线实体类,记录每一条信号传输链路的信号源引脚与目标接收引脚,每一轮迭代批量完成信号赋值传递。
整套仿真采用循环迭代机制持续刷新所有引脚电平,不断执行信号传播、器件逻辑运算,直到连续一轮迭代无任何引脚电平发生变化,判定电路达到稳态,模拟真实硬件电路通电后信号逐级传输、最终稳定的物理过程。第六题额外增加最大迭代次数阈值,防止复杂组合逻辑电路出现信号震荡、无限循环卡死程序的问题。
4.5 稳态判断与标准化结果输出
运算调度类作为整套程序的流程总指挥,统一控制迭代循环、器件分类排序、最终结果打印。电路收敛至稳态后,程序按照器件类型划分列表,再根据器件编号从小到大排序,逐行输出所有有效器件的输出引脚电平,输出格式规整统一,完全适配 PTA 在线评测系统的判题标准。第四题输出逻辑全部堆砌在主类中,重构后拆分独立输出方法,代码逻辑更加清晰。
五、开发调试过程中的问题与优化方案
5.1 全局信号污染问题
第四题全程使用 Main 类静态全局集合存储引脚电平,多个子电路、多个器件运算方法同时读写同一批全局数据,经常出现引脚电平被异常覆盖,输出结果随机错乱。 优化方案:第五题独立封装 SignalDataStore 信号存储类,私有化底层 Map,禁止外部直接修改,所有电平读写仅能通过类内公开方法执行,每一次赋值都会对比原有电平,仅在数值变化时更新,彻底解决信号污染、数据覆盖问题。
5.2 多层子电路信号刷新顺序错乱
第四、六题开发子电路嵌套功能时,曾出现底层子电路信号未完成更新,顶层主电路提前运算,导致电路无法收敛至正确稳态。 优化方案:新增拓扑序列生成逻辑,扫描所有子电路依赖关系,按照 “底层子电路→上层子电路→顶层主电路” 的固定顺序迭代更新信号,保证信号传输顺序符合硬件逻辑,多层嵌套电路运算结果准确稳定。
5.3 空指针、引脚缺失异常
器件运算过程中,若输入引脚未加载有效电平,直接读取数值会触发空指针异常,程序直接崩溃。 优化方案:在读取任意引脚电平前增加存在性、有效性双重校验,无有效信号时返回标记值,器件运算方法提前判断输入合法性,输入缺失则标记器件运算未就绪,跳过本轮输出,大幅提升程序容错能力。
5.4 无限迭代死循环问题
部分存在反馈回路的组合逻辑电路,信号会持续来回切换,迭代循环无终止条件,程序卡死。 优化方案:第六题新增最大迭代次数阈值,设置电路迭代上限,达到阈值后强制退出循环并输出当前稳态结果,兼顾仿真准确性与程序运行安全性。
5.5 代码复杂度过高、分支冗余
通过 SourceMonitor 度量分析,第四题平均圈复杂度 4.43,大量 if-else 区分器件类型,代码可读性差、调试困难。 优化方案:第五题引入抽象类与多态机制,把各类器件的判断逻辑拆分至工厂类,运算逻辑分散至子类,删除主调度流程冗余分支,分支语句占比、平均圈复杂度同步下降,代码维护难度显著降低。
六、实验总结与个人心得体会
本次三轮迭代的数字电路仿真作业,是一次完整的软件工程项目实践,结合 SourceMonitor 静态代码度量工具的量化指标,直观展现了从粗糙过程式代码到标准化面向对象架构的完整优化路径,理论、代码、量化分析三者相互印证,收获十分全面。
在编程技术层面,我系统巩固了 Java 集合框架、正则表达式、抽象类、继承、多态、工厂设计模式、静态内部类、依赖注入等核心语法知识点;同时结合数字电路课程理论,吃透了组合逻辑电路信号传输、迭代收敛、模块化子电路复用、各类基础与高级器件的运算原理,打通了硬件理论与软件仿真的知识壁垒。通过三组 SourceMonitor 度量数据对比,我学会使用代码行数、类数量、圈复杂度、分支占比、嵌套深度等量化指标评估代码工程质量,不再仅以 “程序能跑通” 作为代码优劣的唯一标准,建立起标准化的代码评估思维。
在工程开发思维层面,我深刻意识到功能实现只是程序开发的基础要求,低耦合、高内聚、易拓展、易维护才是工业级代码的核心标准。第四题代码虽然可以正常运行,但度量指标暴露了单类臃肿、分支冗余、耦合度高的致命缺陷;第五题重构通过分层拆分、多态解耦,各项量化指标全面优化;第六题平衡粒度,兼顾功能完整性与代码简洁度。三轮迭代让我养成迭代优化、静态分析、提前架构设计的开发习惯,不再一味堆砌代码快速实现功能。
在问题解决能力层面,大量调试 bug、根据度量指标优化代码的过程,锻炼了我的逻辑排查、分层定位、定量分析问题的能力。面对复杂电路仿真逻辑时,我学会拆分模块、分步调试、借助工具量化定位代码缺陷,处理复杂逻辑的思路更加清晰有条理。
整体而言,本次作业通过三道递进 PTA 作业、静态代码度量分析、多轮代码重构调试,全方位提升了我的 Java 编程能力、系统架构设计能力、代码质量评估能力与逻辑问题排查能力,为后续更复杂的大型程序开发、课程设计项目积累了扎实的理论与实践经验。

浙公网安备 33010602011771号