不错的编程姿势

前不久四个星期,我利用 plantuml (Bell实验室出品了一个顶尖绘图工具
graphviz,
那是一个包装版)把自己的绘图项目做了五回周密的接口和类的可视化。使用了过多设计形式,包蕴:桥接、装饰器、生成器、抽象工厂。绘制完后,图像是很美的,接口之间的互动和参数定义清晰优雅。很雅观!

然并卵!

以此体系在支付之处已经违反了自家的局部感觉,对于程序设计的觉得。从自身对数据库和服务器的连年经验,使用基于数据表和数据表明的用空想来安慰自己结构,你总能得到最简单易行易用可增添的软件结构。

而是,那一个绘图项目真正很复杂,涉及了众多的多态和涉嫌。比如,在一个长的列表中蕴藏序列差别的图形,那几个图片存储的绘图数据和有关信息都分歧,我索要把那几个多少视做同一连串型,然后迭代它们,选出需求的一个同时选用它的连带信息。所以,我尝试拔取学术界的设计方式来化解之中的难题。

当项目变得很巨大的时候,我发现到设计情势屁都不是。诸如桥接、装饰器以及其余,都是手无寸铁在一种假使,借使你的父组件和子组件总是可以忽略对方的底细,而得以统一的拍卖它们。比如,面包有奶油味、抹茶味、水果味,面包又有起码材料、高档材料,那么您能够把味道和资料分为多个分歧的接口,然后分别抽象,并且结合那八个接口生成更丰盛的面包,比如低档材料的抹茶味面包。不过,真实的编程世界中,那样的美妙图景分外少。在实际的编程世界中,面包还想要越来越多的事物,比如奶油味的有糖,抹茶味的远非糖,有糖的面包放在右边柜台上,没有糖的面包放在左侧柜台上。看到了呢,复杂度升级了,柜台跟面包有没有糖是绑定的。那代表,假诺您想像前边那么抽象三个接口—味道和资料,那您现在必须考虑柜台。因为低档材料的抹茶味面包是不曾糖的,放在左侧柜台。现在,你只好抽象出味道和柜台的涉及。在上头的接口之上再追加一层。每当你的需要复杂一点,那种层就会提高。比如,红糖面包和白糖面包。

一句话来说,即使设计方式幸免了类继承的爆裂,不过也防止不了抽象层级的纷纷。

故而,我觉着我又不会编程了。于是,我尽可能的再一次考虑这一个规划,并且重新在网络上查找曾经支持自己的筹划论调:面向数据结构编程而不是目的。即使不是为了那些绘图项目,我相对不会冒险再五回利用设计情势和面向对象。

自家本来搜到了一大堆 Linus 排斥面向对象和 C++ Java
的说话,从感觉上,那么些就是我面临设计困难时候的感到。我曾经无很多次那样解决自身的顺序设计。

git的规划其实至极的简短,它的数据结构很稳定,并且有抬高的文档描述。事实上,我格外的赞同应该围绕我们的数据结构来规划代码,而不是依据其它的,我觉得那也是git之所以成功的来由之一。[…]
依我的理念,好程序员和烂程序员之间的反差就在于他们认为是代码更首要依旧数据结构更关键。

在偌大的项目中,人们对不是祥和开发的模块并不打听,能很快领会其余模块中函数的适用含义才能进步花费功用。而C++引入的各类抽象则使代码卓殊信赖上下文,想精通一段代码,须求看多得多的上下文。

面向对象语言以目标为主导,加一些相关联的措施,几乎是呓语。重要的东西应该是数据结构,对象自我有啥紧要?真正有意思的,是在不一致门类的不比对象交互而且有锁规则的时候。可是,即便是此时,封装什么“对象接口”也断然大错特错,因为不再是单纯对象的难题了。

有意思的是,那里有一篇别的一位长辈的很早的文字,推在 谷歌(Google)+ 上,来自 Unix
宗旨创立者之一 罗布 Pike:

原文链接
A few years ago I saw this page:
Java,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.

— 罗布 Pike (Unix 制造者之一的 (Ken 汤普森, Dennis M. Ritche, and
罗布 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]

相关文章