题目集5~7单步电梯调度题的总结性Blog

前言

在这三次电梯题的编程学习中,我将很多知识点的理论运用到了实践中,从基础的类与对象设计、枚举类型的使用,到封装思想的实践、数据结构(LinkedList)的应用,再到正则表达式解析用户输入、条件逻辑与循环控制的流程设计。三次题目整体题量适中,每一次题目都有着单一且明确的目标且给了充足的时间让我们构建自己的程序。至于题目的难度,我想是随着迭代而逐渐增难的,但是其实真正感到困难的时候是写第一次题目集的时候,完成了从“0”到“1”的突破了,到了后期迭代题目中面对新要求的修葺工作也不会让人那么的望而却步,反而会有得心应手的感觉。接下来我将详细分享我写电梯题把“荒漠”开拓成“绿洲”的过程。

设计与分析

第一次电梯题目

写第一次电梯题,是我最焦虑的时候,眼看着时间快截止了,我却迟迟动不了手,而恰恰我在此之前也没有写过Java的大作业,对Java各种相关的知识使用及其不熟练,于是乎,我在写这个题的时候,类的设计很差,除了最基本Main类外,只有一个Elevator类了。
我没有细分类的设计,甚至都没有用上足够的方法,我想这是我学习面向过程编程语言所遗留下来的问题,严重违背了面向对象编程中类的单一职责原则(SRP)

单一职责原则(SRP:Single responsibility principle)又称单一功能原则,面向对象五个基本原则(SOLID)之一。它规定一个类应该只有一个发生变化的原因。

下面附上我的类设计图

不难看出,类的设计和方法(以简单的get和set方法为主)的设计简直不堪入目。也不难推断出,我Mai类中的main方法承载了多少压力🥹🥹🥹

