在过去的几年里,我拥有与相当多的初学者一起工作和指导的奢侈。虽然我显然见证了我相当一部分编程不, 但事情并不像看起来那么黑白分明。在初学者中,我一直看到一些模式和行为。虽然其中一些行为被误导和有害,但许多行为为高级开发人员提供了学习机会。与普遍的看法相反,从经验较少的人身上可以学到相当多的教训,因为他们有一个没有偏见的观点(初学者的头脑)。

有条件反转

我与初学者看到的最常见的反模式之一是我喜欢称之为"有条件反转"(它可能已经存在一个更好的名称)。使用分支语句控制或限制代码流时,可能会发生有条件的倒置。以下是倒置代码的示例:

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">function</span> <span style="color:var(--highlight-literal)">atleastOneOdd</span>(potentialOdds) {<span style="color:var(--highlight-keyword)">if</span> (potentialOdds !== <span style="color:var(--highlight-literal)">undefined</span>) {<span style="color:var(--highlight-keyword)">if</span> (potentialOdds.length) {<span style="color:var(--highlight-keyword)">return</span> potentialOdds.some((num) => num & <span style="color:var(--highlight-namespace)">1</span>);}}<span style="color:var(--highlight-keyword)">return</span> <span style="color:var(--highlight-literal)">false</span>;
}</code></span>

夸大其词的效果(但我肯定看到了更糟)

如果您认为上述代码对于如此简单的任务来说过于复杂,那么您并不孤单。感知到的复杂性是筑巢的结果,因为筑巢强烈地促成了代码的"感知复杂性"。下面是一个功能上等效但可读得多的实现:

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">function</span> <span style="color:var(--highlight-literal)">atLeastOneOdd</span>(potentialOdds) {<span style="color:var(--highlight-keyword)">if</span> (potentialOdds === <span style="color:var(--highlight-literal)">undefined</span>) {<span style="color:var(--highlight-keyword)">return</span> <span style="color:var(--highlight-literal)">false</span>;}<span style="color:var(--highlight-keyword)">if</span> (!potentialOdds.length) {<span style="color:var(--highlight-keyword)">return</span> <span style="color:var(--highlight-literal)">false</span>;}<span style="color:var(--highlight-keyword)">return</span> potentialOdds.some((num) => num & <span style="color:var(--highlight-namespace)">1</span>);
}</code></span>

教训:

一般来说,更少的嵌套使代码更容易读取和维护。与所有规则一样,总是有例外,因此在做决定之前一定要了解上下文。这里有一个伟大的线程,涵盖了这个特定的场景更深入:

https://softwareengineering.stackexchange.com/questions/18454/should-i-return-from-a-function-early-or-use-an-if-statement

知道什么时候看

重要的是要记住,不只是初学者知道"少",而且他们还没有发展出他们应该期待的本能。在花了一定时间进行编码(不是字面意思)之后,您敏锐地意识到标准库和包中可以期望到的逻辑粒度。一个很好的例子就是我女朋友遇到的情况。我的女朋友是一名计算机科学专业的学生,我最近给她一些关于她为C++作业编写的代码的反馈。作为任务的一部分,她需要检查给定的输入是否是一封信。这大致是她的实施:char

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">bool</span> <span style="color:var(--highlight-literal)">isLetter</span>(<span style="color:var(--highlight-keyword)">const</span> <span style="color:var(--highlight-keyword)">char</span> someChar) {<span style="color:var(--highlight-keyword)">const</span> <span style="color:var(--highlight-keyword)">char</span> letters [] = {‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’, ‘i’, ‘j’, ‘k’, ‘l’, ‘m’, ‘n’,‘o’, ‘p’, ‘q’, ‘r’, ‘s’, ‘t’, ‘u’, ‘v’, ‘w’, ‘x’, ‘y’, ‘z’};<span style="color:var(--highlight-keyword)">int</span> i = <span style="color:var(--highlight-namespace)">0</span>;<span style="color:var(--highlight-keyword)">for</span> (i = <span style="color:var(--highlight-namespace)">0</span>; i < <span style="color:var(--highlight-namespace)">26</span>; ++i) {<span style="color:var(--highlight-keyword)">if</span> (letters[i] === someChar) {<span style="color:var(--highlight-keyword)">return</span> <span style="color:var(--highlight-literal)">true</span>;}}<span style="color:var(--highlight-keyword)">return</span> <span style="color:var(--highlight-literal)">false</span>;
} </code></span>

