曾经作为一个业余爱好者,写代码时没有一套较为标准的开发规范,导致写的许多项目在后来都难以维护。
有些项目在AI时代到来后,利用AI进行重构或维护,但是后来发现代码更加难读/难维护了(这也要归结于我的提示词不到位)。
在校招进入某个中型互联网企业做后端开发后,由于该企业有较好的新人培训流程,我在培训中收获颇多,对于VibeCoding也有更深的理解。
以下是作为业余爱好者,希望通过AI来完成自己项目的一些方法论/规则,由我个人总结,存在不足之处还请指出。
tips:如果是业余开发者,可按需求把文章内容复制并保存为'*.md'(如default_prompt.md),然后直接喂给AI,就能得到较好的VibeCoding效果。
一、命名规范
1. 变量命名规范
局部变量
遵循大驼峰命名规范,主要见下表:
类成员变量和全局变量
在基于局部变量命名规范的前提下,适用下表规范:
2.类命名规范
类命名注意以下几点:
使用大驼峰命名法;
以大写字母C作为命名前缀;
命名含义应使用1-4个单词(不含介词,可以使用单词缩写)来简短表示含义。
示例见下表:
3.方法/函数/接口 命名规范
方法...命名注意以下几点:
使用大驼峰命名法;
命名含义应使用1-4个单词(可以含介词,可以使用单词缩写)来简短表示含义。
示例见下表:
部分业务涉及到
二、设计原则
设计原则并非必须严格遵守,而是更像指导建议,这里推荐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种常见设计模式的总结:
创建型模式 (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):自定义计算器。定义语言的文法并解释执行。
评论