SUMTEC -- There's a thing in my bloglet.

But it's not only one. It's many. It's the same as other things but it exactly likes nothing else...

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

最近受朋友之托,帮别人调一个程序,据说是毕业论文。这个论文是本科还是硕士的,我也不清楚,反正是一个对指纹进行增强的题目。离开学校那么多年了,很多理论知识快忘干净了,比如什么偏导数、内积、卷积……第一眼看这个论文的时候,脑子里面蹦出来的是“好复杂啊”,对科学产生了一种肃然起敬的心情!

不过看到那个程序之后,心情就变了个彻底。别的不说,先看看一个代码片断:
  for(i=0;i<298;i++)
  {
   for(j=0;j<298;j++)
   {
    n1=n2=0;
    for(m2=0;m2<3;m2++)      //*****赋值*****
    {
     for(m1=0;m1<3;m1++)
     {
      u[n1][n2]=tr1[i][j];
      n2++;
      j++;
     }

     n2=n2-3;
     j=j-3;
     n1++;
     i++;
    }
    n1=n1-3;
    i=i-3;

    a=i+1;
    b=j+1;
    xx[a][b]=timesx(u,i,j);
    yy[a][b]=timesy(u,i,j);
  }
 }

还好,这还不是我见过最差劲的校园毕业论文程序,至少还有对齐,也不会一堆的代码写在一行里面。但是,光看这对东西也感觉够怪异的,为什么要修改循环变量j和i?看了半天才明白,其实是想把矩阵中的某一块复制到一个临时数组之中。事实上这样的复制完全没有必要,后来我花了几个小时的时间对这个简单的程序做了一次巨大的重构。其间不断的发现极其重复的代码,甚至有些重复的代码还出现了不一致(即其中某些复制过的代码被修改了,而且还改错了)。我们再来看看这样的代码:
 if (((s[1][1]-s[0][0]+sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))*(s[1][1]-s[0][0]+sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))+4*s[0][1]*s[0][1])<0.0)
{
 {
  w1[0][0]=w1[1][0]=w2[0][0]=w2[1][0]=e1=e2=0.0;
 }
 else
  if(sqrt((s[1][1]-s[0][0]+sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))*(s[1][1]-s[0][0]+sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))+4*s[0][1]*s[0][1])==0.0)
  {w1[0][0]=w1[1][0]=w2[0][0]=w2[1][0]=e1=e2=0.0;}
  else
  {
   w1[0][0]=(2*s[0][1])/sqrt((s[1][1]-s[0][0]+sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))*(s[1][1]-s[0][0]+sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))+4*s[0][1]*s[0][1]);
   w1[1][0]=(s[1][1]-s[0][0]+sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))/sqrt((s[1][1]-s[0][0]+sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))*(s[1][1]-s[0][0]+sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))+4*s[0][1]*s[0][1]);
   w2[0][0]=(2*s[0][1])/sqrt((s[1][1]-s[0][0]+sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))*(s[1][1]-s[0][0]+sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))+4*s[0][1]*s[0][1]);
   w2[1][0]=(s[1][1]-s[0][0]-sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))/sqrt((s[1][1]-s[0][0]+sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))*(s[1][1]-s[0][0]+sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))+4*s[0][1]*s[0][1]);

   //***求特征值***
   e1=(s[0][0]+s[1][1]+sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))/2.0;
   e2=(s[0][0]+s[1][1]-sqrt((s[0][0]-s[1][1])*(s[0][0]-s[1][1])+4*s[0][1]*s[0][1]))/2.0;
  }

妈妈米娅!感觉进入了Matrix电影里面去了,满眼的0和1。
还好,最后总算顺利的给拆卸并重新组装了。其实根本就没有显示的那么复杂,里面有很多是属于重复计算。并且由于没有引入一些必要的中间变量,才会出现这么复杂的代码。
说实话,我是非常佩服写这样代码的人,在写这样代码的时候能够想得清楚的。不过最后我还是在这段代码里面找到了一些错误——与论文中的公式不符。其实写这样的代码,就很难避免一个不小心看走眼的问题。我认为问题不在于写这样代码的同学身上,问题在于高校!

