曾经作为一个业余爱好者,写代码时没有一套较为标准的开发规范,导致写的许多项目在后来都难以维护。

有些项目在AI时代到来后,利用AI进行重构或维护,但是后来发现代码更加难读/难维护了(这也要归结于我的提示词不到位)。

在校招进入某个中型互联网企业做后端开发后,由于该企业有较好的新人培训流程,我在培训中收获颇多,对于VibeCoding也有更深的理解。

以下是作为业余爱好者,希望通过AI来完成自己项目的一些方法论/规则,由我个人总结,存在不足之处还请指出。

tips:如果是业余开发者,可按需求把文章内容复制并保存为'*.md'(如default_prompt.md),然后直接喂给AI,就能得到较好的VibeCoding效果。

一、命名规范

1. 变量命名规范

  • 局部变量

遵循大驼峰命名规范,主要见下表:

数据类型

命名前缀

示例

其它说明

int

i

iExampleVariable

整数

float

f

fExampleVariable

浮点数

complex

c

cExampleVariable

复数

str

s

sExampleVariable

字符串

bool

b

bExampleVariable

布尔值

list

list

listExampleVariable

列表

tuple

t

tExampleVariable

元组

dict

dict

dictExampleVariable

字典

set

set

setExampleVariable

集合

function

func

funcExampleVariable

函数对象

自定义类

obj

objExampleVariable

类的实例化对象

  • 类成员变量和全局变量

在基于局部变量命名规范的前提下,适用下表规范:

成员变量

m_

m_sExampleVariable

全局变量

g_

g_dictExampleVariable

2.类命名规范

类命名注意以下几点:

  • 使用大驼峰命名法;

  • 以大写字母C作为命名前缀

  • 命名含义应使用1-4个单词(不含介词,可以使用单词缩写)来简短表示含义。

示例见下表:

前缀

示例

其它说明

C

CPlayerContainer

玩家容器基类(可被"背包"、"便携口袋"等业务子类继承)

C

CFight

战斗基类(可被"跨服战斗"、"关卡战斗"等业务子类继承)

3.方法/函数/接口 命名规范

方法...命名注意以下几点:

  • 使用大驼峰命名法

  • 命名含义应使用1-4个单词(可以含介词,可以使用单词缩写)来简短表示含义。

示例见下表:

类型

前缀

示例

其它说明

方法

AddItemByPID

通过玩家ID来给予玩家道具

方法

ClearResByEID

通过引擎对象ID清理该对象资源

函数

GetNowSec

获取当前时区的(标准Unix)时间戳

回调函数

Respond/CB(Callback)

RespondPAnswer

回调玩家选择的选项结果

部分业务涉及到

二、设计原则

设计原则并非必须严格遵守,而是更像指导建议,这里推荐10个常用设计原则:

SOLID 原则

SOLID 是面向对象设计中最核心、最广为人知的五个原则的首字母缩写,该设计原则对于写出干净可维护代码有极高的指导价值。

1. 单一职责原则 (Single Responsibility Principle, SRP)

  • 核心思想:一个类应该只有一个引起它变化的原因。

  • 通俗理解:让每个类都专注于一件事,做好一件事。例如,一个用户类只负责管理用户数据,而不应同时负责将用户保存到数据库或发送欢迎邮件。职责的分离使得代码更清晰,修改风险更低。

  • 个人理解:这不仅限于类,对于方法/函数也适用。

2. 开闭原则 (Open/Closed Principle, OCP)

  • 核心思想:软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。

  • 通俗理解:当需要添加新功能时,应该通过增加新代码来实现,而不是去修改已有的、经过测试的稳定代码。这就像给手机增加App,而不是去修改手机的操作系统内核。

3. 里氏替换原则 (Liskov Substitution Principle, LSP)

  • 核心思想:子类对象必须能够替换掉所有父类对象,而不会导致程序出错。

  • 通俗理解:“儿子”应该能完美地扮演“父亲”的角色。如果一个函数接收一个父类对象,那么传入一个子类对象时,函数的行为应该依然正确。这保证了继承关系的正确性和多态的有效性。

  • 个人理解:举个例子,玩家对象有个装备武器的方法,传入单持刀对象,而若有单持刀子类是双持刀,传入后装备武器方法依然正确。

4. 接口隔离原则 (Interface Segregation Principle, ISP)

  • 核心思想:客户端不应该被迫依赖于它们不使用的方法。

  • 通俗理解:多个特定的客户接口要好于一个通用的大接口。不要强迫一个类去实现它根本用不到的方法。这就像给员工发工具,应该按需分配,而不是把整个工具箱都塞给他。

5. 依赖倒置原则 (Dependency Inversion Principle, DIP)

  • 核心思想:高层模块不应该依赖低层模块,二者都应该依赖其抽象。要面向接口编程,而不是面向实现编程。

  • 通俗理解:业务逻辑(高层)不应该直接依赖具体的数据库或网络请求(低层),而应该依赖一个抽象的接口。这样,更换底层实现时,高层业务逻辑无需任何改动,极大地降低了模块间的耦合度。

其他重要原则

