什么时候“适当的”编程不再重要?


49

我在业余时间一直在开发一款Android游戏。它使用的是libgdx库,因此为我完成了很多繁重的工作。

在开发过程中,我不小心为某些过程选择了数据类型。我使用哈希表是因为我想要一些接近关联数组的东西。可读键值。在其他地方要实现类似的目的,我使用向量。我知道libgdx具有vector2和vector3类,但是我从未使用过它们。

当我遇到奇怪的问题并在Stack Overflow上寻求帮助时,我看到很多人只是在技术上“合适”另一个问题时就对使用某种数据类型的问题进行了讨论。就像使用ArrayList一样,因为它不需要定义的范围,而与使用新的已知边界重新定义int []一样。甚至像这样琐碎的事情:

for(int i = 0; i < items.length; i ++)
{
    // do something
}

我知道它每次迭代都会评估item.length。但是,我也知道项目永远不会超过15到20个项目。因此,我是否应该在每次迭代中评估items.length?

我进行了一些测试,以查看应用程序使用我刚刚描述的方法相对于正确方法的性能,并按照教程进行操作,并使用社区建议的确切数据类型。结果:一样。平均45 fps。我打开了手机和银河标签上的每个应用程序。没有不同。

所以我想我对您的问题是:是否不再需要适当的门槛?可以说-“只要完成工作,我不在乎?”


4
这是一个数量级的问题。尝试以亚秒级的响应时间(每分钟成千上万个请求)进行搜索和聚合,使多terrabyte数据库服务于现实世界。您的问题还不够大。尽管您的方法很好,但是如果您遵循这一道路是不可避免的结论,那是一个痛苦的过程,需要花费一些时间才能达成。
吉米·霍法

8
如果您的语言有一个真正的FOR循环,那么就不会发生多重评估问题。不幸的是,C语法需要它,因为它实际上不是一个FOR循环。这是一个戴着假发和大鼻子眼镜的WHILE循环,并且需要接受任意条件(或根本不接受)来终止循环。
梅森惠勒

2
我看到了您的编辑,但是如果您想证明在任何情况下都可以喝醉而鲁ck,除非在星期五晚上与指定的司机聚会,则可能是在树错误。
罗伯特·哈维

17
您如何知道每次迭代都会“评估” item.length?编译器非常聪明。即使它反复获取item.length,那又如何呢?我不希望看到类似'int itemsLength = items.length; for(; i <itemsLength; ...)',除非存在衡量的性能问题。
凯文·克莱恩

6
您的items.length东西与“正确的编程”绝对无关。这是一个微优化,优秀的程序员比浪费时间花更多的心思,直到他们运行了探查器并知道真正的性能问题在哪里,他们才知道得更多。微观优化和良好的编程风格通常是相反的,而不是同一件事。
Michael Borgwardt 2012年

Answers:


65

您编写一个程序来解决问题。该问题伴随着解决该问题的一组特定要求。如果满足了这些要求,则解决问题并达到目标。

而已。

现在,遵循最佳实践的原因是因为某些要求与可维护性,可测试性,性能保证等有关。因此,您有像我这样讨厌的人,他们需要像正确的编码样式这样的东西。跨过T并加点I不需要花费太多的精力,这是对以后必须阅读您的代码并弄清楚它的作用的人们的尊重。

对于大型系统,这种约束和纪律是必不可少的,因为您必须与其他人一起融洽地工作,并且必须最小化技术债务,以使项目不会因自身负担而崩溃。

在频谱的另一端,是您为解决特定问题而编写的一次性工具,这些工具将不再使用。在这种情况下,样式和最佳做法完全无关。您将这些东西砍在一起,运行它,然后继续下一步。

因此,就像软件开发中的许多事情一样,这取决于。


1
我倾向于同意。在工作中我不问任何问题,它被划线并点缀。但是请考虑一下,我为工作所做的许多事情确实是不需要维护的。传递趋势之类的东西。生日应用程式,来来往往。一切正常,但实际上并不需要。
Kai Qing

21
可以证明,随时随地进行纪律可以使您更容易纪律。有些人在不按下shift键的情况下就Stack Overflow提出了问题,其理由是他们可以在没有它的情况下充分传达自己的想法,并且英语无论如何都是一种不断变化的事物。除了发现我的CPU时间是免费的病毒编写者之外,我发现没有什么比这更令人生气了。
罗伯特·哈维

