架构之美-读书笔记之二

架构之美第二章

两个系统的比较,功能类似,但是结局不同。

这两个系统特点有什么不同?是什么导致了不同的结局?

混乱大都市

特点:

微观层面特点:

1. 没有统一的概念将不同的部分组织起来
2. 代码风格不一致
3. 控制流无法预测,即控制流的流向很复杂
4. 额外的数据缓存,其目的让数据停留在更方便的地方(但是,容易造成数据的不一致性,维护或扩展不方便)
5. 没有人了解整个系统,没有任何文档


宏观层面特点:
1. 系统没有弹性,无法变更和添加新功能
2. 版本周期过长,低品质的软件
3. 对第三方支持协议,涉及太多内部结构。会出现难以理解的、不容易复现的错误。
4. 团队新成员不理解整个系统,不能搞请状况,流失率高

原因:
造成的恶果的原因:

1. 没有清晰的需求。这个是项目开始之初,团队就不知道要构建什么。这个是混乱的一个重要原因。

2. 系统结构难以理解,坏的架构设计只会招致更坏的设计(因为想解决问题,只能选用阻力最小的方法)

3. 缺乏内聚,不相关的功能放在一起,没有清晰的角色定义
4. 不必要的耦合。系统没有最底层,没有控制中心,所有组件必须一开始就创建。这使得代码层次的测试不能进行。

5. 没有共同的代码风格,没有共同的库,没有共同的命名习惯。重复的代码到处被使用。

6. 开发周期过长,造成整个系统测试、迭代困难,软件质量没有保证,这个即使恶果,又是原因之一

------------

设计之城


而比较成功的设计,往往是一个持续的过程,不仅仅表现为几个特征


如设计之城的各阶段的特征:
在设计早期:
1. 确定了主要的功能领域,并推出初步架构

2. 系统中各独立部分的位置关系体现为传统的分层结构。并且,这些是基本的系统设计,可以随功能模块添加进行扩展。

3. 一些基本关注点的决定:
1) 顶层文件结构
2) 如何对事物命名
3) 内部"展示"风格
4) 共同的编码惯例
5) 选择单元测试
6) 一些基础设施的选择(如版本控制、系统的构建与持续集成)

在第二阶段,功能扩展:
1. 新代码的定位
一开始就有系统结构清晰的总体视图,所以,新的功能单元可以添加到正确的功能区域,而不是为了一时方便,代码随意添加。(这样,有的时候开发者的工作会需要动写脑筋,但是在系统维护和扩展时,就变得容易了)

2. 系统的一致性
顶层设计的良好风格和决定,为底层代理好处,代码是统一、整洁的。清晰的定义,确保没有重复的代码、接口惯例和常见设计模式被普遍使用、没有特殊生命周期的对象和资源管理问题。(这个重点是在于减少功能重复)

3. 架构增长
没有什么是一层不变的,架构应该是方便扩展、可重构的。这样,代码可以快速增长,同时又保持好的内部结构,添加新的功能不是问题。

4. 延迟设计决定
这部分应该是需求问题。YAGNI(如果不是马上需要,就不要去做),早期只设计中要的部分,将余下的决定推迟。特别是,不确定的需求,需要猜测。

5. 保持品质
结对编程、对代码复审、单元测试。对不正确、不合适的变更都要拒绝。开发者需要对设计负责。

6. 技术债务管理
什么是技术债务?为了赶时间,对于不太重要的功能被砍掉,允许小的代码"瑕疵"存在,发布时避免高风险的改动。这些都应该被标记为技术债务。
应该选择合适的时间,及时集中清理这些技术债务,在后续版本中修改。

7. 单元测试 打造设计
单元测试在很大程度上定性了代码设计,它迫使我们实现好的结构,保证可测性。

8. 遵守设计
新的成员可以比较容易地拿起代码开始工作。开发团队动态地遵守架构设计,项目原则规定没有人"拥有"某部分设计,而是所有人都应该写出高品质的代码,可以改动系统的所有地方。

未来:
1. 没什么是一成不变的,在整洁的背景下,突出的技术争论应该被解决掉。着重于适应性强的架构和灵活的代码结构。


我自己遇到过的


好的系统架构:

我看过一个导航引擎的架构,这个一个好的架构,是因为:

1. 软件清晰的定义,分层的设计,功能划分明确,各部分的依赖关系,数据通信方式确定。如Positioning, DestinationInput, Routing, Guidance, MapViewer等。

2. 代码结构清晰,功能模块划分后,对于底层和组件的关系进一步分析,将结构进行分层设计。划分出common,data access等公共部分。如此,代码的文件结构也比较清晰,每个模块的文件夹下,有各自的头文件与实现文件。

3. 外部接口与内部实现尽量分离。所有外部接口部分的声明都单独放在一个文件中,而内部结构的声明与实现放在其他文件中。如果是大部分模块都使用的数据结构,那就把它放入common层定义,在同一层内的模块间的数据结构基本相互独立,不同模块的数据结构尽量不相互引用(开发中会增加一些麻烦,但结构上更清晰)。

