数字电路模拟程序
第一次作业:
作业内容:
一、核心功能
模拟与门、或门、非门、异或门、同或门 5 种电路元件,根据输入的元件信息、引脚连接关系,计算各元件输出电平并按规则输出。
二、关键规则(输入 / 元件 / 输出)
- 元件规则
类型标识:A = 与门、O = 或门、N = 非门、X = 异或门、Y = 同或门
命名格式:
与 / 或门:标识 (输入引脚数)+ 编号(如 A (8) 1=8 输入与门、O (4) 2=4 输入或门)
非 / 异或 / 同或门:标识 + 编号(如 N1 = 非门、X8 = 异或门、Y4 = 同或门)
逻辑功能:
与门:全输入 1→输出 1,否则 0;或门:全输入 0→输出 0,否则 1
非门:输入反置(0→1、1→0);异或门:两输入不同→1,相同→0
同或门:两输入相同→1,不同→0
引脚:所有元件仅 1 个输出引脚(编号 0);输入引脚连续编号(如 8 输入与门引脚 1-8) - 输入规则
电路输入:格式为 “INPUT: 输入 1 - 信号 1 输入 2 - 信号 2...”(如 “INPUT: A-0 B-1”,A 输入 0、B 输入 1)
连接关系:格式为 “[输出引脚 输入引脚 1 输入引脚 2...]”(如 “[A A (8) 1-1 X5-2]”,A 信号传给与门 A (8) 1 的 1 号引脚、异或门 X5 的 2 号引脚)
结束标志:输入以 “end” 结尾,之后内容忽略
连接约束:1 个输出可连多个输入,1 个输入仅能连 1 个输出;输出引脚不能互接 - 输出规则
顺序:先与门、再或门、然后非门、异或门、同或门
同类排序:按元件编号从小到大
忽略条件:元件输入引脚未接有效信号时,不输出该元件结果
三、程序核心逻辑
读取并解析输入(元件信息、电路输入信号、引脚连接关系)
按元件逻辑计算输出(先确认输入引脚信号是否完整,再算输出)
按规则排序并输出有效元件的输出电平
代码规模:
方法参数统计(Parameter 列)
未直接展示具体方法的参数值分布,但从整体代码结构可推断:核心方法(如门电路类型解析的GateType.XNOR.fromCode()、程序入口Main.Main())参数数量少,输入数据特征单一(无多参数、多维度输入),调试 / 测试时仅需覆盖少量参数场景即可验证逻辑。
代码块深度(Block Depth)与语句数(Statements)
Block Depth:代码块的嵌套层级(0 = 最外层,数字越大嵌套越深);
Statements:对应层级的代码语句数量;
核心特征:
嵌套层级主要集中在 0-4 层(5 + 层的语句数为 0);
嵌套层级为 1 时,语句数最多(90 条),说明代码以单层嵌套逻辑为主(如基础条件判断、简单循环),2 层嵌套次之(67 条),整体嵌套逻辑简单,无过深层级。
Main.java 关键方法与复杂度补充详情:
这是聚焦 “最复杂方法” 和 “嵌套深度分布” 的核心补充数据,聚焦 Main.java 文件:
基础结构指标
Files:分析的文件是 Main.java;
Lines:代码总行数 465 行;
Statements:有效代码语句 265 条;
Classes and Interfaces:包含 2 个类 / 接口;
Methods per Class:平均每个类有 7 个方法;
Percent Lines with Comments:注释占比 2.8%(注释极少,几乎无结构化注释)。
复杂度指标(核心关注点)
Maximum Complexity:最大复杂度 3(对应方法GateType.XNOR.fromCode());
Average Complexity:平均复杂度 1.67;
Maximum Block Depth:代码块最大嵌套深度 4;
Average Block Depth:平均嵌套深度 1.19;
Most Complex Method:最复杂的方法是GateType.XNOR.fromCode()(复杂度 3、语句数 4 条、嵌套深度 3 层),其余方法(如Main.Main())复杂度仅 1。
可视化 / 补充数据
最复杂方法列表:以 “[方法名]:[复杂度,语句数,最大嵌套深度,调用数]” 格式呈现核心方法,直观体现单方法的复杂度分布;
代码块深度分布:以数值列表展示不同嵌套层级的语句数,与第一张图的 Block Depth 数据一致,嵌套层级 0-2 的语句占比超 80%。
总结
这份报告反映出:代码嵌套逻辑极少(最大嵌套深度 4,平均仅 1.19),核心方法GateType.XNOR.fromCode()的复杂度仅 3,整体代码逻辑极简,无高复杂度、深嵌套的业务核心方法;代码注释占比仅 2.8%(几乎无注释),可读性完全依赖代码语法结构;项目结构简单(仅 2 个类),所有方法复杂度均低于 5,维护成本极低,无需拆分逻辑;仅需注意补充必要注释,提升后续可读性。
类图:

