《The Effective Engineer》读书摘要
文章目录
- Part 1: Adopt the Right Mindsets
- Part 2: Execute, Execute, Execute
- Part 3: Build Long-Term Value
高效的工程师是那些被认为可以把事情搞定的人。同时,是可以高效率的把事情搞定的人。
高效工程师聚焦在价值和影响力上。
Part 1: Adopt the Right Mindsets
Focus on High-Leverage Activities
Use Leverage as Your Yardstick for Effectiveness
杠杆率 = 产出 / 时间
简单的说就是 ROI,投入产出比。
时间是最宝贵的资源。
Increase Your Leverage in Three Ways
提高杠杆率的三个途径:
- 减少做某件事的时间
- 增加做某件事的产出
- 换到有更高杠杆率的事情上去
翻译成三个问题:
- 如何缩短完成这件事情的时间?
- 如何提高这件事情的产出价值?
- 有什么值得花费我时间的事情可以产出更多的价值?
Direct Energy Toward Leverage Points, Not Just Easy Wins
聚焦于高杠杆率的事情
Key Takeaways
- 使用杠杆率来评价你的工程效率
- 有条理的提升你时间的杠杆率
- 集中关注在支点上
Optimize for Learning
持续优化学习是高效工程师的一项非常高杠杆的活动
Adopt a Growth Mindset
拥抱成长性思维,意味着对你可以改变的各个方面都承担责任,而不是将失败和缺点都归咎于你无法掌控的事情。
Invest in Your Rate of Learning
- 学习也遵循指数增长曲线
- 越早优化学习,可以享受越久的复利
- 微小的差异在长期未来也能产生巨大的差别
把自己当作是创业或 beta 版的产品,需要每天不断的投资、迭代
Seek Work Environments Conducive to Learning
寻求有利于学习的工作环境
寻找公司或者团队的六个因素:
- 快速成长
- 培训
- 开放
- 节奏
- 人
- 自主性
Dedicate Time on the Job to Develop New Skills
在工作中花时间发展新技能
每天花 1-2 小时整块时间。对你长期未来能够更加高效投资。
可以对你工作的领域或者使用的工具有着更深刻的理解。
也可以获得临近学科的经验。(工作上下游相关其他工种的知识经验)
十条建议:
- 学习公司内最好的工程师的核心抽象代码。特别是在大型公司。
- 写更多的代码。针对提高编码能力,和阅读代码相比,练习是更高杠杆率的活动。
- 浏览内部提供的技术或者教育材料。
- 掌握你所使用的编程语言。
- 将代码发送给最严格的批评家评审。
- 在要改进的地方学习。
- 参加你感兴趣的项目设计讨论会。
- 从事各种各样的项目。
- 确保你所在的团队里,至少还有几个你可以向他们学习的工程师。
- 毫不畏惧的跳入你不懂的代码中。
Always Be Learning
持续不算的学习
学习的机会并不局限于工作场所。其他技能也值得学习。
学什么:
- 学习新的编程语言和框架。
- 在当前高需求的技能上投资。
- 读书。
- 加入一个讨论组。
- 参加一些技术会议、讲座等。
- 建立并维系一些强有力的关系网。
- 关注一些技术博客。
- 写一些东西。
- 做一些业余项目。
- 追寻你所热爱的事情。
Key Takeawsys
- 为自己负责
- 不要降低学习速度
- 寻找可以持续成长的工作环境
- 利用工作机会提高技术技能
- 在工作场所之外学习
Prioritize Regularly
规律性的制定优先级
Track To-Dos in a Single, Easily Accessible List
跟踪所有的 TO-DO 在一个单一、容易找到的列表里
关注于当前立即可以产生价值的,和重要不紧急的。
Focus on What Directly Produces Value
关注当下可以立即产生价值的事情
公司关注的是你创造的价值。价值例如产品推进,用户获取,销售额等,而不是开了多少会、写了多少代码。
Focus on the Important and Non-Urgent
关注重要但不紧急的事情。
我们每天都被紧急的事情淹没:开会、邮件、电话、bug、DDL。其中有些是重要的,有些并不是。
重要、紧急:高优问题、DDL 等
不重要、紧急:大多数的 email、电话、会议
重要、不紧急:职业生涯规划、建立了强人际关系、读书、建立新的高效习惯、构建工具以改善工作流、学习新的语言等等
Protect Your Maker’s Schedule
保护你的时间表。
和其他专业工作相比,软件工程师需要更多长、持续的时间段来提高工作效率。
尽可能的将会议安排在连续的时间段或者一天的早晚,而不是分散这些会议。
Limit the Amount of Work in Progress
限制同时在进行中的项目数量。
人脑的并发处理能力非常有限。
Fight Procrastination with If-Then Plans
通过 if-then 计划来避免拖延。
例如,收集一系列的 20 分钟内可以完成的短任务,如代码评审、写面试反馈、回邮件、调查小 bug、写测试等。
Make a Routine of Prioritization
制定优先顺序。
养成重新回顾这些优先计划的习惯。
Key Takeaways
- 写下并 review to-dos
- 做有直接价值的事情
- 做重要但是不紧急的事情
- 减少上下文切换
- 使用 if-then 计划和拖延作斗争
- 养成制定优先级的习惯
Part 2: Execute, Execute, Execute
Invest in Iteration Speed
高效工程师在迭代速度上进行大量的投资。
Move Fast to Learn Fast
迭代的越快,你能越快的知道这些工作是否有效。
持续部署是提供给你用于加快迭代速度的有力工具之一
Invest in Time-Saving Tools
节省时间的工具可以带来丰厚的回报。
更快的工具会被使用的更多。
值得花费一些努力去寻找一个更平滑的方式以便降低从现有工作流切换到新的工具的成本。
Shorten Your Debugging and Validation Loops
缩短调试和验证的时间周期。
下一次,当你修复一个 bug 或者迭代一个新的 feature,发现自己又在重复进行同样的行为的时候,停下来。想一想,你是否可以缩短这个时间周期。
Master Your Programming Environment
熟练你的编程环境。
- 在版本控制里跟踪变更
- 编译、构建代码
- 跑单元测试
- 重启开发中的 Web Server
- 测试一个表达式的行为
- 查找文档
- 跳到函数定义
- 在文本编辑器里重新格式化代码或者数据
- 找到函数的调用方
- 重新排列桌面窗口
- 导航到文件的特定位置
入手点:
- 熟练你喜欢的文本编辑器或者 IDE:Emacs、VIM or something else
- 学习至少一个高产、高级的编程语言:Python、Ruby
- 熟悉 UNIX 或者 Windows 的 shell 命令:grep、sort、uniq、wc、awk、sed、xargs、find
- 更加习惯于使用键盘而不是鼠标
- 自动化你的手工操作
- 使用交互式解释器来测试自己的想法:Python、Ruby、JavaScript
- 使运行单元测试尽可能的快和简单
Don’t Ignore Your Non-Engineering Bottlenecks
不要忽视你的非工程的瓶颈
优化迭代速度的最佳策略和优化系统性能一样:找出最大的瓶颈,然后解决它们。
高效工程师会找出并处理这些最大的瓶颈,尽管可能这些瓶颈并不涉及到写代码或者不在他们的舒适区内。
一个常见的瓶颈就是对其他人工作的依赖。
沟通对于推进与人相关的瓶颈点至关重要。
另一个常见的瓶颈类型是获得关键决策者的批准。
第三种瓶颈是项目启动之后的审查流程。
在大公司,解决这些瓶颈可能超出了你的影响范围,而你能做的最好的事情是围绕它们开展工作。在小的初创公司,你通常都可以直接解决瓶颈本身。
Key Takeways
- 迭代的越快,学的越多
- 在工具化上投资
- 优化你的 debug 工作流
- 掌握你手艺的基础
- 全面了解你的迭代循环
Measure What You Want to Improve
衡量你要改进的地方
Use Metrics to Drive Progress
使用指标来驱动进步
如果你不能衡量它,你就不能改进它。
- 好的指标可以实现许多目标
- 当随着时间的推移而可视化时,好的指标有助于防止将来的回归。
- 好的指标可以推动进步
- 一个好的指标可以让您衡量一段时间内的效果,并将你正在做的事情与可能要进行的其他活动进行比较
很难衡量目标并不意味着不值得做。
Pick the Right Metric to Incentivize the Behavior You Want
挑选正确的指标来激励你想要的行为
指标选择:
- 最大化影响
- 可行动的
- 反应迅速同时健壮
Instrument Everything to Understand What’s Going On
监控一切以便理解到底发生什么
Internalize Useful Numbers
内部化有用的数字还可以帮助您发现数据测量中的异常
了解有用的数字可以明确改进的领域和范围
有用的数字:
- 注册用户数、日活、月活
- 每秒请求数
- 数据存储容量上限
- 每天读写数据量
- 支持一个特定服务需要的服务器数量
- 不同的服务的吞吐量
- 流量的增长率
- 页面平均加载时长
- 产品不同部分之间的流量分布
- 不同的 Web 浏览器、移动设备、操作系统的流量分布
Be Skeptical about Data Integrity
对数据完整性保持着怀疑态度
有时候会混淆相关性和因果关系
Key Takeaways
- 衡量进度
- 小心的选择最高层的指标
- 监控你的系统
- 知道你的数据
- 优先考虑数据完整性
Validate Your Ideas Early and Often
尽早并且经常性的验证你的想法
尽快根据用户反馈来优化
尽早并经常验证我们的想法有助于我们完成正确的事情
Find Low-Effort Ways to Validate Your Work
找到低成本的方式来验证你的工作
一个可行的验证想法的方式是花 10% 的投入构建一个小而又足够信息的原型
Continuously Validate Product Changes with A/B Testing
持续通过 A/B 测试来验证产品变更
Beware the One-Person Team
当心一人团队
建立有效的反馈渠道:
- 保持开放,乐于接受反馈
- 尽早经常的提交代码评审
- 请求最严格的评审者来评审代码
- 询问同事的想法看法
- 先设计系统的接口和 API
- 投入编码前先展示你的设计文档
- 如果可能,请对正在进行的项目进行结构设计,以便与队友共享一些上下文
- 在投入太多时间之前,对有争议的问题寻求讨论和支持
Build Feedback Loops for Your Decisions
建立你的决定反馈循环
设计实验验证你的猜想,不论好坏,从实验结果中学习
Key Takeaways
- 迭代的去处理问题,以避免浪费投入
- 将大的实现拆分成小模块验证以降低风险
- 使用 A/B 测试来持续的验证你的产品假设
- 当工作在一个独立项目中时,寻求一个定期的外部反馈
- 采取积极的态度去验证你的决定
Improve Your Project Estimation Skills
项目估期是高效工程师需要学习的最难的技能之一。
Use Accurate Estimates to Drive Project Planning
使用准确的估期来驱动项目计划
一些策略:
- 拆分项目成小的任务
- 估期建立在任务需要多久完成,而不是你或者其他人希望多久完成
- 将估期视为概率分布,而不是最佳情况
- 让实际做这项工作的人来估期
- 当心锚定偏差
- 使用多种方式来估计同样的任务
- 警惕神话般的人月:加人缩短不了工期
- 通过历史数据来验证估期
- 使用时间盒子来限制任务的增长
- 允许别人挑战你的估期
Budget for the Unknown
给未知事物留下缓冲预算
Define Specific Project Goals and Measurable Milestones
设定明确的项目目标和可衡量的里程碑
明确定义的目标提供了一个重要的过滤器,用于将任务列表中的必须有与最好有分开
定义特定项目目标的第二个好处是,它可以在关键利益相关者之间建立清晰度和一致性。
Reduce Risk Early
尽早暴露并降低风险
如何降低集成风险?尽早做端到端的脚手架和系统整合测试。
Approach Rewrite Projects with Extreme Caution
极其谨慎的重写项目
有重写经验的工程师,倾向于把大的项目重写分解成一系列的小项目。
Don’t Sprint in the Middle of a Marathon
不要在马拉松比赛中冲刺
- 工作时长增加,每小时工作效率降低
- 和你想象的相比,你可能比计划表落后的更多
- 额外的工作会压垮团队成员
- 增加工作时长会伤害成员的工作热情
- 随着截止日期的临近,沟通的开销会增加
- 最后冲刺会产生大量的技术债
当延期时:
- 确保每个人都了解造成时间表迄今延误的主要原因
- 重新制定现实的时间表
- 如果距离重新修订的时间表很远,随时准备放弃冲刺
Key Takeaways
- 将估期纳入到项目计划中
- 项目表中流出缓冲时间
- 定义可衡量的里程碑
- 先做风险大的任务
- 明确加班的局限性
Part 3: Build Long-Term Value
Balance Quality with Pragmatism
务实兼顾质量
Establish a Sustainable Code Review Process
建立可持续的代码评审流程
好处:
- 尽早发现 bug 和设计缺陷
- 增加对代码变更的责任心
- 建立正面的如何写好代码的样例
- 共享知识
- 提升长期的敏捷度
Manage Complexity through Abstraction
通过抽象来管理复杂度
- 通过降低原始问题的复杂度变成一个简单容易理解的问题
- 降低未来的维护成本并且更加容易后续功能迭代
- 解决一个复杂的问题一次,未来就可以使用很多次
好的抽象应该是:
- 容易学习
- 在没有文档的情况下依然容易使用
- 很难误用、用错
- 足够强大以满足需求
- 容易扩展
- 对使用者很合适
Automate Testing
自动化测试
Repay Technical Debt
偿还技术债
技术债不会只是在我们做快速、肮脏的变通工作时才会积累起来。每当我们在不完全了解问题空间的情况下编写软件时,我们的第一个版本最终都可能设计得不如我们所希望的那么干净。
成为一个高效工程师的关键是在面临 DDL 的时候,可以引入一定的技术债,但同时也会周期性的偿还技术债。
高效工程师花费有限的时间以最高的杠杆率偿还债务——代码库中人流密集的部分中花费最少的时间进行修复。
Key Takeaways
- 建立代码 review 的文化
- 在好的软件抽象上投入以简化困难的问题
- 通过自动化测试提高代码质量
- 管理你的技术债
Minimize Operational Burden
Embrace Operational Simplicity
高效工程师关注于简单性上。
拥有复杂架构设施带来一系列的维护问题:
- 工程师的专长经验被分散到多个系统上
- 复杂性带来潜在人员的单点故障问题
- 新成员面临着陡峭的学习曲线
- 投入到提升抽象程度、库和工具的资源被分散到不同的系统上
可以解决我们的问题并且可以降低未来的维护成本的方案是什么?
Build Systems to Fail Fast
快速失败
快速失败并不意味着让程序给终端用户崩溃。可以用全局的异常处理,快速上报这些错误,但优雅的给普通用户异常降级处理。
Relentlessly Automate Mechanical Tasks
无情的自动化机械任务
每次你做了某些机器可以完成的工作,问问自己是否值得自动化这些工作。
Make Batch Processes Idempotent
让批处理任务保持幂等性
无副作用,可重试
Hone Your Ability to Respond and Recover Quickly
磨练你的快速响应和恢复的能力
针对主要的故障,最有效的防御措施就是经常失败。
建立快速恢复的能力。
将时间和精力集中在我们的快速恢复能力上,比起一开始就预防失败,具有更高的杠杆作用。
Key Takeaways
- 先做简单的事情
- 快速失败以便快速找到问题的根源
- 使决策过程自动化
- 旨在实现幂等和可重试
- 计划和练习失败模式
Invest in Your Team’s Growth
但是,如果您想提高效率,那么重要的是要认识到,建立一支强大的团队和积极的文化具有相当大的影响力。
在职业生涯的早期就思考如何帮助您的同事成功,这会灌输正确的习惯,进而养成您自己的成功。
Make Hiring Everyone’s Responsibility
让招聘成为每个人的责任
良好的面试过程可以实现两个目标。 首先,它筛选可能在团队中表现出色的人员类型。 其次,它使候选人对团队,任务和文化感到兴奋。
- 花时间和你的团队一起考虑清楚,到底哪些特性对于潜在候选人是你最关心的
- 周期性的回顾讨论当前面试流程的有效性
- 设计面试问题,带有多个层次深度,以便能够适配不同能力水平的面试者
- 控制面试节奏以便获得更高的信噪比
- 通过迅速发出简短答案来探测广阔的表面来扫描危险信号
- 在面试中经常另一位团队成员配对
- 不要害怕使用非常规的面试方法,只要它们能帮助您确定团队所关心的信号
Design a Good Onboarding Process
设计一个良好的入职流程
第一印象很重要。 良好的初始经验会影响工程师对工程文化的理解,影响其交付未来影响的能力,并根据团队的工作重点指导他的学习和活动。
入职流程的四个目标:
- 新工程师尽快提升产出
- 传授团队文化和价值
- 使新工程师拥有成功所需的广泛基础知识
- 通过社交方式将新工程师整合到团队中
Share Ownership of Code
共享代码的主人翁意识
当你成为某个项目的瓶颈时,你就失去了做其他事情的灵活性。
策略:
- 避免一个人的团队
- 互相 review 代码和设计
- 在整个团队中轮换任务
- 保持代码的可读性和质量
- 针对软件设计和架构进行技术演讲
- 文档化。不论是设计文档还是代码注释
- 记录完成工作所需的复杂工作流程或非显而易见的解决方法
- 花时间在教学和指导其他团队成员上
Build Collective Wisdom through Post-Mortems
通过事后复盘来建立集体智慧
Build a Great Engineering Culture
建立伟大的工程师文化
伟大的工程师文化:
- 为迭代速度而优化
- 持续无情的追求自动化
- 建立正确的软件抽象
- 通过代码评审关注高质量的代码
- 维护一个互相尊重的工作环境
- 建立一个共享的代码主人翁意识
- 在自动化测试上投入
- 分配实验性时间
- 培养持续学习和提升的文化
- 雇佣最优秀的人才
Key Takeaways
- 帮助周围的同事成功
- 让招聘成为高优先级的事情
- 在入职流程和 mentor 机制上投入
- 建立代码的共享主人翁意识
- 沉淀集体智慧
- 建立伟大的工程师文化