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

近年简单独星期天,我使用 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的宏图则

相关文章