一、核心类与枚举
GateType(枚举,标识:E)
作用:定义 5 种电路元件类型(与门AND、或门OR、非门NOT、异或门XOR、同或门XNOR),每个类型关联对应的字符标识(如AND('A'))。
关键:通过fromCode(char code)方法,可根据字符(A/O/N/X/Y)匹配对应的元件类型。
Pin(类,标识:C)
作用:封装电路中 “引脚” 的属性与依赖关系。
核心属性:
fullName:引脚完整名称(如 “A (2) 1-1”“A”);
isInputPin:是否为电路输入引脚(非元件的输入引脚);
signal:引脚信号(0 = 低电平、1 = 高电平、null = 未定义);
dependencyPin:输入引脚依赖的输出引脚(一个输入引脚仅依赖一个输出引脚)。
Gate(类,标识:C)
作用:封装 “电路元件” 的逻辑与引脚关系。
核心属性:
type:元件类型(关联GateType枚举);
name:元件名称(如 “A (2) 1”“N1”);
inputCount:输入引脚数量(与 / 或门可自定义,非门固定 1、异或 / 同或门固定 2);
number:元件编号(用于同类元件排序);
inputPins:输入引脚集合(key = 引脚号,value = 引脚对象);
outputPin:输出引脚(固定编号为 0);
核心方法:calculateOutput()—— 根据元件类型(与 / 或 / 非等)计算输出引脚的信号。
Main(类,标识:C)
作用:程序入口,负责输入解析、信号传播、元件计算、结果输出的全流程控制。
核心属性:
正则表达式(AND_OR_PATTERN等):匹配元件名、引脚名的格式;
allPins:管理所有引脚;
gates:按元件类型分组管理所有元件(TreeMap保证同类元件按编号排序);
pinDependencyMap:输出引脚→依赖它的输入引脚的映射(用于信号传播);
核心方法:
parseInputLine():解析电路输入信号;
parseConnectionLine():解析引脚连接关系;
propagateSignal():将输出引脚的信号同步到所有依赖它的输入引脚;
calculateAllGates():按依赖层级计算所有元件的输出;
printResults():按规则输出元件的输出结果。
二、类间关系
Gate ↔ GateType:Gate包含GateType类型的属性(“has a” 关系),表示元件关联对应的类型。
Gate ↔ Pin:
Gate包含多个输入引脚(inputPins,“contains > inputPins”);
Gate包含一个输出引脚(outputPin,“contains > outputPin”)。
Main ↔ Gate/Pin:Main管理所有元件(“manages> gates”)和所有引脚(“manages > allPins”)。
Pin ↔ Pin:输入引脚依赖输出引脚(“depends on> dependencyPin”)。
三、核心流程(Main的注释说明)
程序运行逻辑为:
parseInputLine():解析电路的输入信号;
parseConnectionLine():解析引脚的连接关系;
propagateSignal():传播引脚的信号;
calculateAllGates():计算所有元件的输出;
printResults():按规则(与→或→非→异或→同或,同类按编号排序)输出结果。
总结
该类图完整还原了数字电路模拟程序的结构与逻辑:通过GateType定义元件类型,Pin封装引脚,Gate实现元件逻辑,Main控制全流程,类间关系清晰体现了 “元件包含引脚、程序管理元件与引脚” 的核心设计。
复杂度:

无 “坏味道” 复杂度:所有高 ev (G) 的方法(如 calculateOutput),其非结构化逻辑均为 “业务必需”(如 5 种元件的计算分支),并非代码设计缺陷;
耦合风险可控:模块间依赖均为 “自上而下”(Main→Gate→GateType/Pin),无反向依赖,符合 “依赖倒置”;
内聚性优秀:无 “大杂烩” 方法(如同时处理输入解析 + 信号计算 + 结果输出),每个方法仅负责一个核心动作。
第二次作业:
作业内容:
在作业1的基础上增加要求,输入规则(新增 / 调整)
元件命名:
数据选择器 / 分配器:标识 (控制引脚数)+ 编号;译码器:标识 (输入引脚数)+ 编号;其余保持原有格式;
同类元件编号不可重复,不同类可重复(如 X4、Y4)。
引脚命名:仍为 “元件名 - 引脚号”,新增元件引脚需按 “控制 - 输入 - 输出” 顺序编号,同类型引脚按编号升序。
其他输入规则:
电路输入:INPUT: 输入名 - 信号 空格分隔(如 INPUT: A-0 B-1);
连接关系:[输出引脚 输入引脚 1 输入引脚 2...],1 输出可连多输入、1 输入仅连 1 输出;
输入以 “end” 结束,后续内容忽略。
代码规模:

