《高效程序员的45个习惯 - 敏捷开发修炼之道》之读书笔记

《高效程序员的45个习惯 - 敏捷开发修炼之道》之读书笔记
Photo by Welkin Chen / Unsplash

多年前阅读此书时,如醍醐灌顶,从那之后,这些书里面的核心思想,慢慢渗透到我的开发生涯之中,受益良多,把内容分享出来,时时阅读。

  • 金句子
    • 所有学习上的成功,都只靠两件事: 策略和坚持,而坚持本身就应该是最重要的策略之一
    • 只有明白”为什么做“,才能解决”如何做“的问题
    • 敏捷就是管理变化的
    • 程序员在拒绝设计的同时,也就放弃了思考
    • 敏捷并不止是针对代码开发,它存在于软件工程的所有环节
    • 先解决困难的问题,简单的问题留到最后
    • 敏捷依赖人,而不是依赖于项目的甘特图和里程表
    • 如果你没有犯任何错误,说明你可能没有努力去工作
    • 很多开发者由于脏乱代码和看不懂的逻辑而秃顶
    • 每个敏捷开发的"时间盒"必须是短期的
    • 好的设计应该是正确的,而不应该是精确的
    • 敏捷的一大特点就是持续开发,持续保证可开发,持续保证可发布
    • 敏捷使用短迭代
      • 给我一份详细的长期计划,我就会给你一个注定完蛋的项目
      • 在小且重复的周期中,增量完成各种开发任务: 分析、设计、实现、测试和获得反馈
    • 敏捷开发给我的感觉
      • 专注且效率
      • 能看到一个实际并且确切的目标
      • 不会遗留长期悬而未决的问题
    • 硬件成本比开发人员的时间便宜
    • 开发人员应该为能够创造出来一个简单并且可用的设计而骄傲,而不是以程序的复杂性为荣
    • 什么是敏捷
      • 对敏捷的错误理解
        • 越快越敏捷
        • 只写代码不写文档
        • 需要重构而无需设计
        • 敏捷迭代就是尽量做到最小
        • 敏捷只有天才程序员才能用
      • 本意: lightweight processed(轻量型软件开发过程)
      • 概括 -> 敏捷开发是在一个高度协作的环境中,不断地使用反馈进行自我调整和完善
    • 敏捷不是目的,而是手段
    • 敏捷开发宣言
      • 个体和交互胜过过程和工具
      • 可工作的软件胜过面面俱到的文档
      • 客户协作胜过合同谈判
      • 响应变化胜过遵循几乎
    • 敏捷精神
      • 要求团队中的每个人都有专业的工作态度
        • 并非是所有人都是有经验的专业人员
        • 每个人都希望尽最大可能做好自己的工作
      • 持续推进系统前进和完善
        • 需求采集
        • 开发
        • 技术技能的学习
        • 产品部署
        • 用户培训
    • 如何操作
      • 防微杜渐
        • 把问题解决在萌芽状态
      • 可行性先行
        • 探索未知领域,在大量成本投入之前先确定其可行性
      • 持续优化团队协作
        • 往往是小型团队
        • 共享代码和任务
        • 大部分时间能在一起工作
      • 使用自动化工具构建、测试和集成
      • 持续重构
        • 编码永远没有真正意义的结束
      • 以小步迭代的方式工作
        • 尽可能的频繁给客户演示迭代的最新的系统
  • 态度决定一切
    • 做事
      • 出了问题,最高优先级是解决问题,而不是找到解决掉制造问题的人
      • 一再伤害团队的成员需要让他离开
      • 如果大部分成员(尤其是领导者)不职业,那么你就应该主动从团队离开,没必要跟随"死亡之旅"
    • 欲速则不达
      • 出现bug,不要快速修复,而是要真正从根源修复
      • 提升代码的清晰度,让代码变得易读
      • 要理解团队开发方法,不要孤立地编码
      • 使用单元测试
    • 对事不对人
      • 公正的去讨论
        • 不要把对方案设计和实现的讨论,失控成为情绪化的指责
          • 每个人都能有一些极好的创新想法,同样也会萌生很蠢的想法
          • 负面的评论会扼杀创新
      • 尽最大可能放大方案的优缺点
      • 设立仲裁人
        • 防止开会时明星员工操纵会议,并及时打断务虚发言
      • 支持已经做出的决定
        • 一旦方案被确定,就必须通力合作
  • 学无止境
    • 只有变化是不变的,要拥抱变化
    • 迭代和增量式学习
      • 每段时间给制定一个新技术的学习目标
      • 实操
        • 要明白为什么需要这项新技术
          • 它可以解决什么问题,用在什么地方
        • 避免为了学习新技术而直接将应用切换到新技术。必须全面评估造成的影响
    • 对团队投资
      • 找出团队中高手擅长的领域,帮助其他成员迎头赶上
      • 坚持有计划地举行分享
    • 懂得丢弃
      • 丢弃旧的不好的习惯和思维定式
    • 不停地问"为什么"
      • 深入挖掘背后的原因,单点突破,由点方可及面
  • 交付用户想要的软件
    • 真正的敌人,是变化
      • 变化的需求
      • 变化的市场
      • 成功的软件开发方法,取决于你识别和适应变化的能力
      • 保持项目随时可以发布
        • 提早实现自动化部署
          • 在开发之前就要进行全面自动化部署,而不是等到上线之前
          • 能运行在开发环境,也能运行在生产环境
          • 最大程度避免手工操作,且应该简单、可靠及可重复
      • 提早集成,频繁集成
        • 集成的周期越长,成功的风险就越高,代价就越大
        • 避免大范围的修改代码
        • 将持续集成作为编码的日常部分
    • 明确客户/开发人员职责
      • 方案设计时,必须有开发参与
      • 业务方面的决定,要让客户来做
      • 实操
        • 记录客户做出的决定,并注明原因,PS: 使用方便的工具,便于同步
        • 从开发角度,给客户提出好的业务建议
    • 设计和编码都在变化
      • 一旦开始,最初的设计和实际编码都处于不断变化中
        • 需合理性的更新维护设计文档
      • 好的设计应该是正确的,而不应该是精确的
        • 战略级别的设计不应说明程序方法、参数、字段等,详细战术设计文档需包含这些。
      • 不要在前期做大量的设计
    • 合理地使用新技术
      • 避免"新技术-简历驱动设计"
      • 避免出现不可控的"新技术大杂烩"
      • 新技术真的能解决问题吗
      • 新技术维护成本多大
      • 新技术的引入,必读多问挑剔性的问题
      • 如果还没有足够的经验,不要急于决定用什么技术
      • 不要开发哪些你容易下载到的东西
    • 用户侧
      • 统一好用户软件安装所需要的各个版本、数据库、操作系统等
      • 在没有征得用户同意前,绝不能删除用户的数据
      • 软件需保证可以完整的正确安装,卸载,并升级(如果有的话)
        • 尤其是在质量保证人员的电脑上
        • 保证考虑了用户侧的设备,网络和权限
      • 尽量降低维护安装脚本,把这一切做的最简化
      • 频繁给客户演示
        • 使用演示获得频繁的反馈
          • 减少与客户的理解的需求偏差,最大程度接近真实需求
          • 提早发现环境或者功能的bug
        • 跟踪问题
          • 反馈类型
            • 修正
            • 建议
            • 变更需求
            • 功能增强
            • bug修复
            • ...
          • 需保持对反馈的记录
        • 演示周期根据需求和用户的反馈,动态调整演示周期
      • 需维护一份项目术语表,统一跟用户的术语认知
      • 如何报价
        • 使用迭代来报价
          • 每个迭代周期,提供部分功能,从而判断出一个相对合理的报价
        • 避免为整体项目直接报价
          • 当然也需要具体针对项目整体报价的能力,毕竟市场如此...
  • 敏捷反馈
    • 测试
      • 清楚要测试的内容
        • 确保测试是可重复的
        • 测试你的边界条件
        • 不要放过任何一个失败的测试
      • 一定要有本地单元测试,一旦单元测试到位,方便回归测试和重构代码
      • 要使用自动化的单元测试
        • 搭建机器,不断获取最新版本代码,然后编译代码,并运行单元测试
    • 单元测试
      • 及时提供反馈
        • 针对修改或者重写的逻辑,测试用例会检查你是否破坏了已有的功能,可以得到快速反馈
      • 让代码更加健壮
        • 帮你练习正面、反面以及异常情况
      • 是有用的设计工具
        • 有助于实现简单的、注重实效的设计
      • 单元测试会天然强制代码分层
      • 是你自信的根本
        • 减少盲区,提供稳定性
      • 是可信的文档
      • 是学习工具
        • 通过测试新技术的API,加深理解
      • 单元测试需达到一定的测试覆盖率的时候,才能真正发挥作用
        • 可使用一些测试覆盖率工具来了解
    • 不同环境,就有不同问题
      • 使用持续集成工具,在每一种支持的平台和环境中运行单元测试,持续保证每个环境下软件的可用性
    • 错误的反馈最好统一到一个地方,而不是因为一个错误而收到5次通知轰炸
    • 度量真实的进度
      • 不要用不恰当的度量来欺骗自己和团队
        • 要诚实
        • 要找到更加合适的方式
      • 使用TO-DO来评估还需要多少小时
    • 倾听用户的声音
      • 每一个抱怨的背后都隐藏了真正的问题,即时这个抱怨很low,很愚蠢
    • 举办项目复盘会
      • 总结本次项目的所有问题,在以后的项目中逐个避免
  • 敏捷编码
    • 代码要清晰的表达意图
      • 保持代码的简单
        • 注重可读性,而不是只图自己方便和炫技
        • 代码清晰程度的优先级甚至应该排在执行效率之前
        • 无需对设计模式执着
          • 除非有不可辩驳的原因,否则不要使用模式、原则和高难度技术之类的东西
        • 为简单的设计而骄傲
          • 相比一个过分复杂,拙劣的解决方案,简单的方案通常更加难以获得
      • 代码阅读的次数要远远超过编写的次数
    • 用代码沟通
      • 好的编码规范可以让代码变得更加容易理解
        • 逻辑分离清晰
        • 变量名准确
        • 表达式简介
        • ...
      • 清楚的注释
        • 大量节省阅读代码的时间
        • 可以沟通代码以外的问题
        • 可能要说明以下信息
          • 为什么需要这个方法
          • 需要什么样的输入
          • 会更改哪些状态,有哪些返回值
          • 可能会发生什么异常
        • 在代码可以传递意图的地方,不要使用注释
    • 动态评估取舍
      • 没有最佳方案,只有最合适的方案
      • 影响因素,要做到平衡
        • 性能
        • 生产力
        • 优雅
        • 成本
        • 上市时间
    • 增量式编程
      • 在很短的构建/测试循环中编写代码
      • 确保增量过程稳定且易于维护
      • 时常保持对代码的精炼
    • 编写高内聚的代码
      • 单一职责原则
      • 内聚性指一个组件(包、模块等)成员的功能相关性,注意好隔离和分类
      • 具有高内聚的代码的变化,不会导致别的太多的变化,因此更加稳定
      • 低内聚的代码,一旦发生变化,容易引起"涟漪效应",导致无可预估的维护的成本
      • 让类的功能尽量集中,让组件尽量小
        • 避免创建很大的类和组件,也不要创造"大杂烩"类
      • 编码的时候考虑变化及扩展性以及他们造成的影响范围
  • 敏捷调试
    • 所有项目,都有bug,缺陷
    • 记录解决问题的日志
      • 问题简述
      • 解决方案详细描述
      • 引用文章及网址,跟多细节信息
      • 将解决方案的日志保存为可供搜索的方式 - Wiki
    • 警告就是错误!
      • 将其配置到持续集成中,并解决掉这些警告
    • 应该报告所有的异常!
      • 处理掉当前异常,或是向上传播所有的异常,不要将其忽略
    • 提供有用的错误信息
      • 提供出优雅的错误信息
      • 记录错误日志
        • 最起码应该是以文本文件的形式维护
        • 日志要清晰
        • 要易于理解
        • 做好日志类型划分的细节,方便日后阅读和索引
        • 禁止记录敏感信息
    • 对问题各个击破
      • 隔离出发生问题的模块,更容易修复。而不必过多关注整个负责的大型系统
    • 使用断言来提供与异常报告同样的信息,而不是等待系统出错来发现问题
  • 敏捷协作
    • 靠单打独斗在车库里面开发出一个完整产品的日子早已不在
    • 定期安排会面时间
      • 合理动态安排会议周期和时长
      • 每天/每N天(视情况而定)的例会
        • 昨天做了什么
        • 今天计划做什么
        • 有什么障碍
      • 公开问题,并积极寻求帮助
      • 动态分配任务和人手
      • 让大家知道项目的进展情况
      • 防止多人开发重复的解决方案
      • 促进代码和思路的共享,提升效率和质量
      • 看到别人的前进,从而形成正向的激励
      • 保证会议短小且不跑题
        • 例会解决不了的其他问题,可通过专题会议拉上相关人员解决
      • 一般10-15分钟较为合适
      • 注意报告的具体程度
        • 不可太粗略
        • 不可太详细
    • 架构师必须写代码
      • 架构师不应该只是画一些很漂亮的设计图,说一些"黑话",使用一大堆设计模式
        • 有太多"PPT"架构师了
        • 高度概括的。粗略的设计图无法很好地理解系统
      • 通过持续编码来实际了解系统,丰富和改进设计
      • 不存在所谓的最终决策,要根据实际和反馈做出改变
      • 要鼓励主力程序员参与设计,担任架构师的角色
        • 程序员在拒绝设计的同时,也就放弃了思考
        • 优秀的设计,从积极的程序员那里开始演化
          • 积极的编程可以带来更加深入的理解
          • 不要使用不愿意编程的架构师 - 不知道系统的真实情况,是无法展开设计的
      • 指导开发团队,提升水平,以解决更为复杂的问题
    • 实行代码集体所有制
      • 任何成员缺席都不会对项目造成影响
      • 保留技术专家对于其他业务代码的权限
      • 开发人员要向团队分享设计和代码,以便做人员热备
    • 成为指导者
      • 相互分享会得到更多的知识
      • 不必局限于自己的团队所用的技术
      • 开设博客进行技术分享
      • 通过指导而加深自己的结构化知识
      • 提升团队的整体实力,提升效率和质量
    • 允许大家自己想办法
      • 合理给出提示即可
      • 激励大家,给大家解决问题的机会
      • 不要用填鸭式的方式给予别人帮助
    • 合理利用版本控制系统
      • 控制每次提交的意义
      • 控制提交节奏
        • 在保证提交意义的同时,尽可能频繁的提交
      • 不要向代码库提交正在开发的代码
      • 要保证在提交代码之前,所有的单元测试都是通过的
        • 使用持续集成是保证源代码控制系统没有问题的良好方式
    • 坚持做CodeReview
      • 是任何已知形式测试的效果的两倍
      • 能移除80%的代码缺陷
      • 产出质量极高且稳定的代码
      • 每个人都需要进行代码复查
      • 基本的检查列表
        • 代码能否被读懂和理解
        • 是否有明显的错误
        • 是否对应用的其他部分产生不良的影响
        • 是否存在重复的代码或者重复的开发逻辑
        • 是否存在需要重构的部分
        • 所有的异常处理程序不允许为空
        • 所有的数据库调用都要在包的事务中进行
        • 需要积极评估代码的设计和清晰程度
      • 不要随意批评别人的代码,每个人的code风格毕竟不一致,要多鼓励,用开放的心态
      • 及时跟进代码复查的执行结果
    • 及时通报进展及问题
      • 出现不同于计划的情况,要及时向上,向大家通报
      • 根据不同的汇报对象,给出不同的汇报细节
  • 走向敏捷
    • 改变不好的习惯,并持续优化这些习惯
    • 向大家说明,敏捷开发是让大家的工作变得更加轻松
    • 入门习惯
      • 版本控制
      • 单元测试
      • 自动构建

