复制和粘贴驱动的开发

软件开发充满了复制和粘贴:我们所有人有时都使用复制和粘贴编码。 我们知道我们可能不应该这样做,但是我们做到了

无论如何。 这就像行业中肮脏的小秘密:我们主要只是从Internet或从代码库中的其他地方复制并粘贴代码,然后对其进行重击直到起作用。

但是,也许,也许也许,我们不时依赖于此的事实应该告诉我们一些事情吗?

好的

有时,复制和粘贴编码可能是一件好事。 不久前,我与某人配对,我们做了所谓的“搜索和替换编码”。 我喜欢编码高尔夫。 在诸如Eclipse,Intellij或Resharper之类的工具中,总是存在一种进行每种更改的最佳方法,使这些工具可以进行尽可能多的键入。 因此,最近,一位同事通过搜索和替换为我展示了一个有趣的代码高尔夫,这真是令人着迷。

更改是围绕扩展现有类并添加大量新字段。 我们有一个基本的类,有几个示例字段,还有一个测试,它验证了有关该类的一些简单信息–说它可以成功地序列化为JSON。 我们需要向班级添加大量新字段(不要问)。 这涉及五个单独的任务,它们在宏观层面上有很多共同点:

  • 添加每个字段
  • 初始化构造函数中的每个字段
  • 修改测试以设置每个字段的样本值
  • 修改测试以将每个字段的样本值传递给构造函数
  • 写一个断言,每个字段都已成功序列化和反序列化

我的同事表明,我们可以编写一次字段列表。 然后,复制并粘贴,搜索并替换–我们为构造函数提供了一系列参数。 通过精心设计搜索词和合适的替换词,您可以进行一些有限的元编程。 获取字段列表并将其转换为每个实例中所需的实际代码行。 用一种方法替换的字段列表为您提供了构造函数的参数列表; 使用其他替换,您将在测试中获得字段声明; 用另一个替换,您会得到断言语句。

我发现这是一种非常有趣的编写软件的方式。 它无疑优化了键入代码所需的按键次数。冗长而乏味的字段名称列表仅需键入一次; 之后,只需精心设计搜索和替换正则表达式即可为我们完成任务。 但这表明了一个内在的真理:我们进行了五个单独的更改,接受了一个参数。 如果我们实际上可以对此进行元编程,则可以将字段列表中的内容传递给一些元编程代码,该代码将输出所需的代码行。

尽管我们可以为此使用搜索和替换元编程非常聪明 ,但感觉这些工具还是缺少某种方式。

不好

每个人都会不时地从stackoverflow复制代码。 希望您可以明智地将其用作自己的生产代码的起点。 完成您刚刚粘贴的内容以对其进行理解,进行实验,对其进行修改,使其适合您的目的。 而不是盲目地从互联网上复制和粘贴随机代码。 我的意思是,谁会从互联网上随机运行代码

Stackoverflow很棒。 对于程序员来说,这是一个了不起的资源。 在学习WPF时,我感觉到作为一项技术,如果没有stackoverflow之类的东西,它就不可能实现。 技术是如此不透明,很难学习。 我花了很多很多月从stackoverflow复制并粘贴xaml,直到我开始真正了解它的工作原理。 这是一项不容易理解的技术。 如果不能仅从Internet复制并粘贴代码,该技术将需要花费更长的时间来学习。

但是通常,我们很懒,我们尝试一下。 有用。 哇,下一个问题。 我之前写过有关voodoo编程的文章 ,但是问题在于,很容易以为您已经了解了代码在做什么。 如果您实际上不必发明这些线路,就可以进行推理-也许您不了解。 也许您只是认为您知道代码在做什么? 也许您还没有意识到一些可怕的错误?

丑陋的

几乎每当我看到TDD以任何规模完成时,在编写新测试时,首先要问的问题是:“这最像哪个现有测试?” 是的,我可以在哪里复制和粘贴。 我很懒,我不想自己发明整个测试设置。 我只借别人的功课。 我们都做到了。 这似乎是TDD的不成文规则。 到您在给定文件中进行第三或第四次测试时,我保证仅通过复制和粘贴使第五次测试变得非常强大的诱惑。