我甚至不能生气这是一个如此直接和合乎逻辑的实现。但作为一个有经验的开发人员,本能告诉你,必须有一个解决方案的问题,这种常见的。事实上,我眼前的本能是利用 c 字符的数字性质,只需检查输入字符是否在特定的 ASCII a-z 范围内。但由于我的"编程直觉",我怀疑对于这样一个共同的问题来说,这还是太多的工作。我告诉她谷歌,如果有一种方法来检查字符是否是一封信。原来有-我可能已经使用了一百次,但不记得(事情发生在足够的编程-你不记得一切)。isalpha

教训:

开发一个直觉,说明是否已经存在解决您的问题的东西对于作为开发人员的成功至关重要。不管是好是坏,加强这种直觉的唯一方法是用一套不同的语言和范式编写更多的代码。

找到解决问题的最直接方法

初学者在为问题找到直接或字面解决方案方面绝对是惊人的。请举下上一节中的示例。虽然我女朋友的解决方案绝对不是最有效的(记忆或计算明智),这是非常干净的,并完成工作。虽然倾向于最蛮力的解决方案可能代价高昂,但大多数时候它实际上并不重要。我不是说你应该把性能抛在风口之外, 只依靠蛮力解决方案, 但这里有一个教训要吸取。要理解这一教训,重要的是要看看初学者和专家之间的一个关键区别:他们试图实现什么。isLetter

初学者通常是编程,以学习如何编程,而经验丰富的开发人员通常是编程作为实现目的的手段(工作,个人项目等)。在大学里,计算机科学老师很少会给出有绩效要求的作业。这导致学生学习编程时没有考虑到性能。起初,这看起来就像是我们教人们编程方式的巨大赤字,但实际上我认为这是高等教育正确行事的为数不多的事情之一。担心性能通常是一种非常致命的疾病的症状,称为"过早优化"。根据我的观察,一旦程序员开始担心性能,他们很难停止。

如果优化性能不需要额外的时间,这不会是问题,但它确实如此。再加上性能几乎无关紧要(这来自低级别的 C/x86 程序员),很明显,为什么总是优化性能可能会有问题。这种效果是如此强大,我实际上已经看到初学者到达一个工作解决方案比一个非常有能力和有经验的开发人员更快,只是因为初学者只关心让它工作,高级开发人员认为,它必须表现良好。具有讽刺意味的是,即使高年级学生完成了"执行者"解决方案,你也不能分辨出他们与初学者的区别。

教训:

直接天真的解决方案通常就足够了, 又名奥卡姆的剃须刀

/**我假设很多读者会对这一节提出异议,因为它可能看起来像我鼓励人们写坏代码。这绝对不是目的,如果有的话,我认为应该花更多的时间使代码可读和可维护,更少的时间优化性能。*/

一切都必须是一个类

我在初学者中一直看到的最令人沮丧的行为之一是无法在类范式之外进行编码。我责怪每所大学,只介绍学生到Java的计算机科学程序。我一般是语言不可知论者,但我总是发现"一切都必须是一个类"的要求是爪哇的一个特别愚蠢的方面。我们明白了,太阳的某个人真的很喜欢OOP。这种痴迷的代价是,20年后,Java仍在试图将自己重新组合成人们真正想要使用的语言。

要理解为什么这是一个真正的问题,而不仅仅是对Java的抱怨,我们必须考虑初学者如何学习。初学者倾向于将概念内化,因为它们呈现的粒度。因此,当他们使用强制执行类范式的 Java 等语言时,他们倾向于理解代码的最小单位是类,并期望每个变量都像对象一样。使用另一种面向对象的语言,如C++会很快证明代码的最小单位不一定是一个类——为原始和无状态的逻辑编写整个类往往过于熟练和繁琐。不要误会我的意思,现实生活中有很多情况下,这些语义和保证是可取的——事实上,这就是Java是最普遍的语言之一的原因。

问题是,这些语义为首次编程者描绘了一幅误导性的图画。当您缩小 Java 世界时,您会注意到很少有编程语言是面向对象的。这就是为什么只用一种语言学习编程是如此危险的原因。你最终不会学习编程,你最终会学习一门语言。

当我与其他开发人员讨论过这种信念时,他们经常争辩说,这些缺点实际上是有利的,因为 Java 避免让初学者射中自己的脚。虽然这可能是财富 100 强公司需要雇佣大量不受信任的程序员的一个很好的理由,但我们不应该向这样的初学者介绍编程。

教训:

概括事物的能力是您作为开发人员最重要的工具之一。从学习单一语言开始是完全可以理解的,但绝对重要的是,你迅速分支和多样化你的理解。这样做将把你从一个相当不错的 <插入语言在这里 - 程序员到一个伟大的开发人员。

强大的语法和结构

初学者往往比有经验的开发人员更依赖一致的语法和结构。考虑到人类是模式驱动的,代码语法和语义是模式最明显的例子之一,这实际上很有意义。对于经验丰富的开发人员来说,了解一个函数的作用(以及它如何运作)通常是一个去其定义和阅读源代码的问题。这似乎无法想象不以这种方式运作,但我几乎可以保证,即使是最好的开发人员也没有这样开始。模式匹配对于人类的学习方式至关重要,以至于它远远超出了编程范围。例如,英语是出了名的最难学的语言之一。当一些英语学习者被问及与其他语言相比,英语学习如此困难的原因时,他们通常会指出英语学习的不一致和缺乏可靠的语言规则。

/**FTR:对于初学者来说,关于Java最好的论据之一是其强大而一致的语义*/

最近,当我帮助初学者编写一个内部状态相对复杂的C++课程时,就发生了一个实际的编程示例。根据类的目标/预期使用,将某些方法直接改变状态,而其他方法返回副本,这是有道理的。在一起写了相当多的方法后,我离开初学者自己写剩下的。后来我回来时,我的学生没有取得太大的进步,并告知他们被困住了。具体来说,他们对于哪些方法在改变状态以及哪些方法没有变异感到困惑。这是经验丰富的开发人员不会遇到的情况,因为他们只需查看方法的内部逻辑并确定状态是否正在变异。但是初学者还不够流利,无法快速解析同样的逻辑(即使他们以前写过),而是依赖于代码的语法和结构。在审查了代码后,我意识到他们的斗争部分是我的错。

当我们一起实施初始方法时,我确信有可变和不可变的良好组合。我没有意识到的是,这些方法给初学者带来了一种误导性的模式。具体来说,每个可变方法都是一个空隙函数,每个不变的方法都有返回类型。

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">class</span> <span style="color:var(--highlight-literal)">MyType</span> {<span style="color:var(--highlight-keyword)">void</span> <span style="color:var(--highlight-literal)">addElem</span>(<span style="color:var(--highlight-keyword)">int</span> elem);MyType <span style="color:var(--highlight-literal)">createCopy</span>();...
};</code></span>

我无意中教了我的学生一种在实践中显然不正确的模式。因此,当他们需要实施可变或不变的那一刻,事情就崩溃了。我说这是我的错,因为在一天结束的时候,我很懒。作为一个有经验的开发人员,我并不像实际执行的逻辑那样依赖语法和结构。这是愚蠢的,因为我写的代码可以改进,为初学者留下零歧义,并删除潜在的错误,几乎零成本给我。我是如何做到的?通过使用 const 关键字,这允许我明确说明一种方法是否具有变异状态的潜力:bool removeElem(int elem) void printElems()

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">class</span> <span style="color:var(--highlight-literal)">MyType</span> {<span style="color:var(--highlight-keyword)">void</span> <span style="color:var(--highlight-literal)">addElem</span>(<span style="color:var(--highlight-keyword)">int</span> elem);<span style="color:var(--highlight-keyword)">bool</span> <span style="color:var(--highlight-literal)">removeElem</span>(<span style="color:var(--highlight-keyword)">int</span> elem);<span style="color:var(--highlight-keyword)">void</span> <span style="color:var(--highlight-literal)">printElems</span>() <span style="color:var(--highlight-keyword)">const</span>;MyType <span style="color:var(--highlight-literal)">createCopy</span>() <span style="color:var(--highlight-keyword)">const</span>;
};</code></span>

教训:

很容易忘记其他人会如何解释你写的代码。保持一致,并利用语言功能,使您能够编写易消化和明确的代码。

结论

许多初始模式,你拥抱和采用作为初学者将落在路边,因为你被介绍到更高效和可维护的解决方案。话虽如此,我希望这篇文章说明,有时即使是最有经验的开发人员也可以从一点"不学习"中获益。虽然初学者可能不太适应高级功能和语言特质,但有时当工作需要完成时,这是一份礼物。