Read more

郑州互联网薪资统计及 AI 时代的现状

郑州互联网薪资统计及 AI 时代的现状

22 年郑州前端薪资真实统计(200+份样本) 22 年我在郑州前端大群里面统计了一波郑州互联网薪资,当时以为只是开始,想着后面会有更多的企业来到郑州,情况会越来越好,而现在回头来看,没想到那时才是顶峰。 当时在群里面收集到 200+ 位投票,匿名填写自己的薪资情况,当时跟大家特意强调了要保证数据的真实性,也找群员验证过,基本真实性可信: * 🐣 3-6k 占比不少,主要是郑州的工资水平低,对于刚出来的,在小公司的这个薪资也正常,实习生 or 小作坊 * 🐰 6-12k 的占大多数,涵盖了郑州本土大多数互联网公司的薪资范畴,大多数的常规业务开发 * 🐵 12-20k 主要集中在本土大公司、一线城市在郑州的研发团队、外包公司,核心业务开发人员 🦄 20k+ 高学历 or 有大厂经验,主要为本土大公司或者一线公司在郑州的带队 leader ,能力较强,一般承担一些管理角色。 25年:职场寒冬来袭,状况还在持续恶化 一线公司研发部门的撤离 这也是我最在意的一条: 之前有一些一线城市的研发交付部门会在郑州有成立研发交付中心,从疫情之后,