麻烦在于,各种奇怪的测试伪像都被复制了。 您从一个简单的测试开始,并进行一些简单的设置。 说一个空的银行帐户。 然后,要测试非零余额,您需要一个带有交易的帐户。 然后,要测试余额求和,您需要一个有两个交易的帐户。 到目前为止,每个测试都是在最后一个测试的基础上进行的,因此您只是复制并粘贴了之前的测试作为起点。 第四个测试正在插入一个新事务,因此您只需复制第三个测试(具有两个现有事务,此测试不需要)。 测试五是提款不能低于零,因此您复制并粘贴上一个测试并将金额设置为较大的负值。 测试六是透支测试,因此您可以复制并粘贴上一个测试,但是更改帐户设置以包括透支,以便余额可以变为负数。 到您复制并粘贴测试7时,您的起点是一个具有透支额的帐户,其中有两个交易,并添加了第三笔交易。 测试七是增加常规。 不需要这些噪音。

这似乎是一个荒谬的示例,但是我一次又一次地在真实代码中看到。 有时候,不是我做的。 读取测试文件时,这些噪音会累积。 底部的测试具有各种奇怪的伪像,这些伪像仅与文件中途的一项测试有关。 这意味着修复测试和改变行为成为一个现实问题。 例如,如果我更改了上面示例中对透支的定义,则可能要更改六笔测试,其中只有一项甚至涉及透支。 但是他们继承了该设置,因为测试只是复制和粘贴。 这不仅使测试难以阅读和理解,还使其难以维护。

我们都做。 似乎TDD在野外如何发生是相当被接受的一部分。 然而,这显然是不对的。 通过纪律,我们可以保持测试干净。 是的,当我们都是认真的开发人员时,我们每次都会从头开始编写测试。 但是大多数时候我们都很忙,很懒或者什么。

结论

除了复制和粘贴,这三件事有什么共同点? 在每个示例中,我们都使用复制和粘贴来节省时间。 为了找到我们正在做的工作中最有效的途径。 没有人是出于恶意或愚蠢而做的。 懒惰? 几乎可以肯定,但是很好。 一种懒惰,鼓励优雅的解决方案。

但是复制和粘贴并不是一个很好的解决方案。 这是一个更根本的问题的糟糕解决方案:我们的工具不足。 实际上,我们正在解决的问题是我们的工具无法让我们表达我们真正想要的东西。

如果我们可以用高级语言编写测试该怎么办? “使用银行帐户进行两次交易的测试”。 当然,您可以使用内部和外部DSL来执行此操作。 但是通常来说,设置DSL的成本并不值得单元测试的麻烦。 这将完全破坏TDD的流程。 这是否仅仅意味着我们还没有找到一种好的方法呢? 有没有一种方法可以使我们更流畅地表达测试的意图,从而填补我们的空白?

与其从互联网上复制和粘贴代码,不如让我们的工具变得更聪明? 我们能否将正在发生的一些令人赞叹的机器学习知识应用到软件开发中? 我最近尝试使用一个IntelliJ插件来保证这一点。 不幸的是,这是一时的越野车,实际上是行不通的。 但是这个想法极具吸引力。 我喜欢能够表达意图的想法,而不是漫不经心地输入细节。

最后,如果不进行搜索和替换编码,那么如果我们可以真正进行元编程,那不是很好吗? 如果我们真的可以编写为我们编写代码的代码? 不仅是代码生成器,而且还可以生成一小段代码。 一段时间以前,我使用rescripter的经历非常有限-但是事实证明,编写一个体面的元编程工具非常困难,除作者以外的任何人都可以理解。 但是我认为这个想法仍然有好处:我经常发现可以很简洁地描述变更意图的案例,但是实施它所涉及的打字远远超出了我的意愿。

翻译自: https://www.javacodegeeks.com/2017/02/copy-paste-driven-development.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值