点击查看main方法代码
public static void main(String[]args){
        Scanner sc=new Scanner(System.in);
        int minFloor=sc.nextInt();
        int maxFloor=sc.nextInt();
        Elevator elevator=new Elevator(maxFloor,minFloor);
        ArrayList<String> inner = new ArrayList<String>();
        ArrayList<String> outer = new ArrayList<String>();
        String request;
        Matcher outerMatcher = null;
        Matcher innerMatcher = null;
        while (true) {
            request = sc.nextLine();
            if (request.equalsIgnoreCase("end")) {
                break;
            }
            Pattern outerPattern = Pattern.compile("<(\\d+),(UP|DOWN)>");
            Pattern innerPattern = Pattern.compile("<(\\d+)>");
            outerMatcher = outerPattern.matcher(request);
            innerMatcher = innerPattern.matcher(request);
            if (outerMatcher.matches()) {
                outer.add(request);
            } else if (innerMatcher.matches()) {
                inner.add(request);
            }
        }//输入和储存电梯内外部的请求
        String co;
        String ci;
        int o;
        int i;
        int abso;
        int absi;
        String od;
        int xd=0;
        while(true){
            int ik=0;
            int ok=0;
            if(elevator.getDirection().equals("IDLE")){
                elevator.setDirection("UP");
            }
            if (inner.isEmpty() && outer.isEmpty()) {
                break;
            }
            if (!inner.isEmpty()){ci = inner.get(0);
                                  i=Integer.parseInt(ci.replaceAll("[^0-9]", ""));
                                 absi=Math.abs(i-elevator.getCurrentFloor());}
            else {co = outer.get(0);
                                  o=Integer.parseInt(co.replaceAll("[^0-9]", ""));
                                 abso=Math.abs(o-elevator.getCurrentFloor());
                                od=co.replaceAll("[^A-Z]", "");
                if(elevator.isStop(o)){outer.remove(0);
                System.out.println("Current Floor: "+elevator.getCurrentFloor()+" Direction: "+elevator.getDirection());
                 System.out.println("Open Door # Floor "+o);
                 System.out.println("Close Door");
                                         xd=1;
                continue;
                }
                
                
                
                if(elevator.getCurrentFloor()<o)elevator.setDirection("UP");
                  if(elevator.getCurrentFloor()>o)elevator.setDirection("DOWN");
                 ik=1;
                 ci="";
                 i=-1;
                 absi=-1;
                 if(xd==0)System.out.println("Current Floor: "+elevator.getCurrentFloor()+" Direction: "+elevator.getDirection());
                 if(elevator.getCurrentFloor()<o)elevator.setCurrentFloor(elevator.getCurrentFloor()+1);
                if(elevator.getCurrentFloor()>o)elevator.setCurrentFloor(elevator.getCurrentFloor()-1);
                
                  
                  xd=0;
                 continue;
                 }//坏
            if (!outer.isEmpty()){co = outer.get(0);
                                  o=Integer.parseInt(co.replaceAll("[^0-9]", ""));
                                 abso=Math.abs(o-elevator.getCurrentFloor());
                                od=co.replaceAll("[^A-Z]", "");}
            else {ok=1;
                 co="";
                 o=-1;
                 abso=-1;
                 od="";}
            int pan=0;
            int gaima=1;
            System.out.println("Current Floor: "+elevator.getCurrentFloor()+" Direction: "+elevator.getDirection());
            if(elevator.isStop(o,od)){
                outer.remove(0);
                if(elevator.isStop(i))inner.remove(0);
                System.out.println("Open Door # Floor "+o);
                System.out.println("Close Door");
                pan=1;
            }
            else if(elevator.isStop(i)){
                inner.remove(0);
                if(elevator.isStop(o,od))outer.remove(0);
                if(pan==0){System.out.println("Open Door # Floor "+i);
                System.out.println("Close Door");}
            }
            if(!inner.isEmpty() && !outer.isEmpty()){
                ci = inner.get(0);
                                  i=Integer.parseInt(ci.replaceAll("[^0-9]", ""));
                                  co = outer.get(0);
                                  o=Integer.parseInt(co.replaceAll("[^0-9]", ""));
                                  od=co.replaceAll("[^A-Z]", "");
            }
            
            if(elevator.getDirection().equals("UP")){
                if(elevator.getCurrentFloor()<i)gaima=0;
                if(gaima==1){if(ik==1&&o<=elevator.getCurrentFloor())elevator.setDirection("DOWN");
                else if(i<=elevator.getCurrentFloor()&&ok==1)elevator.setDirection("DOWN");
                else if(ik==0&&ok==0&&i<=elevator.getCurrentFloor()&&o<=elevator.getCurrentFloor())elevator.setDirection("DOWN");}
            }
            else{if(elevator.getCurrentFloor()>o)gaima=0;
                
                if(gaima==1){if(i>=elevator.getCurrentFloor()&&ok==1)elevator.setDirection("UP");
                else if(ik==1&&o>=elevator.getCurrentFloor())elevator.setDirection("UP");
                else if(ik==0&&ok==0&&i>=elevator.getCurrentFloor()&&o>=elevator.getCurrentFloor())elevator.setDirection("UP");}
            }
            if(elevator.getDirection().equals("UP"))elevator.setCurrentFloor(elevator.getCurrentFloor()+1);
            else elevator.setCurrentFloor(elevator.getCurrentFloor()-1);
        }
    }

起初输入和存储还是正常的,但是到了电梯控制部分的代码,就变得十分可笑,毫无逻辑的流程,不规范的命名,即使是我自己再来复看这段代码时依旧感觉云里雾里,不仔细想一想都不知道自己在写什么。在考虑电梯内部或外部请求为空时,我在不同的选择分支中复用了很多功能类似的代码。在调试的过程中,我为了让测试用例按照正确的流程走,我甚至用上了两个丑陋的"continue"语句,严重破坏了循环的结构,也严重破坏了程序的可维护性。我将它开源出来,不怕大家笑话,大家可以指出我的问题。
接下来是我的程序在SourceMonitor中的分析结果

点击查看详细分析结果
Parameter				Value
=========				=====
Project Directory			D:\JAVA文件\elevator1\src\
Project Name				电梯1
Checkpoint Name				Baseline
File Name				Main.java
Lines					181
Statements				161
Percent Branch Statements		21.7
Method Call Statements			54
Percent Lines with Comments		1.1
Classes and Interfaces			2
Methods per Class			7.00
Average Statements per Method		9.64
Line Number of Most Complex Method	59
Name of Most Complex Method		Main.main()
Maximum Complexity			44
Line Number of Deepest Block		107
Maximum Block Depth			5
Average Block Depth			2.62
Average Complexity			4.29

--------------------------------------------------------------------------------------------
Most Complex Methods in 2 Class(es):	Complexity, Statements, Max Depth, Calls

