比尔盖子 博客

令人纠结的代码重用

比尔盖子用了 GNU/Linux 之后才真正学了一些编程,才知道“代码重用”的概念,也就是大家口口声声说的“不要重复发明轮子”。例如,别人已经编写了解决问题的工具,就不要自己重新发明,除非遇到问题。例如,自己在 Ruby 里实现 base64 算法实在是愚蠢。

Unix 利用管道和 Shell 脚本,充分发挥了代码重用的优势 —— 只需要把各个 Unix 里的程序 —— 多半还是 C 语言写成的 —— 串起来,就可以完成复杂的任务,这也叫做充分利用软件开发的杠杆效应。

但是,前一种代码重用是在程序内部发生的,后者则是在程序外部。如果后者发生在脚本中,是非常方便的,但如果发生在程序中,则是一个非常棘手的问题。例如,我正在编写一个 C 程序,需要进行一个正则匹配,而 grep 正好完美的实现了我的需求(也就是不考虑其它库),这时该怎么做?

  • 模仿 grep 的行为(可查阅源代码),编写函数 grep()
  • 在程序中调用 grep
  • 将 grep 的匹配算法独立为库 libgrepgrep 和其它程序均可使用
  • 增加一个 grep 的系统调用
  • 使用 Perl

如果你是使用第一种方法,那么根本不算代码重用,即使你从 grep 的实现中复制了大量源代码也不例外;在程序中调用外部程序是不稳定的 – 如果你试图在一个 C 程序里调用外部程序,你就会明白,程序要考虑到数种意料之外的情况 —— 尽管使用带有 sh 模块的 Python 可以大大简化编程;而第三种方式看起来是最为完美的,但是,有多少程序是这么实现的呢?增加系统调用看起来很完美,但系统调用可不是 C++ STL 之类的类库。

如果我们使用 Perl,我们就会发现 Perl 里内置一个 grep,还比较好用。但是,Perl 的 grep 和 GNU Coreutlis 的 grep 毫不相关,实际上只是名字一样,行为很像而已。

也就是说,如果要充分重用代码,那么必须:

  • 使用对外部程序调用友好的语法,利用管道(我不会 Perl,我不知道 Perl 做的如何)
  • 每个程序将算法实现独立成库
  • 使用 Shell 编写所有高层建筑

再想想,C++、Python、Perl、PHP、Ruby,哪个程序没有把基本算法重新实现一次呢?在未来,还真的有必要吗?

这个问题在未来肯定还会纠结下去的,尽管在实际开发中,这个问题的影响并不大。不过,Windows 非常完美的解决了这个问题,因为 Windows 的 CLI 程序,没什么值得重用的。另外,顺便胡说几句,不知道这个问题到了真正的微内核操作系统上会不会这么得到解决 —— 每次程序可以把自己的一个函数“注册”成一个系统调用,以服务的方式运行,其它程序就可以方便的调用了 —— 然而我很快就找出了这个想法中的更多问题。

Categories: Linux, 代码如诗

Arduino 开发环境在 Gentoo/Systemd 下的搭建 » « 对《关于 yum 作者去世引发的地震》一文的澄清与道歉

2 Comments

  1. 管道并没有体现“代码重用”,管道是程序间交互数据的一种方式, UNIX 的 CLI 工具功能尽可能单一。能体现出 “UNIX 哲学”。

    我觉得代码重用显然是在指尽可能使用函数库了。

  2. 代码重用是种思想,偷懒的思想。知道该上哪找偷懒就行了。
    至于多种编程语言的功能重复,你可以理解为不同品牌的面包店。每个面包店卖的都是完整的面包,因为要提供良好的用户体验,不会告诉你买个便宜的干面包,你自己再去其它店买些煎肉,那就会变成汉堡,反而是提供各种口感的面包。也可以理解为生产不同产品的生产线,两条生产线之间或许有同一品牌的机器,但为了保证生产线的顺利生产,肯定建议你放两台机器,而不是一台机器挪来挪去。以上。。。

发表评论

Your email address will not be published.

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

Copyright © 2023 比尔盖子 博客

Theme by Anders NorenUp ↑