高级开发人员可以向初学者学习的内容相关推荐

  1. 30K程序员的简述:如何成为高级开发人员

    这篇文章适用于所有在这个行业已经有了几年时间后想要在职业生涯中取得突破的开发人员,编程人员和程序员(或者你可能刚刚开始,但希望你能看到你的路径).本文适合那些有着简单愿望的人:你想成为一名高级开发人员 ...

  2. 如何成为一名Web前端开发人员?入行学习完整指南

    经过如此多的试验和测试,而不是说你从头开始创建了所有内容,接着,你在网页上创建了第一个登录表单时,你感觉如何? 经过了多次更改后,将布局分配给第一个Web应用程序时感觉如何? 当成功处理了数千个用户的 ...

  3. 如何成为一名牛逼Web前端开发人员?入行学习完整指南

    经过如此多的试验和测试,而不是说你从头开始创建了所有内容,接着,你在网页上创建了第一个登录表单时,你感觉如何? 经过了多次更改后,将布局分配给第一个Web应用程序时感觉如何? 当成功处理了数千个用户的 ...

  4. 2020年 面向高级开发人员的 iOS面试问题

    在本文中,您将找到针对高级开发人员的iOS面试问题和解答. 当您准备进行技术性的iOS面试时,重要的是要了解您可能会被问到的话题以及经验丰富的iOS开发人员的期望.这些问题被许多公司用来衡量iOS候选 ...

  5. 如果成为一名高级安卓开发_什么是高级开发人员,我如何成为一名开发人员?

    如果成为一名高级安卓开发 Becoming a Senior Developer is something many of us strive for as we continue our code ...

  6. java安装_我最喜欢的Java高级开发人员书籍

    java安装 我上一篇博客文章(我对高级Java开发人员的十个最喜欢的在线资源)的想法,是由Xiaoran Wang发表的 "面向高级Java开发人员的十大网站"的启发. Wang ...

  7. 高级java开发_我最喜欢的Java高级开发人员书籍

    高级java开发 我上一篇博客文章 (我对高级Java开发人员的十个最喜欢的在线资源)的想法,是由Xiaoran Wang发表的"面向高级Java开发人员的十大网站"的启发. Wa ...

  8. 我最喜欢的Java高级开发人员书籍

    我上一篇博客文章 (我对高级Java开发人员的十个最喜欢的在线资源)的想法是由Xiaoran Wang发表的针对高级Java开发人员的十大网站的启发. Wang还写了一篇名为<面向Java高级开 ...

  9. 如何像高级开发人员一样思考?

    对广大开发人员来说,思想境界决定人生命运. 作者 | Ann Adaya 译者 | 弯月,责编 | 郭芮 出品 | CSDN(ID:CSDNnews) 以下为译文: 世上的技术千千万,你不可能将所有技 ...

最新文章

  1. UML实践详细经典教程
  2. matlab cep,【CEP】重构和改进HelloInsightObservable
  3. 【LeetCode笔记】剑指 Offer 31. 栈的压入、弹出序列 (Java、栈)
  4. 学考语言成绩c对高考有影响吗_三大影响!考生务必上心,最近正在进行的学考对升学很重要...
  5. Ubuntu为julia安装深度学习框架MXNet(支持CUDA和OPenCV编译)
  6. 游戏开发筑基之判断回文数及static(C语言)
  7. 技术人成长路径之我见
  8. leetcode数组汇总_LeetCode刷题实战74:搜索二维矩阵
  9. 使用python模拟实现PID控制算法
  10. 8.9 马蹄印 2493
  11. 读书笔记,《刻意练习》,第三章,心理表征
  12. 什么原因造成家里的WiFi网速慢?
  13. qt creator插入代码块快速注释snippets代码片段的功能
  14. 解决Vue.directives is not a function报错
  15. There are no devices registered in your account on the developer website
  16. 颜色选择器vue3-colorpicker
  17. gray code java_格雷码Gray Code详解
  18. 计算机的发展历史 发展趋势
  19. MySQL基础 笔记、思维导图、代码
  20. 【优化求解】基于缎蓝园丁鸟优化算法 (SBO)求解单目标问题附matlab代码

热门文章

  1. ZCMU--5154: 体育运动
  2. Prosys OPC Client连接OPC DA
  3. 13-roman-to-integer
  4. SpringBoot项目修改JDK后报错(class file version 55.0)
  5. ESP8266给服务器发送数据
  6. 新规曲线行驶的图解技巧
  7. 全景探秘游戏设计艺术 笔记
  8. 今天薅羊毛薅的好爽啊
  9. GO笔记之为什么要学习GO
  10. 苹果录屏精灵_iPhone自带投屏与录屏,3分钟教你操作!