自身先把这篇文章简述一下,没有糖的面包放在左边柜台上

下一场,使用一个链表或者数组,把那几个 union
装进去,遍历,cast,然后选用你要求的特定数据。

18     }

幽默的是,那里有一篇此外一位长辈的很早的文字,推在 谷歌(Google)+ 上,来自 Unix
宗旨创造者之一 罗布 派克:

05         String osName = System.getProperty("os.name") ;
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]

从罗布 派克 的 谷歌(Google)+上的一个推看到了一篇叫《Understanding Object
Oriented
Programming
》的小说,我先把那篇小说简述一下,然后再说说老牌黑客罗布(Rob)派克的评头品足。

之所以,我以为自家又不会编程了。于是,我竭尽的重新考虑这个规划,并且重新在网络上搜寻曾经接济自己的统筹论调:面向数据结构编程而不是目的。假如不是为着那一个绘图项目,我相对不会铤而走险再几回拔取设计形式和面向对象。

先看那篇教程是怎么来描述OOP的。它先给了上面这几个题材,这一个题材须要输出一段关于操作系统的文字:假诺Unix很不利,Windows很差。

然并卵!

19 }

原稿链接
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.

— 罗布 Pike (Unix 创建者之一的 (Ken 汤普森(Thompson), Dennis M. Ritche, and
罗布(Rob) 派克))

04     {

可是,这些绘图项目实在很复杂,涉及了成百上千的多态和涉嫌。比如,在一个长的列表中储存连串不一的图样,这几个图片存储的绘图数据和连锁新闻都不可同日而语,我急需把这个数量视做同一序列型,然后迭代它们,选出要求的一个还要应用它的连锁信息。所以,我尝试使用学术界的设计形式来解决之中的题材。

13         }

git的设计其实万分的简要,它的数据结构很稳定,并且有加上的文档描述。事实上,我特其余倾向应该围绕大家的数据结构来设计代码,而不是依据其余的,我认为那也是git之所以成功的来头之一。[…]
依我的意见,好程序员和烂程序员之间的歧异就在于他们认为是代码更要紧照旧数据结构更主要。

在特大的品类中,人们对不是协调开支的模块并不打听,能便捷领会其余模块中函数的贴切含义才能加强成本功用。而C++引入的各类抽象则使代码非凡爱抚上下文,想理解一段代码,须要看多得多的上下文。

面向对象语言以目的为主干,加一些相关联的艺术,几乎是呓语。首要的东西应该是数据结构,对象自我有啥主要?真正有意思的,是在分歧品种的分裂目标交互而且有锁规则的时候。可是,即使是此时,封装什么“对象接口”也相对大错特错,因为不再是纯净对象的题目了。

