对的编程姿势。如此清楚面向对象编程。

新近有限独星期日,我用 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的设计则