程序员修炼之道:从小工到专家读书笔记

来源:互联网 发布:域名怎么和服务器绑定 编辑:程序博客网 时间:2024/06/06 05:38

程序员修炼之道-从小工到专家读后感

前言:

  • 书的内容是从开发经验中总结出的一些软件开发的指导原则。所有内容都是围绕核心主题开展的。
  • 书的核心主题是”Progmatic”即实效。实效的具体含义是->高效并且有效地完成任务,即速度要快,质量要高。
  • 让书中的内容落地就要内化原则,内化是指把书中的经验原则融入自己的知识体系,在实际的开发中去应用这些指导原则。

如何落地执行:

  • 本书含有一些经验总结出的tip,如DRY(dont repeat yourself),如何执行这些tip:
    1. 频繁的高强度的外部刺激和自主的有意识的反复提醒是加速内化的两个重要方法。如看到if分支就要看是否有else分支。
    2. 需要抽象出一些简单的词句和规则(如if,else分支查看),靠记忆和不断地提醒,小规模地内化这些小声音。
    3. 实践:先大致理解和记住一些tip,然后每周实践2到3个。实践的方式包含1,2。

一些tips: 这些tips都是以实效为核心

  • 使用靠近问题的领域语言来书写伪代码。这样有利于伪码直接转为代码实现。
  • 不要预设立场。如检查if,else分支是否覆盖所有情况,如果没有,需要说明。(预设立场非常普遍)
  • 不要容忍破窗户,破窗户指存在问题的代码和设计,即使小问题也要解决,防患于未然。如果无法解决,添加注释信息,记录问题。–>总之,要让问题得到暴露和修复。(暴露问题,解决问题,不要隐藏问题,逃避问题)
  • 不要过分地陷入到细节当中,要时刻记得项目的架构。(在项目实现过程中抓大放小)
  • 批判性的分析你独到的和听到的。(即要有个人判断优劣,对错的能力)
  • 把问题放到更大的语境中去考虑。(在需求分析中要抓大放小)
  • 要负责:提供解决方案,而非寻找借口(提高效率,以解决问题为核心,这条比较反人性,在出问题时要记着这条tip
  • 接受变化。(在所有阶段都需要考虑可能的变化,言下之意就是要做灵活的设计,可扩展的实现)
  • 交流(和所有项目相关人员,目的是为了达成一致,及时反馈,不断调整)
  • 当多种数据元素互相依赖时,要保证这种依赖关系。当保证这种依赖关系的开销过大时,需要解除依赖关系,此时可以使影响局部化,不要把这种变化过多地暴露。

注重实效的途径:

  • DRY原则:

    • 即dont repeat yourself,含义是系统中的每一项知识都必须具有单一,无歧义,权威的表示。即要避免重复
    • 程序员需要持续不断的维护,这是整个开发过程中的例行事务。DRY使开发更易于理解和维护。
    • 重复的类型:
      • 强加的重复,指环境因素导致的重复.解决需要智慧。
        1. 信息的多种表示(如不同平台不同语言对同一信息的表示),这样可能导致不一致,通过编写简单的过滤器或代码生成器来解决,即从同一个源(信息的表示)来生成。
        2. 要把低级的知识放在代码中,把注释保留给其他的高级说明。即指分层设计,高层的逻辑尽量抽象以避免修改。这样底层和高层解耦,也防止注释过期。
      • 无意的重复和无耐性的重复要被避免。
      • 开发者之间的重复。
  • 正交性:

    • 含义就是解耦。用来表示某种不相互依赖性或者解耦性。
    • 需要消除无关事务之间的影响。组合正交组件提高效率。不要依赖你无法控制的事务属性。
    • 建立正交的系统:
      • 模块化
      • 层次化。
      • AOP让你在一个地方表达本来会分散在源码各处的某种行为。
      • 限制模块之间的交互。
      • 遵守得墨忒耳法则缩小了调用类中的相应集的规模。
    • 在编码上:
      • 让代码保持解耦
      • 避免使用全局数据
      • 避免编写相似的函数
  • 可撤销性

    • 含义是不存在最终决策,所以功能要可撤销。即代码可回滚
    • 使用版本控制系统。
    • 采用灵活的架构。
    • 设计正交的系统。
  • 曳光弹和原型化

    • 区别在于原型化更注重为交互建立原型,最终会被丢弃。
    • 而曳光弹更偏重对核心功能的实现,最终会成为系统的一部分。
    • 曳光弹的使用场景是当需求模糊,无法做出宏观上完善的系统设计时。采用盲人摸象的方式进行开发,即先实现确定的地方.
  • 估算:从已有的类似项目来进行估算比较靠谱

    • 确定估算粒度。如天,周,月。
    • 确定问题的范围,即制定约束条件。
    • 所有的估算都以问题的模型为基础。去问已经做过这件事的人
    • 估算系统:建立系统模型->把模型分解为组件->给每个参数指定值->计算答案->追踪估算能力

基本工具:

  • 构建自己的工具库。
  • 使用源码控制。
  • 调试bug:
    • 找到问题根源
    • 可以快速**复现**bug。
    • 代码跟踪
    • 向别人解释程序以找到问题所在。
    • 找bug范围:先自己代码–>确定无误再找类库或系统问题。不要固执的认为自己的代码没问题。
    • 不要假设,要验证。

注重实效的偏执:

  • 放弃写出完美软件的偏执。
  • 进行防御性编程。
  • 合约。规定代码的权力和责任,即圈定范围。
  • 用文档(其他形式:断言,注解等)记载以下声明,并进行校验,是按合约设计(简称DBC)的核心所在。
    • 前置条件
    • 后置条件
    • 类不变项
  • 当代码发现某种被认为不可能的事情已经发生时,终止它。
  • 断言式编程:
    • 断言检查的是绝不应该发生的事情。
    • 断言可能会有副作用,引入新的错误。
  • 异常
    • 异常表示即时的,非局部的控制转移,是一种级联的goto。
    • 把异常当做处理逻辑。破坏了封装,通过异常处理,例程和它们的调用者被更紧密的耦合在一起。

当你编码时:

  • 代码需要演化,它不是静态的事务。
  • 重构
    • 不要试图在重构的同时增加功能
    • 在开始重构之前,确保你拥有良好的测试
    • 采用短小,深思熟虑的步骤。
  • 从一开始就可以把可测试性构建进软件中,并且在把各个部分连接在一起之前对每个部分进行彻底的测试。

在项目开始之前:

  • 需求需要挖掘,而不仅仅是收集。找出用户为何要做特定事情的原因,而不是他们目前做这件事情的方式。
  • 建立需求文档:把形式化的模板做备忘录
    • 好的需求文档会保持抽象
    • 项目范围的增大需要被记录和可追溯,以及可评价(通过统计信息)
    • 需求的收集和设计实现不是单向的线性关系,而是双向关系。它们是“交付高质量的系统”的不同方面。
  • 解开谜题
    • 解开谜题的关键在于确定施加的各种约束,并确定你确实拥有的自由度
    • 确定真正的约束
    • 对约束进行分类,并划定优先级
    • 你所需要的知识真正的约束,令人误解的约束,还有区分它们的智慧。
  • 编写程序规范
    • 编写程序规范是一个交流活动,旨在解释并阐明系统的需求
    • 不要追求捕捉系统或需求的每一处细节和细微差别,因为细节不一定可以被自然语言以可理解的方式定义。
    • 不要陷入对规范的追求中,在合适的时候编码,反哺规范。
  • 不要做方法的奴隶,适合的就是最好的,能解决问题就行。

注重实效的项目的标准:

  • 不符合用户期望的项目注定是失败的。即以用户为中心
  • 使项目级活动保持一致和可靠的一个最重要的因素是使你的各种工作流程自动化。
  • 项目的各种活动,分析,设计,编码,测试不会孤立地发生,它们是看待同一问题的不同方式。
  • 在开发一个项目时,我们再寻求内聚的,在很大程度上自足的团队。使用组织代码使用的技术,像合约,解耦,正交性,这样的技术来组织各种资源,有助于使团队作为整体与变化的各种效应隔离开来。
  • 测试:
    • 早测试,常测试,自动测试。
    • 要通过全部的测试,编码才算完成。
    • 集成测试说明组成项目的主要子系统能工作,并且能很好的协同。
    • 测试状态覆盖,而不是代码覆盖。
    • 大多数测试都应该自动完成。
  • 注释:注释应该讨论为何要做某事,它的目的。代码已经说明了它是怎样完成的。

我自己的一些tips:

  • 以实用为主,快速学习。而不是拿到一个东西就系统性的去学习。
  • 当然,深度钻研还是需要的,但是后边再说,尽快上手工作是第一位的。
  • 交流沟通很重要,不懂就问,不能闭门造车。
  • 在Microservices时代,我们更建议外部化你的软件产品差异化配置管理,尽量减少Profile的滥用甚至不用。
  • 可以多看官方文档。
  • 想清楚再去敲代码,这句话可以用一辈子,
  • 备份,版本管理很重要。
  • 有想法,有问题要写下来,不能止步于口头和心里。
  • 公司的各种设计指南、编程规范、XXX规范要仔细学习
  • 公共配置项不要乱动,特别是配置库和编译器的
  • 编码的时候只思考同一个思维层次的逻辑,在这层完成之后再思考下一层。
  • 计算机科学中的问题都可以通过改变使用方式来解决。
  • 针对数据库相关的操作一定要考虑到在大数据量下的性能问题。
  • 通过加点记录程序段运行时间的方式判断性能瓶颈所在。
  • 修复一个Bug往往会引入一个更为隐秘的Bug,所以在进行Bug修复时需要对修复后的程序逻辑重新进行检查,避免引入Bug。
  • 在针对解决问题的态度方面,不要轻易得出”问题无法解决”这样的结论,需要有”问题总是可以解决的”的态度和信念。
  • 在代码风格方面,需要更加规范和一致。
  • 编写关于数据库操作的代码时。一定要考虑到索引的问题,sql的性能的问题。
  • 代码中如果需要生成大量对象,一定要考虑到内存占用的问题。
  • 在对工具的学习中,如git中,充斥着大量的命令和用法,很难一下子熟练掌握。所以对于这种工具的学习,我觉得
    首先熟悉高频命令+学习其工作原理的方式可以起到较好地作用。对应于git就是着重理解其工作区,暂存区,分支和时
    间线的概念。