Elevator.Elevator()			1, 3, 2, 0
Elevator.getCurrentFloor()		1, 1, 2, 0
Elevator.getDirection()			1, 1, 2, 0
Elevator.getMaxFloor()			1, 1, 2, 0
Elevator.getMinFloor()			1, 1, 2, 0
Elevator.getStatus()			1, 1, 2, 0
Elevator.isStop()			3, 3, 2, 1
Elevator.isStop()			2, 3, 2, 0
Elevator.setCurrentFloor()		1, 1, 2, 0
Elevator.setDirection()			1, 1, 2, 0
Elevator.setMaxFloor()			1, 1, 2, 0
Elevator.setMinFloor()			1, 1, 2, 0
Elevator.setStatus()			1, 1, 2, 0
Main.main()				44, 116, 5, 53


虽然我的代码只有181行,算是比较精简的,但这是我牺牲了代码的可维护性换取的,将大部分的"压力"放在了少数的方法身上,只会让我的程序变成一次性程序。
即使不规范,也不完善,但最终我的程序还是实现了所需要的功能并通过了测试点,这是唯一值得我欣慰的地方,拿下了第一道电梯题,也让我更有勇气去挑战更难的题。

第二次电梯题目

在写第二次电梯题时,我已没有了写第一次电梯题时那么的焦虑,一是因为开始着手写题的时间较早,二是因为在写第一次电梯题时已清楚了电梯的运行过程。
但是情况任然是不容乐观的,前面提到了第一次代码的可维护性和可复用性是很差的,以至于即使第二次的题目要求只在原来的基础上变动了一点,但是我需要完成的却是“脱胎换骨”的改动,于是写第二次题目又是一个空前的大工程,整个程序全部重新写了。
好在这次的题目集的题干提供了类图供我们参考,这样我写的时候就不会毫无头绪。
下面附上我自己程序的类图

由我的类图可以看出,此次的电梯的类设计比上一次合理的多,比原来多出了Controller类,ExternalRequest类,RequestQueue类,它们分工明确,职责单一,于是我的程序的可维护性大大增强。。除此之外,通过学习,我还用上了枚举类型(State和Direction)来取代原来只用字符串表示,规范状态值。
在实际编程过程中我在功能上也进行了一些添加和改善,例如:

  1. 输入校验与请求去重
    在 Elevator 类中新增 isValidFloor()方法,校验楼层是否在合法范围。同时还在添加请求时进行去重操作。
点击查看去重操作代码
// 内部请求去重
if(floor!=queue.getInternalRequests().peekLast()) queue.addInternalRequest(floor);
// 外部请求去重
if(!(floor==queue.getExternalRequests().peekLast().getFloor()&&direction==queue.getExternalRequests().peekLast().getDirection())) 
    queue.addExternalRequest(floor,direction);
避免了无效的请求进入队列,导致破坏了程序的合理性,提升程序健壮性。
  1. 方向判断逻辑改得更清晰
    在第一次电梯题中方向切换逻辑混乱(通过 gaima、ik 等临时变量判断),可读性很差,并且难以理解。
    而此次我在 Controller 类中新增 determineDirection() 和 getNextFloor() 方法,根据当前方向和请求队列动态计算下一个目标楼层。
    例如:上行时优先处理当前楼层上方的请求,下行时反之。同时处理内外请求时,通过 getClosest() 方法选择更近的楼层。
    这样判断电梯方向的逻辑十分清晰,所能处理的情况也更加普适。

接下来是我的程序在SourceMonitor中的分析结果

点击查看详细分析结果

Parameter				Value
=========				=====
Project Directory			D:\JAVA文件\elevator2\src\
Project Name				电梯2
Checkpoint Name				Baseline
File Name				Main.java
Lines					283
Statements				227
Percent Branch Statements		23.8
Method Call Statements			123
Percent Lines with Comments		0.4
Classes and Interfaces			7
Methods per Class			5.14
Average Statements per Method		4.67
Line Number of Most Complex Method	195
Name of Most Complex Method		Main.main()
Maximum Complexity			27
Line Number of Deepest Block		220
Maximum Block Depth			6
Average Block Depth			2.44
Average Complexity			2.92

--------------------------------------------------------------------------------------------
Most Complex Methods in 5 Class(es):	Complexity, Statements, Max Depth, Calls

