要理解好的代码,你需要多多编写“不好”的代码

开发 前端
编程语言只是工具。使用的时机、原因以及方法取决于我们自己。不能因噎废食,我们该改进的是使用方式。

本文转载自公众号“读芯术”(ID:AI_Discovery)。

网络上有许多 “切记不要…”的文章:不要使用继承(inheritance),千万别用单例模式(singleton),scrum将被淘汰。这些真的都不能用吗?如果语句真的很差劲,我们又该如何甄别哪些建议可取呢?

没有完美的编程语言,也没有最好的编码方式,有的只是指南(也就是已知的缺陷)。很多编程建议十分夸张,每个人都告诉你不要再做这做那。照这样发展,每个指令都是故障之源,我们很快就没有指令可用了。就如同人们并不指望开卡车过木桥能到达对岸,但这不意味着木桥没有承载力,也不是说人们不该开卡车。

编程语言只是工具。使用的时机、原因以及方法取决于我们自己。不能因噎废食,我们该改进的是使用方式。

[[342887]]

怎样辨别糟糕的建议?

好的建议有三个组成部分。首先,信息本身;第二,何时使用;第三,何时不用。糟糕的建议通常缺少第二和第三部分——通常呈现出永久适用的特征。

一个常见的话题是:“不惜一切代价避免使用继承机制”。如果没有适用和不适用条件,你可能会盲从建议而舍弃面向对象系统(OO系统)最关键的工具。如果该建议变成:“继承机制是非常好的工具,但深层次机构(deephierarchies)通常有害。”这次问题很显然出在“深度”上,这个解释精准且洞悉了问题——浅层次机构是好的。

另一个要注意的就是语言。很多作者往往“肆意下笔,从不更正”,这样的基调在充斥着互联网。为了撰写“肆意”而“肆意”撰写是极有害的,作者不会说明他的建议并非普遍适用。为了避免语气折损,他们往往不点明不适用条件。好的建议应是友好的,而不是强硬的。每个真诚帮助过你的人都不会是怒气冲冲的。

[[342888]]

图源:unsplash

经验之谈

涉及到编码,有两条经验尤其适用:

(1)  创造和维护语言非常昂贵。如果新语言中不断加入某种机制,那说明该机制十分重要。这就是全局作用域、继承机制和如果语句仍然存在的原因。任何一篇声称该摒弃它们的文章都忽视了这些机制的重要性。

举一个很好的例子:类型系统。Python和JavaScript因为不需要分类而吸引了许多开发者,之后就会后悔用无结构语言写了上千行代码。“落伍的”Java和C#就不存在这个问题(也不是说它们就没缺点)。

这就难怪TypeScript会出现。类型系统会返回弱类型语言——你输入一部分,编译器会补足剩下的。这一想法非常成功,分别通过 var 和 auto关键词打入了C#和C++的世界,甚至Python现在也引入了类型系统。

(2) 与之相反,第二条经验是:现代语言从设计上淘汰了混乱的部分。

这就是宏、goto语句和显式内存管理消失了的原因。过去,Java的垃圾回收机制(GC)饱受抨击,但几乎所有现代语言的GC都不再需要Java虚拟机(JVM)了。

最近移除的是空指针异常。像Kotlin和Swift这样的现代语言用设计执行null检查,C#8也是同样的,Raw threading和async callbacks也存在自己的问题。现在,我们编写异步程序时就可以使用便捷的async/await语法。

[[342889]]

图源:unsplash

而这一切都说明:想做一个更好的程序员,需要了解编程语言的历史。

大多语言由富有工具意识的人创造,由社群指引着发展。每次加入新要素,整个群体都会专注地探讨元素的相关性和对群体的价值,也包括如何完善元素设计。改变和移除元素时也是如此,Python 3做了许多引人瞩目的突破性改变,都卓有成效。

多编写不好的代码

我们使用的是数十年以来的创新成果和失败设计。