如果高校的论文需要写一个复杂程度为A的程序,就应该给学生们传授能够写出复杂程度为A的程序的基本功。说实话,这个程序从编程的角度并不算多难,难的地方在理论公式上面。但是就是这样一个难度,现在的学生也不具备正确写出程序的必要能力。与此相对应的一个场景是,要求在IEEE上面发表外语论文。最难的确实是理论上面的事情,但是如果你的英语能力只是good good study day day up,那么要求发表外语论文根本就是瞎掰!对于这种问题,如果教育部认为发表外语论文是必须的,那么就应该加强学生在外语方面的训练;如果认为无法解决外语能力方面的训练,那就不应该要求发表外语论文。可是就是这么简单的一个问题,教育部就是解决不了,至少在我看来就是不诚心,或者没有尽力。

我们还是回到写程序上面。我真想质问一下这个学校的校长,或者该系的系主任:现在都什么年代了,教出来的学生连代码风格都没有及格,他们是怎么毕业的?我也不指望本科生在设计模式上面有什么造诣,但是这一连串的s[0][0]-s[0][1]+sqrt(...)还有那些毫无道理的修改循环变量的代码,教他们计算机的老师看着不觉得惭愧么?要是我教的学生在毕业论文里面写出这样的代码,我就干脆辞职算了——没脸见人!

我也知道,现在的大学在计算机编程上面投入的课时太少,大学新生在计算机方面的基础差距也很大,有各种各样的客观障碍。要是这样就不要拉牛上树赶鸭上架啊,别让他们选一个编程解决指纹增强的毕业论文题目啊!明知不可为而为之的结果,就是一个字“混”。

我原来以为这个程序是托我解决问题的同学写的,我也不好意思写出来,怕打击人家自尊。后来跟他一聊才知道,原来这个程序是他的导师给他的,作者是上一届的毕业生。那我就不客气了,反正打击的也是原来的作者。唉,我感觉这个问题已经是一种常态了,当年我女朋友读研的时候,这种事情我也听得多见的多了。好多人都是拿着导师给的、上一届写出来的、狗屁不通的、执行结果错误的、甚至干脆无法编译的程序,修修改改、胡乱调整几个参数、加几个其实根本没有被调用的方法,最后和他的已经毕业了的师兄师姐一样混毕业了。他们改完之后变得更糟糕的程序还会被流传下去,千秋万代,遗臭万年。试问这样的结果是教育部想要的吗?反正我相信这样的水平绝对不是一个商业软件公司所能够接受的!

我女朋友说我又在抱怨了,是,我就是在抱怨!前两天还有一位同志在我这里评论道“奇怪奇怪真奇怪……设计模式是提高性能”云云,其实当时我心里是挺郁闷的。我所说的那些情况其实并不算是严重的了,如果你跟我今天举的例子比较起来。这些人毕业进了公司,你指望他能够懂设计模式?他们不把你写的好好的代码,设计的好好的框架,应用的好好的第三方工具弄个乱七八糟千疮百孔乌烟瘴气,你就该念“阿弥陀佛(此处删去万余字,免得有侮辱宗教之嫌)”了。再好的设计模式,也经不起胡乱的copy&paste的。更不要说5层循环嵌套,外加内循环修改外循环的循环变量,外加if语句里面一长串的调用,外加完全无畏的重复调用。

我也不想抱怨更多了,最后再抱怨一个:
各大高校,拜托再也不要为了教同学们c语言的关键字,就不使用c++的语法了,看了让人笑话!我在看这个程序的时候就觉得郁闷,为什么每个函数前面都有一长串的变量声明,哪怕是最后面才会用到。最后才发现原来这是一个c文件,而不是cpp文件!我以前还遇到的其它代码类似如下:
int func1(a, b)
int a;
float b;
{
   return (a+b);
}
不知道大家是不是和我一样,看到了化石?不要“用c比c++性能更好,写底层的代码应该用c而不是c++”这样的理由跟我争论,我相信写出这么烂的代码的同学之所以选用c而不是c++标准,绝对不是因为这个原因。首先因为这样的程序的效率问题是用c编译器也无法挽救的,其次因为我相信他们更笨不知道还有这样一个理由。

不说了,开另外一篇写点别的。

P.S.:
@dudu:貌似如果你开一个抱怨区,我会灌很多文章进去,咔咔!

posted on 2007-05-05 00:42  Sumtec  阅读(4857)  评论(51编辑  收藏  举报