写点什么

使用好的工程实践交付可交付产品

2016 年 9 月 04 日

Scrum 和敏捷讲师 Mohammad Nafees Sharif Butt 指出,好的工程实践是一种工具,有助于敏捷团队交付可交付产品。虽然不少工程实践已被证明是有效的,但它们并没有得到应有地广泛使用。Nafees 提到,软件甜筒测试、累积的技术争议和功能筒仓等敏捷反模式(anti-pattern),阻碍了团队在 sprint 末期交付潜在的可发布产品。通过运用系统思维定期地进行检视与调整,可以解决上述反模式问题。

SwanseaCon 2016 大会上,Nafees 将会报告关于创建“潜在可发布产品增量”(potentially releasable product increment)的工具。InfoQ 就此访谈了 Nafees,所涉及问题包括:什么是敏捷反模式及如何处理它们、为什么卓越技术是很重要的、其所推荐的工程实践、组织应如何去建立具有优秀工程实践的文化等。

InfoQ:在组织中,你见到过哪些敏捷反模式?

Mohammad Nafees Sharif Butt:从技术角度看,我观察到了如下十分常见的敏捷反模式:

一、甜筒测试自动化。其中大多数的测试是通过 UI 进行的,这违反了成比例的测试金字塔(Testing Pyramid)理念。遵循这种反模式的团队和组织总是试图通过 UI 测试去自动化大多数接收的测试。如此的 UI 测试中所存在的问题包括:由 UI 测试本质上的非确定性所导致的漏报、测试的运行和维护成本高、迷你瀑布模型的建立延迟了对团队的反馈,团队不能灵活地处理将来的 UI 改进。

二、另一种常见的反模式是罔顾权责的技术争论。这个问题源于紧迫性意识(所有的产品开发组发现他们都陷入当今这样创新的时代中),以及错误地假设团队并不具备足够的时间进行设计。该反模式的一个小的变种也是十分常见的。这种情形下,从业者既不遵循工艺也不去执行“童子军”规则,任由代码库发生腐烂变质。

三、将应用构建服务器与持续集成等同。尽管近十年中持续集成与持续交付相关的工具已成熟了很多,在持续集成过程中组织仍继续丢失“持续”的精髓所在。长生命周期的特性分支、痛苦而破坏性的冲突合并是这种反模式的常见症状。

四、功能性筒仓。这些结构性障碍未必是技术上的限制,但具有严重的技术衍生。在不理解底层原则的情况下就“货物崇拜”式地应用敏捷实践,这种做法所产生的副作用包括:业务分析与“开发”的分离、阶段式地经由架构组实施的大规模架构更改、N+1 方式的设计 sprint。以上这些问题,无论存在其中任何一种,都将导致过程和产品中的消耗。

InfoQ:你是怎么处理上述反模式的?

Nafees:有两种攻击途径可给出解决方案。首要的是持续侧重于“检视与调整”(Inspect & Adapt),其次是系统性思考(System Thinking)。在当前可见的技术实践中,组织不能从一棵树看到整个森林是大多数的反模式的根源所在,导致该问题的原因在于组织决策的结果是局部优化的。一个学习的团队和组织不仅需要具有全局视角,而且需要理解自身行为与系统状态之间的因果关系。定期做这种检视并根据结果进行相应的调整,这有助于对反模式的处理。

一个具体的例子来自我几年前曾供职的一个团队,该团队为避免对其全新产品的每个 sprint 做手工回归测试,开始采用 Selenium Web Browser Automation 产品做接收测试。虽然当时他们成功地实现了测试场景自动化,但是缺点也同时在一些 sprint 中显现出来。在 sprint 回顾中,团队分析了现状,并得出测试目标并非是为了现状而进行自动化的结论。如果因为这些测试延迟了反馈(由于测试需要很长的运行时间)而导致团队遭受返工的损耗(测试需要在 UI 改变时重构),那么就团队就需要一个可替代的策略。这里有经验的从业者是十分有用的,他可引导团队通过皮下测试,即不依赖于需完成的 UI 改变就对 API 进行测试。这种测试可更快地提供反馈,并在 UI 发生改变时无需进行重构。虽然 spint 回顾将激发组员间固执己见的讨论,但是组员专注于为实现总体优秀而做的持续改进,这并没有被完成工作的成就感所阻碍,因此 spint 回顾方法可以解决这样的问题。