这是Main.java的基础静态分析数据,涵盖代码规模、结构、复杂度等维度:
基础信息:
文件总行数 949 行,有效代码语句 616 条;
分支语句(if/switch等)315 个,方法调用语句 321 条;
注释占比仅 2.2%(几乎无注释),代码可读性依赖自身结构。
结构指标:
包含 2 个类 / 接口,每个类平均 9 个方法;
每个方法平均 33.5 条语句,最复杂方法位于第 16 行。
复杂度指标:
最大复杂度 887(对应GateType.DEMUX.fromCode()方法);
代码块最大嵌套深度 6 层,平均嵌套深度 1.60 层;
平均复杂度 1.67,整体复杂度偏低。
第二张图:关键方法与代码块深度详情
补充了 “最复杂方法” 和 “代码块深度分布” 的细节:
最复杂方法列表:
格式为[方法名]:[复杂度, 语句数, 最大嵌套深度, 调用数]:
GateType.DEMUX.fromCode():复杂度 3、4 条语句、嵌套深度 3 层;
Gate.Gate():复杂度 1、14 条语句、嵌套深度 2 层;
其他方法复杂度均≤3,逻辑较简单。
代码块深度分布:
统计不同嵌套深度的代码块对应的语句数:
嵌套深度 0(无嵌套):102 条语句;
嵌套深度 1(单层嵌套,如if/for):213 条语句;
嵌套深度 2:170 条语句;
嵌套深度≥6 时,语句数极少(≤5),无过深嵌套。
总结
这份报告显示:
Main.java代码规模较大(949 行),但注释极少;
核心方法GateType.DEMUX.fromCode()复杂度偏高(887),但其余方法逻辑简单;
代码块嵌套主要集中在 0-3 层,最大嵌套深度 6 层,无过深嵌套导致的逻辑混乱;
整体结构清晰(仅 2 个类),但需注意GateType.DEMUX.fromCode()的复杂度优化,同时补充注释提升可读性。
类图:

一、核心枚举与类
GateType(枚举)
作用:定义 9 种电路元件类型,新增TRI_STATE(S)(三态门)、DECODER(M)(译码器)、MUX(Z)(数据选择器)、DEMUX(F)(数据分配器);
关键:通过fromCode(char code)方法,用字符(A/O/N/X/Y/S/M/Z/F)匹配对应元件类型。
PinType(枚举)
作用:定义引脚类型,包含CONTROL(控制引脚)、INPUT(输入引脚)、OUTPUT(输出引脚),用于区分新增元件的多类型引脚。
Pin(类)
作用:封装引脚的属性与依赖关系,新增pinType(引脚类型)、pinNumber(引脚编号);
核心属性:fullName(引脚名)、signal(信号值)、dependencyPin(依赖的输出引脚)。
Gate(类)
作用:封装电路元件的逻辑,新增适配扩展元件的属性与方法;
核心扩展:
属性:ctrlPinCount(控制引脚数)、decoderOutputCode(译码器输出编码)、demuxOutputStr(数据分配器自定义输出字符串);
方法:initPins()(按 “控制 - 输入 - 输出” 顺序初始化引脚)、calculateTriStateOutput()/calculateDecoderOutput()等(各新增元件的计算逻辑)。
Main(类)
作用:程序入口,负责输入解析、信号传播、元件计算、结果输出;
核心扩展:
正则表达式:新增匹配三态门、译码器等元件名的规则;
方法:printResults()(按元件类型差异化输出,如数据分配器输出自定义字符串)。
二、类间关系
Gate ↔ GateType/PinType:
Gate包含GateType类型属性(“has a” 关系),关联元件类型;
Gate引用PinType枚举(“references” 关系),区分引脚类型。
Gate ↔ Pin:
Gate包含三类引脚:控制引脚(ctrlPins)、输入引脚(inputPins)、输出引脚(outputPins),对应 “contains” 关系。
Pin ↔ Pin:
输入引脚依赖输出引脚(“depends on” 关系),体现引脚的信号传递逻辑。
Main ↔ Gate/Pin:
Main管理所有元件(“manages> gates”)和所有引脚(“manages > allPins”),是程序的控制核心。
三、核心扩展说明
类图通过注释标注了新增元件的关键逻辑:
Gate的核心扩展:initPins()按 “控制 - 输入 - 输出” 顺序初始化引脚;译码器需满足S1=1且S2+S3=0才有效;数据分配器输出自定义字符串(如-1------)。
Main的核心扩展:printResults()实现差异化输出(数据分配器→元件名 + 自定义字符串;译码器→元件名 + 编码;基础门→引脚名 + 信号)。
总结
该类图完整还原了扩展后程序的结构与逻辑:新增元件的引脚规则、计算逻辑、输出格式均通过类属性 / 方法及关联关系体现,类间依赖清晰,是对 “9 类元件 + 差异化输出” 业务需求的可视化抽象。
复杂度:



中等复杂度:
无 “高风险复杂度点”(圈复杂度>10 / 嵌套>4 层 / 高耦合);
复杂度主要来源于 “9 类元件的分支判断”,属于业务扩展的自然增长,非代码质量问题。
无 “必须重构” 的高风险点,当前代码可直接维护;
优化后可进一步降低局部复杂度,提升代码的可扩展性(如新增元件时仅需新增子类,无需修改Gate.calculateOutput());
代码注释占比低(约 2%),建议补充关键方法的业务注释(如译码器的控制引脚规则、数据分配器的输出格式),降低后续维护成本。
浙公网安备 33010602011771号