注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

秒大刀 博客

好好学习 天天向上

 
 
 

日志

 
 
 
 

读《简约之美-软件设计之道》  

2013-03-29 22:02:37|  分类: 读书 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
读《简约之美-软件设计之道》 - 秒大刀 - 秒大刀 博客

 正文之前

  • 好程序员和差程序员的区别在于理解能力


第1章 引言

  • 没有人可以从头到尾理解所有代码是如何工作的。程序越大,越是如此
  • 编程所要用到的艺术和才能——化繁为简
  • 通常来说,更先进的技术只会让事情更简单,只是一开始你得学习,所以整个过程可能没那么简单
  • 如果程序写得很乱,实现最终的目标就显得尤其困难
  • 没有秩序的会给你增添无尽的烦恼
  • 改善代码质量的一切努力都是为了获得更好的结果


第2章 缺失的科学

  • 程序员也是设计师
  • 即便仅仅写一行代码,也包含设计的因素
  • 哪怕是单干,也离不开设计
  • 每个写代码的人都是设计是,团队里的每个人都有责任保证自己的代码有着良好的设计
  • 设计决不应该由某个委员会负责,所有的开发人员都应有权在自己的工作中做出良好的设计决策
  • 软件设计的责任应当落实在真正写代码的人身上
  • 考虑了所有的建议和反馈之后,任何决策都必须由单独的个人而不是一群人来做出
  • 从来不学习的程序员应该被清理出团队
  • 科学不等于全知全能。宇宙里还存在待发现的秘密,在任何领域都存在着未知的事物。发现了新的数据或者事实,就必须修正某些基础规则。
  • 软件设计可以成为科学
  • 软件设计是有章(规则)可循的,它们可以被认识,可以被理解。规则是永恒不变的,是基本的事实,而且确实可行。
  • 软件科学分两部分:软件管理的科学,软件设计的科学


第3章 软件设计的推动力

  • 全部软件都有一个相同的目标——帮助其他人
  • 软件从来都不是用来帮助无生命事物的。软件要帮助的不是计算机,而是人。
  • 软件的目标不是“赚钱”或者“炫耀智商”。不管是谁,只要将这些当成自己的目标,就偏离了软件的目标,就很可能惹上麻烦
  • 一个人写出优秀软件的潜力,完全取决于他在多大程度上理解了“帮助其他人”的思想
  • 在评估开发或维护软件系统的建议时,“它能给用户帮多少忙”绝对是一个重要而且基础的问题
  • 在设计软件时,应当将目标——帮助他人——视为应该考虑的最重要因素,这样,我们才能认识并了解软件设计的真正科学
  • 决定软件公司收入的两个主要因素基本就是组织水平(包括行政、管理、推广、销售等方面),以及软件对他人的帮助
  • 软件设计科学的目标应该是:确保软件能提供尽可能多的帮助,确保软件能持续提供尽可能多的帮助
  • 编写和维护有帮助的软件的主要障碍在于设计和编程。如果软件很难开发或修改,程序员的主要精力就花在让软件“能用”上,而没有精力去帮助用户,不必费心于编程细节。软件的维护难度越低,程序员确保软件能持续提供帮助的难度也越低
  • 设计程序员能尽可能简单的开发和维护的软件系统,这样的系统才能为用户提供尽可能多的帮助,而且能持续提供尽可能多的帮助


