正确的编程姿势

最近两个星期,我使用 plantuml (贝尔实验室出品了一个超级绘图工具 graphviz, 这是一个包装版)把我的绘图项目做了一次全面的接口和类的可视化。使用了很多设计模式,包括:桥接、装饰器、生成器、抽象工厂。绘制完后,图像是很美的,接口之间的交互和参数定义清晰优雅。很漂亮!

然并卵!

这个项目在开发之处已经违反了我的一些感觉,对于程序设计的感觉。从我对数据库和服务器的多年经验,使用基于数据表和数据解释的抽象结构,你总能获得最简单易用可扩展的软件结构。

不过,这个绘图项目真的很复杂,涉及了很多的多态和关联。比如,在一个长的列表中存储种类不同的图形,这些图形存储的绘图数据和相关信息都不同,我需要把这些数据视做同一种类型,然后迭代它们,选出需要的一个并且使用它的相关信息。所以,我尝试使用学术界的设计模式来解决其中的问题。

当项目变得很庞大的时候,我意识到设计模式屁都不是。诸如桥接、装饰器以及其他,都是建立在一种假设,假设你的父组件和子组件总是可以忽略对方的细节,而可以统一的处理它们。比如,面包有奶油味、抹茶味、水果味,面包又有低档材料、高档材料,那么你可以把味道和材料分为两个不同的接口,然后各自抽象,并且组合这两个接口生成更丰富的面包,比如低档材料的抹茶味面包。但是,真实的编程世界中,这样的理想状态非常少。在真实的编程世界中,面包还想要更多的东西,比如奶油味的有糖,抹茶味的没有糖,有糖的面包放在左边柜台上,没有糖的面包放在右边柜台上。看到了吧,复杂度升级了,柜台跟面包有没有糖是绑定的。这意味着,如果你想像前面那样抽象两个接口---味道和材料,那你现在必须考虑柜台。因为低档材料的抹茶味面包是没有糖的,放在右边柜台。现在,你不得不抽象出味道和柜台的关系。在上面的接口之上再增加一层。每当你的需求复杂一点,这种层就会升级。比如,红糖面包和白糖面包。

总之,就算设计模式避免了类继承的爆炸,但是也避免不了抽象层级的复杂。

所以,我觉得我又不会编程了。于是,我尽可能的重新思考这些设计,并且重新在网络上搜寻曾经支持我的设计论调:面向数据结构编程而不是对象。如果不是为了这个绘图项目,我绝对不会冒险再一次使用设计模式和面向对象。

我当然搜到了一大堆 Linus 排斥面向对象和 C++ Java 的话语,从感觉上,这些就是我面临设计困难时候的感觉。我曾经无数次这样解决我的程序设计。

git的设计其实非常的简单,它的数据结构很稳定,并且有丰富的文档描述。事实上,我非常的赞同应该围绕我们的数据结构来设计代码,而不是依据其它的,我认为这也是git之所以成功的原因之一。[...] 依我的观点,好程序员和烂程序员之间的差别就在于他们认为是代码更重要还是数据结构更重要。

在庞大的项目中,人们对不是自己开发的模块并不了解,能快速理解其他模块中函数的确切含义才能提高开发效率。而C++引入的各种抽象则使代码非常依赖上下文,想理解一段代码,需要看多得多的上下文。

面向对象语言以对象为核心,加一些相关联的方法,简直是呓语。重要的东西应该是数据结构,对象本身有啥重要?真正有意思的,是在不同类型的不同对象交互而且有锁规则的时候。但是,即使是这时候,封装什么“对象接口”也绝对错误,因为不再是单一对象的问题了。

有趣的是,这里有一篇另外一位前辈的很早的文字,推在 Google+ 上,来自 Unix 核心创建者之一 Rob Pike:

原文链接
A few years ago I saw this page: http://www.csis.pace.edu/~bergin/patterns/ppoop.html

Local discussion focused on figuring out whether this was a joke or not. For a while, we felt it had to be even though we knew it wasn't. Today I'm willing to admit the authors believe what is written there. They are sincere.

But... I'd call myself a hacker, at least in their terminology, yet my solution isn't there. Just search a small table! No objects required. Trivial design, easy to extend, and cleaner than anything they present. Their "hacker solution" is clumsy and verbose. Everything else on this page seems either crazy or willfully obtuse. The lesson drawn at the end feels like misguided epistemology, not technological insight.

