工作和学习的差别确实特别的大,以前觉得在学校里最重要课程是数据结构,操作系统和编译原理,最不重要的是软件工程这样的“政治课”。到公司实习后才发现,软件工程中基本上每一句都是那么有道理,不论是自己做还是和朋友合作,都应该“按套路出牌”,原因很简单,这样做节省时间!当时在上软件工程课的时候想,麻烦,拿着题目后,做就行了,分析什么题目要求?设计什么结构?画什么流程图?直接写不就得了,等到前面的东西都整完了,黄花菜都凉了!诚然,我们在学校做的东西比较简单,逻辑清晰,直接写也反映不出什么问题,但是只要程序规模大,模块稍微复杂一点,结构稍微难一点,问题就来了,没有事前想好,最可怕的后果是——返工,做着做着,就会发现以前写的东西,阻碍了我们后面要写的东西!到时候……能做的恐怕只能是推倒重来,就算是勉强不用重新来过,程序也尽是bug。所以最好的做法就是——按照软件工程来。在明白了要求后,从要求的东西中把类型确定出来,从类型中把公共部分提取出来,让类型负责他们的行为,确定好每个模块的接口,把每个模块所应做的东西都规范起来,尽量不要出现“狗拿耗子”的情况,也就是高内聚!然后把那些需要想想才能动手的模块的流程在纸上画画,真正确定都能实现了在动手实现。
废话说的挺多,恐怕也没什么说服力,拿我自己最近做的两个小东西当反面教材吧。
刚进部门时,老师想看看我们的能力到底怎么样,于是留了一个作业——虚拟文件系统,就是像dos一样,把硬盘上的东西通过dir、cd等命令反映出来,但是这个硬盘是虚拟的,要求自己写,用内存模拟一块硬盘,在那块模拟的硬盘上做出一系列对于文件的操作。2个星期,一个人做。说实话,当时我就蒙了,啥意思?这不要写一个操作系统么?于是祭出我最喜欢的操作系统教程,翻,看,想,试,忙的一塌糊涂,不明白了就从网上找,麻烦了1天,大概知道这东西是什么了,于是,开始写啦,这么“大”的一个工程,2周够用么?所以不停的敲,不停的想,过了两天欣喜的发现很多命令已经实现了,像cd、dir、md、rd等等,可是写着写着发现问题了,当时设计数据结构的时候没有考虑文件的路径,只能在整个目录结构中做遍历,麻烦啊,于是又重新添加了一个数据成员,用以记录文件的路径。这时候又发现一个问题:文件系统是要能够存储的,怎么存?简单,用fopen和fputc就ok了,可是最后发现,在文件系统里没法用指针的,如果在数据结构中用到了指针,那么就意味着这个部分存储的是一个内存的地址,可能是0x00004000这样的东西,把他保存到硬盘里,然后在读出来的时候问题就来了,能确保这个新的文件系统也用到了0x00004000这个地址么?就算他用到了,能正好是那个位置存储那个东西么?为了确保原来的东西能运行,我想了很多办法,placement new、地址映射,但是麻烦啊,复杂啊,正在这个时候,老师又出现了,让我们讲自己的想法,糊里糊涂的说完了后发现,大家都存在这个问题,没有好好考虑就动手开始做了,结果这样那样的问题一堆,但是不得不赞美一下“交流”这种行为——你把你的想法说出来,我把我的想法说出来,好的东西都能被认可,然后发扬拿来主意,什么问题都解决了。大有拨开云雾的感觉。栽了一个跟头,下回就学乖了,从总体上把各模块理清后开始模块内部的分工,细化。最后只用了2天的编码时间就把这东西写出来了,当然这不算完,随之而来的是调试阶段,但是大的问题就没发现什么了。也挺开心,一个实际的项目,比上一学期的软件工程好使啊。
由于这个项目做的比较快,老师又给了我和其他两个哥们一个项目——差分合并系统,“大概意思”是这样的,一群程序员写程序,然后完成各自模块后提交到网上,找到bug后,再从网上下载下来,修改,我们负责做的东西是在比较新的文件和源文件的差异,记录下来,然后把他们合并。再有了上一个项目的经验后,我们都很慎重,“大概知道”题目的要求后,我们就讨论这个东西的总体设计,模块功能,可是这时却发现我们根本没太明白这个东西到底是什么要求,怎么比较?谁和谁比较?比较强度是什么?……于是做了一个大胆的假设,把所有的可能都考虑到,然后等明天在问问老师,呵呵,好在这个东西不是那么复杂。等到第二天我们把设计告诉给老师,确定下来真正的需求,发现,一般的东西被cut掉了,可以想象,如果这个系统复杂一点,会使什么样。然后我们把各模块确定下来,把模块又细分到函数级别,就分工了,王闯做界面,许庆做遍历,我做比较结果的记录和文件的拷贝,比较函数Win32基本都提供了,于是开始做了,做了两天后我们发现,函数参数传递的信息我们没有确定!于是三个人把参数从对象改成指针,又从指针改成引用,我的模块要用到很多win32 sdk的函数,如拷贝文件,文件夹,记录这些信息等,这些函数需要的是比较底层的char*字符串,而不是mfc的cstring,于是几乎每个函数都要对传递过来的参数进行转换/解析,代码量大了很多,而且函数做了很多与基本功能无关的东西,这又让我们学到了很多。
这两个小项目相辅相成,让我把软件工程重新复习了一边,呵呵,获益良多,希望师弟师妹们如果不小心看完了我的经历,能够规范自己的编码过程,以后避免类似的情况发生,避免时间和精力的损失。