理解和驾驭软件开发的那些事儿
如何高效学习和掌握新技术,如何驾驭软件开发的复杂度,是摆在每位软件工程师的头等课题。 本文谈谈自己从事软件开发六年半左右的一些思考、感悟和方法。
理解力考验
软件开发的核心基本能力是理解和表达事物的能力。 理解力决定能够抵达的高度。
-
从与主管、客户、产品经理和项目经理沟通的角度来说,需要能够理解他们说话的语境和背景,从而推敲其真正的意图;需要理解他人的需要和意图;表达只有在理解的基础上进行才是有效和有份量的;这里的理解指“自然语言层面的”。
-
从熟悉业务和产品的角度来说,需要能够理解现实中的事物、事务以及相互的关联,并简明扼要地绘制出来;这里的理解指“分析语言层面的”。
-
从开发程序的角度而言,需要对所要处理的事物的性质和规则有深入的了解,能够理解抽象的概念、模型和设计思路。这里的理解是“计算语言层面的”。
-
在实际工作中,需要在有限的时间内处理潮涌而来的大量事务,理解不断涌现的各种新的思想和技术以及新的发现,在必要时作出恰当的反应和行动,包括优先处理重要紧要的事情、需求和项目,适当的忽略和放弃。这即对一个人的理解和表达能力提出了“速度”和“敏捷度”的高要求。
纵观软件开发活动,无非是在持续不断地理解话语、理解事物、理解事务、理解软件设计与实现、表达自己的观点、完成所学所能中完成的。
对于初级工程师来说,执行力和具体做事情会很重要;对于高级工程师,设计规划和把事情想清楚更为重要。
方法论
五环相扣
软件开发是科学亦是工程,需要一套有效的方法论更好地指导工作。
- 分而治之。 复杂任务往往是由简单任务通过多层次组合而形成的;将复杂任务进行分解,分解到每个子任务都在能力掌控范围内。
- 系统思考。 仅仅理解事物的子部分还不够,需要以系统思考的视角,去理解事物组成部分的关联,事物存在的支撑机制。从事基本的开发工作,也许只要分而治之,但要掌握软件工程之道,要有系统思考的全局观。
- 抽象模型。 将事物赋予概念,对事物关联建立简要的模型进行处理。对事物的理解从具象的形式到抽象的意义。比如圆形意味着阻抗低;锁意味着隐私;房子意味着庇护;门意味着可授权的入口;盆意味着开放性容纳等。
- 科学规律。 学习和探索事物与逻辑的性质和运行规则集合。比如数学性质;物理学定律;适当的缓存能提升效率。
- 注重细节。 在宏观理解的基础上,还需要关注细节,解决好细节问题,才能做到更好。
分而治之 - 系统思考 - 抽象模型 - 科学规律 - 注重细节, 是从整体到部分,从局部看到全景,从具体深入抽象,从宏观到微观,从理论到实际的方法总论。
两层视角
开发软件系统与堆积木有很大相似之处。熟悉积木的特性和组合方式,然后运用想象力将积木拼成有趣的事物。 积木对应软件的组件,而最终成品则对应软件本身。
可以从两层视角来看待软件系统:组件层和系统层。 组件层是可以直接使用的部分,内部实现可以在适当的情况下去探索,有时也需要自行设计和创造;而系统层则是要构建的整体服务。系统层通常是基于组件层的业务代码组成,需要全景式的视角,代码逻辑相对容易理解,出问题通常出在业务层; 组件层常常属于框架范围,设计得更加抽象一些,需要花更多时间去理解。一旦理解,也会有助于系统层的设计与实现。
组件本身又是更小的系统层,由多个更小的组件集成而成。 这体现了软件系统的层次性。 设计软件系统,不应过早深入细节,而是先在组件级别思考,需要哪些可靠的组件,怎么将这些组件进行集成。
物人事
物
软件研发的主要产出在于开发自动化、可扩展、可靠、安全、高效的软件系统。 要做到这一点,越来越需要对软件系统的整体有一个全景式的理解,而不是局限于所开发的模块。基于一个已有的软件进行开发,往往需要做一些评估,代码改动和 CodeReview 时都需要评估影响范围和风险,而唯有全景式的理解,才能做出准确的影响和风险评估。
只要坚持做软件研发,专业技能的精益求精是必不可少的。
人
尽管软件研发的主要产出在于软件系统,过程中不可避免要与许多人打交道和合作。 与同组小伙伴、TL、中间件团队、上游业务团队、产品经理、项目经理、架构师、测试同学、运维同学、客满同学、运营同学、HR 同学等,都会有广泛的交流。
沟通技能在研发中起着非常重要的支撑作用。
事
在软件开发的过程中,需要应对许多许多的事情。 文档梳理、设计与开发、会议沟通、方案讨论、线上问题的排查与解决、用户麻烦的临时支持等等。 这些事情往往是交织在一起,而且容易挤在一起,因此,需要做一些有效的规划,才能更从容地应对。
对事情的意义、重要性和优先级的理解和规划,决定着是否可以在有限的时间内做出更有成效的事情。
日常工作
编程开发
编程开发的首要任务是深入理解业务。从用户角度来看,是场景、需求、功能与体验;从系统设计角度来看,是模块、接口与交互; 从底层实现角度来看,是流程、规则、数据、影响范围。
软件是逻辑的大规模组合,是精密的逻辑装置。要想一下子吃掉一个比较大型的软件,往往是吞咽困难的。 怎么办呢?
首先用到的方法是分而治之。将整个大型软件分解为多个子模块,弄清楚每个模块的职责及模块之间的交互; 模块还可以进一步分解为微服务、组件。 在分解的过程中,要坚持用系统思考的视角审视整个系统,做到见树亦见林。
其次,要理解组件,则需要运用抽象的方法。 抽象表达了组件的整体特征。以抽象的角度来看组件,就更容易找到组件的普遍特征和差异化特征,做到更好的扩展性。
组件再往下深入一层,就是科学规律。 比如 TreeMap 是基于红黑树实现的。红黑树的原理是什么呢? 是基于着色的二叉查找树的性质。 理解科学规律,才能更好地理解组件的实现。
弄清楚组件的原理和规律后,还需要重点关注: 细节。 细节可以小到一个字段的类型是否合理兼容,中到并发执行的顺序问题,大到整体错误处理的层次性和设计。细节常常决定成败。
工程技术
理解和开发软件系统,可以分为两个层次: 组件,以及组件连接的系统全景图。开发和实现可靠的组件,需要精湛的技术知识;而将组件连接成可维护的软件系统,则需要工程技术。工程技术关注的是组件之上的系统集成层。
软件工程的主要目标是管理复杂性。 复杂性来源何处?
- 缺乏全局的架构设计,代码逻辑散落在各处,相关文档缺失,无从追觅其缘由;
- 作为一项团体协作的产出,不同人的代码风格不一致,导致阅读理解上的困难;
- 市场业务的多样与演进,历史债务与当前需求的交织,设计与实现的不一致,导致系统容易成为一个难以理解和维护的大杂烩;
- 持续保障线上服务的稳定运行,阻止负面影响的 BUG 和故障,需要严格的测试工程和流程保障。
相应的对策有哪些呢 ? 我能想到的如下:
- 规划各个应用和模块的职责与定位,收拢逻辑, 梳理业务的服务依赖关系。
- 制定开发规范,在整体上保持一致的风格,可以允许个性化的创造,更多体现在设计能力上。
- 进行持续而严谨的 CodeReview , 增强团队成员的代码质量意识和技能。
- 迭代消减历史债务,用新方式替换老的方式;对于新需求,遵循设计先行原则,认真评估设计方案。
- 与测试同学密切合作,学习测试方法和技术,保障测试充分。
质量驾驭
要编写出没有 BUG 的程序几乎不可能,但要编写出满足需求,没有负面影响的 BUG 的程序,不造成线上故障,还是可以的。
首先是细心和用心。对于较大的发布,用文档记录涉及应用的发布、任务、配置及其顺序。 发布时,严格按照顺序,允许的话分成几个时段发布,降低一次的发布压力;发布后,半小时内不离开,观察线上服务情况和机器状态。切忌发布过程中离开。
接着,评估改动的影响范围。对于基础部分和必经之路的改动,要高度敏锐,哪怕只是一行 setter 。 反复推敲每一行的改动是否有影响,切忌局部改动影响整体。
然后,遵循良好的代码风格和习惯,掌握常用的编程技巧,避开常见的陷阱。 可以参阅 “从实战角度看如何构建高质量的软件:一线工程师的一份质量手记” 。 积少成多,冰冻三尺非一日之寒。
开发完成后,要遵循严格的测试准则。单测、接口测试,必要的时候进行对比测试。
最后,对于设计问题,要及时吸取教训。
经过一系列的关卡,代码上线就会更有自信更安全。
项目掌控
通常是指互联网企业中存在的多项目并行情况。比如一个项目在提测中,一个在预发中,两个在开发中,涉及的点也比较多,还有两个正在全力赶过来。如何提升多项目的掌控力呢?
从项目经理的角度来看,每个模块的职责在于: 1. 完成预先评估的任务和工作,为整体流程和功能质量提供保障; 2. 在适当可接受的时间范围内完成,保障项目进度,减少延期时间。
-
优先级与预先评估。仔细查看各项目的联调、提测、预发、上线时间,确定优先级,错开时间;留出缓冲余地。此时,并不涉及实际开发,而是涉及到评估。 评估意味着:1. 需求理解; 2. 现有实现; 3. 改动点评估; 4. 任务拆分与工作量评估; 5. 时间评估。 评估性的活动,与编程是同等有挑战的事情。
-
关键点评估。 一定要事先评估好该项目的关键点、重点、难点,识别出风险点,及时报备,并考虑到估时中。
-
充分开发自测。 要提升联调效率,要充分评估到改动点和开发自测,否则联调和提测的问题找上门来,一样让人吃不消。比较理想的情况是,自己的改动点都在掌控之中,只要部署好了,关注项目进度即可。
-
时间管理。 为改动点比较大的项目安排整段的时间,专注地解决问题。减少不必要的任务间切换。
-
申请资源。 再能干的人,多个项目同时挤压过来,也是很可能扛不住的。要及时申请资源,并说明充足理由。 很多事情,需要在做之前就想好。
-
拓展项。 不局限于自己的模块,而是理解整个项目的技术栈,重难点问题及解决方案,收获更多。
交流沟通
-
深入理解事理,下足功夫,准备充分,有说服力;
-
语气和方式委婉柔和。
-
换位思考。从对方的处境考虑问题,理解对方的立场和视角。
实战总结
在实战中学习、总结、提炼经验,做案例分析;通过实战追溯理论,扎实基础,用更好的方式去思考和解决实际问题。探索式工作与学习。
对于重要的案例及经历,要及时加以记录。记录下来的将是工程师职业生涯中的宝贵财富。 因为不记录下来, 三个月或半年或一年之后, 就会忘得干干净净。 这时候,得到的只是“似曾相似”的感觉,而不是确切的可以随时调用的知识和能力。
心境
- 适当地运动、休息和饮食,保证健康的身体状况。
- 放开心灵,观察和探索整个的世界,深入细致地去理解和分析事物。
- 克服急于求成的心理,把事情想清楚再行动。
- 保持进击的状态,进击中自由探索,时而放松。