吐槽:好莱坞原则

这是吐槽版的《什么是好莱坞原则》,移到垃圾桶。请参考什么是好莱坞法则(2016-06-25 12:42)

 

《编程导论(Java)·9.3.1回调》中,介绍了好莱坞法则/好莱坞原则(Hollywood principle),第287页

 

  • Hollywood principle:"Don't call me; I'll call you."      (don't call us, we'll call you)

对于好莱坞原则的解释,在各种书籍、文献中极其混乱。本文介绍《编程导论(Java)》中对好莱坞原则的解释,以及为什么要这样解释。不可避免地,本文会把一些著名文献中的解释作为反面例子。

(重写  别了,DIP、IoC

不懂递归,不要说学过算法;
不懂回调,不要说学过编程;


1.引子:多态

图1 依赖于抽象类型、针对接口编程、遵循OCP 代码的基本结构

Client中有方法test(),代码为:

 

IServer s = new Server();
s.foo(5);


对上述代码的解释:“s被初始化后,将按照s指向对象的实际类型(即Server),动态绑定foo()的代码块。”

 

这是面向对象中对于多态的基本解释方式(后面的讨论,将涉及到这一解释)。这里,yqj2065设定了一个前提

不喜欢对上述代码的其他云山雾绕的解释!

2.回调

在分层结构中,上层依赖于下层,最后依赖于基础设施(如JDK、各种框架)。因为 依赖必须是单向的
 
请注意:按照 依赖的单向性,又因为子类依赖父类,所以:如果两者不同层,子类必须为上层模块。
 
 
之所以需要 回调callback、隐式调用 Implicit invocation(某些软件架构的作者使用的术语),是因为分层结构的 一条线的存在,如图2所示。
图2 回调的应用场景
 

 

回调与通常的非回调代码,从类图和其自身代码上,没有区别——都是调用下层模块的一个接口。非回调代码(如果不考虑OCP),如图1所示的Client,可以直接依赖于(具体类型)Server;而在图2所示的回调的应用场景中,上层的Client直接依赖于下层的Server,但是下层的Server不能够依赖Client,问题是:Server需要调用上层的Client的方法callback,怎么办?

 

因而不得不在下层(Server所在的层或更下层、或基础设施/框架中)定义一个Client的父类型,如接口IClient 或IXxx,结构如图3所示。

图3 回调的基本结构 

 

  1. 【请比较图1和图3】回调与通常的非回调代码,从类图和其自身代码上,没有区别。
  2. (为了使用回调)回调机制不得不在下层(或基础设施/框架中)定义一个Client的父类型IClient或 IXxx,它定义了回调callback(int)的方法头(方法的接口)
  3. (Java中)回调与通常的(遵循OCP 代码的)非回调代码,使用的技术不过是动态绑定/多态。

3.我的好莱坞法则

"Don't call me; I'll call you."  
现实生活中,乘客/you打的士到某地,沿途问司机/me某个景点,天经地义;但是,乘客/you不要从上车的第一秒开始,时时刻刻或每隔5秒问一下司机/me:到了打的的目的地没有,这也太烦人了。
 注意:好莱坞原则中的 me是指 下层模块
 
通常,Client即you(上层模块)调用下层Server即me天经地义,但是,对于某些方法, 你不要轮询/骚扰我,我通知

 


 

 

4.类层次与好莱坞原则

一些著名文献中的反面例子。
 
反面例子之一:
http://www.as3dp.com/category/design-patterns/ template-method-pattern/
 
“Be sure to go over the more detailed post on the Hollywood Principle, but for here, you just need to become familiar with the idea that higher level components (like parent classes and interfaces) should call lower level components (like concrete classes), but lower level components, should not call higher level components. The principle is called Hollywood, because the casting director tells the budding actor,

Don’t call us, we’ll call you.

The parent class tells the child class the same thing.”
驳斥:
  1. 上文中的下划线部分本身就是错误的。画类层次时,可以说父类型是higher level components,蛋是,从依赖关系上看,按照分层和依赖的单向性子类是上层模块、父类是下层模块(如果不在同一层的话)。例如父类是JDK或框架中的某个类,而子类是你的应用中的类。因为子类(必须的)依赖父类型,你不可能将父类型放在上层,而让下层(的子类)依赖于上层
  2. 如“1.引子:多态”所言,有动态绑定,在类层次中使用回调、好莱坞原则的解释是一种极其无聊的解释,而且令人困惑。
  3. 按照他的说法,(不管他的like...)好莱坞原则“应该”意味着“上层调用下层而下层不得调用上层”;对啊,但是,而这一“上层调用下层而下层不得调用上层”,我们称之为单向依赖,不需要搞一个多此一举的“好莱坞原则”作为单向依赖的同义词。当然,如果上层模块说"Don't call me; I'll call you.",也非常符合该字面的解读,这种上层模块所说的好莱坞原则,和白开水一样,没有营养。
 
反面例子之二:[设计模式]
 
“模板方法导致一种 反向的控制结构,这种结构有时被称为 “好莱坞法则” ,即“别找我们,我们找你”[ S w e 8 5 ]。这指的是 一个父类调用一个子类的操作,而不是相反。”
 
驳斥:
  1. 不管模板方法的细节,如“1.引子:多态”所言,s.foo(5)动态绑定,完全不需要”父类调用子类的操作“的说法。通常,父类不可能知道子类的附加的操作;对于override方法,那么s.foo(5)是Client调用IServer的foo然后IServer调用子类Server的overridr方法foo?
  2. [ S w e 8 5 ]的原文:Don't call us, we'll call you (Hollywood's Law): A tool should arrange for Tajo to notify it when the user wishes to communicate some event to the tool, rather than adopt an 'ask the user for a command and execute it' model.",和本文的【3.好莱坞法则】一致,而非【设计模式】的滥用。
  3. 按照面向对象的一般概念,子类是一个父类,父类动物有eat()方法,那么我们喂狗吃的时候即new Dog().eat(),有没有人说:”我喂动物吃,而动物调用狗的吃方法“,”我又喂动物吃,而动物调用猫的eat()方法“?太别扭了。
 
反面例子之三:[敏捷软件开发]11.2.1接口所有权倒置:
Don’t call us, we’ll call you。 低层模块实现了在高层模块中声明并被高层模块调用的接口
驳斥:
  1. 如果(类层次)低层模块=(分层结构)上层模块,(类层次)高层模块=(分层结构)下层模块,没有问题。
  2. 在分层结构中,上层依赖于下层,依赖必须是单向的。他的书中的图11.2除了看起来有点道理外,层次真的能够”倒置“吗?假设图11.2中的Utility是JDK或某个框架,你倒置给我看看。
  3. 他的书中的图11.2中的三个包,如果忽略policy、mechanism和Utility的寓意,从上到下事实上是Utility-mechanism-policy的普通结构,从结构上没有任何特别的地方;如果强调policy、mechanism和Utility的寓意,而且按照依赖的单向性,父类必须是下层模块,因而图11.2并无意义,实践中接口所有权倒置,其意义下图所示。通常将所谓的”policy server interface“等放入公共模块(而非好看地与Policy Layer放在一个包中)。总之,依赖关系没有变化,DIP的“倒置”没有什么营养。从软件开发管理的角度,DIP或许有启发意义,但是DIP既不是架构设计的原则,也不是面向对象类关系的设计原则。
  4. 接口所有权倒置,其意义如图3:
            
    传统3层结构
    接口由BLL定义(所有权上移),但是BLL作为Mapper的下层模块。
 
反面例子之四:
http://c2.com/cgi/wiki?HollywoodPrinciple 
”Hollywood Principle is often called InversionOfControl, or Dependency Injection.
说明:
1.回调机制、好莱坞原则是框架设计的基本手段。即使勉强接受IoC是好莱坞原则的同义词,但是依赖注入、事件驱动编程/GUI,RMI等等,都是回调机制、好莱坞原则的应用。
2.用于事件驱动编程/GUI中的好莱坞原则,与依赖注入一毛钱的关系都没有。
 

5.小结:谁的好莱坞原则

如果站在上层模块的角度,即me是上层模块,所说的好莱坞法则是对的,它反映了分层结构的依赖单向性。(没有再讨论的话题了)
如果站在下层模块的角度,即me是下层模块,所说的好莱坞法则是对的,它是框架设计的基本原则。相关术语有:回调、GUI编程/事件驱动编程、观察者模式、依赖注入、分布式编程(RMI中也经常使用回调机制)、隐式调用、(控制反转)……Java的匿名类,C++的函数指针、C#的λ表达式……
 
 
参考:
http://en.wikipedia.org/wiki/Implicit_invocation
 
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 19
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值