在“关于软件开发者的问答”一文中,Sandro Mancuso 解释了为什么卓越技术是很重要的:

敏捷是为改进我们交付软件的方式而创建的。如果我们以卓越技术为重点,那么我们软件的质量将回退到某一点,在该点上做改变是非常痛苦和缓慢的。同时在该点上采用了哪种敏捷过程都是无所谓的,因为开发人员不再能快速前进,这导致企业失去敏捷性。

InfoQ:为什么卓越技术是如此的重要?

Nafees:过去使用瀑布模型时, 我们可奢侈的在大规模预先设计(Big Design Up Front,BDUF)和架构上花费数月的时间。现在我们再也不能这样做了。按精益软件开发中对湖与石头的隐喻,敏捷中常见的小规模频繁的迭代会立刻显现如上实践的低效。交付增量改变而无需冻结预先设计范围的承诺是一个严重错误,这为使用那些被牢记于心的卓越技术去构建强大产品奠定了基础。如果不使用卓越技术,组织将发现自己不能确保遵守逐次迭代地交付客户需求的承诺,因为它背负着腐烂代码库的包袱。所有这样的努力只能归结为是对敏捷的口头服务,而非真实敏捷的先行者。

以“干净架构”(Clean Architecture)概念为例。依赖规则(Dependency Rule)不仅确保了应用的分层并允许在此后做准时制决策,而且使得规则开放可修改且无需涉及重要工作就可灵活扩展(更多内容可参见 SOLID 原则中的 OCP)。我曾参与了一个健康保险集成计划,其中我们使用了“干净架构”,实现了网关模式的增量创建,最终交易了全国 70% 的健康保险数据。

InfoQ:请给出一个你所推荐的工程实践,并给出推荐理由。

Nafees:根据我最近的经历,我将侧重于大规模产品开发并推荐下面两个工程实践(作为起点),它们是大中型企业为屹立于竞争前头而需要真正牢记的。

首先,对领域驱动设计(Domain Driven Design,DDD)的需求是无论怎么强调也不为过的(我并非在力推微服务,仅是简洁地去设计你的产品,使得产品不仅可跨越领域间所界定的接缝,而且……)。初创企业更容易用少量工程师实现创新理念的快速交付,但是当开发组规模增加到数十人(甚至更多)时,组织对市场需求变化的交付能力开始受到损害,这种损害是由多个团队的不同应用组件间的协调和依赖所导致的。以领域驱动设计为理念所架构的产品就可以实现对组织的授权,甚至是在组织已经跨越了在初创企业和成功商业之间所存在的深渊之后。

其次,对非功能性需求的忽视是我所见到的另一个惯犯(诸如 2016 年澳大利亚人口普查)。在我看来,如果你的产品需要受限于某种具有特定响应时间限制的负载,那么该工作负载就是你功能性需求的一部分,并需要在一开始就被考虑到(并不是留给强化 sprint 和集成 sprint)。在功能性需求中所应用的 ATDD 的严格性标准,需同样被应用到那些被称为非功能性需求的事情上。说实话,将这些需求称为非功能性需求并将以二等公民对待,只能导致具有这些方面需求的产品被忽视,产品交付也因长时间的忽视而延迟。

在先期的“ James Grenning 访谈录:关于测试驱动开发及代码异味”一文中,当被问及在大力实施技术实践以提升技术的卓越的过程中需要做些什么时,James Grenning 的回答是:

我认为强调独自工作以及专业化的文化在某种程度上是错误的。如果你所能见的都只是你自己的代码,你会产生这样的观念,一切都很好并且已经没有什么新东西要学的了。在开发周期的后段进行代码评审意味着改进将变得最困难。公司应当鼓励员工更紧密地一起工作。结对编程对传播技术的卓越之处非常有益,这是个双向的过程。

InfoQ:如果想要建立具有良好工程实践的文化,组织应该怎么做?

Nafees: 去针对未来的状态而招聘人员。新的人才几乎总是会对现有的平衡产生撼动。如果与工程实践相关的现有组织文化是不成熟的,我推荐通过找寻匹配当前文化人才的方式为达成目标成熟度而招聘人才。这种方式下新的人才可用于对现状产生积极的影响,并担当目标成熟的催化剂。

另一个重要的因素是获取外部帮助。对于大多数组织而言,当前架构源于上世纪的程序员,鉴于架构中垂直结构的存在,这使得组织难以成熟化其工程规范,即使在组织的领导层中存在热衷于此事的管理者。获取外部帮助可激发组织对现状的反思,即使这意味着去挑战现存的官僚机制。

