21 | 架构设计:普通程序员也能实现复杂系统?
为什么软件项目需要架构设计?
精英稀缺、全栈稀缺,通过架构设计让普通程序员也能参与其中,一起实现复杂系统。
复杂系统,需求不确定、技术复杂。
技术的复杂性体现在
需求让技术变复杂
人员会让技术变复杂
技术本身也是复杂的
要让软件稳定运行是复杂的
架构设计要解决技术复杂性的问题
降低满足需求和需求变化的开发成本
帮助组织人员一起高效协作
帮助组织好各种技术
保障服务稳定运行
什么是架构设计?
架构设计,就是通过组织人员和技术,低成本满足需求以及需求的变化,保障软件稳定高效运行。
目标
用最小的人力成本来满足需求的开发和响应需求的变化,
用最小的运行成本来保障软件的运行。
常见的架构设计
微服务,把复杂系统拆分成一系列小的服务,服务再拆成功能模块,让人员更好地分工协作。
前后端分离,让程序员更专注于某个知识领域,降低开发难度
分层设计,隔离业务逻辑,减少需求变更带来的影响。
架构设计之道
组织人员和技术进行系统和团队拆分,
安排好切分后的排列关系,
使拆分后的各部分能通过约定好的协议相互通信,
共同实现预想的结果。
如何做好架构设计?
一、分析需求,满足业务需求是架构设计最基础的目标。分析功能、界面、用户、场景。
二、选择相似的、成熟的架构设计方案。选择架构方案、开发语言、框架,根据项目情况、团队情况综合考虑。
三、自顶向下层层细化。
四、验证和优化架构设计方案。架构设计并非一成不表,在实际开发的过程中,需要根据实际情况不断进行优化和调整。
22 | 如何为项目做好技术选型?
技术选型就是项目决策
技术选型看起来是个技术的选择,但其实是一个和项目情况密切相关的项目决策。
回到项目金三角,技术选型同样受时间、范围和成本的约束。
要分析可行性和风险。
要考虑利益相关人
项目决策中常见的坑
把听到的观点当事实,片面相信网络上的技术言论。
先入为主,有了结论再找证据。个人喜好,主观出发。
如何做好技术选型?
四个阶段,问题定义、调研、验证、决策。
问题定义
为什么需要技术选型?技术选型的目标是什么?
提升开发效率,降低开发成本,不是为了使用新酷技术。
Make It Work!Make It Right!Make It Fast!
只有明确了技术选型的目标,才能有一个标准可以来评判该选择哪一个方案。
调研
从以下方面对技术进行分析
满足技术选型目标吗?
满足范围、时间和成本的约束吗?
是不是可行?
有什么样的风险?风险是不是可控?
优缺点是什么?
验证
试用、demo,做的过程中才能知道,选择的技术选型是不是真的能满足技术选型的目标。
决策
在调研和验证完成后,就可以召集所有利益相关人一起,就选择的方案有一个调研结果评审的会议,让大家提出自己的意见,做出最终的决策。
讨论区归纳
宝玉老师的选型原则
成熟的好过新酷的
流行的好过小众的
团队熟悉的好过陌生的
简单的好过复杂的
开源的好过商业的(有时候也视情况而定)
23 | 架构师:不想当架构师的程序员不是好程序员
前言
拿破仑那句名言:“不想当将军的士兵不是好士兵。”原句是Every French soldier carries a marshal’s baton in his knapsack”,意思是“每个士兵背包里都应该装有元帅的权杖”。
其实拿破仑的本意是激励每一名上战场的士兵都要有大局观,有元帅的思维,并不需要每一个人都一定去当将军、当元帅。
这同样适用于技术领域,对程序员来说,并不代表一定要有一个架构师的头衔,而应该心中有大局观,有架构师的思维。从而能理解架构设计,能写出好的程序。
什么是架构师思维?
架构师思维,其实就是这几种思维的集合。
抽象思维
抽象思维可以说是整个架构设计的基础。需求进行抽象建模,隐藏无关紧要的细节,在高层次的架构设计。
分治思维
对复杂系统分而治之,分解成小的、简单的部分。但光分解还是不够的,还需要保证分解后的部分能够通过约定好的协议集成在一起。
复用思维
通过对相同内容的抽象,让其能复用于不同的场景。
迭代思维
好的架构设计,通常不是一步到位,而是先满足好当前业务需求,然后随着业务的变化而逐步演进。
好的架构师什么样?
一个好的架构师,不仅技术要好,还要懂业务;能从整体设计架构,也能在局部实现功能。
好的架构师,应具备以下几个条件:
有架构师思维:具备良好的抽象思维、分治思维、复用思维和迭代思维;
懂业务需求:能很好地理解业务需求,能针对业务特点设计好的架构;
有丰富的编码经验:像抽象、分治、复用这些能力,都需要大量的编码练习才能掌握;另外保持一定量的编码经验也有助于验证架构设计;
良好的沟通能力:架构师需要沟通确认需求,需要让团队理解架构设计。
如何成为好的架构师?
从程序员开始,付出比普通程序员更多的努力,成为好的架构师,没有捷径。
宝玉老师的建议:
成为一个优秀的程序员。技术好是成为架构师的基础条件,首先让代码易读,易扩展,能重用。通过大量的编码实践,逐步培养出好的架构师思维。
多模仿多学习。先把业界成熟的流行的架构吃透,用好。
选择好行业和平台。想当架构师,最好选择一个合适的行业,积累足够的行业知识,以后才能更好地设计出符合业务特点的架构。
24 | 技术债务:是继续修修补补凑合着用,还是推翻重来?
什么是技术债务?
技术债务,就是软件项目中对架构质量和代码质量的透支。
技术债务是有利息的
债务的“利息”,就是在后面对软件做修改的时候,需要额外的时间成本。
技术债务不一定都是坏的
刻意欠债的场景,如
提升短期的开发速度,让软件能尽快推出,抢占市场。
快速原型开发中,通过欠技术债务的方式快速开发快速验证。
技术债务产生的原因
《重构》中 Martin Fowler从两个维度分析技术债务产生的原因
1. 轻率(reckless)还是谨慎(prudent);
2. 有意(deliberate)还是无意(inadvertent)。
不同债务定义、现象及影响
- 轻率 / 有意的债务
定义:团队因为成本、时间的原因,故意走捷径没有设计、不遵守好的开发实践,没有后续计划改善债务。
现象:不做设计直接编码,后期也没有打算重构代码。或者是团队成员以新手程序员为主,没有足够的资深程序员指导和审查代码。
影响:通常这类债务会一直积累,会导致利息越来越多,最终带来的负面效果会越来越大。
- 谨慎 / 有意的债务
定义:团队清楚知道技术债务的收益和后果,并且也制定了后续的计划去完善架构和提升代码质量的情况。
现象:比如说为了尽快发布产品,先采用“快猛糙”的方式开发,后续再对代码进行重构。
影响:因为能及时偿还,所以既可以短期有一定时间上的收益,长期也不会造成负面影响。
- 轻率 / 无意的债务
定义:团队不知道技术债务,也不知道要后续要偿还技术债务的情况。
现象:对于什么是架构设计,什么是好的开发实践一无所知,代码一团糟。
影响:这类债务最危险,既没得到技术债务的收益,还要偿还其产生的利息。
- 谨慎 / 无意的债务
定义:团队其实很重视架构设计和技术债务,但因为业务的变化,或者其他客观因素的原因,所产生的债务。
现象:设计的时候,无法准确预测后面业务的发展,随着业务的发展,设计无法满足好新的需求。
影响:债务难以避免,但如果能及时的对架构升级、重构,就能保证不会造成严重的影响。
如何管理技术债务?
Is it worth the effort to design software well?
策略:让技术债务控制在临界点之下
识别技术债务
开发速度降低
单元测试代码覆盖率低
代码规范检查的错误率高
Bug 数量越来越多
其他,如语言或者框架的版本太老,开发人员总是需要加班加点才能赶上进度
选择处理技术债务策略
重写:推翻重来,一次还清。缺点,工作量很大,新系统没完成之前,同时要对旧系统维护和增加新功能,压力非常大;另外新系统重新稳定下来需要一段时间。
维持:修修补补,只还利息。缺点,越到后面,维护的成本就越高。
重构:新旧交替,分期付款。缺点,整个过程耗时相对更久。
三种策略并没有绝对好坏,需要根据当前项目场景灵活选择。
实施策略
对于重写的策略,要当作一个正式的项目来立项,按照项目流程推进;
对于重构的策略,要把整个重构任务拆分成一个个小任务,放到项目计划中,创建成 Ticket,放到任务跟踪系统中跟踪起来;
对于维持的策略,也要把需要做的修补工作作为任务,放到计划中,放到任务跟踪系统中。
实施策略的关键就在于要落实成开发任务,做为项目计划的一部分。
预防才是最好的方法
预先投资,好的架构设计、高质量代码。
不走捷径,日常能做好代码审查、保障单元测试代码覆盖率。
及时还债,把欠下的技术债务记下来,放到任务跟踪系统中,安排在后续的开发任务中。
课后感
需求分析师和架构师都是IC但又需要leadership的角色。他们是从两个维度降低软件开发的复杂性。需求复杂度和技术复杂度。同时,他们又要组织好团队内的相关活动和知识管理,促进组织发展。
康威定律,Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations. - Melvin Conway(1967)。关联到架构设计,通俗的理解就是,组织沟通方式决定系统设计。
技术债,可以借债加速发展,但债是有利息了。当债务巨大的时候,体现在系统就是系统维护需要大量人力,极小的需求改动也需要大量开发。