RAG不是万能的,附常见误解与澄清

RAG不是万能的,附常见误解与澄清

能给人理清目前 AI 在生产落地的问题,是一件难能可贵的事情,AI 在生产落地会有哪些阻碍的讲解,讲干货的真的是很少,至少我自己曾经在这个问题上困惑了很久。 因为之前我在 AI 电商团队,做具体的 AI Sass 落地的时候,团队经常会沟通做到生产级可用的 AI,需要哪些东西,大概的门槛还是了解到一些的,我的能力也顶多在应用层面去做一些工作量的定制与代码衔接,涉及到模型层面,一概歇菜,很多人估计只是想着,写一个 Prompt ,就是真正的拥抱 AI 了。 当我看到自媒体里面铺天盖地的在讲 AI 如何帮助企业提效,如果重塑行业的时候,有种很复杂的感觉,他们真的懂 AI 吗,甚至他们真的懂软件吗? 基本上现在大家接触到的方式就几种: * 割韭菜卖课,讲概念,前景,这些基本上都是拿别人的产品来给自己做嫁衣,自己顶多是个工具的使用者和营销者,比如用 Midjourney,Kimi,豆包,海螺什么的,告诉大家用了就能提效,获得流量,

Shopify 构建商城页面的几种方式

Shopify 构建商城页面的几种方式

