今天要交的操作系统作业中有一道编程题,让写一个简单的 shell。我之前写过一个类似的,不过和这次的要求有点不同,于是我昨天下午就想把我之前就有的那个程序给改一改交上去。
这次的要求如下:
-
支持从 PATH 里找程序,也就是可以用 ls 代替 /bin/ls
-
支持参数
-
支持更改目录,也就是 cd 命令
- 支持重定向,也就是类似 cat < in.txt > out.txt 的命令
前三个功能我之前的版本就已经有了,于是我主要给我之前的程序加上重定向功能。
我本来以为这是个很简单的问题,于是就直接修改了源文件,结果弄到最后我发现我把代码给搞乱了。中间我曾经有过几次似乎是成功重定向了,但后来又改了哪个地方后又不行了。而且我之前的代码写好的时间也比较长了,我一时间也弄不清一些代码的功能了,比如说记录参数数目的变量为什么在执行 exec 之前要减一之类的问题弄的我很困惑。直到睡觉前我都没有弄好,于是就把问题留在今天。
今天下午我在上课的时候脑子里还在想这个问题,于是把这个程序需要实现的功能整理了一下,发现不外是上面说的四个。前两个都很简单,只是 exec 函数的不同形态罢了;第三个判断三种情况(参数错误,没有参数和普通情况),然后调用 chdir 函数就好了。第四个是调用 freopen 函数来实现,由于是在子进程中调用这个函数,所以也不用考虑恢复问题,昨天晚上我为了这事还查了不少文档,做了无用功。
既然这四个小部分都不难,那我干脆直接从头写应该也不需要多少时间。于是我很快的写好了前三点和部分第四点。写第四点的时候中间出了一点问题,我调试的时候也遇到了困惑,连我在里面用来输出变量值的调试用的代码都奇怪的不执行了。到后来我才意识到我已经把输出重定向了,所以调试用代码的输出已经不输出到屏幕上了。整理了一下,程序马上就好了。
虽说我重写了程序,但昨天晚上的修改程序还是起到了很重要的作用,就是帮我复习了程序的基本架构,因此我今天从头写的时候才能保持头脑清晰。
我之前读过不少关于重写的故事,比如说王建硕在《如果我有时间,我会写更短的代码》中说过:
我个人用的简化代码最有效的方式,就是写一段代码,彻底删掉,重写,然后再删掉。在如此十几遍之后所得到的代码,通常比第一次要好得多。
我这次虽然只是重写了两次,但明显完成了任务。程序中有很多地方可以写的更洗练,所以我如果再重写一便的话应该可以让代码更加紧凑。
我之前读过 Eric S. Raymond 的著名文章《大教堂和市集》,里面有一段话:
继续呢还是换一个? 如果换一个的话,作为得到一个更好开发基础的代价,我就要扔掉我已经有的那些代码。…… …… 但是我有一个更加理论化的原因认为换一下会是一个好主意,这是我在Linux很久以前学到的:“计划好抛弃,无论如何,你会的”(Fred Brooks,《神秘的人月》第11章)
或者换句话说,你常常在第一次实现一个解决方案之后才能理解问题所在,第二次你也许才足够清楚怎样做好它,因此如果你想做好,准备好推翻重来至少一次。
也讲述了类似的道理。