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

前不久少独周末,我利用 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的筹划则

相关文章

admin

网站地图xml地图