07         {

多年来三个星期,我动用 plantuml (贝尔(Bell)实验室出品了一个极品绘图工具
graphviz,
那是一个包装版)把自家的绘图项目做了一回周密的接口和类的可视化。使用了广大设计格局,包涵:桥接、装饰器、生成器、抽象工厂。绘制完后,图像是很美的,接口之间的并行和参数定义清晰优雅。很美观!

08             System.out.println("This is a UNIX box and therefore good.") ;

当项目变得很庞大的时候,我发现到设计方式屁都不是。诸如桥接、装饰器以及其余,都是树立在一种要是,假如你的父组件和子组件总是可以忽略对方的细节,而可以统一的处理它们。比如,面包有奶油味、抹茶味、水果味,面包又有起码材料、高档材料,那么您可以把味道和素材分为五个例外的接口,然后分别抽象,并且结合那八个接口生成更增进的面包,比如低档材料的抹茶味面包。然则,真实的编程世界中,那样的优良状态相当少。在真正的编程世界中,面包还想要更加多的东西,比如奶油味的有糖,抹茶味的没有糖,有糖的面包放在左侧柜台上,没有糖的面包放在左边柜台上。看到了吧,复杂度升级了,柜台跟面包有没有糖是绑定的。那表示,若是你想像前边那么抽象五个接口—味道和材料,那您现在必须考虑柜台。因为低档材料的抹茶味面包是绝非糖的,放在左边柜台。现在,你只好抽象出味道和柜台的涉及。在上头的接口之上再追加一层。每当你的须求复杂一点,那种层就会进步。比如,红糖面包和白糖面包。

12             System.out.println("This is a Windows box and therefore bad.") ;

自身自然搜到了一大堆 Linus 排斥面向对象和 C++ Java
的讲话,从感觉上,这几个就是自身面临设计困难时候的痛感。我早就无多次那样解决自身的主次设计。

OO大师的方案

留意其中的Design Pattern

PrintOS.java

 

 

1 public class PrintOS
2 {
3     public static void main(final String[] args)
4     {
5         System.out.println(OSDiscriminator.getBoxSpecifier().getStatement()) ;
6     }
7 }

OSDiscriminator.java

 

 

01 public class OSDiscriminator // Factory Pattern
02 {
03     private static java.util.HashMap storage = new java.util.HashMap() ;
04   
05     public static BoxSpecifier getBoxSpecifier()
06     {
07         BoxSpecifier value = (BoxSpecifier)storage.get(System.getProperty("os.name")) ;
08         if (value == null)
09             return DefaultBox.value ;
10         return value ;
11     }
12     public static void register(final String key, final BoxSpecifier value)
13     {
14         storage.put(key, value) ; // Should guard against null keys, actually.
15     }
16     static
17     {
18         WindowsBox.register() ;
19         UNIXBox.register() ;
20         MacBox.register() ;
21     }
22 }

BoxSpecifier.java

 

 

1 public interface BoxSpecifier
2 {
3     String getStatement() ;
4 }

DefaultBox.java

 

 

1 public class DefaultBox implements BoxSpecifier // Singleton Pattern
2 {
3     public static final DefaultBox value = new DefaultBox () ;
4     private DefaultBox() { }
5     public String getStatement()
6     {
7         return "This is not a box." ;
8     }
9 }

UNIXBox.java

 

 

01 public class UNIXBox implements BoxSpecifier // Singleton Pattern
02 {
03     public static final UNIXBox value = new UNIXBox() ;
04     private UNIXBox() { }
05     public  String getStatement()
06     {
07         return "This is a UNIX box and therefore good." ;
08     }
09     public static final void register()
10     {
11         OSDiscriminator.register("SunOS", value) ;
12         OSDiscriminator.register("Linux", value) ;
13     }
14 }

WindowsBox.java

 

 

01 public class WindowsBox implements BoxSpecifier  // Singleton Pattern
02 {
03     public  static final WindowsBox value = new WindowsBox() ;
04     private WindowsBox() { }
05     public String getStatement()
06     {
07         return "This is a Windows box and therefore bad." ;
08     }
09     public static final void register()
10     {
11         OSDiscriminator.register("Windows NT", value) ;
12         OSDiscriminator.register("Windows 95", value) ;
13     }
14 }

MacBox.java

 

 

01 public class MacBox implements BoxSpecifier // Singleton Pattern
02 {
03     public static final MacBox value = new MacBox() ;
04     private MacBox() { }
05     public  String getStatement()
06     {
07         return "This is a Macintosh box and therefore far superior." ;
08     }
09     public static final void register()
10     {
11         OSDiscriminator.register("Mac OS", value) ;
12     }
13 }

作者还充足的意地说,他加了一个“Mac
OS”的事物。老实巴交说,当我看看最终那段OO大师搞出来的代码,我快要吐了。我瞬间想到了两件事:一个是先前酷壳上的《面向对象是个骗局》和
各类流行的编程格局》中说的“设计情势驱动编程”,另一个我想开了这几个被神速洗过脑的程序员和咨询师,也是那种德行。

于是乎我去看了须臾间第一作者Joseph
Bergin的主页
,这么些Ph.D是果然刚刚已毕了一本有关敏捷和格局的书。

总的说来,即便设计形式幸免了类继承的爆炸,可是也幸免不了抽象层级的繁杂。

Rob Pike的评论

(罗布(Rob) 派克(Pike)是那时在贝尔lab里和Ken一起搞Unix的主儿,后来和Ken开发了UTF-8,现在还和Ken一起搞Go语言。注:不要以为Ken和Dennis是基友,其实她们才是的确的老基友!)

Rob
Pike在他的Google+的这贴里评论到那篇小说——

她并不认同那篇小说是还是不是搞笑?可是他认为这个个写那篇小说是很认真的。他说她要评论那篇文章是因为她们是一名Hacker,至少那个词出现在那篇小说的术语中。

她说,这一个程序根本就不必要怎样Object,只须求一张小小配置表格,里面配备了相应的操作系统和您想出口的公文。那不就完了。这么简单的设
计,卓殊简单地扩展,他们卓绝所谓的Hack
Solution完全就是愚钝的代码。后边那么些所谓的代码进化万分疯狂和鸠拙的,这几个完全误导了对编程的回味。

然后,他还说,她认为那些OO的狂热份子分外恐惧数据,他们喜爱用多层的类的关系来形成一个本来只要求寻找三行数据表的办事。他说他曾经听说有人在她的行事种用各个OO的事物来替换While循环。(我听说中国Thoughtworks那帮搞敏捷的人确实喜欢用Object来替换所有的if-else语句,他们如故还爱好把函数的行数限制在10行以内)

他还给了一个链接http://prog21.dadgum.com/156.html,你可以读一读。最终他说,OOP的原形就是——对数码和与之提到的行事展开编程。便就到底那样也不完全对,因为:

Sometimes data is just data and functions are just functions.

以此项目在支付之处已经违背了自我的局地深感,对于程序设计的感觉到。从本人对数据库和服务器的连年经验,使用基于数据表和数目表明的抽象结构,你总能获得最不难易行易用可扩展的软件结构。

 

众多言语都有 union 的变体,现代语言中的泛型就是 union
的一种语法糖,然则你往往忘记了那种布局的确实价值和意向。仔细回味下那么些全新的布署:

14         else

科学,我们要求的就是数码的用空想来安慰自己和数目标解释器。用表来存储你须要的种种数据,对于多态,C
语言中概括直接干净:union。使用那样一个简便的结构,你能积存各样分化的花色,而且你只要求仓储他们的指针,那象征你不会浪费多少内存,同时你能赢得一致内存段可是数量差别的空洞。

自身的接头

本人觉得,这篇文章的例子举得圣母皇太后差了,差得感觉就如OO的高等黑。面向对象编程敬爱的是:1)数据和其一言一动的打包封装,2)程序的接口和落成的解耦。你那怕,举一个三个开关和三个电器的例证,不然如同STL中,一个排序算法对多少个分化容器的例子,都比那么些事例要好得多得多。老实说,Java
SDK里孝庄多如此的东西了。

