阅读架构整洁之道
1. 介绍
1.2. 序言
1.2.1. 码农心得
走快的唯一方法是先走好:作为编码者,更快的编码,更快的测试,上线。可以带来暂时的甜头很受用!但是长时间如此不考虑扩展性,代码高可用。迟早也会吃下这个恶果的
有重构的机会,一定要把握住。即使项目经理在催工期,他觉得成本很高,你也要向他说明差的架构加上未来再重新提需求返工带来的成本。一个好的架构,不仅可以在某一个特定的时刻满足软件用户、开发者和所有者的需要,更要在一段时间内持续满足他们的后续要求
1.2.2. 读书笔记
Bob 大叔上来就发问什么是软件架构,但是并没有回答,而是引入了架构学科,从架构学科来看在一定程度上能做到抓大放小,把握住重点,虽然会错失某些重要的细节信息。
架构学科分为两个讲,一是从建筑上来看,物理建筑的架构结构必须遵循"重力"这一自然规律,同时符合材料的物理特性。二是从软件上看,它没有一条一条的约束,大型软件依赖于小软件,小软件内部实现可能是乱七八糟也可能是内容清晰层次分明。
我想到我司的软件架构由多个任务节点串联起来实现一个业务,开发者关心子任务的开发实现即可,想想架构师已经把框架搭好了,开发者往里面拆分任务,塞入内容就好。典型的抓大放小,具体业务就是"小"。
虽然软件架构无法用肉眼看到,但是软件真正运行时是在现实生活中的,所以我们在设计软件架构的过程中,必须理解和遵守现实的约束条件。CPU 速度和网络带宽往往在很大程度上决定了系统的性能,而内存和存储空间大小也会大幅影响代码的设计野心。
系统的性能:通常体现在吞吐量。CPU 是电脑的大脑决定了运算速度,网络带宽高低决定了报文传输的速度,自然会影响到吞吐量的高低。
代码的设计野心:内存和存储空间会影响到我们可以引入多少中间件比如 redis,es,rocketmq 等等。我是这样理解的。
1.3. 前言
1.3.1. 码农心得
编程语言相通性:编程语言中很多东西比如数据类型,控制循环语句,数据结构算法,设计模式,面向对象等等,大都是类似的,只不过语法上有些区别。为什么呢?程序是控制电脑硬件工作的指令,程序的语法就是指令的书写规则,不同编程语言都要编译成相同的指令代码-机器码,不同程序的编译结果,是一堆不同组织顺序的机器码。就像是同一堆积木(机器码),有不同的堆积方法(组织顺序)。
1.3.2. 读书笔记
Bob 大叔介绍了软件架构的规则是相同的!为什么呢?
首先是计算机代码可以看成是机器码是没有变化,软件架构的规则是排列组合代码块的规范,由于这些代码块本质上没有变化,因此排列组合它们的规则也就不会变化。所以软件架构的规则也就一直保持了一致。所以软件架构一直没有变化。不同的编程语言会有不同的语法,但是编译后的机器码是没有变的。编程语言所用的架构规则可以说是一直未变的,而我们学习的就是这些经过历史推敲的架构规则,让我们写出更加优秀的代码!
2. 正文
2.1. 第一章-设计与架构究竟是什么
2.1.1. 码农心得
设计和架构我想着就是一回事,站在另一个角度上看,城市规划者就可以称之为架构师,哪些是娱乐区域,哪些是卫生区域,哪些是原材料生产基地。建筑小兵,去按照规划图去有条不紊的去搬砖。如果城市需要扩建,小兵按照原有的规划图,保持原有的风格进行扩建即可。
为什么需要软件架构?在程序发展之前可没有这一个名词,随着软件慢慢发展,发现如何才能保持着系统稳定性开发,持续性交付。总结出的共性就是需要软件架构支持!软件架构的终极目标是用最小的人力成本来满足构建和维护该系统的需求!就像一所城市需要规划者。
2.1.2. 读书笔记
作者介绍了架构和设计其实没有什么区别,架构是一个更高级的词汇!例如别人问我你们项目架构是什么?我就从 DB 到中间件,服务,Nginx,F5。从下往上依次介绍一波!如果问到设计?我就从一个服务如何处理一个请求入手,更加的深入细节。这些细节撑起了顶层的架构设计。底层的设计加上顶层的架构设计共同组成整个项目架构!
如何判断一个项目架构是否优良?可以用满足用户需求所需要的成本来衡量!如果该成本很低,并且在系统的整个周期内一直能维持这样的低成本,那么这个系统设计就是优良的!如果该系统的每次发布都会提升下一次变更的成本,那么这个设计就是不好的。举个例子:比如你前端需要加一个字段显示,但是评估开发和测试时间很长就很不对劲,背后就代表着你单元测试繁杂,代码逻辑不清晰在深层点就是架构问题。
不知道你有没有这样的感觉,刚进入一个项目,项目才刚刚启动,同事们捶胸顿足,一个月上线一款产品,慷慨激昂!随着产品越来越多,公司招入更多的人开发。但你慢慢会感觉得整体的开发变慢了。。。用户每一次提新需求的时候,测试都要很长一段时间,之前一款产品测试 2 天,三款产品要一个星期。而且用户也会对原有的功能提需求,随着业务的发展原有的功能需要增强,比如统计资产信息需要导出,前端需要添加职业字段等等都是对开发和测试的挑战。
对于我和我的同事来讲很难受,有很大的挫败感,因为每个人都在干活加班 996,但是不管加过多少次班,救过多少次火,产出始终上不去。花费的时间都是对现有的系统修修补补上,而不是真正完成实际新功能,拆东墙补西墙,偶尔才有精力完成一个小功能。
对于领导们,天天喊,“控制成本,尽早验收付款”,他们除了跺脚,喊人,其实什么也干不了!
我突然想到另一本书的一个故事,医生与患者,患者对于医生手术之前卫生清洁工作嗤之以鼻,觉得耽搁时间。便告诉医生没有必要做清洁卫生的工作,直接干!医生说这是我的专业素质,同时也是对你的负责!扯远了。。。
公司如果有架构师,一定要多多咨询,或者多看看他们写的代码,尽量保持同样的风格,这是相当好的。如果没有或者接触不到,那就要多看书,多看源码来提高我们每一个 coder 的专业性!
Bob 大叔在下面也介绍了什么是优秀的,整洁的架构。我们掌握这些方法论多多实践,也能一个长期稳定的,持久优秀的系统的。跟着一起学习吧!
2.2. 第二章-两个价值维度
2.2.1. 码农心得
面试造火箭,入职拧螺丝。进入项目后,根据需求文档进行开发完成就已经达到标准了!好的,这是你应该做的行为,其实还有架构方面,如果你能站在更高一层,思考需求演变,后续如果添加新的需求,你会怎么去方便接口扩展适应业务呢?好这就是加分项,同时也能体现出来你的素质!
行为,往往是业务人员,项目经理最关心的,因为完成后能有钱赚。架构往往需要编码者去关心,有人会说那需要架构师干嘛,架构师的职责是负责整体架构,不会关心到具体行为,而编码者是行为实现者,所以如果自己关心架构的发展,维护架构稳定,这说明你关心了两个价值维度,很有素质!
2.2.2. 读书笔记
对于每一个软件系统,我们都可以通过行为和架构两个维度来体现他的实际价值。软件研发人员应该确保自己的系统在这两个维度上的实际价值都能维持在一个很高的状态。
什么是行为价值呢?软件研发人员通过开发一段程序可以帮助人在现实生活中,比如你开发一个报表,帮助银行职工统计,减少了他们统计的时间,同时提高了准确度。这就是你的行为产生的价值。
什么是架构价值呢?业务提出了一个需求[每日资产分布统计报表],一天完成。业务又提出一个需求[每日资产年龄分布统计报表],两天完成。这两个报表增加导出功能,需要三天完成。从时间上看说明需求变的复杂了,但是这需求都是类似的,对你来说成本却在增加。是不是应该想一下,自己设计是否是应该合理呢?有没有考虑到功能的扩展性。
后面提供代码进行参考,先立个 flag1
这两个维度对我们来说都很重要,哪一个优先级更高呢?Bob 大叔提出了艾森豪威尔矩阵,来进行说明
软件系统的第一个价值维度:系统行为,是紧急的,但是并不总是特别重要。
软件系统的第二个价值维度:系统架构,是重要的,但是并不总是那么紧急。
业务和项目经理总是把认为行为是优先级高的,我说实话大多数为了省事,图快。他们说什么就干什么,没有考虑太多,就写代码把项目搞的乌烟瘴气的,以至于到后面,再来需求,维护又新增需求真心累。看到 Bob 大叔说,评估系统架构的重要程度,这本来就是研发人员自己的工作职责!所以平衡系统架构的重要性和功能需求的紧急性这件事,是软件研发人员自己的职责,我们都希望项目像纯洁的少女,温柔的白雪,所以当项目出现坏味道的时候,一定要停下来问一下自己,现在在干什么,有考虑了系统的扩展性了嘛?
Bob 大叔,这一节强调了我们软件开发人员身上应该有种责任感。
2.3. 第三章-编程范式总览
2.3.1. 码农心得
三大范式都是设置限制,从某一个方面限制和规范了程序员的能力。没有一个范式是增加能力的。这些范式主要是为了告诉我们不能做什么,而不是做什么!
再次让我觉得编程都是相同的,提到三大范式,我以为是最近几年刚提出的概念,谁知道都是上一个世纪的概念,还是我太无知啊,而且从上一个世纪提出之后,在没有新的编程范式提出。觉得很惊讶!这是什么经典玩意,好吧,让我们学习一下经典吧,出发
2.3.2. 读书笔记
结构化编程对程序控制权的直接转移进行了限制和规范。
面向对象编程对程序控制权的间接转移进行了限制和规范。
函数式编程对程序中的赋值进行了限制和规范。
这些编程范式的历史知识与软件架构有关系吗?当然有,而且关系相当密切。譬如说,多态是我们跨越架构边界的手段。函数式编程是我们规范和限制数据存放位置与访问权限的手段。结构化编程则是各模块算法实现的基础。三种编程范式在编程语言中不是明确割裂的,不同语言有各自的侧重点。我是 Java 方面的觉得侧重在面向对象,结构化编程,2014 年发布了 Java8,引入了函数式编程。
这和软件架构的三大关注重点不谋而合:功能性,组件独立性以及数据管理。
2.4. 第四章-结构化编程
2.4.1. 码农心得
相比于 Dijkstra 先生,我们现在编码可真是太幸福和轻松了,编码说小点就是字母随机组合并符合特定的语法,门槛低,需求大,只不过有点卷!
软件开发虽然看起来是在操作很多数学结构,其实不是一个数学研究过程。恰恰相反,软件开发更像是 一门科学研究学科,我们通过无法证伪来证明软件的正确性。在高中,大学时代,数学的证明题永远都是在证明一个正确的结论,软件开发测试就是证伪,证明是一个假命题,费劲努力找到问题,找不到才姑且认为符合当前需求目标。
2.4.2. 读书笔记
可推导性:Dijkstra 先生认为写程序是一件富有技术含量的活,有时候一个细节的错误,会导致整个程序崩溃。于是他提出了使用数学推导方法,总而言之就是将程序分成小的程序单元,证明程序单元是正确的,那么一整块程序就是正确的。在拆分过程中,发现 goto 这个东西可以随意跳来跳去,给拆分造成了极大的困难。Dijkstra 在前人的基础上知道顺序结构,分支结构,循环结构可以造成任何程序,那么这三种结构可以去取代 goto。所以 Dijkstra 通过枚举法证明分支结构,通过数学归纳法证明循环结构,通过数学推导方法证明顺序结构。有理有据,npplus
功能性降解拆分:既然所有程序都可以进行拆分成可推导的程序单元,也就是说明模块可以按照功能进行降解拆分。这个也是抽象的基础,当把功能拆分后,有一些可以复用,封装的慢慢的这些重复的代码程序就会被发现!像不像微服务,一个系统拆分成多个模块,有公共的模块大家共同使用。
测试:Dijkstra 说:"测试只能展示 bug 的存在,并不能证明不存在 bug",在目前阶段只要是无法被证伪,那么就是真的。平常测试程序,很想自己程序一下跑通,怕测试出现很多问题。测试不通过没法交付,其实换一下思路,测试就是找出问题,去证伪,通过无法证伪来说明其正确性!我有时候会有家庭事业的不安全感,但这些都是自己假想出来的,其实都无法被证明,还是要珍惜当下相信彼此,好好做事呐!
结构化编程范式中最有价值的地方就是,它赋予了我们创造可证伪单元的能力。更重要的是,在架构设计领域,功能性拆分仍然是最佳实践之一。
评论