Controller.Controller()			1, 2, 2, 0
Controller.Controller()			1, 0, 0, 0
Controller.determineDirection()		3, 6, 2, 0
Controller.getClosest()			4, 7, 2, 4
Controller.getElevator()		1, 1, 2, 0
Controller.getNextFloor()		25, 39, 4, 23
Controller.getQueue()			1, 1, 2, 0
Controller.move()			3, 4, 3, 4
Controller.openDoors()			1, 2, 2, 2
Controller.removeRequests()		8, 6, 3, 21
Controller.setElevator()		1, 1, 2, 0
Controller.setQueue()			1, 1, 2, 0
Controller.shouldStop()			3, 3, 2, 2
Controller.shouldStop()			2, 3, 2, 1
Elevator.Elevator()			1, 2, 2, 0
Elevator.getCurrentFloor()		1, 1, 2, 0
Elevator.getDirection()			1, 1, 2, 0
Elevator.getElevatorInstance()		1, 1, 2, 0
Elevator.getMaxFloor()			1, 1, 2, 0
Elevator.getMinFloor()			1, 1, 2, 0
Elevator.getState()			1, 1, 2, 0
Elevator.isValidFloor()			3, 3, 2, 0
Elevator.setCurrentFloor()		1, 1, 2, 0
Elevator.setDirection()			1, 1, 2, 0
Elevator.setState()			1, 1, 2, 0
ExternalRequest.ExternalRequest()	1, 2, 2, 0
ExternalRequest.getDirection()		1, 1, 2, 0
ExternalRequest.getFloor()		1, 1, 2, 0
Main.main()				27, 66, 6, 62
RequestQueue.addExternalRequest()	1, 2, 2, 1
RequestQueue.addInternalRequest()	1, 1, 2, 1
RequestQueue.getExternalRequests()	1, 1, 2, 0
RequestQueue.getInternalRequests()	1, 1, 2, 0
RequestQueue.getQueueInstance()		1, 1, 2, 0
RequestQueue.setExternalRequests()	1, 1, 2, 0
RequestQueue.setInternalRequests()	1, 1, 2, 0


虽然Max Complexity还是超过了合理的水平,并且最复杂的方法仍然是Main类中的main方法,但是在功能变多的情况下,我的main方法的复杂度从44降到了27,这对我自己来说无疑是一大进步。

第三次电梯题目

写第三次电梯题的工作量远比写第二次电梯题的工作量要小,因为有很多代码是可以复用的,那即使面对一些功能要求的变动,只要抓住了他们在本质上的联系,只需做出些许的改动便可实现。例如:要求引入Passenger类去除ExternalRequest类,看似需要翻天覆地的变化,但是它们在本质上的工作都是对外部请求的表示,只不过Passenger类要求可以记录乘客请求的起始楼层,这只需我添加一个变量记录下来待需要使用时调用便可。其他的变化,例如名称、get/set方法的修改更是不足挂齿。
下面附上我自己程序的类图

接下来是我的程序在SourceMonitor中的分析结果

点击查看详细分析结果
Metrics Details For File 'Main.java'
--------------------------------------------------------------------------------------------

Parameter				Value
=========				=====
Project Directory			D:\JAVA文件\elevator3\src\
Project Name				电梯3
Checkpoint Name				Baseline
File Name				Main.java
Lines					340
Statements				239
Percent Branch Statements		23.8
Method Call Statements			143
Percent Lines with Comments		2.6
Classes and Interfaces			7
Methods per Class			5.43
Average Statements per Method		4.68
Line Number of Most Complex Method	168
Name of Most Complex Method		Controller.getNextFloor()
Maximum Complexity			36
Line Number of Deepest Block		275
Maximum Block Depth			7
Average Block Depth			2.54
Average Complexity			3.21

--------------------------------------------------------------------------------------------
Most Complex Methods in 5 Class(es):	Complexity, Statements, Max Depth, Calls