只有潜心于“劣质的”C/C++代码,你才能真正地领略到垃圾堆叠的语言之美。这之前你只是想象过去编码有多痛苦,那些写过单例模式并深受其扰(有很多问题,比如编写测试)的人才能真正理解那种痛恨。

教科书上的示例与实际操作千差万别。前者不过是个提示,后者才会真正改变你的编码方式。

大多人开始的时候都不会使用Git或Unit Tests来编码。这些项目往往漏洞很多,也经常不能运行。没有Git,你无法得知是否不小心更改了什么。没有测试,你的代码会在某次故障后直接不再运行。诸如此类的体验是促使我们每天使用这些工具的原因。

要真正理解如何写好代码,首先要会写不好的代码。有几种能促使自己编写糟糕代码的方式(或者找到现有片段的缺点),其实归根结底一件事:试着用另一种方法编码,从而得知你的方案有多好或者过去有多糟。

下面是你闲暇时间可以做的事:

  • 学习一门父系语言: 举例来说, Kotlin的父系语言是Scala,Swift等语言的诞生是为了解决Objective-C存在的问题,C#取代了Java。学习父系语言能为你展示过去没有但“今天拥有的”,也使人们更加珍惜今天人们唾弃的很多工具。
  • 学习一门“承继”语言: C++开发者应该尝试Rust,Java开发者试试Go,Python对应Julia或Nim,JavaScript对应TypeScript或Dart。与学习父系语言不同,学习承继语言将揭露现有缺陷及怎样解决。
  • 学习LISP:很多人觉得这个语言很怪。LISP没有变量,它是纯函数式编程语言(比Haskell简单)。你不需要精通这门语言,只需尝试写一些算法,比如斐波那契(Fibonacci)、快速排序算法( quick-sort)或者哈夫曼编码(Huffman coding)。如果沉下心慢慢做,你会发现变量在很多情况下并不重要。
  • 用纯C语言写一个文本处理器: 为文本文件设置一个路径,打开它并删除所有换行符,在每个句号后(.)加入新换行符,然后重组每个单词,保持第一个和最后一个不变。如果处理后每一行都保持平行就值得表扬。它能快速反映出字符串处理的巨变。
  • 找出设计模式:准备一个设计模式的清单,并打开你正在做的或做过的项目。花些时间阅读每种模式,并找到某种模式适用的地方。想象每个模式运用在这个项目中将会多简洁,这是将设计模式整合到项目中的最佳方法。

[[342890]]

图源:unsplash

这些技巧要么改变你的编码方式,要么帮助你审视已完成的代码。无论哪种都会让你意识到一切都不是想象得那样光鲜亮丽。

我并不是在讲对与错,也不是讲怎样编码,而是在邀请各位多多编码。代码是一种新的语言,尝试用两种方式完成同一件事情,多写代码才是码农的终极进阶之道。

 

责任编辑:赵宁宁 来源: 读芯术
相关推荐

2018-03-30 10:02:08

代码规范维护工程师

2023-01-09 15:16:17

2019-11-08 09:20:57

代码开发工具

2015-04-15 15:01:56

代码好代码科学定义

2014-08-28 11:12:14

谷歌

2011-08-15 10:10:47

编程

2022-06-21 12:27:12

JavaScript前端

2014-12-19 09:59:50

代码

2015-06-25 13:36:56

好代码科学定义

2012-07-11 10:51:37

编程

2013-03-22 16:43:03

可读代码代码的艺术代码编写

2015-07-17 10:02:48

写代码

2015-08-03 09:20:33

代码精华

2022-05-07 10:01:20

好代码坏代码

2022-05-10 10:28:21

JavaScript代码

2015-11-10 09:09:23

代码程序员成长

2023-02-28 11:18:57

CUPID代码

2021-03-17 08:00:59

JS语言Javascript

2012-12-17 13:51:22

Web前端JavaScriptJS

2016-11-30 18:35:03

JavaScript
点赞
收藏

51CTO技术栈公众号