Skip to content

Commit e8b73dd

Browse files
committed
docs: add design principles and protective comments
- Add doc/DESIGN_PRINCIPLES.md - Core design philosophy - Add protective comments to NewQdrantCustom() and NewMySQLCustom() - Document anti-patterns and best practices - Establish 4-layer protection against concept inflation Design Philosophy: - Don't add concepts to solve problems - Every API name is a permanent commitment - Less is exponentially more This document serves as guardian for future development.
1 parent b06b8e3 commit e8b73dd

File tree

3 files changed

+409
-8
lines changed

3 files changed

+409
-8
lines changed

doc/DESIGN_PRINCIPLES.md

Lines changed: 366 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,366 @@
1+
# xb 设计原则
2+
3+
## 🎯 核心原则
4+
5+
### **"Don't add concepts to solve problems"**
6+
7+
**每个具体的命名都是一个概念。** 概念越多,认知负担越重,学习成本越高。
8+
9+
---
10+
11+
## 📜 黄金法则
12+
13+
### 法则 1:概念守恒定律
14+
15+
```
16+
框架价值 = 功能 / 概念数量
17+
18+
理想:功能增加,概念不增加
19+
现实:功能不变,概念减少 ✅
20+
```
21+
22+
**xb v1.2.0 验证**
23+
- 删除 8 个概念(预设函数、专用方法)
24+
- 功能不减反增(智能格式检测)
25+
- 价值提升 = ∞
26+
27+
---
28+
29+
### 法则 2:命名成本定律
30+
31+
```
32+
每个公开 API 的成本 =
33+
学习成本 +
34+
记忆成本 +
35+
决策成本 +
36+
维护成本(永久)
37+
```
38+
39+
**示例**
40+
41+
| API | 学习 | 记忆 | 决策 | 维护 | 总成本 |
42+
|-----|------|------|------|------|--------|
43+
| `NewQdrantCustom()` ||||| ⭐ 低 |
44+
| `QdrantHighPrecision()` ||||| ❌ 高 |
45+
46+
---
47+
48+
### 法则 3:API 不可逆定律
49+
50+
```
51+
增加 API:1 小时
52+
删除 API:永远不可能(breaking change)
53+
54+
结论:
55+
- 每个 API 都是永久承诺
56+
- 宁可少加,不能多加
57+
- Less is more
58+
```
59+
60+
---
61+
62+
## 🚫 禁止模式(Anti-Patterns)
63+
64+
### ❌ 反模式 1:预设配置函数
65+
66+
```go
67+
// ❌ 禁止
68+
func QdrantHighPrecision() *QdrantCustom { ... }
69+
func QdrantHighSpeed() *QdrantCustom { ... }
70+
func QdrantBalanced() *QdrantCustom { ... }
71+
72+
// ✅ 正确
73+
func NewQdrantCustom() *QdrantCustom { ... } // 只有这一个
74+
75+
// 用户配置
76+
custom := NewQdrantCustom()
77+
custom.DefaultHnswEf = 512 // 手动配置,清晰
78+
```
79+
80+
**为什么禁止?**
81+
1. 增加概念数量(3 个额外概念)
82+
2. 用户需要决策(该用哪个?)
83+
3. 配置不透明(HnswEf=512 是隐藏的)
84+
4. 永久维护负担
85+
86+
---
87+
88+
### ❌ 反模式 2:专用方法
89+
90+
```go
91+
// ❌ 禁止
92+
func (x *BuilderX) InsertPoint(point interface{}) *BuilderX { ... }
93+
func (x *BuilderX) InsertPoints(points []interface{}) *BuilderX { ... }
94+
95+
// ✅ 正确
96+
func (x *BuilderX) Insert(f func(ib *InsertBuilder)) *BuilderX { ... }
97+
// Custom 内部智能处理不同格式
98+
```
99+
100+
**为什么禁止?**
101+
1. 破坏 API 统一性
102+
2. 用户困惑(Insert vs InsertPoint?)
103+
3. 维护两套逻辑
104+
105+
---
106+
107+
### ❌ 反模式 3:便捷包装
108+
109+
```go
110+
// ❌ 禁止(除非极其常用)
111+
func (x *BuilderX) Delete() *BuilderX { ... }
112+
113+
// ✅ 正确
114+
// 在方法内部处理
115+
func (built *Built) JsonOfDelete() (string, error) {
116+
built.Delete = true // 自动设置
117+
...
118+
}
119+
```
120+
121+
**为什么禁止?**
122+
1. 增加 API 表面积
123+
2. 不够必要(调用 JsonOfDelete 已经明确意图)
124+
125+
---
126+
127+
## ✅ 推荐模式(Best Practices)
128+
129+
### ✅ 模式 1:单一构造函数 + 公开字段
130+
131+
```go
132+
// ✅ 只有一个构造函数
133+
func NewQdrantCustom() *QdrantCustom { ... }
134+
135+
// ✅ 公开字段供配置
136+
type QdrantCustom struct {
137+
DefaultHnswEf int // 公开
138+
DefaultScoreThreshold float32 // 公开
139+
DefaultWithVector bool // 公开
140+
}
141+
142+
// ✅ 用户配置
143+
custom := NewQdrantCustom()
144+
custom.DefaultHnswEf = 512
145+
```
146+
147+
**优势**
148+
- 概念数:1
149+
- 灵活性:无限
150+
- 清晰度:100%
151+
152+
---
153+
154+
### ✅ 模式 2:在已有 API 上扩展
155+
156+
```go
157+
// ✅ 已有的闭包 API
158+
xb.Of(...).QdrantX(func(qx *QdrantBuilderX) {
159+
qx.HnswEf(512) // 使用已有的,不新增
160+
})
161+
162+
// ❌ 不要新增
163+
xb.Of(...).QdrantHighPrecision() // 新的 API
164+
```
165+
166+
---
167+
168+
### ✅ 模式 3:便捷方法(必须极其常用)
169+
170+
```go
171+
// ✅ 允许(极其常用)
172+
func (built *Built) SqlOfUpsert() (string, []interface{})
173+
174+
// 判断标准:
175+
// 1. 是否 90% 的 MySQL 用户都需要?(UPSERT:是)
176+
// 2. 是否无法通过配置实现?(需要专门逻辑:是)
177+
// 3. 是否会增加认知负担?(SqlOfUpsert 名字清晰:否)
178+
```
179+
180+
---
181+
182+
## 🛡️ 守护机制
183+
184+
### 1. **代码注释守护**
185+
186+
在构造函数中加入:
187+
```go
188+
// ⚠️ 设计原则:只提供这一个构造函数!
189+
// 参考:xb v1.1.0 的教训(预设函数 → v1.2.0 全部删除)
190+
```
191+
192+
---
193+
194+
### 2. **文档守护**
195+
196+
`DESIGN_PRINCIPLES.md` 中明确:
197+
- 禁止模式
198+
- 历史教训
199+
- 决策流程
200+
201+
---
202+
203+
### 3. **Code Review 守护**
204+
205+
PR Checklist:
206+
- [ ] 是否增加了新的构造函数?(如果是 → 拒绝)
207+
- [ ] 是否可以通过字段配置实现?(如果是 → 拒绝)
208+
- [ ] 是否增加了概念数量?(如果是 → 慎重)
209+
210+
---
211+
212+
### 4. **AI Review 守护**
213+
214+
当 AI(包括我)提议增加 API 时,自动问:
215+
216+
```
217+
🤖 AI: "要不要加 QdrantForRAG()?"
218+
219+
📋 Review Checklist:
220+
1. 用户不用这个能实现吗?
221+
→ 能(设置字段)
222+
223+
2. 这会增加概念数量吗?
224+
→ 会(新增 1 个命名)
225+
226+
3. 那为什么要加?
227+
→ ...
228+
229+
结论:❌ 拒绝
230+
```
231+
232+
---
233+
234+
## 📊 历史教训
235+
236+
### xb v1.1.0 的错误
237+
238+
| 添加的概念 | 原因 | 现状 |
239+
|----------|------|------|
240+
| `QdrantHighPrecision()` | "方便用户" | v1.2.0 删除 |
241+
| `QdrantHighSpeed()` | "方便用户" | v1.2.0 删除 |
242+
| `QdrantBalanced()` | "方便用户" | v1.2.0 删除 |
243+
| `MySQLWithUpsert()` | "方便用户" | v1.2.0 删除 |
244+
| `MySQLWithIgnore()` | "方便用户" | v1.2.0 删除 |
245+
| `InsertPoint()` | "专用 API" | v1.2.0 删除 |
246+
| `InsertPoints()` | "批量操作" | v1.2.0 删除 |
247+
| `Delete()` | "统一风格" | v1.2.0 删除 |
248+
249+
**总计删除:8 个概念**
250+
251+
---
252+
253+
## 🎯 决策流程
254+
255+
### 当想增加新 API 时
256+
257+
```
258+
问题:用户需要 XXX 功能
259+
260+
Step 1: 能否通过现有 API 实现?
261+
├─ 是 → 停止,不增加
262+
└─ 否 → Step 2
263+
264+
Step 2: 能否通过字段配置实现?
265+
├─ 是 → 停止,不增加
266+
└─ 否 → Step 3
267+
268+
Step 3: 是否 90% 用户都需要?
269+
├─ 否 → 停止,不增加
270+
└─ 是 → Step 4
271+
272+
Step 4: 是否会增加概念数量?
273+
├─ 是 → 重新思考设计
274+
└─ 否 → 可以考虑(但要慎重)
275+
```
276+
277+
---
278+
279+
## 💎 成功案例
280+
281+
### xb v1.2.0
282+
283+
**问题**:MySQL UPSERT 很常用
284+
285+
**❌ 错误方案**
286+
```go
287+
MySQLWithUpsert() // 新概念
288+
```
289+
290+
**✅ 正确方案**
291+
```go
292+
built.SqlOfUpsert() // 便捷方法,名字清晰,不增加认知负担
293+
```
294+
295+
---
296+
297+
### xb Qdrant
298+
299+
**问题**:Qdrant Insert 数据结构不同
300+
301+
**❌ 错误方案**
302+
```go
303+
InsertPoint(point) // 新 API,破坏统一性
304+
```
305+
306+
**✅ 正确方案**
307+
```go
308+
Insert(func(ib) { ... }) // 统一 API,Custom 内部智能处理
309+
```
310+
311+
---
312+
313+
## 🌟 愿景
314+
315+
**让 xb 成为 Go 生态简洁性的标杆**
316+
317+
- ✅ 概念少:新手 5 分钟上手
318+
- ✅ 功能强:覆盖 SQL + Vector DB
319+
- ✅ API 稳定:一次学习,终身受用
320+
- ✅ 影响 Go 生态:证明简洁可以很强大
321+
322+
---
323+
324+
## 📖 推荐阅读
325+
326+
- [Go Proverbs](https://go-proverbs.github.io/)
327+
- [The Zen of Python](https://www.python.org/dev/peps/pep-0020/)
328+
- [UNIX Philosophy](https://en.wikipedia.org/wiki/Unix_philosophy)
329+
330+
**核心思想相通**
331+
> "Do one thing and do it well"
332+
> "Worse is better"
333+
> "Less is exponentially more"
334+
335+
---
336+
337+
## 🔒 承诺
338+
339+
**xb 项目承诺**
340+
341+
1. ✅ 每个数据库只有一个基础构造函数
342+
2. ✅ 新 API 必须通过"4 步决策流程"
343+
3. ✅ 定期审查:能否删除现有 API
344+
4. ✅ 文档优先于代码
345+
346+
**守护 Go 生态的简洁性!**
347+
348+
---
349+
350+
**版本历史**
351+
- v1.1.0: 学到了教训(8 个概念删除)
352+
- v1.2.0: 实践了原则(Less is more)
353+
- 未来: 永远坚守(Don't add concepts)
354+
355+
---
356+
357+
**这个文档本身就是守护者。** 🛡️
358+
359+
**当你想增加 API 时,先读这个文档。** 📖
360+
361+
**如果 AI 提议增加概念,拿这个文档反驳我。** 🤖
362+
363+
---
364+
365+
**xb - 简洁的守护者!**
366+

0 commit comments

Comments
 (0)