第4章 未来

  • 任何一点改变,其合意程度与其价值成正比,与所付出的成本成反比
  • 可能价值:这个变化有多大可能帮到用户
  • 潜在价值:这个变化对用户提供帮助的时候,将为用户提供多大的帮助
  • 为了确保你的软件有价值,就必须真正发布它。如果某个变化花费的时间太长,最后可能就没有任何价值。不能及时发布,也就无法给人提供切实的帮助。在判断某项工作的合意程度时,评估其发布计划是非常重要的
  • 成本包括实现成本和维护成本,价值包括当前价值和未来价值
  • 改变的合意程度(可行性),正比于软件当前价值与未来价值之和,反比于实现成本和维护成本之和。随着时间的流逝,起初的当前价值和实现成本会越来越不重要,甚至无足轻重
  • 无论如何,只要维护成本的增长速度比价值快,你就会遇到麻烦
  • 理想的解决方案——也即保证成功的唯一途径——保证维护成本随时间降低,最终降到零(或者尽可能接近零)
  • 只要每项决策的维护成本都会随着时间降低到接近于零,未来你就不会陷入危险的境地
  • 理想的情况下,只要未来收益高于维护成本,工作就是值得做的
  • 在设计决策中,实现成本通常并不是重要的因素,所以基本可以忽略
  • 相比降低实现成本,降低维护成本更加重要
  • 设计的质量好坏,正比于该系统在未来能持续帮助他们时间的长度
  • 不要把自己禁锢在某种工作定势里,要保持灵活;不要做任何以后无法改变的决策
  • 软件设计时最应该关注的是未来。不过,关于任何工程:未来的某些事情,是我们所不知道的
  • 程序员犯的最常见也是最严重的错误,就是在其实不知道未来的时候去预测未来
  • 预测短期未来是可能的,但长期未来基本是未知的。可是,相比短期未来,长期未来对我们来说更重要,因为我们的设计决策会在未来更长的时间里产生更大的影响
  • 如果完全不考虑未来,只根据当前已知的确切信息确定所有设计决策,那就百分百安全了
  • 未来并不需要预测——我们不需要知道确切的未来
  • 重要的是要记住,存在着未来。但是,这不要求你必须预测未来


第5章 变化

  • 程序存在的时间越久,它的某个部分需求变化的可能性就越高
  • 变化必然会发生,程序应该保证尽可能合理的灵活性
  • 软件设计的三大误区:编写不必要的代码;代码难以修改;过分追求通用
  • 不应该在真正的需求来临之前编写那些代码
  • 不要编写不是必需的代码,并且要删除没有用到的代码
  • 你需要删除所有用不到的代码,如果真的需要,你随时可以恢复回来
  • 软件项目的一大杀手就是所谓的“僵化设计”:写出来的代码很难修改
  • 僵化设计的有两大原因:对未来做太多的假设;不仔细设计就编写代码
  • 设计程序时,应当根据你现在确切知道的需求,而不是你认为未来会出现的需求
  • 仅仅根据目前确知的需求来考虑通用
  • 渐进式开发及设计


第6章 缺陷与设计

  • 没有那个程序员可以不犯错误。不错的程序员大概每写100行代码就会犯一个错误;最优秀的程序员,在状态最好的时候,每写1000行代码也会犯一个错误
  • 无论程序员的水平是高还是低,有一条是不变的:写的代码越多,引入的缺陷就越多
  • 在程序中新增缺陷的可能性与代码修改量成正比
  • 最好的设计,就是能适应外界尽可能多的变化,而软件自身的变化要尽可能少
  • 永远不要“修正”任何东西,除非它真的有问题,而且有证据表明问题确实存在。在动手修正问题之前,获得证据是很重要的。如果没有获得证据就动手修正问题,很可能只会添乱
  • 如果相当多的用户认为某个行为是bug,它就是bug;如果只是少数用户(比如一两个)认为它是bug,那么它就不算bug
  • 理想情况下,任何系统里的任何信息,都应当只存在一次


