毋庸置疑的编程姿势。如此清楚面向对象编程。

毋庸置疑的编程姿势。如此清楚面向对象编程。

近期零星个星期,我使用 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地图