IoC/DIP其实是一种管理思想
关于IoC的的概念提出来已经很多年了,其被用于一种面象对像的设计。我在这里再简单的回顾一下这个概念。我先谈技术,再说管理。
话说,我们有一个开关要控制一个灯的开和关这两个动作,最常见也是最没有技术含量的实现会是这个样子:
然后,有一天,我们发现需要对灯泡扩展一下,于是我们做了个抽象类:
但是,如果有一天,我们发现这个开关可能还要控制别的不单单是灯泡的东西,我们就发现这个开关耦合了灯泡这种类别,非常不利于我们的扩展,于是反转控制出现了。
就像现实世界一样,造开关的工厂根本不关心要控制的东西是什么,它只做一个开关应该做好的事,就是把电接通,把电断开(不管是手动的,还是声控的,还是光控,还是遥控的),而我们的造各种各样的灯泡(不管是日关灯,白炽灯)的工厂也不关心你用什么样的开关,反正我只管把灯的电源接口给做出来,然后,开关厂和电灯厂依赖于一个标准的通电和断电的接口。于是产生了IoC控制反转,如下图:
所谓控制反转的意思是,开关从以前的设备的专用开关,转变到了控制电源的开关,而以前的设备要反过来依赖于开关厂声明的电源连接接口。只要符合开关厂定义的电源连接的接口,这个开关可以控制所有符合这个电源连接接口的设备。也就是说,开关从依赖设备这种情况,变成了,设备反过来依赖于开关所定义的接口。
只要你看过我的那篇《面向对象设计其实和面象对象一点关系也没有》,你就知道这样的例子在生活中太多见了。比如说:
1)在交易的过程中,卖家向买家卖东西,一手交钱一手交货,所以,基本上来说卖家和买家必需强耦合(必需见面)。这个时候,银行出来做担保,买家把钱先垫到银行,银行让卖家发货,买家验货后,银行再把钱打给卖家。这就是反转控制。买卖双方把对对方的直接控制,反转到了让对方来依赖一个标准的交易模型的接口。股票交易也是一样的,证交所就是买卖双方的标准交易模型接口。
2)上面这个例子,可能还不明显,再举一个例子。海尔公司作为一个电器制商需要把自己的商品分销到全国各地,但是发现,不同的分销渠道有不同的玩法,于是派出了各种销售代表玩不同的玩法,随着渠道越来越多,发现,每增加一个渠道就要新增一批人和一个新的流程,严重耦合并依赖各渠道商的玩法。实在受不了了,于是制定业务标准,开发分销信息化系统,只有符合这个标准的渠道商才能成为海尔的分销商。让各个渠道商反过来依赖自己标准。反转了控制,倒置了依赖。
可见,控制反转和依赖倒置不单单的一种设计模式,反而更是一种管理模式。
在大公司中,有很多很多的团队,这些团队开发的软件有很多依赖,跨团队合作是一件挺麻烦的事情,下面是一些比较真实的示例:
1)一个网页会有很多频道,于是,我们的前端工程师进入到各个页面为各种频道开发他们的页面,随着频道越来越多,前端开发工程师的人数也越来越多,每增加一个频道,就要增加一个为这个频道服务的前端团队,于是,人数越来越多,干成了劳动密集型。为什么不反转控制,倒置依赖呢?前端的同学完全可以开发出各种页面的标准组件,布局,模板,以前与后端交互框架,然后,让后端的同学反过来依赖于前端的标准,使用前端的框架,前端的布局,模板,和组件,以向前端接入后端的模块。
2)一个平台需要接入各种各样的业务系统,这些垂直业务系统都有自己的账号体系,于是这个平台为了要兼这些垂直系统的账号体系以做到权限控制,需要做各个系统和自己系统中的账号映射,并为账号和分配出来的资源设置各垂直系统的标识,还要在自己的代码中要写很多很多的依赖于各种账号体系的代码。其实,一个依赖倒置和反转控制就很简单。开发一个权限体系标准,让接入方的账号系统反过来依赖并控制这个标准的权限系统,从而做出一个干净的系统。
3)还有一个云平台中的管理模式,一些底层服务的开发团队只管开发底层的技术,然后什么也不管了,就交给上层的开发人员,在底层团队的开发出来的产品上面开发各种管理这个底层资源的东西,比如:生产底层资源的业务,底层资源的控制台,底层资源的监控系统。这个让底层团队只干纯技术,不干与底层技术无关的东西,看似很科学,其实是做错了。因为,上层为各个云资源控制生产,开发控制台和监控的团队,随着接入的资源的越来越多,完全干不过来了,苦逼得一塌糊涂,因为底层的资源千差百怪,每接一个就要开发一堆这个产品的代码。这个时候依赖倒置和反转控制又可以解决问题了。很简单,上层为各个云资源控制生产,开发控制台,和监控的团队应该制定一个标准,让底层的IaaS云资源开发团队反过来依赖这个标准,统一接入方式,如果开发的云资源不符我的生产控制模型,没有控制台,不把监控数据喂入我的监控系统,对不起,请不要接入我这个PaaS平台。
4)一个集中式的处理电子商务中的订单的流程。各个垂直业务线都需要通过这个平台来处理自己的交易业务,但是垂直业务线上的个性化需求太多。于是,这个技术平台开始出现了黑魔法——“为了害怕改变数据库表结构,不得不在数据库中预留一些字段,里面存把业务方的个性化字段存成如JSON这样的东西”,并为之自豪认为可以快速解决业务问题(WTF)。然而,恶梦并没就此结束,管理这个技术平台的小组开始发现,对来自各个业务方的需求应接不暇,各种变态需求严重干扰系统,各种技术决定越来越不好做,导致需求排期排不过来。于是,不单单得到了各个业务方的各种抱怨,最可怕的是还有高层老大们压过来的Deadline,加班加点,苦逼之极,最后业务方自己要去一个自己的平台。为什么不用依赖倒置和反转控制的思想呢?开发一个插件模型、工作流引擎和Pub/Sub系统,让业务方的个性化需求可以以插件的方式插入我的订单流程中,业务方自的数据存在自己的库中,业务逻辑也不要侵入我的系统,并可以使用工作流引擎或Pub/Sub的协义标准来自己定义工作流的各个步骤(甚至把工作流引擎的各个步骤的Decider交给各个业务方自行处理)。让各个业务方来依赖于我的标准插件和工作流接口,反转迭控制,让他们来控制我的系统,依赖倒置,让他们来依赖我的标准。(这个团队想过把自己的系统内部开源出去让别的团队也进来参与,可以是可以,但一定要用Linux/Git这种方式,允许出现多个分支,多个发行版。但多个版本又造成了多个业务平台,这会上上层垂直业务不知所措)
5)看过《SteveY对Amazon和Google平台的吐槽》的人都知道,Amazon内部系统的SOA架构(这个SOA架构离IBM定义的那个非常变态的SOA还有一定距离),但是这基本上都是依赖倒置和控制反转的思路了—— 与其让我来帮你实现你的业务逻辑,不如把我的业务逻辑开放成服务的方式让你来控制。
6)再说一个我在Amazon经历的例子。有一个项目是在给Amazon的各个商区(Marketplace)做国际出口的业务,我们先把Media类的产品(书,DVD之类的)做国际出口开放,项目不难,就是让商家同意一个法律协议(上传自己的签名),然后后台小改一下。美国的,欧洲的做的都没有问题,物流团队在出口报关单上打的都是Amazon仓库的地址和商家的签名(本来这就是错的,打的应该是商家的地址和商家的签名),但是到了日本,就出了问题,因为日本海关即要日文信息,也要商家的英文名和英文地址,而我们的系统里面只有商家的日文信息。本来,这是一个挺简单的事——数据库里加两个字段,在那个同意条款的网页上收集一下商家的英文名和地址,然后把这些信息传给后面的物流团队。物流团队一看这个,发现搞不了,因为他还要传给仓库,N多的地方都要加这两个字段,还要写下各种if (site == JP)这样的判断。物流团队不蛮干,重新设计自己的系统。做一个Document Template的东西,这个就是那个那个要贴在物流盒子上的单子。再也不让各个业务团队把那些信息传过来,而是把这个Document Template的东西传给上面的业务方,他们想怎么写就怎么写, 写完后,把这个东西传回来。于是,大家依赖了一个标准的协议,而不是一其字段。(当然,这个改动过多,为此改了半年多,不过非常值)
所以说啊,在跨团队的工作中,
- 如果依赖和控制的东西过多了,就需要制定标准,倒置依赖,反转控制。
- 控制欲望最好不要太强,不要想着能干所有的事情,要学会控制反转和依赖倒置原则。否则只会引火烧身。
- 反转控制和依赖倒置是一种智慧。
(全文完)
(转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)
《IoC/DIP其实是一种管理思想》的相关评论
通俗易懂,技术和管理都可以用的思想。
只不过不是所有的团队都愿意跟你来搞接口。
挺明白的
做技术完全可以倒置一下,给出各类文案的格式标准,让产品按照我们的格式来这样可以省事很多,还能减少交流障碍。
好像挺有意思的…
你好,我想问一个问题。依赖倒置原则在某些时候肯定能发挥很大的作用,如果把这个原则极端的在任何情况都使用,过度使用的话,除了每次使用某个类时要书写对应接口,比较麻烦外,还有没有其他副作用。
” 控制欲望最好不要太强,不要想着能干所有的事情,要学会控制反转和依赖倒置原则。否则只会引火烧身。”感同深受!
s/面象对像/面向对象/
写得真心不错
那个high一下,挺有意思的:)
程序里面的IOC还好办。开发团队之间的更或者开发商之间的反转可没那么容易。站在以你为中心的角度,你出一个接口,让别人(可能是多个开发商)依赖这个接口,那么他可能就要修改已有的代码。可是很可能多个开发商和你思考的一样,而且早就做好了各自的接口,让你来依赖。
配图很传神 哈哈
谁nb就依赖谁。。。
多对多的情况下就看谁给饭谁吃了T_T,可怜我们总是在依赖那一方。。。
获益良多,谢谢老大哈~~~
感觉作者写的不太对,IOC并不是DIP,这两个是有些区别的,他讲的例子只不过是DIP而已,这样有些混淆了IOC的理念。IOC要比DIP宽泛很多。可以参考martin的这篇文章
http://www.martinfowler.com/articles/injection.html
想起了子目录分层的故事
台湾电子代工业的繁荣可以做个例子。印象中代工是劳动密集型,处于产业链低端,附加价值低,利润少,竞争大。但像富士康和英华达经过几十年的经营,生产模式具备一定规模后就形成规模经济。以前Intel AMD找它们代工的时候都是提供设计图纸,根据设定的架构制定流水线;现在反过来,富士康对Intel说我们的流水线已经成规模了,而且是有统一标准的,如果你们架构根据我的流水线匹配的话,我可以提供世界上最有效率的生产力。搞得现在Intel、苹果等一堆芯片提供商设计时不得不参考下游的代工流水线标准。
想了一会儿,我觉得可以理解为“不断增加的需求”与“人为解决方案”之间的交互的一种管理。
开始时需求很少,每一个需求对应一种解决方案;而当相似的需求不断增加时,那么就需要不断的去开发新的解决方案。这时如果聪明的我们可以发现“新增的需求和已有的需求有共同点,可归纳为一类时”,就可以引入“标准规范层”,利用分层的思想,将线性增长的解决方案转换为一套“相似需求”的解决方案。
这和“多条相同指令变成一个循环”本质是差不多的。
陈皓老师,一直关注您的博客,也从中收益良多。今天这篇文章我发现了两处显著的错别字。
1.其被用于一种*面象对像-面向对象*的设计。
2.《面向对象设计其实和*面象对象*一点关系也没有》
好文
不依赖具体的上下层,依赖于共同的一个标准。
很好,通俗易懂。
皓哥写得好!不过现实中会有好多好多的限制和约束,真能让多方妥协去服从某个通用的标准也许不那么容易,至少在这个潜在的“通用标准”成为真正的通用标准之前。
Juven,也刚写了一篇关于DIP 的文章。这个话题怎么这么火了。
看着复杂啊;统一标准,管理复杂性,是讲这个吗?
读这个文章,更理解了标准化的意义。
皓哥,你这文被cnblog转了,而且还不说原作者!
go语言的interface?
好文。其实微软的很多设计思路,也都来源于windows系统的设计模式。说到底unix确实是集合c/c++所有设计范式。抽象出来,设计模式都是相同的,跑不了那几样。
今天看新闻《老太为证明自己健在6次赴派出所盖章》。这就是坑爹的依赖倒置管理模式?
@hongzy
向要知道老人是否健在,需要下去一个个访查,太累了,如果要求他们自己来报道盖章,那就省事了。spring的作者一定是在中国干过公务员
这种思想是好,就是从行政的角度执行太难。公司与公司之间的接口更是处理起来难操作。
对IOC和DP的解释完全错误。对light的举例只能说明在面向对象的处理过程中抽象不够,比如,如果只需要turn on和turn off,为什么会定义为light,这样的话,就依赖了不必要的特性,说明还需要更进一步的抽象,于是得到了switchable。这个和IOC、DP扯不上干系。
IOC和DP的解释实际上martin给得很详细,还是比较容易理解的。
初学者吸收中
@光荣的彼方
对,比如我们是做公司内部多个自动化运维监控平台的,理论上我们可以制定统一的标准来做监控,但是一是限于我们自己的设计能力,二是其他项目已开发了很多年,根本不会再按照我们的标准重写一些代码。所以觉得IoC要尽早开始,知易行难。
想法非常好也很科学,但实际执行时,却有不少无法控制的局面;就像上面其他人说的,每个团队都这么想,接口就太多了,总有主次吧,谁听谁,谁服从谁?还有时是用户懒得改代码,不愿按你的标准重写即使是不多的代码,或者上层业务不想干,并且每个团队都有自已的自主权,他听你的吗?虽然对整体有益,但不一定对某些人有益。我认为这最终还需要高层配合,有真正科学理智的领导层这一切才真正有效,否则也只是治标不治本,成为办公室集团的内斗。
反转控制和依赖倒置,这两个翻译名词,不恰当,容易把人弄晕。
Dependency Injection。
其实就是,原先依赖关系和运行时多态全都是代码决定的。现在把这块放到xml文件里写明。
工作并没有减少,只是一个转移。这个转移带来了一些好处。我觉得仅此而已。
皓哥,我对这个的理解是,当自己职责太多了的时候,分出去,给地方三方来做,任何问题都可以在中间加一个环节而变得简化,同时,也变得负杂。
看您的文章都挺有意思的,多谢您的分享。
这篇文章的配图超牛
反转实际上,也是让双方遵从了另一种无形的标准,且需在标准化与个性化上需要找到一种相对的平横。
管理的例子似乎都是“标准化”的问题,与IoC好像不是那么类似。
而“标准化”的确是西方思维的一个很有意思的特点,分解、标准、规范