正文

Humane Programming——人性化编程2005-03-26 09:53:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/jzyray/405.html

分享到:

Humane Programming——人性化编程
    尽管现今各国均投入大量人力物力去研发所谓的真正的“人工智能”,但大家每日所对的计算机始终是个死物——一个让它做它才做的死物,甚至懂得罢工偷懒的死物。
    因此,支持库(Java VM,VB Runtime,.net Framework等)总是机械地吞吐着指令集中的动作。即使是那高智能的优化器,也只不过是将某句或多句汇编代码与优化库案例作对照,然后拟出相应的优化代码罢了(当然也并非如此简单)。
    那么,对于下面的案例,优化器又能做什么呢?
    小A为某网站的用户管理系统制作支持模块,具体来说,就是去写程序来管理用户信息。小A采用顺序文本文档为载体,亲自编写了针对顺序文本的繁琐的基本操作模块。但是运行之后,查找匹配速度极慢,I/O超出负荷,缓存文本大小呈几何级数增长。总而言之,该产品很不尽人意。
    然后,小A找来了优化器套件,优化器针对程序中所调用的函数库进行了部分更改后,带宽占用下来了、CPU占用率也下来了,但是最要命的速度与空间占用问题却得不到解决。这真是个耗时又不便利的豆腐渣工程。
    其实,我们早就发现,如果小A采用MySQL等专业数据库引擎作为后台支持,不仅有关代码的编写容易、维护方便,而且也不会出现速度滞后、空间利用差的问题。可是,优化器却不能为小A指出一条明路。
    尽管上面这个案例很愚蠢,但它也从一个方面向我们阐述:人对软件过程又绝对的作用。这就是Humane Programming的宗旨,要让每一句有效代码都人性化,让每一个开发阶段人性化,我们应当进行人性化编程。
    以下是我对Humane Programming的诠释。


一.不要总为简短的语句沾沾自喜
    似乎程序设计的进步总是伴随着编码量的减少。VB.net2005为我们带来了My命名空间,借助My.Forms可以像在VB6中一样不用发愁窗体间的交流,借助My.Computer可以轻易访问本机资源……这无疑是令人振奋的,VB.net2003中部分臃肿的代码得以瘦身,清爽干净。
    但并非所有简化方案都令人满意。
    VB6中提供IIf函数,可以将赋值型IF…ELSE…END IF语句在一行内完成,例如
    IF a>b THEN
        max=a
    ELSE
        max=b
    END IF
    就等价于
    max=IIf(a>b,a,b)
    乍看之下,不禁令人心动,但是再看下面这段代码
    IF i>=0 AND i<=2 THEN    ‘i的类型为Integer
        re=a(i)    ‘a是以0为下界,2为上界的一维数组
    ELSE
        re=a(0)
    END IF
    转换之后变为
    re=IIf(i>=0 AND i<=2,a(i),a(0))
    好像没有问题吧。不,别忘了IIf是一个函数,VB Runtime会先将函数的所有参数压入堆栈然后才跳入函数代码区。也就是说,IIf的调用会先令系统取得所有参数。那么,举个例子,当i=-1时,IIf的三个参数变为False,a(-1)和a(0)。然而a(-1)是无意义的,这时会发生下标越界的运行时错误。哦,这该死的逻辑错误,编译器在检查时是不会发现它的,运行时无奈的错误提示才会给你自以为聪明的想法泼上冷水。你会发现转换之前的语句是多么的美好。
    还有,复杂的语言也总会给你无限的空间来组装自己的代码,使它更精简。例如(C++)
    int a[100];
    for(int i=0;i<100;i++){
        if(i%2==0){
            *(a+i)=0;
        }else{
            *(a+i)=1;
        }//if
    }//for
    等价于
    int a[100];
    for(int i=0;i<100;i+=2)
        *(a+i)=0;
    for(int i=1;i<100;i+=2)
        *(a+i)=1;
    上两段代码均可简化为
    int a[100];
    for(int i=0;i<100;i++)
        *(a+i+1-2*(i%2))=(i+1)%2;
    但是可想而知,不可能一眼明白简化后的代码的意图,这也很不易维护,需要一定的注释,而这又将花费不少精力,然而却没有开发和运行效率上的提升,何苦而为之?
    此外,从事多语言交互开发的人有时也会有以下的困惑([游智超2005]):
    func(a<b,c>(d))
    上面这句代码应当如何理解?
    在C#2.0中func只有一个参数,a十一个泛型类,d是变量而b和c是替代泛型类型的真实类型或类;在Java中,func有两个参数,第一个是a<b的布尔值,第二个是c>(d)的布尔值。
    所以,如果只熟悉一门语言也就罢了,而经常使用多语言进行软件开发的人一定要重视这类情况,或许多写几行代码反而一目了然。
    由此可得,机器固定的运行模式会让聪明的人犯错。


二.以人为本
    程序的最终使用权归用户所有,所以,产品的好坏往往由用户作出最终的判断。而用户做出的第一判断往往是对GUI等界面的感受。
    如果界面能响应人的需求并且考虑到人的弱点,那么它就是以人为本的。[Raskin2004]
    人性化编程要求产品与用户有人性化的交流。
    依然举个例子,小B是数据库开发高手,他现在要为家庭主妇们设计一款家用财会管理软件,用户小C女士试用了这款产品。
    小C现在想要在2005年1月1日的记录下新建一条支出信息:“购买鸡蛋1斤——3元”。小C单击“添加支出项目”命令之后弹出一个输入框,提示信息是“请为您新建的字段命名”。“字段?我好像没要使用一个什么叫‘字段’的东西吧。” 小C被小B不考虑用户适应能力的产品搞糊涂了,只好怏怏地取消了操作。
    “字段”是我们最常见的数据库用语,但是我们在设计程序界面交互时不应当把用户定位成自己,不应当把自己的感受当作用户的感受,而应当认真分析使用人群的运用能力以及工作领域,否则自己的作品只会以失败告终。
