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。

  • 相关阅读:
    Two strings CodeForces
    Dasha and Photos CodeForces
    Largest Beautiful Number CodeForces
    Timetable CodeForces
    Financiers Game CodeForces
    AC日记——整理药名 openjudge 1.7 15
    AC日记——大小写字母互换 openjudge 1.7 14
    AC日记——将字符串中的小写字母换成大写字母 openjudge 1.7 13
    AC日记——加密的病历单 openjudge 1.7 12
    AC日记——潜伏着 openjudge 1.7 11
  • 原文地址:https://www.cnblogs.com/antai/p/designPattern.html
Copyright © 2011-2022 走看看