如何巧合地克服编程问题?[关闭]


24

《实用程序员》一书中,作者提到了巧合概念编程。它解释了它的原因,原因,可能遇到的危险,并将其与战争中的地雷场进行了比较。

您是否曾经看过黑白战争电影?疲倦的士兵谨慎地从灌木丛中驶出。前面有一个清理工作:是否有地雷,或者可以安全穿越?没有任何迹象表明它是雷区-没有迹象,铁丝网或陨石坑。士兵用刺刀猛扑着他的脚向前扑地,期待爆炸。没有一个。因此,他在田野上辛苦地前进了一段时间,并在前进时刺探和戳戳。最终,他确信场地是安全的,他站起身来,骄傲地向前迈进,结果被炸成碎片。

士兵最初对地雷的探测没有发现任何东西,但这只是幸运。他被误认为是一个错误的结果。

作为开发人员,我们还在雷区工作。每天都有数百个陷阱在等着我们。记住士兵的故事,我们应该警惕得出错误的结论。我们应该避免碰巧进行编程(依靠运气和偶然的成功),而要刻意进行编程...

但是我对他们描述“如何克服它”问题的方式并不满意。是的,您必须在编写代码之前先思考,但是如何实践呢?我唯一能想到的就是在现有的开放源代码项目中添加功能,您必须在这些知识上既了解“我现在正在做什么”又了解“其他代码段如何工作”,但这并不适用当您编写自己的项目时。

编辑:

您的帖子摘要:

  • 不要猜测您的下一步行动,证明它是正确的
  • 必要时尽可能进行单元测试和重构
  • 添加功能-编译-经常测试
  • 如果您无法向菜鸟解释代码,则可能是巧合。

顺便说一句,很难接受答案,这真的很难。所有答案都非常棒:)


6
它将帮助那些可能很长一段时间没有读过这本书的人获得pragprog.com/the-pragmatic-programmer/extracts/coincidence之类的链接。
btilly

除非您的编程职业生涯很短(或者是一家专卖店),否则您很可能会遇到看起来很陌生的代码,后来又经过一些代码遍历,便会大跌眼镜:这是您的。这不仅仅是开放源代码的考虑……
Robbie Dee 2013年

@罗比·迪 你能再澄清一点吗?我不明白你的意思。确实,我的编程生涯很​​短,这就是使用初级程序员的原因。
py_script

2
@py_script我只是想指出,几年之后,您可以像遇到别人一样轻松地碰到自己的代码(并感到困惑)。因此,如果您养成良好的习惯,这将在以后获得回报。
罗比·迪

Answers:


26

您不必预先考虑,只需对所做的事情非常清楚,就对您现在所做的事情非常清楚。

子例程应该说出自己的所作所为,按照他们说的那样做,并且没有隐藏的依赖关系。然后,打电话给他们的人可以更轻松地推断出他们将要做什么。

避免全局状态。(变量,单例变量等),要想了解做什么事情,脑中必须具备的状态越多,就越难理解应该发生的事情并找到边缘情况。

编写单元测试。单元测试非常适合捕获您刚编写的代码的实际行为,而不是您希望找到的理想行为。

缩短您的编辑/编译/测试周期。当您添加大量代码并进行不良测试时,很可能它的行为将与您想象的不同。然后,您可以通过随机更改来“修复”它,并且您暂时获得了正确的答案,但不知道它是如何实际发生的。您现在正巧巧地进行编程。但是,当您添加5行然后进行测试时,您得到正确答案的几率很高,因为它像您认为的那样工作会好得多。我可以说,从经验来看,每个测试的10个行中的5个块是与一次测试的50行代码完全不同的野兽。

狠狠地重构。很多时候,我发现了一个重构,它将使我的代码更简单一些,但是却做了很多我不想做的工作。在我开始优先考虑那些重构之后,我发现它通常会在一个月内收回成本。但是请注意关键,我关注的重构是使日常工作变得更简单的重构,而不是那些具有更好或更一般的任意美感的重构。我了解到的那些重构要谨慎得多。

这些事情都不需要事先计划。但是它们都使理解现有代码更加容易,因此使以有意方式实现下一个小块变得容易。


谢谢,真的很好的答案。我认为有关周期的部分确实很有价值。您能给我一些重构示例,您应该做这些重构,但是实施起来会花费很长时间,并且可能使某人灰心?
py_script

1
我有很多例子。在C ++项目中,我创建了没有字符串化方法的类。创建这些文件后,调试变得更加容易,并且开发速度加快。在Perl项目中,我们有一个配置哈希,其中每个开发人员都有每个新配置的自己调整过的副本。添加配置参数很麻烦,因为您必须编辑每个开发人员的配置。我写了哈希的模板系统,这变得更加容易。在报告系统中,我添加了一项功能以显示中间结果。我的开发加速了,我什至收到了用户错误报告……
btilly 2013年

1
财务部门在哪里追踪了我的逻辑,并找到了我出错的确切查询以及我的错误所在。(我不小心UNION在需要的地方挤压重复的行UNION ALL。)等等。
btilly

1
一个月之内?我通常会发现,每当我触摸代码时,都应该重构,但是还没有重构,它花费的时间几乎相当于重构它的时间。
艾米·布兰肯希

