《Google软件工程》是由中国电力出版社出版的一本关于Google方面的书籍,作者是提图斯·温特斯,主要介绍了关于Google、软件工程方面的知识内容,目前在Google类书籍综合评分为:9.8分。
书籍介绍
编辑推荐
这本书解释了谷歌做软件工程的方式,讲述了需要考虑的各种权衡。
如今,软件工程师不仅需要知道如何有效地编程,还需要知道如何发展适当的工程实践,以使代码库可持续且健康。这本书强调了编程和软件工程之间的区别。
软件工程师如何管理一个活跃的代码库,这个代码库在其生命周期里不断响应变化的需求,不断地发展?软件工程师TitusWinters和HyrumWright,携手技术作家TomManshreck,基于他们在谷歌的经验,坦率而有见地的为大家介绍了的从业者是如何构建和维护软件的。
“这本书解释了谷歌做软件工程的方式,这种方式让我有很高的生产力,并且很快乐,同时本书也直言不讳的讲述了需要考虑的各种权衡。”
内容简介
你将学习到软件组织在设计、架构、编写和维护代码时应牢记的三个基本原则:时间如何影响软件的可持续性,以及如何使代码随着时间的推移而具有韧性。模如何影响工程组织内软件实践的可行性。在评估设计和开发决策时,一位典型的工程师需要做出哪些权衡。
目录
- 序1
- 前言3
- 部分理论
- 第1章什么是软件工程13
- 时间与变化15
- 海勒姆定律18
- 案例:哈希排序18
- 为什么目标不是“没有变化”呢20
- 规模与效率21
- 阻碍规模化的政策22
- 促进规模化的政策24
- 案例:编译器升级24
- 左移思想26
- 权衡与成本28
- 案例:白板笔29
- 决策投入30
- 案例:分布式构建30
- 案例:时间与规模的博弈32
- 数据驱动的决策32
- 软件工程VS编程33
- 小结34
- 本章要点34
- 第二部分文化
- 第2章如何更好地参与团队合作37
- 隐藏代码37
- 天才神话38
- 隐藏有害40
- 及早检测41
- 巴士系数41
- 小步快跑42
- 拒绝隐藏44
- 一切为了团队44
- 社交的三大支柱45
- 三大支柱的重要性46
- 谦虚、尊重和信任46
- 无指责的回顾文化50
- 谷歌范儿(Googley)52
- 小结53
- 本章要点53
- 第3章知识共享55
- 学习的挑战55
- 知识共享的哲学57
- 设定基调:心理安全58
- 导师制58
- 大型群体的心理安全59
- 不断充实知识60
- 提问60
- 理解上下文61
- 扩大提问渠道:向社区提问62
- 群聊62
- 邮件列表63
- YAQS:问答平台63
- 分享你的知识:你总有可以教别人的地方64
- OfficeHours64
- 技术讲座与课程64
- 文档65
- 代码67
- 组织知识发展68
- 培养知识分享的文化68
- 建立规范的信息源70
- 让信息流动73
- 可读性:通过代码评审规范化指导74
- 什么是可读性流程74
- 为什么需要可读性流程75
- 小结78
- 本章要点78
- 第4章平等工程79
- 人类的偏见80
- 理解多样性的必要性82
- 建立多元文化能力82
- 使多样性具有可操作性84
- 拒绝单一的方式85
- 挑战既定流程86
- 价值观与成果87
- 保持好奇心,向前推进88
- 小结88
- 本章要点89
- 第5章团队领导的艺术91
- 经理和技术主管(或两者兼任)91
- 工程经理92
- 技术主管92
- 技术主管经理92
- 从个人贡献者到领导者93
- 需要担心的是……嗯,一切94
- 仆人式领导95
- 工程经理96
- “经理”是一个令人厌恶的词96
- 如今的工程经理96
- 反模式98
- 反模式:雇用平庸的人98
- 反模式:忽视低绩效员工99
- 反模式:忽视“人”的问题100
- 反模式:做老好人101
- 反模式:打破招聘门槛102
- 反模式:像对待孩子一样对待你的团队102
- 积极的模式103
- 抛弃“自我”意识103
- 成为一名禅师104
- 成为催化剂106
- 移除障碍106
- 成为老师和导师107
- 设定清晰的目标107
- 坦诚108
- 追踪幸福感109
- 出乎意料的问题110
- 其他提示和技巧111
- 对待人像植物一样113
- 内在激励和外在激励114
- 小结115
- 本章要点115
- 第6章大规模团队领导力117
- 总是在做决策118
- 飞机的故事118
- 识别盲点119
- 识别关键的权衡120
- 决策,然后迭代120
- 总是不在场122
- 你的使命:建立一个“自驱”的团队123
- 划分问题空间123
- 总是在扩展126
- 成功的循环127
- 重要VS紧急128
- 学会放弃130
- 保护你的精力131
- 小结133
- 本章要点133
- 第7章度量工程生产力135
- 为什么要度量工程生产力135
- 鉴别:它值得度量吗137
- 根据目标和信号来选择有意义的指标141
- 目标142
- 信号144
- 指标145
- 使用数据验证指标145
- 采取行动并跟踪结果150
- 小结150
- 本章要点150
- 第三部分流程
- 第8章风格指南与规则155
- 为什么要有规则156
- 创建规则157
- 指导原则157
- 风格指南165
- 修改规则168
- 流程169
- 风格仲裁者170
- 例外情况170
- 指南171
- 应用规则173
- 错误检查工具174
- 代码格式化工具175
- 小结177
- 本章要点177
- 第9章代码评审179
- 代码评审流程180
- 谷歌如何进行代码评审181
- 代码评审的好处184
- 代码正确性185
- 代码理解187
- 代码一致性187
- 心理和文化方面的好处188
- 知识共享189
- 代码评审实践190
- 礼貌而专业190
- 小的变更191
- 清晰的变更描述193
- 评审者数量少化193
- 尽可能的自动化194
- 代码评审类型194
- 绿地代码评审194
- 行为变更、改进和优化195
- 缺陷修复和回滚195
- 重构和大规模变更196
- 小结197
- 本章要点197
- 第10章文档199
- 什么是文档200
- 为什么需要文档200
- 像代码一样对待文档202
- 了解文档的读者204
- 读者的类型205
- 文档类型206
- 参考文档207
- 设计文档210
- 新手教程210
- 概念文档212
- 着陆页面213
- 文档评审214
- 文档的哲学216
- WHO,WHAT,WHEN,WHERE和WHY216
- 开头,中间和结尾217
- 优秀文档的要素217
- 丢弃文档218
- 什么时候需要技术文档工程师219
- 小结219
- 本章要点220
- 第11章测试概述221
- 为什么要写测试222
- “GoogleWebServer”的故事223
- 当今开发速度下的测试224
- 编写,运行,响应224
- 测试代码的好处227
- 设计测试套件228
- 测试粒度229
- 测试范围233
- 碧昂丝规则235
- 代码覆盖率236
- 谷歌规模下的测试237
- 大型测试套件的陷阱238
- 谷歌测试的历史239
- 入职培训课240
- 测试认证241
- “马桶测试”241
- 如今的测试文化242
- 自动化测试的局限性243
- 小结244
- 本章要点244
- 第12章单元测试245
- 可维护性的重要性246
- 防止脆弱的测试247
- 努力做到不更改测试247
- 通过公共API进行测试248
- 测试状态,而不是交互252
- 编写清晰的测试253
- 使测试完整简洁254
- 测试行为,而不是方法255
- 不要把逻辑放进测试260
- 编写清晰的失败信息261
- 测试与代码共享:DAMP,而不是DRY263
- 共享值265
- 共享设置267
- 共享helper和验证269
- 定义测试基础设施270
- 小结270
- 本章要点270
- 第13章测试替身273
- 测试替身对软件开发的影响274
- 谷歌的测试替身274
- 基本概念275
- 测试替身的示例275
- 缝(Seams)276
- 模拟(Mocking)框架277
- 使用测试替身的技术279
- 伪造(Faking)279
- 打桩(Stubbing)279
- 交互测试280
- 实际实现281
- 实际实现比隔离更好281
- 如何决定何时使用实际实现283
- 伪造(Faking)285
- 为什么伪实现(Fakes)如此重要286
- 什么时候写伪实现286
- 伪实现的保真度287
- 伪实现应该被测试288
- 如果没有伪实现怎么办288
- 打桩289
- 过度使用打桩的危险性289
- 何时使用打桩合适291
- 交互测试292
- 状态测试优于交互测试292
- 何时使用交互测试合适293
- 交互测试的实践294
- 小结296
- 本章要点296
- 第14章较大型的测试299
- 什么是较大型的测试299
- 保真度300
- 单元测试中的常见问题301
- 为什么不要有较大型的测试303
- 谷歌的较大型的测试304
- 较大型的测试和时间305
- 谷歌规模下的较大型的测试306
- 大型测试的结构308
- 被测系统(SUT)309
- 测试数据314
- 验证315
- 较大型的测试的类型316
- 一个或多个交互二进制文件的功能测试316
- 浏览器和设备测试317
- 性能、负载和压力测试317
- 部署配置测试318
- 探索性测试318
- A/B差异回归测试319
- 用户验收测试(UAT)321
- 探针和金丝雀分析321
- 灾难恢复与混沌工程322
- 用户评估324
- 大型测试和开发者工作流325
- 编写大型测试325
- 运行大型测试326
- 大型测试的所有权329
- 小结330
- 本章要点330
- 第15章弃用331
- 为什么弃用332
- 为什么弃用很难333
- 将弃用融入设计335
- 弃用的类型336
- 建议性弃用336
- 强制性弃用337
- 弃用警告338
- 弃用流程的管理339
- 流程负责人340
- 里程碑340
- 弃用的工具341
- 小结342
- 本章要点343
- 第四部分工具
- 第16章版本控制与分支管理347
- 什么是版本控制348
- 为什么版本控制很重要349
- 集中式版本控制系统VS分布式版本控制系统351
- 真实来源354
- 版本控制VS依赖管理356
- 分支管理356
- 分支等同于在制品357
- 开发分支358
- 发布分支359
- 谷歌的版本控制360
- 单一版本361
- 场景:多个可用版本362
- “单一版本”规则363
- (几乎)没有长周期的分支363
- 发布分支呢365
- 单一代码仓(Monorepos)365
- 版本控制的未来367
- 小结369
- 本章要点370
- 第17章代码搜索371
- CodeSearch的用户界面372
- 如何使用CodeSearch373
- 在哪里373
- 做什么374
- 如何用374
- 为什么375
- 谁以及何时375
- 为什么需要一个单独的Web工具375
- 规模375
- 无需设置即可浏览全局代码376
- 专业化377
- 与其他开发工具集成377
- 开放API379
- 规模对设计的影响379
- 搜索查询延迟380
- 索引延迟381
- 谷歌的实现382
- 搜索索引382
- 排序383
- 权衡387
- 完整性:代码库的Head387
- 完整性:所有结果VS相关的结果387
- 完整性:HeadVS分支VS所有历史VS工作空间388
- 表达性:TokenVS子串VS正则表达式389
- 小结390
- 本章要点391
- 第18章构建工具与构建哲学393
- 构建系统的目的393
- 没有构建系统会发生什么395
- 但是我只需要一个编译器395
- 用shell脚本来拯救396
- 现代构建系统397
- 一切都是为了依赖397
- 基于任务的构建系统398
- 基于制品的构建系统402
- 分布式构建408
- 时间,规模,权衡412
- 处理模块和依赖413
- 使用细粒度依赖与1:1:1规则413
- 小化模块可见性414
- 管理依赖414
- 小结419
- 本章要点420
- 第19章Critique:谷歌的代码评审工具421
- 代码评审工具的原则421
- 代码评审流程423
- 通知424
- 步:创建一个变更425
- 差异比较425
- 分析结果426
- 紧密的工具集成428
- 第二步:请求评审429
- 第三步和第四步:理解和评论变更430
- 评论430
- 了解变更状态432
- 第五步:批准变更(评价变更)434
- 第六步:提交变更435
- 提交后:跟踪历史436
- 小结437
- 本章要点438
- 第20章静态分析439
- 有效静态分析的特点440
- 可扩展性440
- 易用性440
- 让静态分析发挥作用的关键经验441
- 关注开发者的体验441
- 让静态分析成为核心开发者工作流的一部分442
- 赋予用户贡献的权力442
- Tricorder:谷歌的静态分析平台443
- 集成的工具444
- 集成反馈渠道445
- 建议的修复446
- 按项目定制447
- 预提交448
- 编译器集成448
- 编辑和浏览代码时的分析449
- 小结450
- 本章要点450
- 第21章依赖管理451
- 为什么依赖管理这么难453
- 冲突的需求和菱形依赖453
- 引入依赖455
- 兼容性承诺455
- 引入时的注意事项457
- 谷歌如何处理引入的依赖459
- 从理论上讲,依赖管理460
- 没有变化(又名静态依赖模型)461
- 语义化版本号462
- 绑定分发模式463
- LiveatHead464
- SemVer的局限性465
- SemVer可能过度约束466
- SemVer可能过度承诺467
- 动机468
- 小版本选择469
- 那么,SemVer有效吗470
- 资源无限的依赖管理471
- 导出依赖473
- 小结477
- 本章要点477
- 第22章大规模变更479
- 什么是大规模变更480
- 谁来处理LSC481
- 原子变更的障碍483
- 技术限制483
- 合并冲突483
- “没有闹鬼的墓地”484
- 异构性484
- 测试485
- 代码评审487
- LSC的基础设施489
- 政策与文化489
- 代码库分析490
- 变更管理491
- 测试491
- 语言支持491
- LSC流程493
- 授权493
- 变更创建494
- 切片与提交494
- 清理498
- 小结498
- 本章要点498
- 第23章持续集成499
- CI的概念501
- 快速反馈循环501
- 自动化503
- 持续测试505
- CI的挑战511
- 封闭测试512
- 谷歌的CI515
- CI案例研究:GoogleTakeout518
- 但是我无力做CI524
- 小结525
- 本章要点525
- 第24章持续交付527
- 持续交付在谷歌的习语528
- 速度是一项团队运动:如何将部署分解为可管理的单元529
- 隔离评估变更:特性开关530
- 力求敏捷:建立发布火车531
- 没有一个二进制是完美的531
- 赶上你的发布期限532
- 质量与聚焦用户:只发布有用的功能533
- 左移:更早地做出数据驱动的决策534
- 改变团队文化:建立发布规则535
- 小结536
- 本章要点537
- 第25章计算即服务539
- 驯服计算环境540
- 将琐事自动化540
- 容器化与多租户542
- 总结545
- 为托管计算编写软件545
- 为失效设计架构545
- 批处理VS服务547
- 管理状态549
- 连接到服务550
- 一次性代码551
- CaaS随时间和规模的演化552
- 抽象容器552
- 一个服务统御余众555
- 提交的配置557
- 选择计算服务558
- 集中化与定制化559
- 抽象层次:Serverless561
- 公有云VS私有云565
- 小结566
- 本章要点567
- 后记569