此外,我们还应当考虑到用户的所有可能操作。
    比方说,有一个输入框供用户输入数字。那么,我们应当保证从输入框传到处理模块的数据是合法的数字形式,因此:如果输入框为空,则传入0;如果有非法字符,则进行剔除;如果数位超过要求,则应作相应的舍取;如果小数点前后出现无数字的情况,则应考虑是否补0;……
    总而言之,设计界面时,我们应当做到以人为本。我们是为用户而不是为机器装配软件。


三.不要被机器所禁锢
    在这里,我首先要重申文章开头所揭示的事项:不要过分依靠优化器。当然,到了“听天命”的地步,也只能用优化器了。
    我再举一个优化器造成困扰的粒子(C++)。
    void sample(){
        int pw;            //用于储存密码的变量
        pw=GetPassword;    //获取相关密码
        ……            //进行一些需密码的简单无停顿(即无对话框等)的操作(CodeI)
        pw=0;            //置pw为0(CodeII)
        ……            //进行无需密码的复杂或有停顿的操作(CodeIII)
    }//sample
    我们不想让CodeI部分所用的pw的值被用户所知,但是我们是无法奈何调试器的。而幸运的事,大多数用户并不会使用复杂的调试器,最多是使用内存查看器。而人一般来不及在CodeI短暂运行期中抓拍内存,只有在CodeIII部分才有可能。所以,只要利用CodeII将pw设为真实密码以外的数,便可以令拍下的内存中的pw值为错误值(此例中设为0)。
    然而,有些优化器认为CodeII之后没有再用到pw变量,所以CodeII没有用处,于是便在优化过程中删去了CodeII部分来完成它自以为是的提速。结果可想而知。
    我们在研究一下优化器以外的情况。
高级语言到汇编代码的转换是单向的,机器无法将汇编代码自动转换为高级语言代码,除非中间有人的参与。[Kaspersky2004]
    为什么会这样呢?就是因为机器不会思考,而人会!这应当是我们所反复念及的。机器无法将简易的汇编代码变成具有分支等具体结构的高级语言,而人经过分析对照,便可以尝试进行几种转换方案,直至可行性被验证为止。
    我们的聊天机器人也是如此,您可以尝试将一个关键词放入不同的句子中与机器人聊天。看到结果了吧,一样的回复信息!
    因此,我们不应当过分依赖所谓的智能工具。在编程过程中,我们应当学会运用工具来提高效率和质量,但是离开了工具就活不下去便是不对的了。人才是生产力中的决定性因素!


四.寻求针对自身的解决方案
    现今,OOP、XUL、UML等都炒得很火,大批有关资料在市面上涌现出来。大批人蜂拥而至。不过,你的确需要吗?
    比如说,.net的兴起使得大批的应用迁移到.net上——这当然是一个趋势,但是像Adobe,Macromedia和金山这样的软件大厂为什么没有将核心产品转移呢?因为还有大比例的Win32用户,这一点是必须考虑的!
    再举例说,如果要设计一个整数加减处理模块,可是你却要同时加上小数处理模块,理由是为了方便今后的拓展。然而,这样却拖延了开发进度,减慢了模块处理速度。况且需求是不断变更的,说不定在最坏的情况下,研发部放弃了这款产品,那时还怎么会有机会去拓展?
    就自身而言,我是一个自由开发者,不参与团体开发,所以完全有理由将团体开发方法束之高阁,同时也省去了不少学习时间。
    同样,如果linux 2.6的新特性对你很有帮助,那么升级是有必要的;否则,2.4已经十分稳定耐用,何必为了“新”而去放弃早已熟习的环境,去花费时间适应新的环境呢?


五.为自己的软件设计好未来
    如同父母总努力为孩子营造良好氛围去铺砌孩子们的未来,我们也应当为自己的软件的未来做好准备。
    [四]中提到了一个为软件未来着想却不可行的案例,案例失败的原因是对需求评估的不合理。我们提倡在需求计划稳定的前提下,为软件的发展拟定下1个版本甚至下几个版本的计划(用户暂不需要或较难实现的计划可归在下几个版本中进行)。这样,自己便有充足的时间去研究提前拟定的计划的可行性及易用性,并能在实现之前及时做出更改。此外,还可以在研究计划的同时产生有它引发的其他想法或思路。于是,一环套一环,推动产品的不断进步。
    当然,诸如及时添加注释、产品类说明等有关方便软件维护这类老掉牙的事项更不必赘述。


    好了,我已将我所提的人性化编程诠释完了。人性化编程不但是一个方法论,它应当贯穿软件的设计、开发、维护及用户的最终使用等多个阶段。谨以此文愿大家今后能高效进行更多体现人这一要素的软件开发项目。




参考资料

[游智超      2005]探讨和比较Java和C#的泛型机制(Generics)
[Raskin      2004]人本界面——交互式系统设计
[Kaspersky   2004]黑客反汇编揭秘
[段钢        2003]加密与解密(第二版)
[Sommerville 2000]Software Engineering(Sixth Edition)
http://msdn.microsoft.com
http://kernel.org

阅读(4500) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册