zoukankan      html  css  js  c++  java
  • 编程习俗和设计模式

    03-31-2016, 6th edition

    04-10-2013, 5th edition

    09-21-2012, 4th edition

    08-28-2012, 3rd edition

    05-19-2012, 2nd edition

    10-05-2011, version 1.0

    在进入正题之前,我请大家看下面这张图片。学建筑的朋友给我讲到说古希腊三大柱式:

     

    如果不是有人告诉我,我可能永远也不知道建筑学院底下那柱子是爱奥尼克式的⋯

    编程习俗的话,也需要有人点明出来。本人在接触编程相当久后,才深刻反思“如何写程序”这个问题。

    人们似乎有着这样的感觉,就是编程是无国界的,这个论断不准确。首先,所有的编程符号大都是拉丁字母,从代码到伪代码的角度来讲,西方国家的人更容易理解。 这个理由太牵强?那我就具体道来,每一门程序语言的community都有自己的convention(习俗,所谓习俗就是约定俗成,人尽皆知的)。比如说当说到set, 这表示有这么一个collection,他们的元素没有重复的;当说到List, 它表示这个collection的元素新元素会经过一定方法append到老元素之后。一个类是另一个类的factory, 就是说它能以某种方式生产出其关联类。设计模式为叫那个名字,observer为什么也叫publish-subscribe, strategy为什么也叫policy,本身的意义和类比对于讲英语的人是make sense的,可是对于非英语母语的我们来说,他就是一个记忆的名称而已,感悟自然不够深刻。再比如一些Community,比如Java community,写interface让你尽可能用形容词(作名词), Runnable, Collidable, Collectable, 如果想不起来这些英语单词,怎么做到”readable“?

    还有一些习俗,比如.NET和ActionScript写interface喜欢加一个“I”为前缀;  微软程序员喜欢匈牙利(其某个程序是匈牙利人)命名法则,每一个命名的首字母提示他的类型。再比如SFX的前缀常常表示音效文件sound effects。再比如一系列的naming convention。

    举几个设计模式的例子。我们说,“开汽车”的时候,我们实际上是在动方向盘,而真正让车子动起来的是发动机,让车子跑的是轮子。但是我们看不到发动机,也不知道发动机怎么工作的,我们做的, 如果描述成一个method,可以是:

    车{
        左转() {
            方向盘.左转();
        }
    }

    (方向盘左转的implemenation中,可能又调用了调用了其他元件,我们就不深究了)

    这个就是delegation的概念。

    虽然说继承是面向对象很重要的特征,但实际中composite还是首选,其意思就是“包含”。所以当写程序的时候,你要先考虑一下你的写法是否make sense. 比如汽车可以放CD, 你会写汽车继承了CD player, 同时又多了一些轮子什么的么?或者汽车继承了空调,同时有几个参数是座位什么的?这些显然没那么准确,要考虑有没有“is a"这种relationship,实际中情况更复杂。

    比如说,有人想租房,有人出租房,有人中介。你想租房找中介,中介给你介绍。这个模式叫做mediator, 中间人,你是不知道到底那个人拥有那个房子的。同时,另外一个人也想租那一幢,中介告诉他有人租了,他灰溜溜走了。他也不知到是你租的。这就是一个很好的封装性。

    所谓设计模式也是从建筑学中借来的概念。你要盖大楼,每一层怎么盖,每一户怎么盖,每一间怎么盖,电线怎么走,插头放哪里,插头什么形状。写程序也是一样。

     其实对于Software Engineering来讲,没有人是因为脑子不够用,我们要知道的是更多的习俗和经验,

    如果说编程分为面向过程和面向对象(也有其他的paradigm),其实不少人不属于二者中的任何一种。因为在课堂上没有人告诉你、即便有——你也无法从言谈中了解,到底什么是面向过程的从思维到实施方式,什么是面向对象的思维到实施方式。这是国内和国际计算机教学的一个普遍问题。做为计算机专业的学生,把代码写好是没有什么错的。工程能力和科研能力是不矛盾的,相反,杰出的科研团队往往有具有明星级别的工程师。

    用Java不代表你在面向对象,用C也不代表是在面向过程。编程的理念,这些属于“心法”,到底用 system.out还是printf的招式不重要,20年后用什么语言谁也不知道,但是20年后设计模式是不会变的,就好像几千年来建筑模式没有怎么变。

    举例一些geek的习惯,比如用四个空格代替一个 tab, 这样你的代码在不同的编辑器里显示的比较一样,粘贴来粘贴去直接可以用的。想想国内论坛上90%的代码,直接copy/paste是没法工作的,即使在 csdn, pudn找到的资源很多也是不能用的。(这也有一个弊端,比如你在写make file或者写 script的时候,就一定需要tab了)

    "All good writers- including those who write software- know that a piece of work isn't good until it's been rewritten."

    9.21.2012 Started writing... 

    当我们谈到程序设计的时候,就没有渭泾分明的错与对,只有对于某个具体case的相对适用性好与不好~

    Composite,有的时候为了满足接口的一致性(uniform),就可能引入不确定性(如类别)和冗余信息。但如果区分每个个体,又会带来遍历(traverse)函数的不便。

    State,到底谁决定状态的转换,每个状态自己还是另有其他class还是根据一个table?如果是自己的话那coupling就不loose了;外部class的话flexibility又下降,一旦添加新的state,所有的logic都需要变;如果是由外部table决定的话,那程序的可读性下降。

    说到observer,到底是用push model还是pull model呢。前者,subject一旦有更新就把详细的数据更新讯息告诉observer(们),不管他们需要需要想不想要。而pull model,只告诉最小的更新讯息,哪个observer之后要用再自己索取。前者假定subject和observer互相了解,这样程序的复用性(reusability)下降,而后者虽然精简,但是会低效,因为observer需要独自查明确定到底subject发生了什么改变。

    再比如,effciency和coupling的tradeoff,需要高效,那类之间的联系就会更具体和确定,而这样相对独立性和复用性就下降。很多时候是传一个类作为参数,还是传若干个变量呢?前者更直接,而两个类的关系必然会紧密。而传参数的话,method会更general,但还要对结果进行一定加工。

    需要command更智能,那它就需要知道了解的越多,这样他的reference就自然多了,也就越针对某个个体,而不是general的。。维护(maintenance)起来也就麻烦。

    有的时候subclassing和复杂的structure本身过于繁复也会让人望而却步,不够直观,可读性下降。到底什么才是subclassing的度呢。用template class还是subclassing呢? 前者可以高效,后者可能更make sense。

  • 相关阅读:
    Keil MDK5 硬件仿真之查看变量的值(内附变量值不随程序的运行而刷新的解决办法)
    15 Q点稳定的放大电路和基本共集放大电路
    13 H参数等效模型
    12 放大电路的分析方法
    文件处理
    基本数据类型及内置方法
    for循环及字符串操作
    while循环
    用户交互、运算符
    变量与基本数据类型
  • 原文地址:https://www.cnblogs.com/antai/p/designPattern.html
Copyright © 2011-2022 走看看