程序员有时对自己的代码不具有100%的清晰度是正常的吗?[关闭]


19

我不是专业的程序员,所以这也许就是原因。但是我注意到,每当我创建复杂的代码(例如我最近制作的国际象棋游戏)时,我都可以编写正确的代码来使程序正常工作,尽管我后来发现,甚至几秒钟之后!

不仅如此,我还倾向于不考虑代码,而是直接键入。例如,在我的国际象棋游戏中,我决定使用一个五维数组来处理移动,而我发现无需过多的自觉思考就可以做到这一点。但是,当我停下来仔细阅读它时,发现对整个5维概念有所了解是很困难的,并且花了几分钟的时间才能完全了解我的操作以及代码本身的工作方式。

对于程序员来说,编写复杂的代码而一半时间都不了解他们在做什么是正常的吗?


13
这表明您正努力地变得聪明。如果您自己无法阅读代码,则需要编写更简单,更具模块化的代码。
SHODAN 2014年

3
要添加其他(有见地的)答案,就好像它散发出过分复杂或设计不良的代码一样(不用担心,我们大多数人都必须通过该阶段):Document。通过给变量/方法/类/模块赋予适当的名称,为每个函数添加适当的描述,以及(当您看不到其他方法时)写一个简单的内联注释来解释为什么以及如何使用一些复杂的代码片段。码。
SJuan76

4
从来没有对自己的代码有100%的清晰度。
CodesInChaos

2
5D数组听起来确实可以使用某种抽象。

3
任何开发人员在任何时候都对其代码有100%的清晰度吗?
2014年

Answers:


30

不,这是不正常的1。至少,对于优秀的程序员而言,这是不正常的。学习编程的人可能正常的。

编写软件不只是将代码行打成一片,直到它起作用为止。您需要自觉地努力使代码易于理解。我非常尊重的程序员曾经告诉我“代码被读取的次数比被编写的次数更多”。虽然这应该是完全显而易见的,但是直到他告诉我,我才意识到这一事实。您的大部分代码只编写一次,也许再编写一次或两次,但是最终您会在软件的整个生命周期中经常阅读代码。

如果您在编写代码后几分钟内发现难以理解的代码,则表明您的代码过于复杂。停止添加代码,并找出更好的方法。例如,一个五维数组几乎从来都不是一个好主意。即使是非常聪明的程序员,也很难理解如此复杂的数据结构。

告诉我代码可读性的同一位程序员还说:“告诉我您的数据结构,我可以告诉您代码的工作方式”。意思是,好的代码始于干净易懂的数据结构。如果您正确设计数据,那么代码几乎是第二要务。诚然,该声明有点夸张,因为软件显然不仅仅是数据,而是数据开始的。因此,创建干净,易于掌握的数据结构的工作将大大简化代码。


1当然,即使有最聪明的程序员,那里也有非常复杂且难以理解的代码。有些问题天生就很复杂。但是,我敢说,绝大多数程序员编写的绝大多数代码不是那种类型的代码。


8
[1]从更悲观的角度来看,这是正常现象,但不是很好。
2014年

1
如果“五维数组”仅仅是从4元组或5元组到策略的映射,那么作者可能使用了哈希表或帮助程序查找功能。但是,如果作者花了大部分时间对初始化数组的机制(嵌套循环)进行编码,那么实际的“算法见解”将被大量“机械代码”淹没。程序员试图将后一种噪声分开。因此,优秀的程序员必须知道如何主要编写库来容纳那些机械代码。
rwong 2014年

1-D数组是一条线,2-d是网格,3-d是立方体,4-d是立方体线,5-d是立方体网格,依此类推,但我看不到象棋这样复杂的数据结构。
user2785724 2014年

15

这有两种:1.)困惑2.)幸福的无知

第一个不好,可能会随着时间和经验而消失。

第二个是一个很好的方案,如果项目变大:如果您只需要记住每个实现细节以能够使用您的代码,那么它就有问题了(请参阅“信息隐藏”)。

每个开发人员都会忘记代码是如何工作的,因此他以另一位新开发人员能够理解并能够维护它的方式来编写代码,而不会破坏他也不知道的程序的其他部分。