第7章 简洁

  • 软件任何一部分的维护难度,反比于该部分的简洁程度
  • 长期来看,能保证效率的恰恰是简单的系统,而不是复杂的系统
  • 你的代码一般总是归你负责,化简也归你负责——你不能奢望最初的设计永远都是最恰当的。在新的形势和需求面前,你必须不断重新设计系统的各个部分
  • 目前可行的,能够降低软件设计方程式中维护成本的最重要的事情,就是把代码变简洁。我们不必预测未来,完全可以只审视自己的代码,如果它足够复杂,就立刻动手简化它。这就是随时间推移降低维护成本的办法——持续不断的让代码变得更简洁
  • 化简代码可以降低维护成本,也就是增加了各种可能修改的可行性
  • 工具的简洁程度是与每个人的使用熟练程度相关的。任何人,只要使用某款工具足够长的时间,都会更熟悉它,从个人角度出发,会觉得它比其他工具更简洁
  • 如果你把事情做得简单而不是复杂,大家会更羡慕你
  • 保持一致是很重要的工作。如果你在一个地方采用了某种规则,就应当在其他每个地方都遵守这种规则
  • 真实世界里或许不存在这样的一致性,但是程序的世界由你负责,所以必须保持程序的简单和一致
  • 代码被阅读的次数远多于编写和修改的次数
  • 代码可读性主要取决于字母和符号之间的空白排布。空白太多是不必要的,因为这样很难发现事物之间的联系。空白太少也不必要,因为这样很难分解。代码之间留出的空白应当保持一致规范,空白应当能有助于读者理解代码的结构
  • 如果某段代码有很多bug,又难以阅读,那么首先要做的是让它更容易阅读。然后,bug在哪里才能看得更清楚
  • 可读性的另一部分重要内容是为变量、函数、类等选择合适的名字
  • 名字应当足够长,能够完整表达其意义或者描述其功能,但不能太长,以免影响阅读
  • 为保证代码的可读性,好的注释也很重要。但是代码的意图通常不应该用注释来说明,直接阅读代码就应当能够理解。如果发现意图不够明显,那么就说明这段代码还可以变得更简单。如果你的代码实在不能更简单,才应该写注释来说明
  • 保证代码的可读性是非常重要的,而且它往往是通往优秀设计之路上应当走出的第一步
  • 于是,设计师就成了一个费力不讨好的工作。解决重大缺陷为你赢得很多赞誉,但是避免缺陷发生……嗯,没有人会注意到


第8章 复杂性

  • 复杂性是会叠加的,而且不是简单的线性叠加
  • 原有功能越多,新增功能的成本就越高。优秀的设计可以尽量避免此类问题,但是每项新功能仍然会有单独的成本
  • 应当绝对禁止扩展软件的用途!这样的需求你必须尽全力抵制。软件应当坚守已经确定的用途,只要妥善完成这些目标
  • 往团队里增加新人并不会让事情更简单,相反会更复杂——《人月神话
  • 相比众多平庸的开发人员,少量精干的开发人员更容易获得成功
  • 每做一点新变化,整体复杂性就会增加一点,所以变化越多,每个变化要花的时间就越长。做出某些变化是重要的,但是应当谨慎决策,而不是一拍脑瓜就定了
  • 你必须一开始就做好设计,而且在系统膨胀时不断进行优秀的设计,否则,复杂性就会迅速增长,因为如果设计得不好,每项功能都会让代码加倍复杂,而不是只复杂一点点
  • 决不要什么都靠自力更生,不要在非必要的情况下重新发明轮子
  • 自己重新发明的轮子会逐渐影响你的项目,但不会在短时间内凸显。它们大多数会造成长期的负面影响,甚至一两年内觉察不出来,所以如果有人指出这些问题,通常大家也不觉得有什么坏处。即便你走上这条路,重新发明的轮子可能看来也没有问题。但是随着时间的推移,尤其是这些轮子堆积起来后,复杂性会越发明显,不断累加
  • 你正开发的任何系统,其基本用途应当相当简单。但是,如果你给系统添加新功能去满足其他目标,事情就立刻变复杂了
  • 身为软件设计师或是技术经理,你的职责是保证软件的基本用途,防止它偏离正轨,这个责任其他人谁也担不起。有时候,你可能需要为此据理力争,但从长期来看,这肯定是值得的
  • 没有必要玩太多花样,做太复杂,尝试用单个软件瞬间完成500个任务。最受用户喜欢的软件是专注而简洁的,并且始终执着于基本用途
  • 出现复杂性的另一个常见原因就是,系统里选择了错误的技术
  • 三个判断技术是否“糟糕”的因素:
    • 生存潜力:持续获得维护的可能性
      • 如果某项技术现在有足够的活力,你可以相当肯定它不会很快灭亡
      • 是否只有一家供应商在推进这项技术,以及它是否被不同开发人员开发的各种程序所接受和使用
      • 应当从符合需求的技术中选择接受最广泛的。不过,还是必须辨别,到底是经过考验才被大家接受,还是仅仅因为某种垄断而被接受
    • 互通性:如果需要,从一种技术切换到另一种技术有多难
      • 如果选择非标准系统,就会身陷罗网,难以切换
    • 对品质的重视
  • 如果某件事情变得非常复杂,也就意味着绝不是表面的复杂那么简单,而是设计出了问题
  • 一旦程序里出现了“无法解决的复杂性”,就说明设计中有些深层次的基本错误
  • 如果问题在这个层面上无法解决,应当回过头去看看产生问题的真正原因是什么
  • 如果事情变复杂,不妨回过头去看看真正要解决的是什么问题
  • 你真正要做的就是,找出自己所处的环境中最好的办法
  • 大多数麻烦的设计问题,都可以用在纸上画图或写出来的办法找到答案
  • 许多重设计或重写的工作之所以最终失败,就是因为它们引入了更多的复杂性,结果最后和原有的系统同样复杂
  • 不必设计“完美”的系统,因为它不存在。你只需要持续不懈的追求比现有系统更好的系统,最终就会得到相当容易管理的简洁系统
  • 掌握多门编程语言,熟悉多种不同的类库。每一种语言和类库都会用自己的方式来思考问题,即便你并不使用这些语言和类库,这种思维方式也可以用到你的具体环境中
  • 我们的选择永远是,在当前的环境下,当前的代码中,做合适的事情
  • 对于不可避免的客观复杂性,你要做的就是屏蔽这种复杂性。在程序外面妥善包装上一层,让其他程序员更容易使用和理解
  • 如果下面的条件全部满足,你才应该重写:
    • 你已经完成了准确评估,证明重写整个系统会比重新设计现有系统更有效率。你需要真正去做一些重新设计现有系统的试验,然后对比结果
    • 你有足够的时间用来开发新的系统
    • 你要比原有系统的设计师更高明,或者,如果原有系统是你设计的,但现在你的设计能力已经大大提升了
    • 你完全打算好了通过一系列简单的步骤设计整个新系统,在每一步都有用户提供反馈
    • 你要走足够的资源,可兼顾维护原有系统和重新设计系统。绝对不要为了让程序员重写新系统而停止对原有系统的维护。系统只要在使用,都离不开维护
  • 你自己的精力也是一种资源,必须慎重分配