当用户需要对 Shopify 商城页面有自定义的需求时,一般会选择: 1、直接使用官方商城的 theme 来构建,可以使用,但是免费模板较少,只有 13 个。 2、使用第三方 theme 来构建,也有很多的模板可以选择,比如 envato 上有数百个 shopify 的模板,这是个非常大的市场。 3、完全自定义开发,自由度最高 当用户对 Shopify 商城页面,有完全自定义的需求,通常是常规主题无法满足需求,推荐使用 Shopify Hydrogen 的官方方案,开发人员可以对商城进行完全的页面级别的自定义。 而对于开发人员来说,官方的 Shopify Liquid 开发起来的效率和体验,是不如 Shopify Hydrogen 来的舒服,而且使用 Shopify Hydrogen ,还可以对性能有提升,

Meepo 要找一份远程前端(全栈)开发的工作

Meepo 要找一份远程前端(全栈)开发的工作

为什么找远程岗位 我一直是比较喜欢远程合作的方式,基本上从事远程开发的团队,都是奔着做事去的,大家能筛选到一起,为一个目标而努力,是一件很难得的事情,远程协作的方式,在自由度和产出之间能保持非常好的平衡,没有必要在通勤以及办公室的无效沟通上浪费太多的时间。 技术特点如何 前端: React + TypeScript 生态体系,常规的网页开发,浏览器插件,Electron 客户端开发都 OK,对各种前端技术方案有一定的沉淀和实践。 后端: Nextjs + Nestjs 开发全栈站点及后端 API 服务 个人特点 即插即用,对于大多数的前端场景和技术方案,都有所涉及。 多年的开发经验,对企业自有产品开发,大客户定制,以及独立开发,有一定的观察和沉淀。 拥抱 AI,对当下比较热门的 AI 技术有一定的了解和沉淀。 喜欢分享和交流,对技术和业务,以及营销都感兴趣。 之前接触的一些业务形态 公司层面: 主要是国内客服领域,涉及到全流程客服,IM,音视频等