毋庸置疑的编程姿势。如此清楚面向对象编程。

因为低档材料的抹茶味面包是没有糖的,它先给了下面这个问题

不久前个别个周末,我动用 plantuml (贝尔实验室产品了一个至上绘图工具
graphviz,
这是一个包装版)把自身的绘图项目做了扳平赖到的接口和好像的可视化。使用了森设计模式,包括:桥接、装饰器、生成器、抽象工厂。绘制了后,图像是老得意的,接口之间的相互和参数定义清晰优雅。很妙!

打Rob Pike 的 Google+上的一个推动看到了平等篇让《Understanding Object
Oriented
Programming》的章,我先将当时篇稿子简述一下,然后再说说老牌黑客Rob
Pike的评介。

然并卵!

先押即篇教程是怎来描述OOP的。它先给了脚这个题目,这个题目要输出一段有关操作系统的亲笔:假设Unix很正确,Windows很不同。

这个类型在支付之处在就背了自家的有些觉得,对于程序设计的感到。从自我对数据库与服务器的连年涉,使用基于数据表和数量说明的抽象结构,你究竟能获取最简易容易用而扩大的软件结构。

本条把下面就段代码描述成是Hacker
Solution
。(这帮助人看下面这为黑客?我估摸就帮人真是没有看罢C语言的代码)

然,这个绘图项目确实特别复杂,涉及了众多底多态和涉及。比如,在一个增长之列表中蕴藏种类不一之图片,这些图存储的绘图数据与血脉相通信息都不比,我欲将这些多少视做同一栽档次,然后迭代它们,选出需要的一个而利用它的相干信息。所以,我尝试下学术界的设计模式来缓解之中的题材。

 

当型转移得慌巨大的下,我发现及设计模式屁都非是。诸如桥接、装饰器以及其他,都是建立在一如既往种使,假而你的父组件和子组件总是可以忽略对方的底细,而好合的拍卖它们。比如,面包来奶油味、抹茶味、水果味,面包又闹起码材料、高档材料,那么您得将味道与素材分为两独例外的接口,然后分别抽象,并且做这点儿单接口生成更增长的面包,比如低档材料的去除茶味面包。但是,真实的编程世界被,这样的精良状态不行少。在真的编程世界面临,面包还惦记要重新多之事物,比如奶油味的出甜,抹茶味的远非糖,有甜味的面包放在左边柜台上,没有糖的面包放在右边柜台及。看到了咔嚓,复杂度升级了,柜台和面包来没起糖是绑定的。这象征,如果你想像前那么抽象两只接口—味道和资料,那尔现在必考虑柜台。因为低档材料的删除茶味面包是从未有过糖的,放在右边柜台。现在,你不得不抽象出味道与柜台的干。在点的接口之上再长一重叠。每当你的需要复杂一点,这种层就会见升级。比如,红糖面包和白糖面包。

01 public class PrintOS

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

02 {

所以,我以为自身以不见面编程了。于是,我尽可能的重新考虑这些计划,并且再在网达到探寻曾经支持我之设计论调:面向数据结构编程而休是目标。如果未是为这个绘图项目,我绝对不见面冒险再同赖利用设计模式和面向对象。

03     public static void main(final String[] args)

自自然搜到了平不行堆 Linus 排斥面向对象和 C++ Java
的言语,从感觉上,这些就是我面临设计困难时的感觉到。我早就无数糟糕这样解决自己的次第设计。

04     {

git的设计其实大的简便,它的数据结构很平静,并且有添加的文档描述。事实上,我异常的倾向应该围绕我们的数据结构来设计代码,而无是基于其它的,我道当下吗是git之所以成功的原故有。[…]
依我之见解,好程序员和烂程序员之间的歧异就在他们觉得是代码更要紧或者数据结构更要紧。

于大幅度之路遭到,人们对不是团结支付之模块并无了解,能迅速了解外模块中函数的恰到好处含义才会增高支付效率。而C++引入的各种抽象则使代码非常靠上下文,想明白一截代码,需要看多得差不多之上下文。

面向对象语言为目标啊主干,加有交互关联的道,简直是呓语。重要之物应该是数据结构,对象自我来何要?真正有意思的,是于不同档次的例外对象交互而且有锁规则的时段。但是,即使是此时,封装什么“对象接口”也断然大错特错,因为不再是单一对象的问题了。

05         String osName = System.getProperty("os.name") ;

趣之凡,这里来同一首另外一各长辈的老大早的亲笔,推在 Google+ 上,来自 Unix
核心创建者之一 Rob Pike:

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

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

07         {

没错,我们得之就是是数量的空洞和数码的解释器。用表来存储你得之顺序数据,对于多态,C
语言中概括直接干净:union。使用这样一个简易的结构,你能够储存各种不同之种,而且若才需要仓储他们的指针,这意味着你切莫会见浪费多少内存,同时你能够获取同内存段但是多少不同之悬空。

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

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

09         }

洋洋语言都出 union 的变体,现代语言中之泛型就是 union
的同等种植语法糖,但是若往往忘记了这种组织的真正价值跟企图。仔细回味下是全新的宏图:

10         else if (osName.equals("Windows NT") || osName.equals("Windows 95"))
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]
11         {
12             System.out.println("This is a Windows box and therefore bad.") ;
13         }
14         else
15         {
16             System.out.println("This is not a box.") ;
17         }
18     }
19 }

然后开为此面向对象的编程方式一样步一步地提高之代码。

率先以过程化的笔触来重构之。

 

过程化的方案

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 }

下一场是一个稚气的面向对象的思绪。

 

 

纯真的面向对象编程

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的面向对象的缓解方案。

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是当年于Bell
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.

自家的接头

本身以为,这首文章的例子举得极度差了,差得发就是比如是OO的尖端黑。面向对象编程注重的是:1)数据与那表现之打包封装,2)程序的接口和落实之解耦。你那怕,举一个大抵独开关和多个电器之事例,不然就如STL中,一个排序算法对几近只例外容器的例证,都较是事例要好得差不多得差不多。老实说,Java
SDK里最多这样的东西了。

本人先给一部分商家说有设计模式的培训课,我数提到,那么23单经的设计模式和OO半毛钱关系并未,只不过人家用OO来促成罢了。设计模式就三独准则:1)中意被做要未是后续,2)依赖让接口而休是促成,3)高内聚,低耦合。你看,这全然就是是Unix的设计则