3. 软件架构设计
本文最初作为知乎专栏的README,当时的构思是这样的::
前几天发现知乎可以写专栏了,抱着试试看看的心思申请了一下。现在专栏开通了,我的
感想是:又多一个累赘……
所以我就构思一下我可以在这里写什么。作为方向性的构思,我先想到如下几条:
1. 必须写我非常熟悉的,这样我可以少动点脑筋,随口就来。
2. 因为我是做这一行的,有的是人想探我的底线。所以,这里肯定不会碰我工作有关的方
向。读者也请不要和我讨论和架构选择相关的问题。这好比打牌,我可以告诉你牌是怎
么打的,但你不要跑过来看我的底牌
3. 目标读者。我考虑的目标读者是软件相关领域的从业人员和在校学生。特别是后者。笔
者读书时的理想一直是当老师,这也算是过个干瘾。另外,自己写软件写了二十多年了
,从对软件一无所知到现在也叫有几个成功产品经验了,深感我们国家软件教育之落后
。这句话不是说要崇洋媚外。笔者职业生涯中,团队中一直不乏来自不同国家的工程师
,我们的软件学生确实在基础训练上不如别人。笔者这样说,不是说自己就可以改变什
么,而是说明,这个Gap是存在的,既然如此,这个事情就可以做。至于做的意义——意
义这种东西,那是哲学家的问题,我不讨论。
然后就是写作思路,我的想法是先定软件构架的概念——不是学术的那种概念,而是和读者
对齐软件构架是什么这个问题。是为了理解上的对齐,而不是严谨的范围区分,这两者的
区别是什么,读者很快可以看到。然后我会先介绍开发的一些基本的技能,比如怎么做单
元测试,怎么做数据结构定义等。这些知识看来简单,实际上很多开发者都学错了,在这
种问题上有错误的理解,后面我们谈什么都没有用,之后我们才会看是谈构架设计上的各
种考量。
基本上我会想到哪里写到哪里,根据读者的讨论也会走到不同的方向,欢迎读者一起讨论
。
最后,笔者是过来讨论问题的,读者来讨论,无论表达什么观点我都非常感激,但不要指
望仅过来装逼:)。装逼是一件快乐的事,但失去了要做的事情本身,仅剩下装,这个装
起来实在很丑。所以,我们要虚心实腹地“顺便装”,不要为装而装,那是很丑的。
对于软件工程师来说,什么意见会造成Patch的生成,什么意见完全是无效代码,这个其实
是很清楚的。对于无效代码,如果是无关紧要的tag我不管,但对那些我看不顺眼,解释又
会浪费逻辑空间的,我不会跟你废话,我会直接删除,所以,Please,装逼可以,请用干
货装。也许你会说,“难道你就可以肯定你是对的吗?难道你不应该谦虚一点吗? ”,你说
得对,我在这个问题上,我就是武断的。这正是软件和自然语言的讨论不同的地方。软件
每个表述,某种程度上,都是单一结果的,每行代码改进去,我们都预期唯一的结果(唯
一的含义可以斟酌,但方向是这个方向)。软件工程师是最在乎“断”的人之一了。对的判
断,和错的判断,对软件工程师来说都是“有效的”,无用的判断,才是无效的。因为软件
的成本都来自逻辑量(代码量),if(a&b&c&(d|e|f))这个判断如果写反了,前面加一个!
就解决问题了,但如果这个判断整个写乱了,这个代码就彻底没有用了。
我说的这个“有效(对/错)/无效”的名称空间就好像老子写《道德经》前面的道可道非常
道,名可名非常名一样,是全文的根本。后面读者们应该可以看到,我的所有表述,其实
都是对这个空间定义的证明。
Contents:
- 3.1. 什么是软件架构
- 3.2. 大型软件架构设计
- 3.3. 架构师具体设计什么
- 3.4. Use Case图有什么用?
- 3.5. 使用软件的四种方法
- 3.6. 从单元测试理解软件
- 3.7. 名可名
- 3.8. 小国寡民
- 3.9. 需求分析的中心思路
- 3.10. 关于自然语言编程的方向问题
- 3.11. 反者道之动——欣赏架构设计的基本逻辑
- 3.12. 让代码变立体
- 3.13. 生成优秀的架构
- 3.14. 分支设计要领
- 3.15. 怎样做项目管理
- 3.16. 谈谈子女教育问题
- 3.17. 两种基本的构架表述方法
- 3.18. 弱者道之用——谈技术工作中的守弱问题
- 3.19. 在Linux下做性能分析
- 3.20. 架构设计的0层逻辑
- 3.21. 解耦设计
- 3.22. 怎么做高层设计
- 3.23. 理解架构版本
- 3.24. PCIE总线的保序模型
- 3.25. 做与不做都是战略
- 3.26. 海洋战术式的软件设计方法
- 3.27. 解耦和不解耦
- 3.28. 再谈“守弱”
- 3.29. 互斥算法设计
- 3.30. 英文版本的“弱者道之用”
- 3.31. 什么是“守”
- 3.32. 从用户功能开始构架系统框架
- 3.33. Linux发行版的库软件包组织
- 3.34. 地址空间的故事
- 3.35. 工作和读书有什么不同
- 3.36. 怎样快速调试Linux内核
- 3.37. 架构设计中的“少了”和“多了”的问题
- 3.38. 怎样做代码Review
- 3.39. 怎样做客户访谈
- 3.40. RancherOS架构分析
- 3.41. 再谈什么是软件架构
- 3.42. 大道曰守,当时曰行
- 3.43. 不为天下先
- 3.44. 关于AI的胡说八道
- 3.45. 学习本质?
- 3.46. “设计的流程”和“代码的流程”
- 3.47. 概要设计不是代码
- 3.48. “病病”
- 3.49. 关于架构师的爱恨情仇——《黑客帝国》世界观解读
- 3.50. Linux Socket 0拷贝特性
- 3.51. 用户态DMA的问题
- 3.52. Multiprocess Support for Linux IOMMU driver
- 3.53. Linux RAS特性分析
- 3.54. 写论文
- 3.55. 基于“语义”编程
- 3.56. 从学习assert的用法开始理解如何写“专业的程序”
- 3.57. 架构的存在性
- 3.58. Makefile概念入门
- 3.59. ARM服务器进展小结
- 3.60. 怎么做初步的需求分析
- 3.61. 关于设计方案中的逻辑链问题
- 3.62. 从逻辑链问题讨论怎么做高层设计
- 3.63. 工程逻辑链
- 3.64. 为什么你会在你的数据中心中部署ARM服务器
- 3.65. 如何为libvirt设置虚拟主机
- 3.66. 给普通人解释Spectre和Meltdown安全漏洞
- 3.67. 给程序员解释Spectre和Meltdown漏洞
- 3.68. Is retpoline really safe?
- 3.69. 逻辑链,道,学和架构工作的本质
- 3.70. Serverless是什么——谈如何捕获一个特性的架构本质
- 3.71. 道法自然
- 3.72. 自然,守弱和Plan B
- 3.73. 守弱的内涵和外延
- 3.74. 找到道法自然的“度”
- 3.75. Specification的写法问题
- 3.76. 小姐和丫鬟的故事
- 3.77. 知不知
- 3.78. PCIE总线的地址问题
- 3.79. 气和深度学习
- 3.80. 单元测试的效果问题
- 3.81. Requirement Analyzing vs. Voting
- 3.82. 抽离设计逻辑
- 3.83. 盗夸
- 3.84. 抽象还是不抽象的问题
- 3.85. Tegra TX2一瞥
- 3.86. Progress and confusion of the IOMMU name space
- 3.87. 一样还是不一样
- 3.88. 运营还是交付
- 3.89. 科普一下GPL和开源软件
- 3.90. 怎么确定道
- 3.91. 回调还是直调
- 3.92. 接口的封装层次问题
- 3.93. git的基本架构欣赏
- 3.94. 让设计自生
- 3.95. 架构控制的从权问题
- 3.96. 设计的需求问题
- 3.97. 性能优化的目标问题
- 3.98. 加速器和其他硬件的区别
- 3.99. 君子与其练达不若朴鲁与其曲谨不若疏狂
- 3.100. 有无之道——一个新的软件架构定义
- 3.101. 什么是管理
- 3.102. 从香农熵谈设计文档写作
- 3.103. YVR18资料关注点
- 3.104. 理解关联
- 3.105. 如何撰写技术交底书
- 3.106. 再谈什么是高层设计
- 3.107. 再谈“法自然”的设计思路
- 3.108. 设计规范
- 3.109. 开源交付
- 3.110. 道纪
- 3.111. X86上的ARM Linux调试环境
- 3.112. IOMMU的现状和发展
- 3.113. 单元测试的强与弱问题
- 3.114. 做事,做名,绩效主义,以及架构战略
- 3.115. 没有规则的规则
- 3.116. 大成若缺
- 3.117. 非易失内存随想
- 3.118. 参考平台
- 3.119. 一个例子:名的边界效应
- 3.120. 抽象问题的模型
- 3.121. 另一个例子:名的边界效应
- 3.122. Zircon架构简单分析1:Overview
- 3.123. 在qemu中模拟设备
- 3.124. 国产操作系统问题
- 3.125. 软件飞线
- 3.126. 状态机方法
- 3.127. 一些典型的架构设计错误
- 3.128. 从CPU和TPU的不同语言抽象看抽象原则
- 3.129. 限制管理
- 3.130. UACCE as a General Heterogeneous Platform
- 3.131. Multiarch概念调查
- 3.132. ARM NUC
- 3.133. UML有没有用
- 3.134. 推演一个Buffer分配的语法设计
- 3.135. 架构师和项目经理的基本职责问题
- 3.136. 锁使用设计
- 3.137. 从内核终止用户态程序的IO访问
- 3.138. epoll和select
- 3.139. 状态机退出方法
- 3.140. 不为天下先2
- 3.141. 设计逻辑和代码逻辑
- 3.142. 流水线深度
- 3.143. 谁是主线?
- 3.144. 理解指令集
- 3.145. 给使用设备的进程发信号
- 3.146. Linux设备异常复位逻辑分析
- 3.147. 投资开源社区的基本逻辑
- 3.148. 一个Linux死锁信息分析
- 3.149. 如何说谎
- 3.150. 代码生成器
- 3.151. 弟子规:美国军方禁止在C语言程序中使用malloc
- 3.152. 自下而上和自上而下的设计
- 3.153. 正面竞争
- 3.154. 不知为美
- 3.155. 高层封装的设计战略
- 3.156. 产业生态的原理和作用
- 3.157. 弯道问题
- 3.158. 无名概念的深入探讨
- 3.159. 解释On-Chip Debug和Off-Chip Debug
- 3.160. 接口和名称空间辨识
- 3.161. RISCV WMO和TSO具体解决什么问题
- 3.162. 利益链
- 3.163. 从C的for和Python的for聊起
- 3.164. 安全建模问题讨论
- 3.165. Accelerator vs. Co-processor
- 3.166. 一个逻辑空间控制的例子:uacce生命周期管理
- 3.167. 软件构架设计的入题角度问题
- 3.168. 接口分层的问题
- 3.169. 对Cache Coherence的重理解
- 3.170. 接口定义的工作模型
- 3.171. Linux net和net-next分支的维护策略
- 3.172. WarpDrive用户态方案重构建议
- 3.173. 主线逻辑
- 3.174. 架构设计的粗与细问题
- 3.175. 狂人日记读后感——名称空间囚笼
- 3.176. 写程序和写小说的区别
- 3.177. 再谈《弟子规》问题
- 3.178. 理解弱内存顺序模型
- 3.179. 思维上的洞2
- 3.180. 后软件时代和技术沙盘陷阱
- 3.181. 怎么做项目管理2
- 3.182. 语言的控制力问题
- 3.183. 分享我的Linux内核开发环境
- 3.184. 开发视图
- 3.185. 概念视图
- 3.186. 处理视图
- 3.187. 语言控制力问题
- 3.188. 新手设计文档典型错误
- 3.189. 讨论:OpenCL2.0SVM有什么好?
- 3.190. 设计逻辑的细致和严密问题
- 3.191. 逻辑的平面和立体问题
- 3.192. 自由和约束
- 3.193. 给非专业人士介绍架构设计工作
- 3.194. AML工作原理快速调研
- 3.195. qemu PCIe总线结构
- 3.196. ARM64 Linux Kernel 5.7无法GDB调试问题
- 3.197. 分层抽象
- 3.198. 见素抱朴:一个关于交付的例子
- 3.199. 三个锦囊
- 3.200. 多核MMU和ASID管理逻辑
- 3.201. PMA和PA方案对比
- 3.202. 真假架构设计
- 3.203. 怎样写标准提案
- 3.204. 安全问题的本质
- 3.205. 名称内涵的发展
- 3.206. 标准和设计的区别
- 3.207. cond/mutex模型
- 3.208. 一个例子:架构的重要性和从权
- 3.209. nvdimm AD模式的内核应用模型
- 3.210. 早期架构设计问题
- 3.211. 所谓内部设计
- 3.212. “知不知”如何影响决策的?
- 3.213. “优秀架构设计”
- 3.214. Linux Kernel架构赏析
- 3.215. 说说对协程的看法
- 3.216. 架构设计和实施的对齐和同步问题
- 3.217. 一个关于4+1视图的案例:从概念视图开始
- 3.218. “硬件状态机”
- 3.219. 设计的减熵原理
- 3.220. 架构设计入门知识
- 3.221. 架构设计的大忌:我没错
- 3.222. “解决方案”
- 3.223. 讨论一下eBPF
- 3.224. 交付中的Version和Revision
- 3.225. 约束选择
- 3.226. 在概念空间选择方案
- 3.227. git submodule的理解
- 3.228. 思维的串行化要求
- 3.229. 什么是函数式编程
- 3.230. 管理上的判断和技术上的判断
- 3.231. 基于逻辑链建立约束
- 3.232. 高级需求分析
- 3.233. 假共享内存(False Sharing)
- 3.234. 芯片验证软件的4+1方法
- 3.235. 软件之硬
- 3.236. 诚其意
- 3.237. 把什么放入架构设计
- 3.238. ARMv8的安全特性的主线逻辑
- 3.239. 指令寻址模式
- 3.240. 线程的本质
- 3.241. 限制的可移动性
- 3.242. 2020年又写的一个什么是架构设计的定义
- 3.243. 政善治
- 3.244. 概念空间建模要领
- 3.245. 例子和全集定义
- 3.246. 编译阶段和运行阶段算力
- 3.247. 逻辑闭包和抽象概念定义
- 3.248. 主语问题
- 3.249. 关于概念空间,接口的一些具体讨论
- 3.250. 构架和没错问题的进一步讨论
- 3.251. 专家意见和编辑意见
- 3.252. 架构设计和普通设计的区别
- 3.253. 构架设计的接地气问题
- 3.254. 一个例子——逐句翻译是怎么掐断逻辑链的
- 3.255. 一个逻辑链断裂引起架构设计方向错误的实例
- 3.256. 确定逻辑的根
- 3.257. 机器腔和人类腔
- 3.258. 附录
- 3.259. ABI
- 3.260. 视图和决策面
- 3.261. 架构首先是一种信念
- 3.262. 一个架构设计实例:qemu iommu
- 3.263. 架构的改革属性
- 3.264. 逻辑如水
- 3.265. 综合
- 3.266. 几个架构定义问题的实例
- 3.267. 细节的丢失
- 3.268. 一个架构评审案例
- 3.269. 建模
- 3.270. 逻辑正交
- 3.271. 一些架构设计引导的例子
- 3.272. iommu设备和uacce关系分析
- 3.273. 什么叫做“没有设计成分”
- 3.274. 逻辑闭包的范围管理
- 3.275. RISCV中断方案分析
- 3.276. 逻辑的范围问题
- 3.277. 我们是怎么放弃架构的
- 3.278. Uacce fork问题建模
- 3.279. 设计和科普
- 3.280. 向前兼容数据格式设计
- 3.281. 架构和装修
- 3.282. 关于敏捷项目的一些逻辑
- 3.283. 硬件同步时间差问题的设计逻辑
- 3.284. 抽象的一个具象
- 3.285. 天网恢恢
- 3.286. 逻辑闭包V2
- 3.287. 抽象和细节的信息屏障
- 3.288. 什么是架构设计V3
- 3.289. 一个架构设计模糊精确的例子
- 3.290. 硬编码Tag方案
- 3.291. 设计语言和编码语言的区别
- 3.292. 用Qemu调试Linux内核的技巧总结
- 3.293. 什么是架构设计V4
- 3.294. 软硬件结合设计的实践问题
- 3.295. 信心和建模问题
- 3.296. 在语义上评价逻辑
- 3.297. 细节迷信
- 3.298. 接口对象问题
- 3.299. 设计的驱动力问题
- 3.300. 什么是架构设计2023
- 3.301. 抽象思维
- 3.302. 架构设计和一般设计的区别
- 3.303. 为什么架构设计必须使用自然语言
- 3.304. 目标约束和实施约束
- 3.305. 专利思维和设计思维
- 3.306. 为什么很多人看书学不会架构设计
- 3.307. 对卷积的感性理解
- 3.308. 为什么不要画市场式的架构图
- 3.309. 不要把细节特征当作设计
- 3.310. 架构设计中猜的成分
- 3.311. 对一个设计评审意见的深入探讨
- 3.312. 关于语义的辨识
- 3.313. 基于状态机的行为定义
- 3.314. 设计问题总结的问题
- 3.315. 高层设计和下层设计的区别V2
- 3.316. 集合分界不同的问题
- 3.317. 一个简单的复杂视图建模例子
- 3.318. 无价之宝——一个设计仿写的例子
- 3.319. 设计的本质
- 3.320. 关于队列模型
- 3.321. 语义纠偏——细节调研的目的和方向
- 3.322. 填空问题
- 3.323. 中文标准写作总结
- 3.324. 一个例子:为什么我们的信息组织不成设计
- 3.325. AI架构设计入门
- 3.326. 三生万物
- 3.327. 解释Transformer模型
- 3.328. 一个架构设计的具象例子
- 3.329. AI编程中人的作用
- 3.330. 把AI Agent关到笼子里的一点体验总结
- 3.331. AI时代的知识管理
- 3.332. 从一个Skill的设计过程理解概念空间
- 3.333. 一些未分类的例子