第9章 测试
  • 我们无法保证程序将来一直可以正常使用,只能保证目前它可以正常运行
  • 你对软件行为的了解程度,等于你真正测试它的程度
  • 软件最后一次测试的时间离现在越近,它可以继续正常运行的可能性就越大
  • 除非亲自测试过,否则你不知道软件是否能正常运行

附录A 软件设计的规则
  • 软件的目的是帮助他人
  • 软件设计的方程式是:

                                                    当前价值 + 未来价值
    变化的合意程度(可行性) = ——————————
                                                    开发成本 + 维护成本

    这是软件设计的主要法则。随着时间的推移,这个方程式简化为

                                                    未来价值
    变化的合意程度(可行性) = —————
                                                    维护成本

    也就是说,相比降低实现成本,降低维护成本更重要
  • 变化定律:程序存在的时间越久,它的某部分需要变化的可能性越大
  • 缺陷定律:在程序中新增缺陷的可能性与代码修改量成正比
  • 简洁定律:软件任何一部分的维护难度,反比于该部分的简洁程度
  • 测试定律:你对软件行为的了解程度,等于你真正测试它的程度
  • 软件设计时要记得的两句话:
    • 相比降低开发成本,降低维护成本更加重要
    • 维护成本正比于系统的复杂程度

附录B 事实、规则、条例、定义
  • 事实:好程序员和差程序员的差别就在于理解能力。差劲的程序员不理解自己做的事情,优秀的程序员则相反
  • 条例:“好程序员”应当竭尽全力,把程序写得让其他程序员容易理解
  • 定义:程序就是
    • 给计算机的一系列指令
    • 计算机依据指令进行的操作
  • 定义:软件系统中任何与架构有关的技术决策,以及在开发系统中所做的技术决策,都可以归到“软件设计”的范畴里
  • 事实:每个写代码的人都是设计师
  • 事实:设计与民主无关,它应当由个人完成
  • 事实:软件设计是有章(规则)可循的,它们可以被认识,可以被理解。规则是恒久不变的,是基本的事实,而且确实可行
  • 规则:软件的目的就是帮助其他人
  • 事实:软件设计的目的如下:
    • 确保软件能提供尽可能多的帮助
    • 确保软件能持续提供尽可能多的帮助
    • 设计程序员能尽可能简单的开发和维护的软件系统,这样的系统才能为用户提供尽可能多的帮助,而且能持续提供尽可能多的帮助
  • 条例:做多少设计,应当正比于未来软件能够持续为人们提供帮助的时间长度
  • 条例:未来的某些事情,是我们所不知道的
  • 事实:程序员犯得最常见也是最严重的错误,就是其实不知道未来的时候去预测未来
  • 条例:最安全的情况是,完全不尝试预测未来,所有的设计决策都应当根据当前确切知道的信息来做
  • 条例:变化定律:程序存在的时间越久,它的某个部分需要变化的可能性越大
  • 事实:在落实变化法则时,软件设计师容易犯的三个错误是:
    • 编写不必要的代码
    • 代码难以修改
    • 过分追求通用
  • 条例:直到真正要用了才编写代码,清理掉用不到的代码
  • 条例:代码的设计基础,应当是目前所知的信息,而不是你认为未来要发生的情况
  • 事实:如果设计让事情变得更复杂,而不是更简单,就犯了过度工程的错误
  • 条例:在考虑通用时,只需要考虑当前的通用需求
  • 条例:采用渐进式开发和设计
  • 条例:缺陷概率法则:在程序新增缺陷的可能性与代码修改量成正比
  • 条例:最好的设计,就是能适应外界尽可能多的变化,而软件自身的变化要尽可能少
  • 条例:永远不要“修正”任何东西,除非它真的有问题,而且有证据表明问题确实存在
  • 条例:理想情况下,任何系统里的任何信息,都应当只存在一次
  • 规则:简洁定律:软件任何一部分的维护难度,反比于该部分的简洁程度
  • 事实:简洁是相对的
  • 条例:如果你真的希望成功,最好是把产品简化到傻子也能懂
  • 条例:要保持一致
  • 条例:代码可读性主要取决于字母和符号之间的空白排布
  • 条例:名字应当足够长,能够完整表达其意义或描述其功能,但不能太长,以免影响阅读
  • 条例:代码应当解释程序为什么这么做,而不是它在做什么
  • 条例:简洁离不开设计
  • 条例:你可以这样增加复杂性:
    • 扩展软件的用途
    • 新增程序员
    • 做无谓的改变
    • 困于糟糕的技术
    • 理解错误
    • 糟糕的设计或者不做设计
    • 重新发明轮子
    • 背离软件原来的用途
  • 条例:可以通过考察生存潜力、互通性、对品质的重视,判断某种技术是否“糟糕”
  • 条例:通常,如果某件事情变得非常复杂,也就意味着深藏在表面的复杂之下,设计出了问题
  • 条例:在复杂性面前,问问自己“真正要解决的问题是什么”
  • 条例:大多数麻烦的设计问题,都可以用在纸上画图或写出来的办法找到答案
  • 条例:要应付系统中的复杂性,可以将系统分解成独立的小部分,逐步重新设计
  • 事实:所有可行的简化,其核心问题都是:怎么做,才可以让事情处理或者理解起来更容易
  • 条例:如果遇到不可解决的复杂性,在程序外面妥善包装上一层,让其他程序员更容易使用和理解
  • 条例:推倒重来只有在一些非常有限的情况下才是可以接受的
  • 规则:测试定律:你对软件行为的了解程度,等于你真正测试它的程度
  • 条例:除非你亲自测试过,否则你不知道软件是否能正常运行
  评论这张
 
阅读(1614)| 评论(2)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017