作者 | 袁慎建
保持简单
简单是一个成年人司空见惯的词,然而,大部分成年人却觉得纯真的孩子才是简单的。
很多时候,人们习惯把“简单”跟“容易”理解成一个意思。简单和复杂多用于形容事物或人的属性或状态,容易和困难一般形容达到某种目标的过程。生活中经常听到这样的感慨:「人活简单点真难啊!」、「系统一不小心就搞复杂了」。这些感慨背后流露出一种心愿 -- 保持简单。
对于人来说,保持简单可能意味着人情世故的简单、工作关系的简单、心态的简单。对于软件系统来说,则意味着系统设计的简单、部署运维的简单等等。
三重境
看山是山,看水是水;看山不是山,看水不是水;看山是山,看水是水。
保持简单的确不是一件容易的事情。禅宗提出的人生三境界中也诠释了这个理:人从简单开始,以复杂贯穿了大部分甚至整个人生,最后返璞归真。
对应到一个需求简单的软件系统中,系统的设计一开始处于简单的状态。然而软件开发的核心问题是复杂多变的业务需求,随着时间的推移,软件系统可能呈现出以下三个状态:
正常情况下,没有人希望系统处于第三个状态,而是希望从第二个状态回到第一个状态。映射到禅宗的人生三境界,系统的理想三境界是:
- 清晰 -- 单一化
- 复杂 -- 层级化
- 清晰 -- 模块化
在面临复杂多变的业务需求,如何设计一个恰好简单够用的系统?如何保持系统的高响应力?程序员们一直都没有停止对最佳实践的探索,始终为这些目标奋斗。软件开发的所有问题最终都能归结到人身上,那么驱动程序员不断改进的力量是什么?
我心中有一个答案:对简单设计、高响应力价值的认可,对简单设计价值观的深层内化。
核心观
价值观往往给人一种感觉:看着这些高大上的词汇,缺点什么,却总又说不上来。比如极限编程(XP)的价值观:沟通、简单、反馈、勇气、尊重。再比如 Scrum 的价值观:专注、开放、承诺、勇气、尊重。尤其是刚开始接触这些知识体系的新人,每个词都能看懂,只是不知道如何用它们去指导 XP 和 Scrum。
在 Thoughtworks 工作这么多年,我亲自实践过 XP 和 Scrum,也在很多场合传授过它们,再回过头来看,我深刻体会到一点——XP 和 Scrum 的那些实践跟它们的价值观都非常吻合。我能够在日常开发以及培训和练习中去落地简单设计,这背后驱使我不断探索的是已内化于心的观念:
专注
在 Scrum 中,专注强调的是所有人都专注于 Sprint 目标,团队同为一个目标努力。对于简单设计,要专注在哪里呢?我结合自身经历的几个典型的场景来看:
- 一上来匆匆忙忙编写业务代码,没有Tasking,没有测试,没有设计,业务Scope逐步偏离或扩大
- 在编码阶段,听到声音:“你这个设计太土气了,都没用设计模式”,于是琢磨着怎么去套设计模式
- 在系统架构设计阶段,有人说:“什么年代了,你还不拆出几个微服务”,于是尝试拍脑袋拆出一个分布式单体
上述三个场景,究其根本,是没能很好地专注于自己要实现的真实业务价值,要么缺乏思考和设计,要么受外界影响,舍本琢末。你可能会质问:不应该多做点设计来兼容后期可能出现的情况吗?为未来做设计,难免会掺入不合时宜的猜测,不仅增加系统当前的复杂度,还可能浪费成本。
我觉得要始终保持对当下真实业务价值的专注,专注理解业务本质,专注于刚好够用的设计,时刻让系统保持简单,尽可能跟业务模型保持匹配和同步。
克制
克制力是一项非常重要且需要长期培养的能力。由于受到太多外界的干扰而难以定静,程序员经常会因为沉浸在自己的世界里,可能出现乐观估算,还可能经常过度设计。
而实际上,大部分乐观的估算会让团队交付面临更多风险,大部分健壮性设计会让系统难以理解和修改。我想起来自己曾经面试过的一个候选人,一个很简单的业务需求,硬生生地套用了5种设计模式,叹为观止。
在日常交付项目和工作坊中,我会较为留意开发人员嘴里发出的 “我觉得”、“假如”、“万一”、“以后”等用语,这些用语背后所隐藏的溢念(溢出的想法),很可能促使该开发人员交付一个不满足需求的软件,或者一个难以维护的系统。
我觉得程序员克制自己一个有效的方式是培养业务视角,站在用户使用系统的视角尝试深刻理解业务,通过将业务需求进一步拆解成小颗粒度的任务来让自己保持聚焦。Think Big(深刻理解业务问题并拆分),Start Small(每次只聚焦在某一个小的任务),Move Fast(快速完成一个个小的任务并获得反馈)。
洁癖
我经常在 Code Review 中被同事开玩笑说有代码洁癖,比如对命名太较真了。一开始我会有所妥协,毕竟软件开发是一个团队来完成的,如果因为某个人的洁癖而让其他人不舒适,可能不利于团队协作。可是时间后来告诉我,那些身披“不认真”或者“不严格”标签的小魔头会在后面出来制造各种噪音,比如命名看不懂、结构不一致、架构混乱臃肿等等。
做程序员这几年,洁癖潜移默化影响着我的编码和设计风格,小到变量命名、代码注释、文档管理,大到系统架构,我都会时刻保持警惕,尽其所能去消除噪音污染。在没有其他不可抗拒的因素前提下,我都会尽力尝试让团队接纳自己对代码洁癖的追求。
洁癖更侧重于团队个体成员,对于个体,可以通过不断提升自己的整洁代码认知来强化它,并尝试在实践中去运用它们。而对于团队,我想到一条指导原则:任何有助于提升系统质量的洁癖都不应该被忽视,团队应该尽力接纳并落实。
懒惰
恰当的“懒惰”是一个优秀的程序员必备的特质,因为 Ta 总是勤于思考如何才能少做重复的事情。
懒惰听起来是一个负面的词,中国几千年的文化价值观在告诉每一个人要做勤奋努力的人。在软件开发领域,我认为恰当的懒惰是解放程序员生产力、保持系统简单的助推剂,比如:
- 需求或设计变更,懒得改太多代码。怎么办?消除代码重复,隔离和封装变化,分离关注点
- 手工集成和测试,懒得重复做。怎么办?增加自动化测试并做好CI/CD
- 用户鉴权分散在各个服务中,懒得修改所有的服务。怎么办?引入API Gateway
- 新人上项目,搭建环境反复找我,懒得重复讲。怎么办?编写自动化脚本和文档指南
如果每次面对相同的问题,不得不花精力去处理,在这种毫无挑战的重复性工作中,人通常很容易犯错,所以,当手懒得去做这些事情,懒惰会驱使大脑去思考一种更加高效的方式,比如隔离变化将其封装,引入自动化,从而取代一遍遍重复的操作,并且大脑还会思考如何运用 KISS(Keep it Simple and Stupid),Yagni,如无必要,勿增实体。
有一种看似很”勤快”的CCCV(CMD + C | CMD + V)编码行为,这些行为背后跟我提倡的懒惰大相径庭。CCCV行为是思想上的懒惰,在这种思维的指导下,双手会乐此不疲去重复做很多重复的事情,CCCV当规避之。
勤于思考,惰于盲行,做一个具备恰当惰性的程序员是一种快乐。
需要勇气
在 XP 和 Scrum 鼓励人们要有勇气去做正确的事情、处理棘手的问题、做出承诺、坚持原则、拒绝损害工作的行为、暴露自己的不足并寻求帮助、提供有建设性的意见等。
要保持简单,这些勇气也是不可或缺的。同时,我提倡程序员培养 保持专注、克制溢念、养成代码洁癖、滋养恰当的懒惰的勇气。