1. 迪米特法则 (Law of Demeter, LoD)

  • 核心思想:也叫“最少知识原则”。一个对象应该对其他对象有最少的了解。只与你“直接的朋友”通信,不要和“陌生人”说话。

  • 通俗理解:减少对象之间的直接联系。例如,一个人想开车,应该直接和“车”交互,而不是去操作车里的“发动机”。这能有效降低类之间的耦合,提高系统的封装性。

2. 组合/聚合复用原则 (Composition/Aggregation Reuse Principle, CARP)

  • 核心思想:优先使用组合(或聚合),而不是继承来复用代码。

  • 通俗理解:“有一个(Has-a)”的关系通常比“是一个(Is-a)”的关系更灵活、更安全。继承是白盒复用,耦合度高;组合是黑盒复用,耦合度低。当需要复用功能时,应优先考虑将已有类的对象作为新类的成员。

3. DRY 原则 (Don't Repeat Yourself)

  • 核心思想:系统中的每一处知识都必须有一个唯一、明确、权威的表示。

  • 通俗理解:避免代码重复。相同的逻辑不应该在多个地方出现,否则修改一处时,很容易忘记修改其他地方,从而引入 bug。

4. KISS 原则 (Keep It Simple, Stupid)

  • 核心思想:保持简单。

  • 通俗理解:设计应尽可能简洁,避免不必要的复杂性。简单的代码更容易理解、调试和维护。

5. YAGNI 原则 (You Aren't Gonna Need It)

  • 核心思想:你不会需要它。

  • 通俗理解:不要预先实现“可能”会用到的功能。只实现当前明确需要的功能,避免过度设计和浪费。

三、设计模式

这里推荐阅读两本书:《设计模式:可复用面向对象软件的基础》《大话设计模式》,前者推荐那些能啃的下硬骨头的人去读(太过于严谨枯燥,毕竟是学术派书籍),后者则推荐所有想要了解设计模式的人去读(后者有烂代码和好代码的对比,且其所有伪代码的实现都更贴近生活和业务要求,容易理解)。

根据关注点来进行分类,得到下表:

分类

核心关注点

包含的模式 (共23种)

创建型
(5种)

对象怎么创建
隐藏创建逻辑,解耦对象的创建与使用。

单例模式工厂方法模式抽象工厂模式建造者模式原型模式

结构型
(7种)

类/对象怎么组合
将类或对象组合成更大的结构,简化关系。

适配器模式装饰器模式代理模式外观模式组合模式桥接模式享元模式

行为型
(11种)

对象怎么交互
分配职责,管理对象间的通信和算法。

观察者模式策略模式模板方法模式责任链模式命令模式迭代器模式状态模式中介者模式备忘录模式访问者模式解释

关于23种常见设计模式的总结:

创建型模式 (Creational Patterns)

核心目标:把对象的“创建过程”和“使用过程”分离开,让系统更灵活。

1. 单例模式 (Singleton)

  • 生活案例:全公司只有一台打印机,或者一个班级只有一个班主任。

  • 作用:保证一个类只有一个实例,并提供一个全局访问点。

  • 场景:数据库连接池、配置文件读取器、日志对象。

2. 工厂方法模式 (Factory Method)

  • 生活案例:你去奶茶店点单,你只需要说“我要一杯奶茶”,具体的制作是由店里的员工(工厂)完成的,你不需要知道奶茶是怎么做出来的。

  • 作用:定义一个创建对象的接口,但让子类决定实例化哪个类

  • 场景:日志记录器(根据配置创建文件日志或数据库日志)。

3. 抽象工厂模式 (Abstract Factory)

  • 生活案例:小米生态链。你买一套“小米智能家居”,里面包含了小米的手机、小米的电视、小米的路由器。它们是一套相关的系列产品。

  • 作用:提供一个接口,用于创建相关或依赖的一系列对象(产品族),而无需指定具体类。

  • 场景:换肤功能(一套UI主题包含按钮、窗口、边框等多种控件)。

4. 建造者模式 (Builder)

  • 生活案例:点外卖套餐。你可以一步步选择:主食选汉堡,配菜选薯条,饮料选可乐。最后组装成一个完整的套餐。

  • 作用:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

  • 场景:构建复杂的SQL语句、生成复杂的报表对象。

5. 原型模式 (Prototype)

  • 生活案例:Word文档的“另存为”。你基于一个现有的模板文件,复制一份出来修改,而不是从头新建。

  • 作用:通过复制(克隆)现有实例来创建新对象。

  • 场景:对象创建成本较高(如读取大文件),且新对象与旧对象结构相似时。


结构型模式 (Structural Patterns)

核心目标:像搭积木一样,将类或对象组合起来,形成更大、更稳定的结构。

1. 适配器模式 (Adapter)

  • 生活案例:USB转接头。你的电脑只有USB-C接口,但鼠标是USB-A接口,中间加个转接头就能用了。

  • 作用:将一个类的接口转换成客户期望的另一个接口,解决接口不兼容问题。

  • 场景:整合旧系统代码、数据格式转换。

2. 装饰器模式 (Decorator)

  • 生活案例:奶茶加料。基础是原味奶茶,你可以动态地加珍珠、加椰果、加布丁。每加一种料,功能(口感/价格)就增加一点。

  • 作用:动态地给对象添加额外的职责,比继承更灵活。

  • 场景:Java IO流(new BufferedInputStream(new FileInputStream(...)))、函数装饰器。

3. 代理模式 (Proxy)

  • 生活案例:明星经纪人。你想找明星演出,不能直接找明星,必须通过经纪人。经纪人可以控制访问(比如检查你的预算、安排时间)。

  • 作用:为另一个对象提供一个代理或占位符,以控制对它的访问。

  • 场景:远程代理(RPC调用)、虚拟代理(图片懒加载)、保护代理(权限控制)。

4. 外观模式 (Facade)

  • 生活案例:一键启动。开车时,你只需要按一个“启动键”,不需要先去开油泵、再点火、再开空调。这个按钮就是外观。

  • 作用:为复杂的子系统提供一个统一的、简化的接口

  • 场景:框架的入口类、封装复杂的第三方SDK调用。

5. 组合模式 (Composite)

  • 生活案例:文件夹。文件夹里可以放文件,也可以放子文件夹。你对“文件夹”执行删除操作,里面的所有内容都会被删除。

  • 作用:将对象组合成树形结构以表示“部分-整体”的层次结构,让用户对单个对象和组合对象的使用具有一致性。

  • 场景:UI组件树(Window包含Panel,Panel包含Button)、文件系统。

6. 桥接模式 (Bridge)

  • 生活案例:遥控器与电视。遥控器(抽象)和电视(实现)是分离的。你可以用小米遥控器控制索尼电视,只要接口匹配。它们可以独立变化。

  • 作用:将抽象部分与实现部分分离,使它们都可以独立变化。

  • 场景:不同数据库驱动、不同操作系统的UI绘制。

7. 享元模式 (Flyweight)

  • 生活案例:五子棋。棋盘上有许多黑子和白子,但内存中只需要两个棋子对象(一个黑、一个白),通过共享位置坐标来显示。

  • 作用:运用共享技术来有效地支持大量细粒度的对象,减少内存占用。

  • 场景:文本编辑器中的字符对象、游戏地图中的树木/草地模型。


行为型模式 (Behavioral Patterns)

核心目标:关注对象之间的通信、职责分配以及算法的封装。

1. 观察者模式 (Observer)

  • 生活案例:B站关注。UP主(被观察者)发了新视频,所有关注他的粉丝(观察者)都会收到通知。

  • 作用:定义对象间的一种一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知并自动更新。

  • 场景:事件驱动系统、消息队列、MVVM框架的数据绑定。

2. 策略模式 (Strategy)

  • 生活案例:导航软件。从A到B,你可以选择“驾车”、“步行”或“骑行”策略。不同的策略对应不同的路线算法,可以随时切换。

  • 作用:定义一系列算法,将它们封装起来,并使它们可以相互替换

  • 场景:支付渠道切换(微信/支付宝)、压缩算法选择(Zip/Rar)。

3. 模板方法模式 (Template Method)

  • 生活案例:做菜流程。做“红烧肉”和“红烧鱼”流程类似:热油 -> 煎食材 -> 加调料 -> 出锅。流程框架固定,具体煎什么食材由子类决定。

  • 作用:定义一个操作中的算法骨架,而将一些步骤延迟到子类中实现。

  • 场景:框架生命周期钩子(如Django/Flask的请求处理流程)、SOP标准化流程。

4. 责任链模式 (Chain of Responsibility)

  • 生活案例:请假审批。请假3天找组长,3-7天找经理,7天以上找CTO。请求沿着链条传递,直到有人处理。

  • 作用:使多个对象都有机会处理请求,从而解除请求发送者和接收者之间的耦合

  • 场景:OA审批流、Web框架的中间件(Middleware)、异常处理。

5. 命令模式 (Command)

  • 生活案例:餐厅点单。服务员把顾客的要求(命令)写在单子上,厨师根据单子做菜。这使得支持“撤销”或“排队”变得容易。

  • 作用:将请求封装成对象,从而支持撤销、重做、排队等操作。

  • 场景:GUI按钮点击事件、任务队列、宏命令。

6. 状态模式 (State)

  • 生活案例:手机模式。手机在“静音模式”下,来电不响铃;在“正常模式”下,来电响铃。手机内部状态改变,其行为也随之改变。

  • 作用:允许一个对象在其内部状态改变时改变它的行为

  • 场景:订单状态流转(待支付->已发货->已完成)、TCP连接状态。

7. 其他行为模式

  • 迭代器模式 (Iterator):提供一种方法顺序访问集合中的元素,而不暴露内部结构(如Python的for x in list)。

  • 中介者模式 (Mediator):房产中介。房东和租客不直接联系,通过中介沟通,减少对象间的直接依赖。

  • 备忘录模式 (Memento):游戏存档。保存对象在某一时刻的状态,以便后续恢复。

  • 访问者模式 (Visitor):会计师查账。在不修改数据结构的前提下,对数据元素执行新的操作。

  • 解释器模式 (Interpreter):自定义计算器。定义语言的文法并解释执行。