本文主要讨论一些程序员使用搜索引擎时的一些使用技巧,及关于搜索引擎的一些讨论。
注意,本文的搜索基本上都是关于技术层面问题与知识(特别是计算机方向的问题与知识)的搜索,这里不讨论一些人文、社会、历史之类学科的搜索。
本文不考虑“有的网站需要通过特殊方式上”、“有的内容需要一定英语能力”之类的问题。
标题致敬CSAPP(
写本文的时候我突然发现我好像已经不能进行 大段 非技术类 内容输出了。。。语文全还给老师了属于是。
本文较长,可以通过右下角的目录按钮跳转自己感兴趣的内容。
当我们在搜索时,我们在做什么?
这个小标题看起来是在搞笑,毕竟我们在搜索的时候显然正在搜索。但是搜索这个词其实过于宽泛了,我想用一个更严谨的说法。比如,我们想要写一个shell脚本,其中涉及到“怎么读取一系列命令行参数和变量”(比如gcc
编译命令gcc -Wall -Werror -c test.c -o test.o
里面的-Wall
、-Werror
、-c
就是命令行参数,-o
之后的test.o
就是命令行参数带的变量,假设我们现在要实现自己的gcc
命令,所以想知道怎么读取这些变量),我们的搜索过程是:
明确我们的搜索目标
t
。在本例中,
t
就是“怎么读取一系列命令行参数和变量”将目标转化成字符串
X
。在本例中,
X
的中文版可能就是“shell输入参数”,英文版可能就是“shell input argument”。选择一个搜索引擎
F
。后文中我们会把百度和Google(不屏蔽英文结果)做对比。
得到一系列结果
Y=F(X)
,然后从Y
中选择一个我们需要的结果y
,使之和我们一开始的目标t
最符合。这就是我们在网页按“搜索”之后,针对显示出来的结果进行筛选的过程。
用Y
反向训练F
。
所以这里有这么一些问题需要我们研究:
- 我们应该怎么明确我们的搜索目标
t
。 - 对于我们的搜索目标,我们应该输入什么样的
X
。 - 我们应该使用什么样的搜索引擎
F
。 - 什么样的结果
Y
是好的,是我们可以点进去参阅的。
实际上,后三个问题是环环相扣的:判断“好的”搜索引擎F
需要我们先定义什么样的搜索结果是好的;确定搜索引擎后我们才能根据搜索引擎的特点决定输入X
的风格。而第一个问题虽然很重要(甚至我觉得比后三个还要重要),但是是另一个层面的东西,这篇文章不会做讨论。
下面先说说我们需要什么样的搜索结果。
我们到底要什么样的结果?
我们想要“相关”的内容。
废话,但是百度的研发人员可能不太懂这句话。
我们想要“简短且正确的答案”。
如果你想在C++中实现单例,但是不知道怎么实现,于是你选择使用搜索引擎,你搜索到了三个结果:
- 简书文章(百度搜索“C++实现单例”的第一条结果)
- 百度文库文章(百度搜索“C++实现单例”的第二条结果)
- stack overflow question(Google搜索”singleton c++ example”的第二条结果)
你可以自行点开看看,你觉得这三个中哪个最好?我觉得是第三个,因为它“针对你的问题”,给出了“最简短,并且能保证正确”的答案,其他两篇文章都花了太长篇幅介绍一些不那么正确的方式。
这里有一个问题:复杂且正确的解决方案(比如上述的第二个来自百度文库的结果)是不是更好呢?我认为不是。我们在搜索的时候,应该把精力放在目标上。如果你的目的是解决问题Q,那么你需要找的就是问题Q的答案S,至于“关于答案S为什么是对的的解析”或者“Q有没有多种多样的答案”之类的事不应该是你现在需要考虑的。如果你真的好奇,那应该把这些事记下来,之后再以“深入解析S为什么是对的”或“Q的多种解法”为关键词搜索。之所以要这样,有以下几点原因:
这种搜索方式可以保证你的注意力不被分散。
如果你的每个问题Q的答案S里都包含了“深入解析S为什么是对的”或者“Q的多种解法”之类的东西,那么你的搜索时间中的大半都会消耗在这些与当前问题Q无关的东西上,这些东西会拖慢你解决Q的速度,进而拖慢你完成工作的速度。
在搜索Q的答案时得到的“深入解析S为什么是对的”与“Q的多种解法”这类内容,质量上一定不如你直接搜索得到的内容高。
我们想要“正确且易于理解的知识介绍”。
有时候我们想要学一些知识,此时我们希望我们参考的知识介绍易于理解(至少不像某些中文教科书那样不说人话)。举个例子,如果你在学习编译优化的时候看到了“向量化并行”这个名词,想要了解什么是编译优化中的“向量化并行”。
如果你非常幸运地搜索到了answer from stack overflow,那你可以秒懂了,因为这个回答的作者提供了两段代码,完美地解释了“向量化并行”:
1
2
3
4
5
6// Add two array
for (int i=0; i<16; ++i)
C[i] = A[i] + B[i];
// Vectorizing it produces something like this:
for (int i=0; i<16; i+=4)
addFourThingsAtOnceAndStoreResult(&C[i], &A[i], &B[i]);当然,如果你搜索到这篇知乎文章,那你也是很幸运的,因为这个文章的作者提供了一张图,也完美解释了“向量化并行”(左为原代码,右为向量化并行之后的):
当然,如果你不幸只找到了这篇CSDN文章,那么你可能就没法搞懂“向量化并行”是什么了。
这就是“易于理解”的威力,前两个文章可以让你看一眼就懂,第三个文章只会让你摸不着头脑。
我们想要“官方的解决方案”。
“官方的解决方案”的官方来自哪里?
有时候我们需要找到一些软件的安装方法和使用介绍。举几个例子:
- 我最近正在学习MIT 6.828课程,课程中需要安装riscv64-unknown-linux-gnu-gdb,但是我的Linux中本来并没有这个东西,我需要找到“下载安装的方法”。
- 我想试试QEMU软件,但是我不知道该怎么下载安装它。
对于这类问题,其实都有且大多数时候只有唯一的去处:官网,比如对于“怎么下载安装QEMU”就可以直接从QEMU官网找到答案。
当然,对于一个programmer来说,有时也需要从最大的同性交友平台代码托管平台GitHub下载,比如第一个例子,我们实际上需要下载的是riscv-gnu-toolchain,它的代码托管在GitHub,并且在链接的GitHub页面里就说了如何安装。
以上两种本质都是一样的,都是“官方的解决方案”,它都是由软件/代码发布者发布的。
二手的信息源,垃圾!
那非官方的解决方案值得看吗?比如你百度“ubuntu 安装riscv gdb”的话,可以看到第一页的结果的全部选项会指向“CSDN”、“知乎”之类的网站分享安装方法。
我的回答是:绝大多数情况下,对于“怎么下载安装”这种问题,二手的信息就是垃圾。我之前安装过很多东西,没有一次是“官方信息不如二手信息有用”的。软件安装官方不仅会发布下载安装方式,还会收集用户在安装过程中遇到的问题;并且在官网提供解决方案和一些严谨的提示,这些信息远比博客之类的二手信息源来得准确和全面;并且官方信息是实时更新的,二手信息则很难做到实时更新。以“ubuntu 安装riscv gdb”在百度的搜索结果为例:
搜索排名第一的是CSDN上的文章,他并没有介绍怎么安装,他介绍的是因为网速的原因安装失败怎么办,且不管这个搜索结果内容如何,百度把这种非我们想要的内容放在第一个就很恶心,因为它在浪费我们的耐心。
搜索排名第二的是CSDN上的文章,他的安装中有这么一句:
1
2
3git clone https://github.com/riscv/riscv-gnu-toolchain
cd riscv-gnu-toolchain
git submodule update --init --recursive但是实际上按照GitHub上官方的提示”This repository uses submodules, but submodules will fetch automatically on demand, so
--recursive
orgit submodule update --init --recursive
is not needed.”,这一步是不需要的。此外,他的安装过程中增加了非常多的环境变量
1
2
3
4
5
6
7
8su
./configure --prefix=/opt/riscv
make
export PATH=/opt/riscv/bin:$PATH
cd ..
export RISCV=/path/to/install/riscv/toolchain
./build.sh
export PATH=/path/to/install/riscv/toolchain/bin:$PATH但是按照GitHub上官方的提示”To build the Linux cross-compiler, pick an install path. If you choose, say,
/opt/riscv
, then add/opt/riscv/bin
to yourPATH
now. Then, simply run the following command:”,只需要增加一个环境变量(并且官方也说明了为什么需要这个环境变量)。之后的文章的安装方法和官方的安装方法比都或多或少有些出入,这里就不再赘述了。
实际上,除了安装方法之外,其他很多方面也往往是官方的更全面、细致、完善。比如,如果你想要Matlab中一个函数的使用方法,最好直接看Matlab官方文档,而不是看博客。你可以感受一下Matlab文档里对plot
的介绍和百度搜索结果第二的介绍(第一更烂)。
什么样的搜索引擎是好的?
在定义了我们想要的结果后,我们就需要讨论用什么搜索引擎了。
我直接给出我的判断:英文搜索Google >> 中文搜索百度。实际上,在我写前面内容时,就在有意识地对比两个搜索方式的结果,最后的评价就是:英文搜索Google的结果绝大多数时候比中文搜索百度的结果好,剩下少数时候则是两者相当。我没有什么大样本测试,不过,给出我自己的判断应该不需要这种东西。具体来说:
不知道为什么,百度的搜索结果似乎并不会将英文内容放在前面(即使你用英文搜索。相关知乎讨论:知乎),也因此你很难通过百度搜索到优质的英文内容(这包括了stack overflow和geekforgeeks这类有相当多优质内容的网站)。
问题是,我们用的很多软件和代码就是英文互联网原生的(比如在Google和百度搜索“install riscv gnu toolchain”,Google上第一个就是riscv-gnu-toolchain的GitHub仓库连接,百度上第一页则没有这个内容),这些英文内容本来是很重要的官方信息源,却被百度忽略了。
如果中文互联网内容比英文的优质的话,上述一点也不是什么大问题,但是现在的情况是,仅讨论技术领域,仅从我使用中文互联网的感觉看,百度似乎宁愿呈现CSDN、博客园等等站点里不明所以、抄袭成风的内容,也不愿意展示官方的或者优质的内容。也就是,你恐怕很难从百度的结果中找到“简短且正确的问题答案”或者“正确且易于理解的知识介绍”。
举个例子,同样以”matlab plot”作为关键字,百度的结果里CSDN、百度百科、百度文库、百度经验、百家号等等内容占据了第一页,唯独没有Matlab官方文档,而Google的结果的第一条就是官方文档。
因为某些原因,有的网站,比如维基百科的内容是不会被百度放在前排显示的(我甚至觉得百度不会抓取维基百科的内容),也因此百度的结果中损失了相当一大部分优质内容。
综合以上内容,我的建议是:远离百度。
当然,如果你不想上Google的话,bing据说也是一个不错的选择。
我们该怎么搜索?
这里讨论的不是知乎问题:如何高效使用搜索引擎里提到的一些搜索技巧,而是“哲学”层面的东西。
我们必须明白,很多时候搜索是没有必要的。
如果有提示,先把提示弄明白。
如果你的代码编译失败了,产生了提示:
1 | error: control may reach end of non-void function [-Werror,-Wreturn-type] |
你第一件应该做的事是按照提示修改你的代码,而不是搜索这句话。
如果你知道可能的测试方式的话,先在本地测试明白。
这是为了保证搜索效率。即使你的尝试可能是无效的,但是这种尝试也可以让你更加清楚自己真的需要查询的东西,也可以让你提前判断什么样的结果是你需要的,因为你要找的东西可能并不是问题的本质。
更重要的,万一你一测就测出解决方案了呢?
把问题提炼成抽象的,而非具体的。
这点非常重要。搜索引擎并不擅长处理具体的问题,比如说,一个程序员写的int c=a==b;
可以被另一个程序员写成int z=x==y;
,而搜索引擎是“想”不到两个语句本质一样的,搜索引擎更不懂得这个语句的意义是“将C语言两个变量的相等与否关系赋值给另一个变量”的,但是搜索引擎知道怎么处理”what is the value of == in C”这种信息,因为和int c=a==b
这种信息相比,这个信息是抽象的。
举几个例子:
对于初学Java的人来说,可能会想像C++的
std::vector<int>G[MAXN]
一样创造一个ArrayList<Integer>[MAXN]
,但是下面的语句(或者其他类似的语句)却过不了编译:1
ArrayList<Integer> []G= new ArrayList<Integer>()[26];
如果你直接在Google上搜这个语句的内容的话,是搜不到有效信息的,因为它是一个具体的问题,搜索引擎并不擅长怎么处理具体的问题。因此你可以将这个问题抽象化:你这里想做的是创建一个”array of arraylist in Java”,但是你失败了,所以,不妨以”create array of arraylist in Java”在Google搜索,第二个结果是question in stack overflow,它的第一个回答只用两行就解决了你的问题:
As per Oracle Documentation:
“You cannot create arrays of parameterized types”
同样是对于初学Java的人,可能会写出下面的判断数组相等的程序:
1
2int[] x = {1, 2, 3, 4};int[] y = {1, 2, 3, 4};
System.out.println(x.equals(y));并且不明白为什么会输出
false
。如果你把上述的代码直接拷贝到Google,你是搜索不到任何结果的。而如果你提炼了问题,在Google搜索”equality of arrays in Java”,第一个来自geeksforgeeks回答就完美解释了你的问题,并且给出了正确的实现方法。如果你的链接器链接错误了,并且输出下面的信息。
1
2
3/home/lee/Proj/MoeCompiler/moe/main.cpp:27: undefined reference to `mdb::sysEnable'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Makefile:16: compiler] Error 1你可能确实不知道该怎么处理这个信息,并且如果你直接Google这段话的话是没有任何结果的,但是你发现这个语句中最关键的可能是倒数第三行的”undefined reference”,于是你Google了它,看安排搜索结果第一的文章后,瞬间明白了可能是
mdb::sysEnable
声明了却没定义导致的,于是你查了下你的代码,发现果然是这样。
总之,提炼你的信息,然后搜索它,往往会比直接搜索具体的信息来得有效。
使用一系列关键词,而非一个整句。
Google搜索”Is it better to use full sentences or key words to do an Internet search?”之后的第一个结果就说了”Instead of long sentences, keep everything nice and short. Use only the specific keywords or phrase you’re looking for and nothing else.”。所以,”Keep it simple”,多用关键词而不是整句吧。
顺便,这个文章里提供了更多的搜索技巧,您也可以参考。
结语:搜索引擎只是工具,更重要的是你的能力。
一个不懂计算机科学的人,即使非常懂怎么使用搜索引擎,恐怕也不能代替你做搜索的事。如果你不能理解你做的东西,搜索能力再高超,也只是无米之炊。
但是,提升搜索能力和提升能力并不冲突,甚至可以说是相辅相成的。所以,从今天起,提升你的搜索能力吧!
至少,对于技术问题,咱是不是可以不用百度了?
- 本文作者: ChrisLee
- 本文链接: https://ipchrislee.github.io/2022/03/14/How-to-use-search-engine-A-programmer-perspective/
- 版权声明: This article is licensed under a Creative Commons Attribution 4.0 International License. Code sippets may be used under the MIT Licence.