4. 统一的框架和一些代码生成工具。保证了内部统一的风格,编码惯例。但是这些框架和工具也增加了入门的难度。

5. 保证单元测试,并且有一个完整的simulator,离线模拟器,replay模块,保证了测试的及时性。

6. perforce,版本控制工具。


其他:
1. 基本没有重复的代码
2. 独立的模块,单元测试,迫使结构走向高内聚,低耦合的状态。


另外一个,说不上是失败的系统,但是有一些特点是明显需要改进的地方:
1. 对新成员,没有完整的系统结构文档可以理解

2. 对于一个MVC式的结构,数据传递要经过很多层,特别是底层处理部分,新成员一般了解不到。如果一个模块没有完整的系统结构说明,开发人员需要很久才能完整的了解这个模块。
开发人员一般容易被一些类图累到,而容易忽视底层或外在的数据/控制流向。

3. 重复的代码随意可见,为了及时完成业务逻辑,相同的代码被复制粘贴。造成比较严重的技术债务。



其他比较大型的项目的通病:
1. 编写比较复杂的结构,并使用一些自制工具,这使得入门比较难。知其然不知其所以然。

第一部分 论架构 第1章 架构概述  13 1.1 简介  13 1.2 创建软件架构  19 1.3 架构结构  23 1.4 好的架构  27 1.5 美丽的架构  28 致谢  30 参考文献  31 第2章 两个系统的故事:现代软件神话  33 2.1 混乱大都市  34 2.2 设计之城  40 2.3 说明什么问题  47 2.4 轮到你了  48 参考文献  48 第二部分 企业级应用架构 第3章 伸缩性架构设计  51 3.1 简介  51 3.2 背景  52 3.3 架构  56 3.4 关于架构的思考  61 第4章 记忆留存  67 4.1 功能和约束  68 4.2 工作流 69 4.3 架构关注点  70 4.4 用户反应  90 4.5 结论  90 参考文献  90 第5章 面向资源的架构:在Web中  91 5.1 简介  91 5.2 传统的Web服务  92 5.3 Web  94 5.4 面向资源的架构  99 5.5 数据驱动的应用  102 5.6 应用面向资源的架构  103 5.7 结论  108 第6章 数据增长:Facebook平台的架构  109 6.1 简介  109 6.2 创建一个社会关系Web服务  114 6.3 创建社会关系数据查询服务  121 6.4 创建一个社会关系Web门户:FBML  129 6.5 系统的支持功能  142 6.6 总结  147 第三部分 系统架构 第7章 Xen和虚拟化之美  151 7.1 简介  151 7.2 Xenoservers  152 7.3 虚拟化的挑战  154 7.4 半虚拟化  155 7.5 Xen的变换形式  158 7.6 改变的硬件,改变的Xen  163 7.7 经验教训  165 7.8 延伸阅读  166 第8章 Guardian:一个容错操作系统环境  169 8.1 Tandem/16,将来所有的计算机都会像这样构建 170 8.2 硬件  170 8.3 物理布局  172 8.4 处理器架构  172 8.5 处理器间总线  178 8.6 输入/输出  178 8.7 进程结构  179 8.8 消息系统  179 8.9 文件系统  183 8.10 轶闻趣事  188 8.11 弊端  189 8.12 后继者  190 8.13 延伸阅读  191 第9章 JPC:一个纯Java的x86 PC模拟程序  193 9.1 简介  193 9.2 概念验证  195 9.3 PC架构  198 9.4 Java性能技巧  199 9.5 把4GB放入4GB:这不起作用  200 9.6 保护模式的危险  203 9.7 从事一项毫无成功希望的斗争  206 9.8 劫持JVM  210 9.9 终极灵活性  220 9.10 终极安全性  222 9.11 第二次做会更好  223 第10章 元循环虚拟机的力量:Jikes RVM  225 10.1 背景  225 10.2 与运行时环境相关的传言  227 10.3 Jikes RVM简史  229 10.4 一个自足执行的运行时自举  230 10.5 运行时组件  234 10.6 经验教训  246 参考文献  247 第四部分 最终用户应用架构 第11章 GNU Emacs:滋长的特性是其优势  251 11.1 使用中的Emacs  252 11.2 Emacs的架构  254 11.3 滋长的特性  260 11.4 另外两个架构  262 第12章 当集市开始构建教堂  267 12.1 简介  267 12.2 KDE项目的历史和组织结构  269 12.3 Akonadi  274 12.4 ThreadWeaver  289 第五部分 语言与架构 第13章 软件架构:面向对象与面向函数  299 13.1 概述  299 13.2 函数式示例  302 13.3 函数式解决方案的模块性评价  305 13.4 面向对象视图  313 13.5 面向对象模块性的评价和改进  319 13.6 代理:将操作封装到对象中  323 致谢 328 参考文献 328 第14章 重读经典  331 14.1 所有东西都是对象  335 14.2 类型是隐式定义的  342 14.3 问题  348 14.4 砖块和灰浆建筑架构  352 参考资料  359 跋 漂亮地构建 363
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值