Controller.Controller()			1, 2, 2, 0
Controller.Controller()			1, 0, 0, 0
Controller.determineDirection()		3, 6, 2, 3
Controller.getClosest()			4, 7, 2, 5
Controller.getElevator()		1, 1, 2, 0
Controller.getNextFloor()		36, 41, 4, 24
Controller.getQueue()			1, 1, 2, 0
Controller.move()			3, 4, 3, 4
Controller.openDoors()			1, 2, 2, 2
Controller.removeRequests()		6, 5, 3, 17
Controller.setElevator()		1, 1, 2, 0
Controller.setQueue()			1, 1, 2, 0
Controller.shouldStop()			3, 3, 2, 2
Controller.shouldStop()			2, 3, 2, 1
Elevator.Elevator()			1, 2, 2, 0
Elevator.getCurrentFloor()		1, 1, 2, 0
Elevator.getDirection()			1, 1, 2, 0
Elevator.getElevatorInstance()		1, 1, 2, 0
Elevator.getMaxFloor()			1, 1, 2, 0
Elevator.getMinFloor()			1, 1, 2, 0
Elevator.getState()			1, 1, 2, 0
Elevator.isValidFloor()			3, 3, 2, 0
Elevator.setCurrentFloor()		1, 1, 2, 0
Elevator.setDirection()			1, 1, 2, 0
Elevator.setState()			1, 1, 2, 0
Main.main()				33, 74, 7, 81
Passenger.getDestinationFloor()		1, 1, 2, 0
Passenger.getSourceFloor()		1, 1, 2, 0
Passenger.Passenger()			1, 2, 2, 0
Passenger.setDestinationFloor()		1, 1, 2, 0
Passenger.setSourceFloor()		1, 1, 2, 0
RequestQueue.addExternalRequest()	1, 1, 2, 1
RequestQueue.addInternalRequest()	1, 1, 2, 1
RequestQueue.getExternalRequests()	1, 1, 2, 0
RequestQueue.getInternalRequests()	1, 1, 2, 0
RequestQueue.getQueueInstance()		1, 1, 2, 0
RequestQueue.setExternalRequests()	1, 1, 2, 0
RequestQueue.setInternalRequests()	1, 1, 2, 0

现在我回想第三次题目相对于第二次题目的进步,远没有第二次相对于第一次题目的进步大。单从最大复杂度来说,我甚至可以说是退步了,即使最复杂的方法已经不是Main.main(),但是main方法的复杂度并未降低,取而代之的是更加复杂的Controller.getNextFloor()。此外我根据SourceMonitor中的分析结果发现,平均栈深度和最大栈深度都不同程度地在偏离正常水平,说明我电梯的算法并未进行优化反而更加复杂了。在功能增加了地情况下,我并未花时间去优化算法,这是我的过错。

踩坑心得

(踩坑发生在收到Blog作业之前,由于并未记录,我只能根据记忆分享我的心得)

未考虑内部或者外部请求其中之一为空导致运行错误

在电梯题的look算法中,我们需要不断获取内部请求和外部请求的队头请求,然后经过一系列判断后再继续处理,直到两个队都为空则跳出循环结束程序。但是在我写第一次题目时,竟然忽略了处在空与非空的中间情况----内部或者外部请求其中之一为空。当他们其中一个为空时,我仍然要求从链表中获得它们的信息并且赋值给另一个变量,自然就发生错误了。从中我明白了,有时候程序的情况并不是非0即1,需要从多维度考虑多种情况。

正则表达式的相关语法使用不规范导致错误

在输入后解析输入内容时,通常要使用正则表达式的分组,我的程序也不例外。但是在使用捕获组时,我却错误地使用Pattern.group(1)(正确的应为Matcher.group(1))导致一直编译错误,弄得我还一直以为是我正则表达式部分错了,一直在查阅相关资料进行修改,但是最后却发现是个这样令人哭笑不得的原因。我们要对基本语法烂熟于心,不能像我一样犯这种低级错误,另外我觉得程序员更需要的是那份细心。

电梯掉头时发生逻辑错误

在一次测试用例的结果出现后,我发现过程中电梯竟然惊人地来到了第0层,我知道这一方面是我未设置边界值检测导致的,但问题更大的是我的电梯时在掉头时发生逻辑错误了,因为如果逻辑正确的话,只要给出的测试用例数据合理,电梯就不会来到第0层。当我进行跟踪调试时,发现问题出现在了一个小小的判断条件。彼时我的条件为当电梯状态处于下行时,下一个内部请求和外部请求都大于当前楼层时则电梯状态改为上行,但正确的判断应该是大于等于。

改进建议

注释

在三次电梯题的编程实践中,我的代码始终面临注释量严重不足的问题。从 SourceMonitor 的分析结果来看,三次注释率均未达标,尤其是第一次编写的代码,因缺乏必要注释,程序逻辑非常难懂。由于没有对类的设计意图、方法的功能和实现的逻辑以及关键流程的判断条件进行说明,导致代码可读性极差。这一问题不仅使得他人难以快速理解程序结构,即便于我而言,现在再回顾代码时,也需耗费很多精力重新梳理逻辑。其实不只是这三次电梯题目集的问题,注释的缺失暴露了我在编程习惯上的短板,也为代码的维护和协作埋下隐患,需要改进。