It has become clear that OO zealots are afraid of data. They prefer statements or constructors to initialized tables. They won't write table-driven tests. Why is this? What mindset makes a multilevel type hierarchy with layered abstractions better than searching a three-line table? I once heard someone say he felt his job was to remove all while loops from everyone's code, replacing them with object stuff. Wat?

But there's good news. The era of hierarchy-driven, keyword-heavy, colored-ribbons-in-your-textook orthodoxy seems past its peak. More people are talking about composition being a better design principle than inheritance. And there are even some willing to point at the naked emperor; see http://prog21.dadgum.com/156.html for example. There are others. Or perhaps it's just that the old guard is reasserting itself.

Object-oriented programming, whose essence is nothing more than programming using data with associated behaviors, is a powerful idea. It truly is. But it's not always the best idea. And it is not well served by the epistemology heaped upon it.

Sometimes data is just data and functions are just functions.

--- Rob Pike (One of the Unix creators (Ken Thompson, Dennis M. Ritche, and Rob Pike))

几年前我看到了这个网页: http://www.csis.pace.edu/~bergin/patterns/ppoop.html

我真的不知道这篇文章到底是不是在搞笑。读了一下,我虽然很想说这不是一篇搞笑的文章,但是,拜托,它根本就是。让我来跟你们讲讲他们在搞笑什么吧。

e...按照他们的话语,我应该称自己为 hacker (黑客),不管我不关心这些。Hello! 你只需要一个小的不能再小的 table ! 根本不需要什么对象。朴素平凡,容易扩展,容易清除,(比起他们的那种设计)多 TM 简单。他们的 “hacker solution” 真的是又蠢又笨。他们写出来的那堆东西到处透漏着疯狂和愚蠢。他们缺乏技术认知。

很显然,OO 的狂热者们害怕数据。他们喜欢用语句或者构造器来初始化 tables 。他们根本不写 table-driven 的测试。Why is this? 得有多大的心才会选择用多级并且多层的类抽象,而不去用一个小小的三行 table ? 我曾经听说有人用各种 OO 的东西替换掉 while 循环。

不过好消息是,hierarchy-driven, keyword-heavy, colored-ribbons-in-your-textook orthodoxy 这些东东快到头了。更多的人选择组合而不是继承。有些人已经重新开始认识 OO。

面向对象编程语言,其本意是使用数据和相关的行为进行编程,这是一个很好的想法。事实确实如此。但是,这个想法并不总是最好的 idea。 这个想法并没有完全的认知编程的世界。

Sometimes data is just data and functions are just functions.

--- Rob Pike (Unix 创建者之一的 (Ken Thompson, Dennis M. Ritche, and Rob Pike))

没错,我们需要的就是数据的抽象和数据的解释器。用表来存储你需要的各个数据,对于多态,C 语言中简单直接干净:union。使用这么一个简单的结构,你能存储各种不同的类型,而且你只需要存储他们的指针,这意味着你不会浪费多少内存,同时你能获得相同内存段但是数据不同的抽象。

然后,使用一个链表或者数组,把这个 union 装进去,遍历,cast,然后使用你需要的特定数据。

很多语言都有 union 的变体,现代语言中的泛型就是 union 的一种语法糖,但是你往往忘记了这种结构的真正价值和用意。仔细体会下这个全新的设计:

enum ShapeKind {
  skLINE, skPORT, skBOARD
}

class Shape {
  kind: ShapeKind   
  value: Line | Port | Board
  contains(x: number, y: number): boolean
}

class ShapeContainer {
  shapes: Array<Shape>
  search(x: number, y: number): [ShapeKind, Shape]
}
type
  ShapeKind = enum
    skLINE, skPORT, skBOARD

  Shape = ref object
    case kind: ShapeKind
    of skLINE:
      line: Line
    of skPORT:
      port: Port
    of skBOARD:
      board: Board
    contains: (x: number, y: number): bool

  ShapeContainer = object
    shapes: seq[Shape]

proc search(c: ShapeContainer, x: number, y: number): tuple[kind: ShapeKind, shape: Shape]
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容