作者:熊节 《重构》译者
《重构》的坏味道列表,虽然已经很精炼了,终归还是有二十几条。前两天我看见有人说“要记住所有的坏味道并非易事”,他给出的办法呢就是“遵循Kent Beck的简单设计原则”:通过所有测试;尽可能消除重复;尽可能清晰表达;更少代码元素。
有没有错呢?站在非常抽象的层面来说,他这个说法当然是对的。但是我其实很难想象一个场景:
二十几条坏味道都还没记熟的程序员,怎么就能把“清晰表达”这么抽象的标准掌握好的?
所以在这个上下文里,他的办法并不是说Kent Beck的简单设计原则能帮助你更好地记住所有的坏味道、更快地用坏味道来匹配你的代码,只是给你一组比二十几条坏味道更容易记的原则,至于你记住了这几条以后能不能“清晰表达”……反正我们这个行业的事嘛大家心里都有数,自己说清晰就清晰了呗。
这是我这几年在我们这个行业里、尤其是搞敏捷的圈子里经常看见的一种现象:过度抽象。《重构》为什么给你那么明细的二十几条坏味道,因为重构这本书的正确用法是这样:记不住没关系,把书放手边,写半个小时代码就把所有坏味道拿来遍历一遍,看有没有匹配的。这套模式匹配做的次数多了,“记不住”和“嗅觉的敏感性”的问题自然就解决了。无他,唯手熟尔。遇见细节太多背不下来练不熟就扣一个过度简化过度抽象的帽子然后跟自己说我会了,那结果自然是
眼睛:我会了。
手:不,你不会。
过度抽象紧跟着就会带来过度泛化。比如说敏捷这个事,有个同学非常有高度地抽象了这么几句话,
敏捷围绕价值
强调人本主义
只做有意义的事情
往对的方向努力
我就想知道,有哪个公司会说自己不围绕价值不重视人专做没意义的事专往错的方向努力?
学过逻辑的同学都知道,一个概念,外延越宽,内涵越少。当你把一个概念过度抽象到一切事情都可以往里面装,那么就等于在说这个概念啥也不是。当然这本来也正是敏捷圈很多大老师一贯以来的目标,他们就是想把“敏捷”这个概念弄成啥也不是,这样他们就可以卖他们自己的私货。如果不是这个情况,如果确实认为敏捷这个东西还有点价值,就不应该这么去无限扩展这个概念的外延、稀释它的内涵。
敏捷是一种软件开发方法,对于软件开发之外的事它保持沉默,对于软件开发之内的事,做到了就是做到了,没做到就是伪敏捷。严格一点,对大家都好。这也是为什么我尝试写一些文章来划清边界的原因,
为什么总有很多人喜欢过度抽象和过度泛化呢?因为过度抽象和过度泛化以后就看不见细节了,就可以偷工减料了。正如Steve McConnell在《卓有成效的敏捷》里入木三分地说的,大多数号称在搞Scrum的团队,其实搞的都是“Scrum,but……”:我们在做Scrum,但是没有每日站会;我们在做Scrum,但是没有回顾……当然我知道最流行的是:我们在做Scrum,但是我们每个Sprint结束时并没有可交付的增量。与通常庞大的敏捷实践不同,Scrum是管理工作流的最小流程。因为它真的已经是最小的了,所以真的不能移除Scrum的任何部分却仍能获得Scrum的好处。Steve McConnell,《卓有成效的敏捷》
外行才聊抽象和泛化的理论,内行都是直接穷举。这一点,在《重构》和《实现模式》中展现得很清楚,《卓有成效的敏捷》也是同样风格:想做好敏捷,你就是得关注28个不同的问题。一个穷举的列表会让南郭先生立即现形:别跟我扯那些虚头巴脑的,开发团队的自动化测试到底做了没?具体明细的穷举列表是真想改进的人最需要的,也是打着敏捷旗号招摇撞骗的大老师们最害怕的。
面对一个并不算短的穷举列表,一开始你会很慢、记不住,那么你就得慢慢来,不断地翻开书拿这28条一个一个来对应着看。这个过程不可能一开始就快,因为这就是菜鸟与熟手之间的区别,你得通过反复的练习和反思逐渐熟练之后才会快。忽视所有细节不会让你变成熟手,只会让你变成一个找不到方向的菜鸟。
最终,敏捷不是几句高度抽象高度泛化的口号,不是外延无限宽广内涵无限稀薄的片儿汤话。敏捷是一系列非常具体的原则和实践,做到了,就有效果,做不到,就仍然是全凭本能的瞎搞。只有坦白承认绝大多数人、绝大多数团队搞的都是短斤少两的伪敏捷,货真价实的敏捷这个东西才有意义。