main方法

三次电梯题的main 方法复杂度都很高,不难推断主要是因为它承担了过多的职责。细数一下包括输入处理、请求处理、调度处理等。为了降低其复杂度,我认为可以再进行职责分离,将不同的功能再封装到独立的方法或类中。比如给RequestQueue类添加一个handleInput方法,给Controller类添加一个runElevator方法,都是可行的方法。

冗余方法

部分冗余的方法可以删去,拿电梯题三举例,Elevator类getElevatorInstance方法的作用是创建一个新的Elevator对象,不过这和直接使用构造函数的效果一样,没有必要额外封装,可以把它去掉。而RequestQueue类getQueueInstance方法和Elevator类的getElevatorInstance方法类似,此方法没有必要,也可以去掉。

determineDirection 方法

该方法的逻辑较为复杂,导致整个程序的最大复杂度超过了正常值,我认为可把一些判断逻辑封装成独立的方法。我有一个具体的方案,分成三个方法1.获取上行方向的下一个目标楼层 2.获取下行方向的下一个目标楼层 3.根据目标楼层决定最终方向。

总结

三次电梯题的编程实践,是我从面向过程思维向面向对象设计逐步蜕变的过程。第一次面对题目时,因缺乏Java大作业经验,类设计极为简陋,仅靠Main和Elevator类支撑,所有逻辑一股脑塞进main方法,输入处理、请求调度与状态管理混杂,临时变量命名随意,循环结构还因continue语句割裂,代码变成了经典的“屎山代码”,可读性极差。Elevator类仅有基础get/set方法,状态靠字符串管理,违背单一职责原则,虽实现功能却因可维护性差成为“一次性代码”,SourceMonitor显示1.1%的注释率与main方法44的复杂度,是对我编程能力与编程习惯的直白警示,这些都是我日后需要努力的方向。
第一次虽然是“屎山代码”,但pta全红的通过提醒却给足了我信心。第二次在类图指引下重构了我的程序,新增Controller、RequestQueue、ExternalRequest等类,首次实践职责分离:枚举Direction和State规范电梯状态,isValidFloor方法校验楼层合法性,输入时的请求去重避免无效数据。尽管main方法复杂度仍达27,但我的代码开始有了“模块”的概念——电梯不再是数据集合,而是有行为的实体,控制器则成为调度核心。这次改进让我初识面向对象编程语言的魅力:通过合理的分层分工,让每个类和方法都专注于单一职责,这样清晰的代码结构就可以为后续的迭代奠定基础。第三次迭代的目的聚焦在了请求部分的升级,用Passenger类替代简单楼层和方向,记录乘客起点与终点,实现了一个更接近于阵势电梯的完整流程。这一改动需重构请求解析与队列管理,却在调度逻辑上暴露算法复杂度问题:Controller的getNextFloor因为要兼顾内外请求和方向判断陷入多层if-else嵌套,复杂度急剧上升。此外,冗余的getElevatorInstance方法、main方法仍显臃肿、注释缺失等问题,暴露出了我对面向对象设计的理解不够深刻,面向对象设计的能力也不够强。
这三次实践完美地记录了我从单纯追求功能实现到注重设计思维和设计规范的转变,从最初的混乱编码到后来慢慢有了架构,从满足于“能用就行”到关注代码的可维护性和可扩展性。很好的工具SourceMonitor的数据分析提醒我,注释的作用不仅仅是浮于解释代码本身,更是与未来的自己对话的桥梁。这段经历让我深刻理解了面向对象的核心——职责分离,并认识到代码质量的提升始于对细节的关注。如今回想起来,第一次的头皮发麻是突破“0到1”的必经之路,第二次的重构是掌握面向对象设计原则的关键,而第三次的瓶颈则指引我走向算法优化。顿悟,编程能力的成长,正是在这不断的试错、改错与反思中逐渐实现的,代码不会说谎,我们的思维从零散变得系统,能力从弱变强,代码就会从粗糙变得精致!

魔术字符串(Magic Strings)是指在代码中多次出现且与代码形成强耦合的具体字符串或数值。这种做法会降低代码的可维护性,因为如果需要更改这些字符串的值,开发者需要在代码的多个地方进行修改,这不仅耗时而且容易出错

posted @ 2025-04-18 10:16  GallonLee  阅读(51)  评论(1)    收藏  举报