本篇读书笔记的内容大部分是来自我刚参与的掘金的读书打卡活动. 我在这次读书打卡活动选择了《简约之美: 软件设计之道》这本书. 我把这几次打卡的内容作了整合, 也加了一点没有在打卡活动里面写的内容构成了这篇读书笔记, 希望读者可以有些收获.
追求卓越还是得过且过
"程序中复杂的部分必须以某种简单的方式组织起来... 这就是编程所要用到的艺术和才能 - 化繁为简.'差程序员'是不会化繁为简的. 他们总以为编程语言" 能跑通 " 的程序, 就已经化解了复杂性, 而没考虑降低其他程序员需要面对的复杂性... 在这些程序员看来, 他们写出来的东西是能用的, 这就是他们的老板需要的, 看来也应该是客户需要的... 他们把结果交给其它程序员, 其他程序员又会在这之上增添复杂性, 完成自己的工作.
程序员对化解复杂性考虑得越少, 程序就越难懂... 所以,'好程序员'应当竭尽全力, 把程序写得让其他程序员容易理解. 因为他写的东西都很好懂, 所以要找出 bug 是相当容易的.
-- 来自《简约之美: 软件设计之道》"
这里提到的化繁为简, 我认为就是将复杂的系统以清晰的结构与高可读性的代码呈现出来的过程. 作者认为不能仅仅为了完成需求来写代码, 这是一种应付老板和客户的行为. 他认为写代码的时候还要考虑到代码是否可以让人容易理解, 当然也包括是否易修改, 易扩展, 易维护. 因为随着需求的不断增加, 代码的维护成本会越来越高.
其实这本身就是认知高度和自我要求的问题: 你是选择追求卓越, 还是选择得过且过? 我相信两种态度随着时间的推移, 所造成影响的差别应该是非常巨大的; 不仅是写代码, 做任何事情都是.
你的程序有在帮助他人么?
" 其实, 全部软件都有一个相同的目标: 帮助其他人.
文字处理软件帮助大家编辑文档, 浏览器帮助大家浏览网页... 服务于动物或植物的软件, 其目的还是帮助人类... 即使你写的是程序库, 它们也是为程序员服务的, 程序员也是人... 软件从来都不是用来帮助无生命事物的. 软件要帮助的不是计算机, 而是人.
软件的目标不是'赚钱'或者'炫耀智商'... 即便赚钱和炫耀智商可以'帮助'你, 但这只是非常狭隘的帮助; 相比为帮助别人而设计的, 满足其他人需求的软件, 仅仅考虑狭隘目标的设计, 很可能收获糟糕的软件.
任何情况下, 你所赚的钱都直接维系于你的软件能为他人提供多少帮助.... 在做与软件有关的决策时, 指导法则就是判断能提供什么样的帮助. 各项需求也可以照这个标准排除先后顺序. 哪项需求能为人们提供最大的帮助, 就应当赋予最高的优先级.
所以, 软件设计科学的目标应该是:
确保软件能提供尽可能多的帮助
确保软件能持续提供尽可能多的帮助
设计出程序员能尽可能容易开发和维护软件系统, 这样的系统才能为用户提供尽可能多的帮助, 而且能持续提供尽可能多的帮助
-- 来自《简约之美: 软件设计之道》"
作者认为软件的目的是服务他人, 而且软件是否成功在很大程度上取决于软件本身对人的帮助有多大.
这一点很值得程序员, 设计, 产品经理思考:
现在这个需求或设计是否真的可以帮助我们的目标客户; 如果有, 帮助大还是小? 如果帮助小, 那如何改进可以更好地帮助他们?
现在这个代码库是否真的可以帮助我们的业务方? 这些功能真的都是可以解决业务方的问题么? 是否有些功能是可有可无的? 业务方接过来用是否会觉得不方便? 或者同事看了我的之后是否能马上理解我代码的意思, 不需要花费太多的时间和精力去理解和修改它们?
另外, 作者所说的需要可持续提供帮助这一点也非常好.
比如这个需求将来能否还有可以做得更好的可能?
或者这段代码或者模块扩展性是否很强? 是否容易修改? 出现问题的时候我们能否积极响应并修复?
我认为这是一个格局的问题:
你是只为了挣钱, 拿到钱就满足了, 还是为了真心想帮助他人, 解决他人的问题?
你是只为了 KPI, 完成某个特定任务而已, 还是为了真心想帮助同事, 帮助公司的客户, 让公司越来越好?
格局决定高度.
价值与成本的时间维度
" 公式: D = (Vn + Vf)/(Ei + Em)
其中:
D: 可取程度
Vn: 当前价值
Vf: 未来价值
Ei: 实现成本
Em: 维护成本
未来价值和维护成本都取决于时间... 一般来说, 软件系统都需要维护很长时间, 大多数情况下, 未来长期收益和维护成本才是真正需要考虑的. 与之相比, 当前价值和实现成本变得无足轻重.
如果我们忽视事实, 放弃对未来的思考, 只考虑当下 "能用" 的软件, 那么我们软件在未来就会很难维护. 如果软件很难维护, 就很难确保它能够帮助别人(而这正是软件设计的目标).
相比短期, 长期的未来对我们来说更重要, 因为我没打呢的是决策会在未来更长的时间里产生更大的影响.
在软件设计时, 可以根据已知的信息做某些决策, 目的是为了创造更好的未来(提升价值, 降低维护成本), 而不必预测未来究竟会发生什么具体的事情.
-- 来自《简约之美: 软件设计之道》"
很多事情我们都需要把时间一同考虑进去: 比如蛀牙会随着时间的推移可能会导致后面整个牙都拔掉, 但是有的人缺忽视了时间的作用, 一拖再拖导致最后要把整颗牙拔掉; 再比如基金可能会长期持有才会有一个比较好的收益, 但是有的人在看到一跌再跌就忍不住杀跌, 对行业的发展没有关注, 更没有想法, 而后面再回来看的时候基金又涨回去了..
软件开发也是如此, 我们不仅仅需要解决当下的难题, 还要考虑当前的设计在未来的可维护性(也包括可扩展性). 我们不能仅图一时时快, 为了应付需求, 设计最求短平快, 给未来毫不留余地.
我们应该在动手写代码之前要多考虑一下当前设计的可维护性, 可扩展性, 也就是这个设计在未来会带给我们多大的便利和好处, 而不是一步一步让它把我们推向无尽的深渊.
应对变化
" 你并不需要预测什么会变化, 你需要知道的是, 变化必然会发生. 程序应该保证尽可能合理的灵活性, 这样,>不管未来发生什么变化, 都可以应付得了.
请回顾整个过程中的每次修改. 问问自己, 最初写这个文件时, 你能预测到这些变化吗? 是否一开始写好就能够减轻后期的工作量. 总的来说, 就是要尝试理解每次修改, 看看是否能从中得到一些关于软件开发的新的收获.
渐进式开发及设计: 它要求按照特定顺序, 一点一点地设计和构建系统.
举一个实现一个支持加减乘除计算器的例子.
设计一个只能进行加法运算的系统.
修改现有的设计, 让它支持减法运算.
实现减法运算功能. 现在系统支持加法和减法.
再次修改现有的设计, 让它支持乘法运算.
实现乘法运算功能. 现在系统支持加法, 减法和乘法了.
再次修改现有的设计, 让它支持除法运算.
添加除法的功能. 最后得到一个我们期望的可以加减乘除的计算器.
这个方法的精妙之处在于, 它是根据实现的顺序来决策的. 总的来说, 在其中的每个阶段, 下一步都只做最容易的事情: 首先选择加法, 因为这是最简单的运算; 其次选择减法, 因为从逻辑上说它与加法只有很小的差异; 第二步也可以选择乘法, 因为乘法无非是把加法执行很多次而已. 而唯一不应当选择的是除法, 因为从加法到除法的距离太远了, 步子太大了. 而从乘法到除法却相对简单很多.
这里混合了两种做法: 一种叫做'渐进开发', 另一种叫做'渐进设计'. 渐进式开发是一种通过该小步骤构建整个系统的办法; 渐进式设计也是一种类似的方法, 它也通过一系列小步骤来创建和改进系统的设计.
-- 来自《简约之美: 软件设计之道》"
作者指出了我们应该认识到变化是必然会发生的, 因此我们在设计系统的时候要尽可能保持灵活, 让系统便于修改. 而且在每次改动之后我们最好也可以做一个复盘: 这个修改我们是否当初想到过, 当初的设计是否可以很好地应对这个修改. 如果不能, 我们以后应该如何避免类似的情况发生? 或者我们是否可以积累一下经验, 对比变化前后的差异, 弥补我们在思考方面的不足?
来源: https://juejin.im/post/5c2b46c46fb9a049a979cdf6