最后,如果工程师被要求去实现一个解决方案而非提出一个需要解决的问题,这会使得迭代开发感觉上像是永不终止的恶性循环。授权全体员工,让他们进行自组织(甚至自构形)并提供项目的目的所在,这可提升全体员工的主人翁意识并激发他们努力工作。每个员工都是珍惜挑战机会的,这超越了传统管理所愿意认同的。如果适当地辅以自治和做事目的,员工会愿意将自身的所有能量投资于项目中。

SwanseaCon 2016 大会将于九月 12 日至 13 日期间在英国斯旺西自由体育场(Liberty Stadium)召开。2016 大会将会是第二届敏捷开发和软件工匠大会,面向南威尔士的软件开发人员、软件架构师、项目经理、分析师和顾问。InfoQ 将以问答、摘要和报道文章等方式全程覆盖大会。

查看英文原文: Deliver Shippable Products with Good Engineering Practices


感谢夏雪对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2016 年 9 月 04 日 19:00993
用户头像

发布了 226 篇内容, 共 59.5 次阅读, 收获喜欢 14 次。

关注

评论

发布
暂无评论
发现更多内容

游戏夜读 | 如何分析游戏体验?

game1night

图说前端-内存管理(1/3)

梦见君笑

前端 内存 前端进阶训练营

图说前端-使用Atomics避免SharedArrayBuffers中的race conditions(3/3)

梦见君笑

前端 内存管理 前端进阶训练营

【计算机网络】网络层——路由器与路由选择协议

烫烫烫个喵啊

计算机网络 网络层

基于Kubernetes实现的大数据采集与存储实践总结

岿然独存5

Docker Kubernetes S3 EFK Fluentd

《精益思想》读后感分享

zhongzhq

高效工作 精益 精益思想 精益生产方式

架构师必须知道的架构知识

Chank

架构 架构师 Architecture Architect

使用 Dockerfile 创建镜像 | Docker 系列

AlwaysBeta

Docker 容器 镜像 Dockerfile 容器技术

玩转Redis高可用 - 哨兵(Sentinel)模式

Man

高可用 redis高可用 中间件

给 Spring Boot 项目减减肥!18.18M 到 0.18M 是如何做到的?

给你买橘子

Java 程序员 Spring Cloud 编码 SpringBoot 2

啃碎并发(九):内存模型之基础概述

猿灯塔

Java 猿灯塔

redis里的数据结构

流沙

redis

架构师训练营第六周作业

张明森

不会有人还不知道全文检索工具Lucene怎么用吧?文字长文教程

给你买橘子

Java 搜索引擎 lucene 程序员 开发工具

如果你想写自己的Benchmark框架

程序那些事

JVM 性能调优 GC benchmark

如何基于 BitMap 进行海量数据分析

GrowingIO技术专栏

互联网 数据分析 科技互联网 数据化

DOM 树的构建

法正

html DOM 前端进阶训练营

基础篇:JAVA基本类型

csc

Java Java 25 周年

无价值人生记录.0:浪费1000%时间去做一个用来节省1%时间的“轮子玩具”(上:因缘)

八苦-瞿昙

C# 程序员人生 随笔 随笔杂谈 aop

图说前端-ArrayBuffers 和 SharedArrayBuffers(2/3)

梦见君笑

前端 内存管理 前端进阶训练营

RESTful 架构及实践

pingan8787

Java 前端 RESTf

如何搭建一个HBase集群

Rayjun

HBase

Java 线程的生老病死

武培轩

Java 线程 多线程 并发 线程状态

计算机的时钟(一):NTP协议

ElvinYang

基础篇:Object对象

csc

Java Java 25 周年

猿灯塔:spring Boot Starter开发及源码刨析(三)

猿灯塔

Java 猿灯塔

ARTS 打卡 第2周

Scotty

分布式系统的一些基础理论

俊俊哥

分布式事务 CAP Base

那些让程序员目瞪口呆的Bug

Java小咖秀

程序员 程序员人生 bug

java 后端博客系统文章系统——No3

猿灯塔

redis系列之——Redis为什么这么快?

诸葛小猿

Java redis 程序员

InfoQ 极客传媒开发者生态共创计划线上发布会

InfoQ 极客传媒开发者生态共创计划线上发布会

使用好的工程实践交付可交付产品-InfoQ