因此,“不知道”实际上是软件开发中的一个常数-这就是您如何管理或是否对其进行管理。


1
您在这里讨论的是重要的事情,这就是使用常识性模式和约定进行编程的重要性,因为实现细节确实被忘记了。但是,如果代码中的模式和约定合理,那么在必要时从上下文中提取细节就足够容易了。另一方面,如果代码都是整体的,难以理解的并且过于聪明,那么不仅您最终会忘记细节,而且其他尝试维护代码的程序员也将面临更多困难。
克雷格2014年

12

我说这比人们关心的要普遍得多。甚至Brian Kernighan也提到了这一点:

调试的难度是一开始编写代码的两倍。因此,如果您尽可能聪明地编写代码,那么根据定义,您不够聪明,无法对其进行调试。

当我们开车去商店时,我们会对踏板和方向盘的位置进行一系列详细的调整。目前,这非常容易。现在,假设您将这些调整记录在纸上,然后交给需要商店指示的朋友。

同样,我们喜欢在一个抽象级别上编写代码,但是我们希望在多个更高的抽象层上阅读代码。因此,我们偏爱的编写和读取代码的方式存在冲突。这意味着使代码易于阅读通常是一个单独的,有意识的步骤,具有不同的技能。

一个好的程序员的原因是,当他们难以阅读刚刚编写的内容时,他们会在那时创建一个抽象。一个更好的程序员会多次这样做,每次都会变得更加挑剔。最终,经验丰富的程序员会在此过程中更进一步地开始工作,但是在阅读了刚写的内容后,他们仍然经常仍然可以看到改进的空间。


在这一点上,我必须不同意Brian的观点,我喜欢调试,我是行业中认识的少数几个会这样做的人之一,但是我不认为我编写的代码如此高。
James Snell 2014年

@JamesSnell他没有说调试不好或令人讨厌,只是说很难,而调试复杂的代码则更加困难。
cbojar 2014年

5

我认为这会随着经验而消失。

如果您正在编写复杂的系统,则需要具备编写干净的,可维护的代码的能力,这些代码将来您以及将来的其他人都可以理解。因此,从本质上讲,您现在正在做的事情是不可扩展的。

您会花很多时间查看6个月前编写的某些代码,然后思考“到底发生了什么?”,但是如果在编写代码的第二天发生这种情况,您就必须认为“干净”代码更多。

来源:从未使用过5维数组:)


3
@ 83457-因为5d数组是2d问题的较差模型。如果您真的认为这是不错的代码,则将其放到codereview.stackexchange.com上,看看会得到什么答案。
James Snell 2014年

2
@ 83457-如果它“像地狱一样令人困惑”,您已经回答了自己。无论我们的技术水平如何,5-D阵列可能都不会使人困惑,但对于我们大多数人来说可能不是。
dbasnett 2014年

2
@ 83457像地狱一样令人困惑,应该已经是一个很好的动机,不要使用它。
Fabio Marcolini 2014年

3
只要您对每个尺寸都有充分的理由,我就没有理由避免使用5D阵列。也许有更好的解决方案,例如带有复杂键的字典或几个较低维的数组,但是我可以很好地想象5D数组适用于像国际象棋AI这样的棘手问题。
CodesInChaos 2014年

2
@CodesInChaos除了那些不仅仅是数组之外,它们还表示有意义的序列(例如嵌套的决策树)。通过适当地命名它们并给它们指定类型,以使它们不被滥用(即使这些类型是数组的thon包装器),您也可以使代码更清晰,包含错误的可能性更低,而几乎不花任何费用。
deworde 2014年

5

“正常”是非常主观的,所以我说:这很普遍,但是应该避免。

“好代码”(我听说存在)的特征之一就是清晰度:它应该像潜在问题所允许的那样清晰。如果问题很复杂,那么代码也将很复杂,但这是固有的复杂性,而不是由于错误使用或未使用正确的工具,模式,技术和方法而导致的意外复杂性(我在Rich Hickey的演讲中首先听说过这种区别)。实践。

在某些情况下,即使问题不是很复杂,缺乏明确性也是可以接受的,例如,您编写了一个促销网站,而您知道促销网站将持续进行很长时间。那是一个必须维护的一次性代码。对于其他(和大多数)情况,这是不可接受的,因为维护此类代码会花费很多。但是,这很常见。

