1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="author" content="韩暮秋">
<meta name="subtitle" content="暮秋小屋">
<meta name="description" content="这里是暮秋小屋,思念和灵感的寄存处">
<meta name="keywords" content="韩暮秋,MuqiuHan,'Muqiu Han', 'muqiu han', muqiuhan">
<title>
谈谈软件工程 |
暮秋小屋
</title>
<link rel="icon" href="/favicon.ico">
<style>
@font-face {
font-family: CarroisSong;
src: url('/fonts/CarroisSong.ttf');
}
</style>
<!-- stylesheets list from _config.yml -->
<link rel="stylesheet" href="/css/style.css">
<!-- scripts list from _config.yml -->
<script
src="/js/menu.js"></script>
<script
src="https://polyfill.alicdn.com/polyfill.js?features=es6"></script>
<script
id="MathJax-script"
async
src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/mathjax/3.2.0/es5/tex-mml-chtml.js"></script>
<meta name="generator" content="Hexo 6.3.0"></head>
<body>
<div class="mask-border">
</div>
<div class="wrapper">
<div class="header">
<div class="flex-container">
<div class="header-inner">
<div class="site-brand-container">
<a href="/">
暮秋小屋
</a>
</div>
<div id="menu-btn" class="menu-btn" onclick="toggleMenu()">
菜单
</div>
<nav class="site-nav">
<ul class="menu-list">
<li class="menu-item">
<a href="/">
主页
</a>
</li>
<li class="menu-item">
<a href="/categories/gallery/">
日记本
</a>
</li>
<li class="menu-item">
<a href="/tags/Medicine/">
医学
</a>
</li>
<li class="menu-item">
<a href="/tags/Technique/">
计算机/互联网
</a>
</li>
<li class="menu-item">
<a href="/tags/Life/">
生活
</a>
</li>
<li class="menu-item">
<a href="/archives">
全部
</a>
</li>
<li class="menu-item">
<a href="/about">
关于
</a>
</li>
<li class="menu-item search-btn">
<a href="#">Search</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="main">
<div class="flex-container">
<article id="post">
<div class="post-head">
<div class="post-info">
<div class="tag-list">
<span class="post-tag">
<a href="/tags/Technique/">
Technique
</a>
</span>
</div>
<div class="post-title">
谈谈软件工程
</div>
<span class="post-date">
Dec 20, 2025
</span>
</div>
<div class="post-img">
<div class="h-line-primary"></div>
</div>
</div>
<div class="post-content">
<blockquote>
<p>在有限认知下,持续对抗系统熵增,在相互冲突的目标间做出最优权衡,以可工程化的方式交付价值。</p>
</blockquote>
<p>一、复杂性是固有属性,而非偶然缺陷</p>
<p>软件复杂性源于<strong>状态空间的指数级爆炸</strong>。一个仅有100个布尔变量的系统,其状态空间已达 $2^{100}$(约 $10^{30}$),远超人类认知极限。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 示例:复杂度不在于代码行数,而在于状态组合</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Order</span>:</span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self</span>):</span><br><span class="line"> <span class="variable language_">self</span>.paid = <span class="literal">False</span> <span class="comment"># 2^1</span></span><br><span class="line"> <span class="variable language_">self</span>.shipped = <span class="literal">False</span> <span class="comment"># 2^2</span></span><br><span class="line"> <span class="variable language_">self</span>.cancelled = <span class="literal">False</span> <span class="comment"># 2^3</span></span><br><span class="line"> <span class="comment"># 3个布尔值 -> 8种合法状态,但业务规则会禁止某些组合</span></span><br><span class="line"> <span class="comment"># 真实系统有上千个状态变量 -> 灾难</span></span><br></pre></td></tr></table></figure>
<p>复杂性是软件的本质,无法消除,只能转移或控制。这与建筑工程有本质区别,桥梁不会自发产生新状态。</p>
<p>二、 熵增是不可逆热力学过程</p>
<p>组织沟通结构的混乱会精确映射为代码结构的混乱。代码在没有外力干预下必然走向腐烂。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">graph TD</span><br><span class="line"> A[需求变更] --> B[快速补丁]</span><br><span class="line"> B --> C[技术债务]</span><br><span class="line"> C --> D[开发速度下降]</span><br><span class="line"> D --> E[更多补丁]</span><br><span class="line"> E --> C</span><br><span class="line"> style C fill:#f00,stroke:#333,stroke-width:2px</span><br></pre></td></tr></table></figure>
<p>技术债务的利息是<strong>超线性</strong>增长的。一个类被10个模块依赖时,修改它的成本不是10倍,而是约 $O(n^2)$ 倍,因为需要理解所有依赖方的上下文。</p>
<p>三、人类认知约束</p>
<p>人类工作记忆容量为 $7 \pm 2$ 个信息单元。这是代码审查、架构设计、故障排查的硬性天花板。</p>
<ul>
<li><strong>微观影响</strong>:函数参数超过5个,Bug率指数上升(认知过载)</li>
<li><strong>宏观影响</strong>:微服务拆分粒度需匹配团队规模(2个披萨团队原则)</li>
</ul>
<p><strong>工程化手段</strong>:通过<strong>抽象</strong>和<strong>封装</strong>将信息压缩到认知边界内。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 坏:每次调用需理解10个参数</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">processOrder</span><span class="params">(<span class="type">int</span> userId, <span class="type">int</span> productId, String addr, ... )</span> <span class="comment">// 8+参数</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 好:将认知负荷压缩到1个概念</span></span><br><span class="line">orderProcessor.handle(<span class="keyword">new</span> <span class="title class_">OrderContext</span>(...)); <span class="comment">// 单一职责</span></span><br></pre></td></tr></table></figure>
<p>四、权衡是唯一的决策动作</p>
<p>不存在"最佳实践",只存在"在特定约束下的最优权衡"。</p>
<table>
<thead>
<tr>
<th style="text-align:left">维度</th>
<th style="text-align:left">方案A</th>
<th style="text-align:left">方案B</th>
<th style="text-align:left">权衡代价</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left"><strong>一致性</strong></td>
<td style="text-align:left">强一致 (分布式锁)</td>
<td style="text-align:left">最终一致 (事件驱动)</td>
<td style="text-align:left">可用性↓ vs 延迟↓</td>
</tr>
<tr>
<td style="text-align:left"><strong>性能</strong></td>
<td style="text-align:left">缓存热点数据</td>
<td style="text-align:left">实时查询DB</td>
<td style="text-align:left">一致性风险 vs 成本↑</td>
</tr>
<tr>
<td style="text-align:left"><strong>交付</strong></td>
<td style="text-align:left">重构老系统</td>
<td style="text-align:left">增量迁移</td>
<td style="text-align:left">短期风险 vs 长期成本</td>
</tr>
<tr>
<td style="text-align:left"><strong>灵活性</strong></td>
<td style="text-align:left">抽象接口</td>
<td style="text-align:left">硬编码</td>
<td style="text-align:left">复杂度↑ vs 开发速度↑</td>
</tr>
</tbody>
</table>
<p><strong>决策框架</strong>:每次技术选型必须回答:</p>
<ol>
<li>优化了什么指标?(延迟、吞吐、正确性)</li>
<li>牺牲了什么?(成本、一致性、简单性)</li>
<li>牺牲是否可接受?(业务是否允许P99.9延迟上升50ms?)</li>
</ol>
<p>五、工程化 = 可重复 + 可验证 + 可协作</p>
<p>代码本身是廉价的,<strong>可维护、可演进的系统</strong>才是工程目标。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">graph LR</span><br><span class="line"> subgraph "工程化三支柱"</span><br><span class="line"> A[自动化测试] --> D[可验证]</span><br><span class="line"> B[CI/CD流水线] --> E[可重复]</span><br><span class="line"> C[Code Review + 文档] --> F[可协作]</span><br><span class="line"> end</span><br><span class="line"> D & E & F --> G[对抗熵增]</span><br></pre></td></tr></table></figure>
<p><strong>关键指标</strong>:</p>
<ul>
<li><strong>MTTR</strong>(平均修复时间) < <strong>MTBF</strong>(平均故障间隔)是伪命题。真实目标是:<strong>MTTR 必须小于业务容忍的极限</strong>。</li>
<li><strong>Bus Factor</strong>:核心模块的 Bus Factor=1 时,系统已处于高风险状态,与人无关,是工程化失败。</li>
</ul>
<hr>
<p>自然界趋向无序,软件工程通过持续注入<strong>负熵</strong>(规范、测试、重构)维持秩序。</p>
<p>在认知约束下,通过严格的工程纪律,将不可控的复杂性转化为可控的复杂性,并在永恒的权衡中追求局部最优解。</p>
<p>没有银弹,只有<strong>在正确的时间,为正确的目标,做出正确的权衡,并准备好为选择付出代价</strong>。</p>
</div>
<script>
window.onload = detectors();
</script>
<div class="post-footer">
<div class="h-line-primary"></div>
<nav class="post-nav">
<div class="prev-item">
<div class="icon arrow-left"></div>
<div class="post-link">
<a href="/2025/12/25/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%94%E6%97%A5/">Prev</a>
</div>
</div>
<div class="next-item">
<div class="icon arrow-right"></div>
<div class="post-link">
<a href="/2025/12/19/%E4%B8%B4%E5%BA%8A%E7%A0%94%E7%A9%B6%E4%B8%AD%E7%9B%B2%E6%80%81%E8%A7%84%E5%88%99%E5%AD%98%E5%9C%A8%E7%9A%84%E5%8E%9F%E5%9B%A0/">Next</a>
</div>
</div>
</nav>
</div>
<div class="post-comment">
</div>
</article>
</div>
</div>
<div class="footer">
<div class="flex-container">
<div class="footer-text">
韩暮秋 |
希望路过的人可以添点柴火让这里暖和点
</div>
</div>
</div>
</div>
<div class="search-popup">
<div class="search-popup-overlay">
</div>
<div class="search-popup-window" >
<div class="search-header">
<div class="search-input-container">
<input autocomplete="off" autocapitalize="off" maxlength="80"
placeholder="Search Anything" spellcheck="false"
type="search" class="search-input">
</div>
<div class="search-close-btn">
<div class="icon close-btn"></div>
</div>
</div>
<div class="search-result-container">
</div>
</div>
</div>
<script>
const searchConfig = {
path : "/search.xml",
top_n_per_article: "1",
unescape : "false",
trigger: "auto",
preload: "false"
}
</script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/search.js"></script>
<script src="/js/search.js"></script>
</body>
</html>
|