永利网上娱乐自家先把那篇小说简述一下,因为低档材质的抹茶味面包是绝非糖的

近些年多个礼拜,笔者使用 plantuml (Bell实验室产品了叁个最棒绘图工具
graphviz,
那是三个包装版)把笔者的绘图项目做了1回周详的接口和类的可视化。使用了见惯不惊设计形式,包涵:桥接、装饰器、生成器、抽象工厂。绘制完后,图像是很美丽的,接口之间的互相和参数定义清晰优雅。极美丽貌!

从罗布 Pike 的 谷歌+上的贰个推看到了1篇叫《Understanding Object
Oriented
Programming
》的稿子,笔者先把那篇作品简述一下,然后再说说老牌黑客罗布Pike的评说。

然并卵!

先看那篇教程是怎么来描述OOP的。它先给了上边那么些题材,这一个题材供给输出一段有关操作系统的文字:假如Unix很不利,Windows很差。

那几个类别在支付之处已经违反了自家的某个感到,对于程序设计的感觉。从自己对数据库和服务器的连年经验,使用基于数据表和数码表达的抽象结构,你总能获得最简便易用可扩展的软件结构。

这几个把下边那段代码描述成是Hacker
Solution
。(那帮人觉着上边那叫黑客?小编测度那帮人当成没看过C语言的代码)

唯独,那一个绘图项目实在很复杂,涉及了不少的多态和涉嫌。比如,在四个长的列表中储存类别分歧的图样,那个图片存款和储蓄的绘图数据和连锁音信都不及,小编索要把这几个数据视做同一种档次,然后迭代它们,选出要求的贰个并且使用它的连带消息。所以,小编尝试采纳学术界的设计方式来缓解个中的难题。

 

当项目变得很庞大的时候,小编发觉到设计形式屁都不是。诸如桥接、装饰器以及任何,皆以成立在1种假使,即使你的父组件和子组件总是能够忽略对方的底细,而得以统1的拍卖它们。比如,面包有奶油味、抹茶味、水果味,面包又有起码质感、高档材质,那么你能够把味道和资料分为多个不等的接口,然后分别抽象,并且结合那五个接口生成更拉长的面包,比如低档材料的抹茶味面包。不过,真实的编制程序世界中,那样的可观图景非凡少。在实际的编制程序世界中,面包还想要更多的事物,比如奶油味的有糖,抹茶味的远非糖,有糖的面包放在右侧柜台上,未有糖的面包放在左边柜台上。看到了呢,复杂度升级了,柜台跟面包有未有糖是绑定的。那象征,假设你想像前面那么抽象七个接口—味道和素材,那你现在必须思考柜台。因为低档材质的抹茶味面包是尚未糖的,放在左侧柜台。将来,你只可以抽象出味道和柜台的涉嫌。在上边的接口之上再充实1层。每当你的须要复杂一点,那种层就会升级。比如,红糖面包和白糖面包。

01 public class PrintOS

总之,即使设计情势幸免了类继承的爆炸,可是也幸免不了抽象层级的错综复杂。