有关:

  • 当理解意味着重写时 -有关理解代码问题的文章。
  • 有效的ML-在ML / OCaml中,长期讨论如何为“读者”(即维护者)编写代码:“对读者而言是好读者。” 无论您使用哪种语言,我都建议您观看。

2

我认为这不是正常现象,但是对于非常复杂的程序(例如您提到的国际象棋程序),我认为这肯定是可能的。

很多年前,当我刚从研究生院毕业时(因此我对大型程序的编写仍然相对缺乏经验),我编写了第一个真正的编译器。解析很简单,但是随后我需要将其定位为四个不同的微处理器指令集。我打算用自己的语言编写编译器,因此我首先只使用了我绝对需要的语言功能,用汇编语言编写了第一个代码生成器,并测试了它为该语言子集生成了正确的代码。从那时起,我便能够使用编译器进行自身编译,并添加其余功能并在编译器本身中使用它们

然后,我为每个微处理器编写了后端代码生成器,并测试了它们均生成了正确的代码,但是尽管正确,但它并不是最佳选择。因此,我接下来为每个代码生成器编写优化器。

添加所有优化后,当我测试代码生成器的输出时,我经常对编译器生成的代码感到惊讶。通常,这不是我手工编写代码的方式,但是它是正确且简洁的。

当对我来说不明显的是代码生成器是如何生成某些代码的时,我试图手工遵循逻辑,但有时我只是放弃了。如果我添加了很多跟踪输出,我本来可以跟踪它,但是由于生成的代码令人满意,因此我无需打扰,我需要继续进行其他项目。


在我看来,您受过良好的教育,具有坚实的基础,并且已将知识内化到很高的水平。我猜这在典型的程序员中很少见。大多数典型的程序员(包括我在内)都必须努力跟上当今任务所需的知识,因为技术变化如此之快。
rwong 2014年

@rwong谢谢。其中大部分是经验-我从事程序的编写已经有46年了,无意很快退出。
tcrosley14年

2

这里有很多不错的答案。

我对此有几点看法。

一种是,如果您不了解代码为何起作用,那么a)可能就不起作用(它似乎只能看起来起作用),b)您要么对问题域的理解不够充分,开始编码,或者在开始之前没有将问题域分解成较小的简化单元。

我对此的其他看法是,真正的关键是在代码中使用常识模式和约定。这个话题比一个小帖子可以解决的要大得多。但是,请寻找有关该主题的好的文献资料,包括一些旧的备用文献,例如“代码完成”和“编写可靠代码”。

实施细节发生变化。唯一的实际常数是代码的功能目标。如果您编写了多个函数,随着时间的流逝,您将忘记特定的详细实现细节。但是,您当然应该在构造它们时了解这些零件的工作原理,并且应该能够绘制整体图并了解这些零件如何协同工作。

如果您使用模式,并遵循常识约定,那么当您再次查看代码时,选择备份特定的实现细节将容易得多。或者,以前从未见过代码的人第一次看它。同样,随着时间的流逝遵循这些约定和模式将意味着实现细节将从约定和模式本身中脱颖而出,这是另一个使代码易于理解的因素。

我们使用软件解决的大多数问题本质上都是复杂的。软件设计是管理复杂性的一种练习。


1

我不会称其为正常,但肯定会发生。如果您在编写有问题的代码之后不久就遇到了这种情况,那么我想您的代码不必要地复杂,应该简化,或者您很容易分心。:)

但是,如果您放下代码,专注于其他项目,然后在数周,数月甚至数年后返回它,那么您必须再次弄清楚所有内容就不足为奇了。

但是您可以对此做一些事情。从您所说的来看,似乎您在编写代码时对代码的考虑不够充分,因此使您将来的自我难以理解正在发生的事情。利用这些知识为您带来好处:这是生成结构良好,文档完善,易于理解的代码的最佳动力。您可以从第一手的经验中了解到,如果不注意代码质量,会发生什么情况。从长远来看,知道这一点应该使您成为更好的程序员。当您在软件项目上进行协作时,您的同事将感谢您提供易于理解的代码。而且您的代码的缺陷率也会提高。

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.