自家原先给部分商行讲一些设计情势的培训课,我频仍提到,那23个经典的设计情势和OO半毛钱关系远非,只可是人家用OO来贯彻罢了。设计形式就多个准则:1)中意于整合而不是屡次三番,2)保养于接口而不是落到实处,3)高内聚,低耦合。你看,那完全就是Unix的安顿准则

 

03     public static void main(final String[] args)
17         }
15         {

先是以进程化的思绪来重构之。

其一把下部这段代码描述成是Hacker
Solution
。(那帮人认为下边那叫黑客?我估量那帮人真是没看过C语言的代码)

02 {
16             System.out.println("This is not a box.") ;

进程化的方案

01 public class PrintOS
02 {
03     private static String unixBox()
04     {
05         return "This is a UNIX box and therefore good." ;
06     }
07     private static String windowsBox()
08     {
09         return "This is a Windows box and therefore bad." ;
10     }
11     private static String defaultBox()
12     {
13         return "This is not a box." ;
14     }
15     private static String getTheString(final String osName)
16     {
17         if (osName.equals("SunOS") || osName.equals("Linux"))
18         {
19             return unixBox() ;
20         }
21         else if (osName.equals("Windows NT") ||osName.equals("Windows 95"))
22         {
23             return windowsBox() ;
24         }
25         else
26         {
27             return defaultBox() ;
28         }
29     }
30     public static void main(final String[] args)
31     {
32         System.out.println(getTheString(System.getProperty("os.name"))) ;
33     }
34 }

然后是一个童真的面向对象的思路。

 

 

09         }
01 public class PrintOS
11         {

纯真的面向对象编程

PrintOS.java

 

1 public class PrintOS
2 {
3     public static void main(final String[] args)
4     {
5         System.out.println(OSDiscriminator.getBoxSpecifier().getStatement()) ;
6     }
7 }

OSDiscriminator.java

 

 

01 public class OSDiscriminator // Factory Pattern
02 {
03     private static BoxSpecifier theBoxSpecifier = null ;
04     public static BoxSpecifier getBoxSpecifier()
05     {
06         if (theBoxSpecifier == null)
07         {
08             String osName = System.getProperty("os.name") ;
09             if (osName.equals("SunOS") || osName.equals("Linux"))
10             {
11                 theBoxSpecifier = new UNIXBox() ;
12             }
13             else if (osName.equals("Windows NT") || osName.equals("Windows 95"))
14             {
15                 theBoxSpecifier = new WindowsBox() ;
16             }
17             else
18             {
19                 theBoxSpecifier = new DefaultBox () ;
20             }
21         }
22         return theBoxSpecifier ;
23     }
24 }

BoxSpecifier.java

 

 

1 public interface BoxSpecifier
2 {
3     String getStatement() ;
4 }

DefaultBox.java

 

 

1 public class DefaultBox implements BoxSpecifier
2 {
3     public String getStatement()
4     {
5         return "This is not a box." ;
6     }
7 }

UNIXBox.java

 

 

1 public class UNIXBox implements BoxSpecifier
2 {
3     public String getStatement()
4     {
5         return "This is a UNIX box and therefore good." ;
6     }
7 }

WindowsBox.java

 

 

1 public class WindowsBox implements BoxSpecifier
2 {
3     public String getStatement()
4     {
5         return "This is a Windows box and therefore bad." ;
6     }
7 }

他俩觉得下边那段代码没有消除if语句,他们说那叫代码的“logic
bottleneck”(逻辑瓶颈),因为一旦你要加进一个操作系统的论断的话,你不仅要加个类,还要改那段if-else的讲话。

故此,他们整出一个叫Sophisticated的面向对象的化解方案。

06         if (osName.equals("SunOS") || osName.equals("Linux"))

下一场伊始用面向对象的编程格局一步一步地开拓进取这几个代码。

10         else if (osName.equals("Windows NT") || osName.equals("Windows 95"))