2
@KaiQing有人需要交给您5mloc的旧应用程序,该应用程序是在pascal上诞生的,并且一直移植到此应用程序,因为您首次尝试在此应用程序上添加或更改任何功能时,您会立即意识到为什么存在最佳实践并受到启发。
吉米·霍法

5
@KaiQing,《愤怒的小鸟》必须在多个平台上运行,如果游戏挂起2秒钟,x%的观众将放弃它,这对《愤怒的小鸟》人来说意味着少了多少钱。我敢打赌,它的写法非常非常仔细。也许这回答了您的问题。如果代码只适合您,那么谁在乎您的工作呢?如果有金钱或其他人处于危急关头,那么您最好非常非常小心。
查尔斯·格兰特

2
@KaiQing没有人可以告诉您这个阈值,它随项目的不同而变化,并且随时间的推移而变化。影响系统可维护性和不依赖性之间的阈值的变量数:LOC,用户群,开发者群,应用程序类型(加密与杂项与驱动程序),功能健壮性,冗余要求,软件重要性(电子邮件服务器与(生命支持设备与时钟小部件),受支持的平台,技术堆栈,正在处理或分析的数据量,历史审核约束以及许多其他因素会影响错误代码的状态
Jimmy Hoffa 2012年

18

有句明智的老话:“不要跟随老者的脚步。寻求他们寻求的东西。” 对于“正确”编码的所有规则都有其原因。知道为什么存在这些规则比知道这些规则是什么更重要。

有一个规则,你不应该在这样的for循环中放置可以重复重新计算的测试。在发明该规则以进行补救的情况下(实际上性能会有所不同),这是有道理的。在这种情况下,只有一个正确的答案。在您的示例中,众所周知没有性能差异,并且最多只能进行几十次迭代。在这种情况下,有两个正确答案:要么简单地应用规则,因为它很简单,不会伤害任何东西,可以帮助养成良好的习惯;也可以忽略规则,因为没有性能差异。

我喜欢第一个正确的答案,而您似乎更喜欢第二个答案。你对此没有错。我认为您对“适当的”编程的想法是错误的。这与遵循随机选择的规则集无关,这些规则对您没有帮助,也没有任何目的。您未在示例中修复for循环实际上遵循了反对过早优化的非常好的规则。

真正正确的编程是关于遵循以智能方式有意义的良好规则。


我不会说我喜欢第二个。有人编辑了我的帖子,删除了有关使我的这款Android游戏几乎完全醉的部分(只是为了好玩),结果我很惊讶地看到我的醉酒选择对性能没有影响。我用适当的类替换了一些奇怪的类进行测试。我确实同意,尽管知道规则的存在比知道规则的重要性更重要……
Kai Qing

另外,我的“适当”编程思想是对stackoverflow社区的重复性观点的总结,以及在我工作的公司中来来往往的程序员的集合。一些具有CI学位,一些是自学的。有一个普遍的观点可以根据这些观点为基础,在决定一种方法是对的,一种方法是错误的之前,我倾向于同意每个人的集体说法。感谢您的参与。
Kai Qing

1
如果听起来像是我要告诫您违反规则,那么我的措辞很差。您所谈论的事情都不是我会反对的事情。我试图指出,“法律精神”比“法律文字”更为重要。
迈克尔·肖

嘿,不,我不认为您是在告诉我。我只是在交流。我问这个问题是有原因的,我很高兴有这么多人在未投票结束的情况下做出了回应。
Kai Qing

10

解决这个问题的正确方法是减少收益:将开发程序的额外收益与额外开发的成本进行比较。

当边际收益小于边际时间/努力时,收益就会递减。

您能提出一个items.length摆脱for循环的商业案例吗?从经济上讲,这种改变是否可以证明花费时间进行证明?由于用户体验没有区别,因此即使花费时间进行测量,您也将一无所获(除了要记住的有用课程)。用户将不会再比以前更喜欢该程序,并且由于该更改,将不会出售更多副本。

这并不总是容易评估的,因为业务案例充满了未知数和风险,因此很容易沦为未考虑因素的牺牲品,而这些因素在事后才变得显而易见。提议的更改可能是完全无关紧要的,因此确实可以带来很大的改变。

收益递减类型的思维可能意味着寻找不采取任何行动的借口,并避免冒险,这在事后看来可能是一连串的错失机会。

但有时很明显,当没有做一些事情。如果某项发展似乎需要发生经济奇迹,只是为了支付发展成本(收支平衡),那可能是个坏主意。


写得很好。就我而言,从未计划过返回。任何回报可能都是偶然的,但不应该被驳回,因为我认为一些最大的成功始于骗局。在客户工作方面,没有那么多的钱危在旦夕,如果应用程序挂起或某事变得不便,只会使事情恶化,这是一个更厚的门槛。如果基准看起来不错,但是已知代码不是最有效的,那么在代码开发之前就不会有人来审核它,也许无论如何都需要进行迁移……对此很难说。
Kai Qing

确实。我们不能总是做出某种客观的案例。并非每个人都以相同的方式评价该计划。假设程序中的主要实用程序是编写它的乐趣。这可能对其他任何人都没有好处,并且没有人会为改进付出代价(即使程序员旁边还有用户),但这足以证明以任何方式进行改进都是合理的。
卡兹(Kaz)2012年

您可以添加两个有用的字眼来进行“投机性投资”,​​这是因为您推测未来会有所回报。
mattnz

@mattnz-您说的是正确的,即使回报是一个很好的笑声,也没有人为回报而做某事。我几乎所有的个人项目都是出于幽默。几乎所有人都足以证明自己的要求。他们都没有让我退出。
Kai Qing

确实,大家。因此,首先我们确定希望从编写此程序中获得什么,或者继续这样做。那可能是“消磨时间,使它变得有趣”。但是即使这样,我们仍然可以认为:正在某程序中进行某某事物的最佳方法是获得最大乐趣,还是我们将时间花在了其他事情上。
卡兹(Kaz)2012年

3

当您不关心代码是否正确时

  • 如果您设法满足业务目标,并以较低的开销保持其长期运行。(用户在向您付款之前不会查看来源)
  • MVP / POC-如果编写正确的代码意味着在知道如何赚钱之前浪费时间在一个概念上(如果您花了数年时间和4,500万美元来编写应用程序并最终因为没有市场而关闭了商店,那么没人会在乎如何代码是正确的)
  • 当遇到威胁生命的情况时(例如,钢铁侠原型1是肮脏的骇客,但它使他脱离了洞穴?)
  • 或者如果您根本不知道如何编写正确的代码(如果某人设法写出不正确的代码来谋生,我说在当今的失业中,编写糟糕的代码比无家可归者更好)
  • 如果您只是知道自己在做什么,或者认为自己可以假装自己逃脱了

何时编写适当的代码

  • 如果会对业务产生重大影响,例如绩效会影响收入或阻止销售
  • 如果维护代码不成问题是业务问题(维护成本高)
  • 如果您是从事大型开源项目的知名程序员
  • 一家为全球贡献内部图书馆的大公司也是如此
  • 如果您想在以后的采访中将自己的作品展示为作品集

1
令人遗憾的是,在很多人不知道的情况下,还有一个不关心适当清单的清单:当客户向您的护理中呕吐一个旧系统并告诉您他们需要在一周内完成它。有时,时间和/或预算不适合进行正确的编码,并且您对项目的关注比业务交易更为优雅。例如,如果他们的代码使用了不推荐使用的方法,但是需要进行一些修补(在Web场景中使用)。无法解决整个问题。必须变脏。
Kai Qing

“如果维护代码太不恰当,将成为业务问题(维护成本很高)。” 实际上,此阈值比大多数没有经验的开发人员倾向于相信的要低。编写可靠的代码通常会在数小时内,而不是数天或数月内收回投资。
PeterAllenWebb

2

性能是您的主要关注点吗?这就是您要最大化的目标吗?

如果是这样,则有一个基本的课程需要学习,如果您这样做,您将是少数几个。

不要试图“思考”应该做些什么以使其更快—那是猜测。如果您问“我应该使用这个容器类还是那个容器类?”或“我应该length处于循环状态?”,那么您就像是一位医生,会看到患者并试图决定在没有实际治疗的情况下应给予何种治疗询问或检查病人。

那是猜测。每个人都这样做,但它不起作用。

而是让程序本身告诉您它的问题是什么。 这是一个详细的示例。

你看得到差别吗?


我会说,我唯一关心的是,在我的测试中,我没有发现针对特定场景使用不正确和正确使用数据类型之间的性能差异。根据您的建议,我在类中重载了更多数据,以查看它是否太少而无济于事。最后,两者表现均等。当然,我正在制作一个基本的RPG类型的游戏。这不像银行软件或其他复杂的东西。但是,这使我想知道,业务不总是那么合适是否会更好。
Kai Qing

由于性能是您的关注点,因此您应该问程序应该看什么,而不要问您的先入为主的问题是否有所作为。请单击此链接,然后按其说明进行操作。它会告诉您该程序实际上在花时间,并且将告诉您如何使其更快。
Mike Dunlavey 2012年

好吧,表现是我质疑程序的基础,而不必担心。我不是想说基准。仅观察低效率的代码就不会产生性能差异。对用户而言,基本上透明的程序是有效的还是无效的,因此使这种概要分析变得无关紧要。诚然,我必须首先关注基准测试,但这主要是出于好奇。并且,如果产品完成并且速度明显较慢,则可以,分析器很有意义。感谢您的链接
Kai Qing

2

您的问题是“只要完成工作,我不在乎?”

我的回答是:“您永远都不知道代码会发生什么。” 我参与了许多项目,这些项目起初是“嘿,让我写这篇简短的文章来解决用户的问题”。写下来,放到那里,再也不要考虑了。

有一次,我写的东西变成了“哦,现在用户的整个部门都想使用该代码”,在我转身之前,这变成了“整个公司都在使用该代码,现在我必须证明它可以在审核中幸存下来而且计划明天进行20人的代码审查,并且一些副总裁已经将其出售给我们的客户。”

我意识到您“只是在业余时间编写Android游戏”,但您永远不知道该游戏是否会成名,并成为名利双收的门票。更糟糕的是,该游戏可能会成为您臭名昭著的入场券,因为它不断使用户的手机崩溃。您是否想成为因为某人的孩子无法停止在手机上玩游戏而获得工作机会的人,还是想成为像这样的留言板上受辱的人?


1

答案是,它永远都没有关系,而且永远都很重要。

没关系,因为编程(适当与否)是实现目标的一种方式,而不是目标本身。如果没有“适当的”编程就可以实现该目标(从业务角度来看,最好是无需编程就可以实现该目标)。

这总是很重要,因为正确的编程是可以帮助您实现目标的工具。正确的做事方式只是认识到,从长远来看,以另一种方式做事比所节省的事要痛苦得多。

哪一个回答了您什么时候可以忽略它的问题-当您确定从长远来看会更容易使用另一种方法时(可能是因为从长远来看不会)。

一次性工具通常会尽可能地快速而肮脏地完成,几乎没有错误检查或进行其他验证,没有日志记录异常,带有少量更改的cut-n-paste代码,甚至没有更改而不是通用函数,等等。 。

只是要当心:有时那些快速又肮脏的应用程序会自行生存,这意味着所有捷径都会在您的网站上咬住您...


1
“从不”和“始终”相互抵消。使您的回答既好又坏。
图兰斯·科尔多瓦

@ user1598390:他们互相抵消是重点。取消教条,这似乎很有用。而且您会弄错它并从中学到东西。
jmoreno

我想说我同意你的看法,但我不会把它推到极致。我不认为经常会逃脱测试或调试的麻烦。如果性能和稳定性不受简报的影响,仅是因为它没有经过优化,并且完美的设计并不能使它成为产品。最终这就是我的观点,为什么我想知道为什么每个人都对并非最重要的编码示例这么臭?它在stackoverflow上经常发生。
Kai Qing

@KaiQing:测试和调试当然会发生,但通常仅限于目前存在的情况,因此,例如,如果该过程可能因使用UTF编码的文件而失败,并且您实际上没有使用任何文件,可以,您无需测试。确定性能问题后,应进行优化。至于为什么在SO上的非顶级代码示例上发臭-我认为这是站点目标的功能。它旨在成为永久资源,因此可以将答案(甚至是问题)中的代码视为他人使用的模板。
jmoreno

1

甚至像这样琐碎的事情:

for(int i = 0; i < items.length;i ++) {
     // do something 
}

我知道它每次迭代都会评估item.length。但是,我也知道项目永远不会超过15到20个项目。因此,我是否应该在每次迭代中评估items.length?

实际上,在最终代码中,由于编译器会对其进行优化,因此不会在每次迭代中都对item.length进行评估。即使不是,length也是数组对象中的一个公共字段。访问它不需要花费。

所以我想我对你的问题是:当它不再>适当时,是否存在阈值?可以说-“只要完成工作,我就不在乎?”

这实际上取决于您对最终产品的期望。普通产品和优质产品之间的差异取决于细节。Tata Nano之类的汽车和Mercedes S之类的汽车“就能完成工作”-它可以将您从一个地方带到另一个地方。不同之处在于细节:发动机功率,舒适性,安全性等。现有的任何产品(包括软件产品)都是相同的;例如,由于MySQL和Postgre是免费的,为什么有人会向Oracle,IBM或Microsoft支付Oracle数据库,DB2或MS SQL Server的费用?

如果您想注意细节并获得高质量的产品,则应该关心这些东西(显然是其他东西)。


我认为我不同意。在我的帖子中,我没有提到性能上的差异。这表明没有平均或伟大的产品,但是尽管有一个缺点,但平衡是平等的。但是,如果有一个非常重要的特定项目,我们都将其用作比较,我会同意你的说法。但是抽象地来说,一般的观察是,在这个匿名项目中,一个效率极低的类与一个优化的类均表现出色。那么,是否可以对此采取懈怠的态度或每次争取完美?
Kai Qing

@Kai Qing一个班级没有(或不应该)有很大的不同。我说过:如果您希望自己的产品是高质量的产品,那么请注意细节(即使这意味着可能要进行一点优化或精心设计);另一方面,如果您唯一想要的是功能系统,那么您可能不需要过多关注微小的细节。
m3th0dman 2012年

是的,没错,即使在设计上稍加注意,它也不会有所作为。但是它可能会有所不同,具体取决于其目的,或者总的来说,其目的会随着时间的推移而转变为原本不希望的东西。以前见过,但我在这里正切。公平地说,产品可以是高质量的,而不仅仅是功能。
Kai Qing

1

如果您在家为自己编程,那么也许可以偷工减料。当您进行实验和尝试时,这是完全合理的。

但是请注意。在您给出的示例中,实际上并不需要任何麻烦,您需要小心。这可能会引发一种趋势,而您在家中的不良习惯可能会渗入工作中的代码中。更好地练习和改善家里的良好习惯,让他们在工作中渗透到您的代码中。它会帮助您和他人。

您所做的任何编程工作以及对编程所做的任何思考都是练习。值得,否则它会回来咬你。

看起来不错。您已经问过这个问题,所以也许您已经知道我的意思了。


1
是的,我知道,但问题的关键是,在较小的封闭环境中,似乎没有理由如此恰当。在我所有的编程岁月中,确实没有很多东西可以咬我们。我怀疑我们是否合适。我认为语言和期望会像普通软件一样发生变化。有些比其他少。但是最后,只有在过去的项目不再重要时,才可能意识到一个项目的低效​​率。很难证明如此僵硬的头痛。
Kai Qing

这是一个公平的观点。今天的规则可能是明天的限制。我不喜欢被告知该怎么做,但是我确实尊重别人,这些人以前曾经学习过,并且学到了艰辛的方法。有时候,找出哪些规则有用以及现在超过其销售日期可能会很有趣。
Daniel Hollinrake 2012年

1

如果家具制造商正在制造一件家具时,要在质量不是最重要的地方使用,或者在质量可能不被注意的地方使用,那么他们是否仍应设法使切口平直,并正确地将这些家具连接在一起?

许多人将软件视为工艺。我们构建的内容不仅要执行功能,还需要可靠,可维护和健壮。制作此类软件需要技能,而该技能来自实践。

因此,即使根据当前工作选择循环构造可能并不重要,但随着时间的流逝,您始终努力使用正确的构造这一事实将使您成为一个更好的程序员。


我在编程中遇到了一些实例,这些实例的代码不需要可维护,也不需要在需要之外执行。就像信息亭实用工具,用于非常特定且不可能重复使用的贸易展览或活动。就我自己的游戏而言-我是唯一维护它的人,因此这种说法可能不是最适用的。我仍然对“更好的程序员”的普遍观点存有疑问,因为严格遵循准则,可维护性和正确使用数据类型可能会令人沮丧,无法完成项目。如果代码按预期工作,为什么还要完善呢?
Kai Qing

即使您不需要构建right_now的软件,也要像编写软件一样编写软件,以增强您的编码技能。当您最终不得不编写可维护的代码时,您将能够更轻松地做到这一点。
布莱恩·奥克利

我必须一直编写可维护的代码。只是在某些情况下不一定如此。但是,我确实有很多经验,所以我通常知道何时何地走捷径。这篇文章的重点是,无论出于什么目的,都引起关于适当和草率的门槛的讨论。我的示例只是轻描淡写,因为给出的示例在较小的应用程序中几乎无害。但是,如果我正在编写银行软件,我永远不会那么粗心。
Kai Qing
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.