[编程碎碎念] 为啥要重复造轮子

前言

作为一个完全没有参加各类编程补习班,当然也不是完全没有,至少我入门编程的时候上了一段时间的Pascal的课,不过现在已经忘光了。笑。

我的大部分编程技能都是自学来的,这也导致了,我的编程习惯总体来说就是非常的野路子。即使现在上了一部分大学的课,但正规科班的教学依旧无法改变我的习惯。

那么我有一个习惯,我也不知道是好是坏,那就是造轮子,或者说的更明白一点重复造轮子。怎么说呢,我特别热衷于造轮子,即使已经有非常好的现成的项目了,我依然会尝试自己造一个。

为啥我这么热衷于造轮子,说实话我自己一开始也说不太明白,总觉得这样子比较好。但是随着最近和网友,同学的交流,我大概有了一些想法。

所以,我想记录下我的着一些想法,一方面是为了为了我自己,另一方也是为了那些或许对这方面有问题的网友和同好。

正文

总之什么是轮子

我不太知道网上具体的定义是啥。狭义来说呢,就是一个库,比如一个math库,里面有各种数学函数可以让你进行调用。

但是在这里我想使用一下我自己对于轮子这个词一个广义的定义,即任何一个可以实现某一个功能的项目

比如一个可以让你下载动漫的下载器,一个util库,这种都算一个轮子。一个轮子对我来说不单单就指一个库,他也可以是一个实现某种功能的软件或者程序程序。

可能或许是现状

看到这里,你可能已经看不懂 造轮子 这三个字了,因为我已经看不懂了。

那么换一个语言,why should we Recreating the Wheel?

现在网上总有那么一些言论,“你在开发什么东西啊,啊,这个啊,这边有个框架,直接用这个框架就行了”。 这种论调在网上频繁出现,只要你稍微混迹在一些编程社区里,你每天至少都能看到一条。

这个现象在稍微小型一点的公司(或许在中大型公司)里就更容易发现了。有个网友在和我聊天时提起公司在进行开发的时候,基本就依赖于现成的框架了 (在他的公司里,就是RuoYi),通过这个框架来实现业务逻辑。

那么用轮子好么?我个人来说,在实际开发的时候,用框架无疑是一个非常好的选择,用现成的框架,不光你可以更快的完成开发,只关注与业务逻辑上,不用关心其他的问题,同时,框架越完善,出现重大事故的概率就越低,因为框架给你做好了大部分的工作。中小型公司喜欢使用使用框架也不是不无道理,这可以更好的压榨员工,节省开发的开支啊。

但是这也带来了一些的问题,what if (当然就是what if, 大框架一般不会出现这种问题), 你想实现一个功能,但是这个框架不支持。又或者,出现了一个问题且业务逻辑部分的代码没有任何问题呢?好了,这下你除非自己深入框架内部然后定位问题,就只能给框架开发者提issue然后干等了。

有人会问,啊,那你为什么就不能debug框架么?这不也是代码么?你既然能写业务代码,解决这些问题不也很简单么?问题就出在这里,由于框架的出现,以及框架被大量的使用,很多人的开发完全就是基于现成框架 - 即在现有的基础上进行二次开发。再加上部分无良培训机构培训出来的流水线程序员,只学了如何调用框架。一些基础的计算机知识,框架内部具体时如何实现的完全就是一抹黑,啥都不知道。甚至于,有些做前后端开发的程序员,连http报文长什么样都不知道。

题外话,我当然不是说我自己有多么多么厉害,了解多么多么的深入,我自己也只是知道皮毛。而我也并不是说你必须知道http报文,但是你得至少知道http报文大概长什么样子。如何不用任何一个请求框架,单纯通过tcp链接来执行http请求吧。

举一些更为极端的例子,现在有些人似乎把一门框架当成了一门技术,就比如 (你会vue么?)。 我的理解是,框架是基于一个编程模型在一门编程语言里的具体实现,总的来说,他就是一堆别人写的代码。把一堆别人写好的代码当作一门技术是否有点本末倒置了。

再者,如果一个人自己长期使用于这个框架,他就把自己限制在这个框架能做的东西里面了,逐渐的他除了知道怎么在这个框架中编程,其余就基本属于一问三不知的状态了。这个时候,要是这个框架做了一个升级,或者这个框架不让人用了。那么一切的东西都要从头开始学起。

说到底,框架/轮子 对于我们来说只能是工具!而看现状来说,很多人都做了框架的工具。在我看来,这一点是非常愚蠢的。

为什么要重新造轮子

首先一点要声明的是,我在这里说的是轮子,而不是发明轮子。你要是有这个能力发明轮子,我估计你也看不起我写的这勾八文章了。

所以,在造轮子的时候,借鉴前人造好的轮子是一个非常重要且不可避免的过程。

再来说说为什么要重新造轮子。

首先,也是最主要的一点就是造轮子可以让你从头到尾了解一个项目是怎么运行起来的,而不是只知道众多步骤步骤中的其中一步。简单来说就是这个项目具体是怎么实现的。

很多人可能认为这些东西是没有必要的,就像部分网友说的,“我只需要知道冰箱会制冷就行了,而不需要知道冰箱是怎么制冷的”。雀氏,作为一个普通人,我们只要知道会使用冰箱就可以了,这足以实现我们日常生活所需,比如,把肉放冷冻,把菜放冷藏。万一冰箱坏了,你可以找人修,你雀氏可以不用了解冰箱的工作方式。虽然需要付出一点时间,一点金钱,结果来说依旧可以解决。 但是,假如你稍微懂那么一点冰箱是怎么制冷的,比如,主要的部件是哪几个。那么,如果冰箱坏了,你甚至可以自己尝试换掉可能坏了的零件并尝试修复它。就成本来说,这不比请人来修低好多。