02 {

故而,小编认为本身又不会编制程序了。于是,作者尽量的再次思量那几个布署,并且重新在网络上摸索曾经帮忙笔者的安顿论调:面向数据结构编制程序而不是指标。假设不是为着那一个绘图项目,小编相对不会铤而走险再次利用设计情势和面向对象。

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

自身自然搜到了一大堆 Linus 排斥面向对象和 C++ Java
的言辞,从感觉上,那一个便是本身面临设计困难时候的觉得。小编早已无数1七遍那样化解自个儿的先后设计。

04     {

git的规划其实特其余简便,它的数据结构很平静,并且有拉长的文书档案描述。事实上,笔者丰富的倾向应该围绕大家的数据结构来统一筹划代码,而不是依照别的的,小编觉着那也是git之所以成功的因由之一。[…]
依小编的观点,好程序员和烂程序员之间的距离就在于他们以为是代码更注重还是数据结构更器重。

在高大的门类中,人们对不是和谐支付的模块并不打听,能神速明白其余模块中等高校函授数的适用含义才能增加开发成效。而C++引进的各样抽象则使代码卓殊依赖上下文,想清楚1段代码,必要看多得多的上下文。

面向对象语言以指标为主干,加一些相关联的措施,差不离是呓语。主要的事物应该是数据结构,对象自小编有何主要?真正有意思的,是在分化品种的例外对象交互而且有锁规则的时候。可是,就算是此时,封装什么“对象接口”也断然大错特错,因为不再是纯粹对象的标题了。

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

诙谐的是,那里有一篇别的一位长辈的很早的文字,推在 谷歌+ 上,来自 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

本身的确不了解那篇作品到底是或不是在搞笑。读了瞬间,小编即便很想说那不是1篇搞笑的篇章,可是,拜托,它根本正是。让我来跟你们讲讲他们在搞笑什么吗。

e…依据他们的口舌,小编应当称自身为 hacker
(黑客),不管笔者不爱慕这个。Hello! 你只须求二个小的不能够再小的 table

根本不需要怎样目的。朴素平凡,简单扩大,容易清除,(比起他们的那种设计)多
TM 不难。他们的 “hacker solution”
真的是又蠢又笨。他们写出来的那堆东西随处透漏着疯狂和笨拙。他们不够技术认知。

很强烈,OO 的狂热者们心惊肉跳数据。他们欣赏用言语也许协会器来初始化 tables
。他们一贯不写 table-driven 的测试。Why is this?
得有多大的心才会采纳用一体系并且多层的类华而不实,而不去用一个非常的小3行
table ? 作者1度听别人讲有人用种种 OO 的事物替换掉 while 循环。

可是好消息是,hierarchy-driven, keyword-heavy,
colored-ribbons-in-your-textook orthodoxy
这一个东东快绝望了。更加多的人采取组合而不是一而再。有个别人早已重新初步认识
OO。

面向对象编制程序语言,其本意是采用数据和连锁的行事进行编制程序,那是贰个很好的想法。事实当真那样。但是,这几个想法并不总是最棒的
idea。 这一个想法并从未完全的回味编制程序的世界。

Sometimes data is just data and functions are just functions.

— 罗布 Pike (Unix 创立者之1的 (Ken 汤普森, 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大师搞出来的代码,作者就要吐了。小编瞬间想到了两件事:3个是原先酷壳上的《面向对象是个骗局》和
各类流行的编制程序格局》中说的“设计格局驱动编制程序”,另3个自作者想开了那几个被高速洗过脑的程序员和咨询师,也是那种德行。

于是本人去看了壹晃首先小编Joseph
Bergin的主页
,这些Ph.D是果然刚刚形成了一本关于敏捷和格局的书。

Rob Pike的评论

(罗布 Pike是当时在Belllab里和Ken壹起搞Unix的主儿,后来和Ken开发了UTF-八,将来还和Ken一起搞Go语言。注:不要觉得Ken和Dennis是基友,其实她们才是当真的老基友!)

Rob
Pike在他的Google+的这贴里评论到那篇小说——

他并不认可那篇小说是或不是搞笑?可是她觉得那一个个写那篇小说是很认真的。他说她要评论那篇小说是因为他们是一名Hacker,至少这些词现身在那篇小说的术语中。

他说,那一个程序根本就不供给如何Object,只须求一张小小的配置表格,里面配备了相应的操作系统和你想出口的公文。那不就完了。这么简单的设
计,很是容易地壮大,他们充裕所谓的HackSolution完全正是古板的代码。前边这么些所谓的代码进化分外疯狂和鸠拙的,这几个完全误导了对编制程序的认知。

然后,他还说,他认为这么些OO的狂热份子分外恐惧数据,他们喜爱用多层的类的涉嫌来形成三个理所当然只供给摸索三行数据表的工作。他说她现已听他们讲有人在他的干活种用各样OO的事物来替换While循环。(小编传说中国Thoughtworks这帮搞敏捷的人实在喜欢用Object来替换全部的if-else语句,他们还是还爱好把函数的行数限制在十行以内)

她还给了三个链接http://prog21.dadgum.com/156.html,你能够读壹读。最后她说,OOP的原形正是——对数码和与之提到的行为开始展览编制程序。便就终于那样也不完全对,因为:

Sometimes data is just data and functions are just functions.

本人的知晓

自家觉得,那篇文章的例证举得太差了,差得感觉就像OO的高等黑。面向对象编制程序器重的是:一)数据和其一颦一笑的打包封装,贰)程序的接口和达成的解耦。你那怕,举3个多少个开关和四个电器的例子,不然就如STL中,一个排序算法对多少个例外容器的例证,都比那一个例子要好得多得多。老实说,Java
SDK里太多那样的事物了。

自小编原先给一部分铺面讲一些设计方式的培养和磨炼课,小编数十一遍提到,那贰三个经典的设计形式和OO半毛钱关系未有,只不过人家用OO来落到实处罢了。设计方式就多少个准则:1)中意于整合而不是一而再,2)正视于接口而不是促成,三)高内聚,低耦合。你看,那全然就是Unix的设计准则

相关文章