煮胡萝卜
2016年6月23日
我从小就讨厌胡萝卜,讨厌它的气味和口感。但当我离开家开始自己做饭后,我开始喜欢它们了。胡萝卜本身没有改变,我的味蕾也没有发生根本性的改变,区别在于烹饪方式。我的母亲,像她那一代的许多英国人一样,不是一个好厨师——尤其是蔬菜。她的做法是将胡萝卜煮20分钟或更长时间。后来我才知道,如果你用正确的方法烹饪,胡萝卜会是完全不同的体验。
这不是一个关于烹饪的网站,而是关于软件开发的。但我发现,很多时候,一种技术或工具就像可怜的胡萝卜——被指责为糟糕,而真正的问题是这种技术被错误地使用了。
让我们举几个例子。我的一些朋友评论说存储过程是一场灾难,因为它们没有被保存在版本控制中(而是使用像 GetCust01、GetCust02、GetCust02B 这样的名称)。这不是存储过程的问题,而是人们在使用它们时采用了不好的做法。同样,对 TDD 导致脆弱设计的批评,在进一步询问后发现,该团队没有进行任何重构——而重构是 TDD 中的关键步骤。
这两者都是煮胡萝卜——有用的工具,却被误用了。我见过一些团队从存储过程和 TDD 中获得了价值。如果我们不考虑它们的用法就抛弃它们,就会失去工具箱中一些有用的工具。
并非所有技术的失败都是煮胡萝卜。据可靠消息称,没有办法烹饪松鼠,让除了绝望的人以外的任何人觉得好吃(这真可惜,考虑到它们今年春天一直在对我们的花园做些什么)。如果我遇到一个团队在共享文件夹中编写代码,没有任何版本控制,那么就没有办法烹饪这种技术,它不会同样令人厌恶。
所以,当我们听到技术失败的消息时,我们需要问更多的问题。
- 是技术本身有问题,还是遗漏了一些其他东西?这种技术是否会对这种情况产生影响?(版本控制与存储过程是独立的,但由于所涉及的工具的性质,使用版本控制来管理存储过程可能更难。)
- 这种技术是否被用在了不适合它的环境中?(不要在没有测试的情况下进行大规模的手动重构。)请记住,软件开发是一项非常人性化的活动,很多时候,技术不适合某个环境,是因为文化和个性。
- 是否遗漏了技术中的一些重要部分?
- 人们是否专注于与现实不符的外在迹象?这种事情就是史蒂夫·麦康奈尔所说的货物崇拜软件工程。
- 这种技术是否在某种程度上有效,但正在被用在超出其适用范围的地方?值得记住帕拉塞尔苏斯的原则,即药物和毒药之间的区别在于剂量。通过 UI 测试系统在少数情况下是有用的,但如果你把它作为主要的测试方法,最终会得到缓慢而脆弱的测试,要么会拖慢你的速度,要么会被忽略。
有趣的是,某些技术是否很脆弱;也就是说,它们是否难以正确应用,因此更容易出现错误的应用?如果很难正确使用某种技术,那么这对于这种技术来说是一个合理的限制,减少了它可以使用的环境。一些精致的食物必须留给大师级厨师。这并不意味着它们是一种不好的技术,但确实降低了它们对更熟练团队的适用性。我认为这是组件后期集成的根本问题。虽然一些团队可以根据仔细的规范开发组件,并在后期进行集成,但在实践中,很少有团队能够做到这一点,后期集成最终就像河豚一样。
虽然我们需要警惕煮胡萝卜,但我们也需要牢记,我们也遇到了我观察到的“没有一种方法论会失败”的情况。对于任何失败(假设你能够知道什么是失败),你都可以找到方法论的一些变体——这会导致它的支持者说它没有被遵循,因此没有失败。这里存在一种真正的张力,一种无法在不深入理解技术背后的更深层原则的情况下解决的张力。真正重要的是,这些技术无法被严格地描述,就像意大利肉酱面没有一个精确的食谱,可以不加思考地遵循。最终,真正重要的是菜肴,准备它的技术可以启发和指导一位好厨师,但不能保证一个没有一定技能的人成功。
就像任何职业一样,如果我们从彼此的经验中学习,我们可以更快地进步。人们使用技术和工具的报告很重要,这样我们就可以判断在自己的工作中尝试什么。然而,一个简单的标签通常是不够的。我们既无法衡量对正确使用技术的遵守程度,也无法衡量它们的成功程度。重要的是,每当你听到技术失败的消息时,都要深入挖掘,看看胡萝卜是否在锅里放得太久了。否则,我们就有可能错过一些有价值的东西。
我最初是在“错误的技术二分法”标题下写了关于这个主题的文章,但现在觉得煮胡萝卜的比喻更令人难忘。
进一步阅读
我喜欢 Ron Jeffries 为类似现象提出的一个比喻"我们尝试过棒球,但它没有奏效"。