那么,和冰箱类似,写程序也是一个道理。如果你稍微了解了一下这个框架/程序它内部的逻辑是怎么样的,遇到问题的时候至少大概会有一个想法知道是哪块地方出了问题,而不是一头雾水不知道哪里出了问题。假如你了解的在深入一点,或许就能找到诱发bug的原因,然后尝试进行修复了。再说了,冰箱坏掉的几率,可比你在一个程序/框架时会遇到bug的几率小太多了。同样,制作造一个简单的轮子也比造一个冰箱简单多了。

然后就是在造轮子的时候你会学到很多普适性的知识,其中的很多东西你甚至可以用到其他地方。

前面也说了,我们的目的应该是造轮子,在这个过程中,我们必然会去借鉴前人造好的轮子。这对于我们来说无疑是一个完美的学习机会,不仅可以培养快速阅读代码的能力,在代码里你可以进一步的看到某些功能中所使用的数据结构,小功能的实现方法之类的。同时,你还可以进一步对这些东西进行学习。

就拿一个最简单的例子来说吧,如何判断一个字符串是不是网页链接。这个是我在研究django的时候看见的,一个判断是否是url的正则匹配。(我把它复制粘贴了下来,然后用golang重新实现了)

1
2
3
4
5
6
7
8
9
10
func IsUrl(url string) bool {
urlRegExp := regexp.MustCompile(
"(?i)^(?:http|ftp)s?://" +
"(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\\.)+(?:[A-Z]{2,6}\\.?|[A-Z0-9-]{2,}\\.?)|" +
"localhost|" +
"\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})" +
"(?::\\d+)?" +
"(?:/?|[/?]\\S+)$")
return urlRegExp.FindString(url) != ""
}

更进一步说,写轮子可以培养critical thinking,你在写轮子,借鉴别人的代码的时候必然会想到,“欸,这个功能为什么是用方法A这样实现的,为什么没有用方法B,没有更好的办法了?” 这之类的的问题。

对于我来说,我经常会这么做。看到不明白的东西,会自己尝试用自己的方法试一试,看看自己的方法行不行。虽然大部分情况下,也不说大部分了,几乎是99%的情况下,最后发现还是别人写的好用。有些人可能会觉得,啊,这有意义么,这不是浪费时间么。我觉得不是的,这其实是一个试错的过程,会让你知道为什么某个方法可以,为什么每个方法不行,哪个方法适合那种情况。那么在你下次遇到类似的问题的时候,大概就知道要做什么了。

怎么说的,总的来说就是经验的累积吧。

那么如何开始呢

每个人都有自己的理解,有自己的学习方式。我无法提供一个适合所有人的方法。在这里我仅仅讨论我自己是怎么做的。

首先,我想说的就是自己造一个轮子不需要从非常底层开始做起,你可以从使用别人的框架开始慢慢深入。因为你最开始是根本没有这个能力的。而且,如果一开始就从最底层做起的话,这个花费的时间和获得的反馈不成正比,得不到正反馈,往往会丧失继续造轮子的动力。

就拿我自己的一个爬虫框架作为例子吧 deepcolor,爬虫麻,肯定要对付多种信息格式。比如html,json,text。那么对于html,json这种需要从解析文本的结果,我们可以先不用自己整一个什么json解析器。这要做起来花费的时间就太大了。而我做的就是写了一个统一的接口,那么在处理不同的信息格式的时候可以使用同一套api,然后我的轮子按照对应的格式调用别人写好的解析器,并返回结果。

等之后有能力了,就可以慢慢的把用到的别人的轮子改成自己写的轮子。还是这个项目,最开始,我实现等待队列的方式是使用别人的代码,后来,因为自己的一些需要,我慢慢就重新写了一个自己的等待队列来替换掉别人的轮子。

还有就是,写框架/轮子这个东西是一个循序渐进的过程,千万不好不需要一下子把所有功能从一开始就定下来。可以从最开始的一个demo,慢慢往上面添加东西,或者说到了某一个时间段发现前面写的东西太垃圾了,就进行一次重构。或者当你学到了一点新的东西,你感觉可以用在这个项目上时,在想办法

还是拿我的爬虫框架作为例子,最开始只有一个json解析器,后来慢慢添加了html和正则的解析器。大致完成了解析器的部分之后又慢慢的把多线程请求,请求池之类的给加上了。

所以说,不要害怕造轮子,一步步慢慢来就行了。

后记

最近在和网友已经一些身边的人交流的时候,脑子里会突然冒出一些关于编程的想法。但真想要明确表达的时候,有不是很好表达。想了想,大概是我太久没有写过长文章的缘故。

说实话,因为现在大部分作业,工作都在电脑上完成了,甚至做笔记都在使用电脑。加上长期不使用中文,我的中文水平感觉已经只有小学生水平了(笑。

总之,为了更好的把我自己的想法记录下来,顺便也重新锻炼一下写长文章的能力,决定开设一个新的项目,那就是编程碎碎念。 为什么要叫碎碎念呢,因为我的语文水平不支持我写出一长段连贯的文字。而且我的想法大多数时刻都比较跳跃,不是以连续的形态出现的,所以,出现在我文章中的句子大概都是一小段一小段的想法。

总之说了这么多,基本上就是我为啥要写博客的原因。