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

近日个别独星期天,我用 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的统筹则

相关文章