1
@AmyBlankenship是的。一个月之内。有时在内部很荒谬,有时没有。我上面提到的配置文件是“有时不是”的示例。我花了几天的时间来编写,记录和测试新的模板引擎。然后重写现有配置以使用它,并且要短得多,但会产生相同的精确数据结构。(那是项目中最困难的部分。)因此,..天被浪费了,绝对没有可见的结果。然而,这项工作在不到一个月的时间里就得到了回报,但此后一直在引起人们的兴趣。
btilly 2013年

41

几乎可以归结为不要猜测。大多数情况下,新程序员都这样做,但是我也看到退伍军人也这样做,因为他们认为这样做可以节省研究时间。某些方法不起作用,因此您添加a +1或a -1,将a更改true为a false或反之亦然,对某些语句重新排序,添加或更改延迟,更改线程优先级,以及其他小的转换,基本上测试随机排列直到它起作用。

这主要适用于更改现有代码,但也是全新代码中的一个因素,因为没有人真正从头开始。您总是在标准库,操作系统或至少处理器体系结构之上构建。

换句话说,直到您知道修复程序为何有效之后,您才能完成工作。您到达那里所走的道路并不重要。甚至随机排列有时也有助于缩小难以诊断的错误,只要您花一些时间问自己:“好吧,将true更改为false可以解决问题,但是为什么?”


1
优秀点+1。这比代码修复更能适用……
Robbie Dee

不幸的是,我也是如此。老实说,存在客观困难,例如有时缺乏文档。今天,我稍微修改了我的代码,但由于缺乏文档,我不知道参数对什么有用,这一事实使我无法解决。我们只知道这是一个数字。
py_script

我承认。当面对倾斜的牙签综合症时,将\ s堆叠起来直到它起作用之前要比找出要与之竞争的逃逸层数要容易得多……
btilly 2013年

16

我在程序中遇到的最可怕的评论是

请勿触摸。有用。我们不知道如何或为什么,但是它有效。1个

仅仅因为它承认这段代码是巧合编程的结果,就令人恐惧了。

为了避免巧合编程,你应该能够解释(给同事,自己或橡皮鸭子)究竟是什么代码的功能和为什么它的工作原理。故意进行编程的项目符号在很大程度上有助于实现能够解释代码的目标。


1对于上下文,此注释出现在处理原始OS中的上下文切换的代码中。当我遇到该代码时,它已经投入生产了几年。


2
这也称为voodoo鸡编码c2.com/cgi/wiki?VoodooChickenCoding
min13

1
即使编码人员认为它是正确的,这种注释也无济于事。该代码可能很复杂,但是如果您以其他方式阅读该代码,您可能会认为它很简单。评论只不过是增加了妄想症!
罗比·迪

3
当维护旧的代码库时,也可能发生这种情况,这是当前大多数开发团队都不习惯的语言。
pcurry

因此橡皮鸭不仅用于调试。很好...我认为我们正在同一个公司上班,我们有很多这样的评论:P
py_script 2013年

在某些情况下,由于API的故障而导致修补程序只能工作,并且没有更好的逻辑修补程序。调试某些已编译的第三方lib可以像内核调试一样深入。即使发现了问题,经过数小时的调试,您几乎无能为力。因此,您对问题的处理方式有所不同。您采用“黑匣子”模型,该模型迫使您巧合地编程。您会玩弄黑匣子的怪异行为,如果设法使它以您想要的方式工作,那就太好了,添加带有“不可触摸的魔术”的注释,然后继续。
Radu Simionescu

7

对于新程序员来说,克服这一点最重要的部分是真正了解他们在做什么。

在许多地区,当您不知道如何做某事时,您会经历反复的尝试。试试吧;如果有效,那么很好,如果没有,请尝试其他方法。

在编程中,尤其是在使用具有不确定行为概念的语言(例如C或C ++)时,这种方法根本行不通,因为成功不再是布尔决策。您可以拥有“某种”工作的东西,有时可以工作,并且对某些输入有效,而对其他输入则无效。

我有时会辅导新的程序员,并且倾向于尝试键入随机的东西以查看其是否正常。他们会打线,然后转向我,问:“这样行吗?” 很明显,他们绝对不知道是否可以。

要点是,作为一名新程序员,您实际上必须能够解释您的代码做什么。您必须学习阅读代码,而不仅仅是编写代码。

(当然,这也适用于经验丰富的程序员,但是我在这里的经验主要是面向新的完整初学者。)


<<您必须学习阅读代码,而不仅仅是编写代码。>>因此,关于我的第一个问题,您认为它将帮助我在开源项目中添加功能吗?
py_script

2

在“赛车线上”进行编码,测试和修复太容易了。您有给定X和Y的某些功能,可以生成Z。但是,如果X损坏而Y不可用怎么办?如果您无法输出Z怎么办?不断记住可能出问题的地方,并在测试周期中记下它。

保持例程简短和描述性-最佳代码需要很少(如果有的话)注释。

有意义的方法,类和变量名在帮助提高可读性方面大有帮助。

如果遇到代码异味,请停止。这种气味不太可能消失,现在稍加努力可以在以后为您节省大量的痛苦。

在您的开发过程中包括测试。我主张使用BDD而不是TDD,因为它会迫使您描述要实现的目标,而不是盲目地依赖大量的测试,这些测试可能会给您带来虚假的安全感。

抵制添加额外炫酷功能的冲动(除非这是您自己的宠物项目)。任何额外的代码都需要设计,编写,测试和维护。如果客户/企业不需要这样做,则您可能会浪费大量资源。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.