关于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的东西传给上面的业务方,他们想怎么写就怎么写, 写完后,把这个东西传回来。于是,大家依赖了一个标准的协议,而不是一其字段。(当然,这个改动过多,为此改了半年多,不过非常值)

所以说啊,在跨团队的工作中,

  • 如果依赖和控制的东西过多了,就需要制定标准,倒置依赖,反转控制。

  • 控制欲望最好不要太强,不要想着能干所有的事情,要学会控制反转和依赖倒置原则。否则只会引火烧身。

  • 反转控制和依赖倒置是一种智慧。

IoC/DIP其实是一种管理思想的更多相关文章

  1. 【转】IoC/DIP其实是一种管理思想

    原文转自:http://blogread.cn/it/article/6487?f=wb 关于IoC的的概念提出来已经很多年了,其被用于一种面象对像的设计.我在这里再简单的回顾一下这个概念.我先谈技术 ...

  2. 【Todo】Java学习笔记 100==100 & Reflection API & Optional类详解 & DIP、IoC、DI & token/cookie/session管理会话方式

    为什么1000 == 1000返回为False,而100 == 100会返回为True?   Link Java Reflection API:Link Java8 Optional 类深度解析: L ...

  3. 一个由正则表达式引发的血案 vs2017使用rdlc实现批量打印 vs2017使用rdlc [asp.net core 源码分析] 01 - Session SignalR sql for xml path用法 MemCahe C# 操作Excel图形——绘制、读取、隐藏、删除图形 IOC,DIP,DI,IoC容器

    1. 血案由来 近期我在为Lazada卖家中心做一个自助注册的项目,其中的shop name校验规则较为复杂,要求:1. 英文字母大小写2. 数字3. 越南文4. 一些特殊字符,如“&”,“- ...

  4. Spring IOC(二)beanName 别名管理

    Spring IOC(二)beanName 别名管理 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 一.AliasReg ...

  5. react-redux状态管理思想

    最近一段一直在加班做项目,几乎每天都要加班到晚上9点,每周也只休息一天,一直没有时间把eact全家桶,再整体熟悉一遍.索性,就在最近的项目中,借鉴了react-redux的思想,维护状态和发布acti ...

  6. 软件公司的两种管理方式 总体来说,这个世界上存在两种不同的软件公司的组织结构。我把他们叫做 Widget Factory(小商品工厂) 和 Film Crews(电影工作组

    软件公司的两种管理方式 一个简单的回答应该是——“因为在我们的社会里,我们总是会认为薪水和会和职位的层次绑在一起”.但是,这个答案同时也折射出一个事实——我们的薪资是基于我们的所理解的价值,但这并没有 ...

  7. sed匹配两种重要思想

    1,sed匹配两种重要思想 屏蔽思想:遮住不想要的 挑出思想:遮住所有,挑出想要的. 2,实例 屏蔽思想: [root@lanny ~]# sed -n '2p' file.txt |sed -r ' ...

  8. Spring IOC容器交给application域对象管理

    在项目开发中,我们不能在每次使用IOC容器时,都创建一个ApplicationContext对象, 因此我们将IOC容器交给application域对象管理,application对象在服务器启动时创 ...

  9. IOC初始化销毁的2种实现方式

    IOC初始化销毁的2种实现方式 1.bean内调用init-method 和destroy-method 2.通过注解实现@PostConstruct 和@PreDestroy ----------- ...

随机推荐

  1. write() ,read();

    int main1(int argc ,char *argv[]){ if(argc < 2 ) return 0; int fd = open(argv[1] , O_RDONLY); if( ...

  2. 常用的工具GCC GDB Make Makefile

    系统调用系统调用是操作系统提供给外部应用程序的一组特殊的接口.应用程序通过这组特殊“接口”来获得操作系统内核提供的服务.在 C 语言中,操作系统的系统调用通常通过函数调用的形式完成, 这是因为这些函数 ...

  3. 深入了解line-height

    1.定义   行高:两行文字baseline(基线)之间的距离 示意图: 2.为何line-height可以让单行文本垂直居中       其实并没有垂直居中,除非将font-size:0; 3.li ...

  4. Python3 模块

    为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式.在Python中,一个.py文件就称之为一个模块(Module ...

  5. svn-添加忽略文件

    svn ps svn:ignore '文件夹名|文件名(不能是文件夹/文件名)' . svn pe svn:ignore . export SVN_EDITOR=/usr/bin/vim #设置环境变 ...

  6. less学习-浏览器端编译(一)

    demo地址 http://www.qq210.com/shoutu/android 1.下载less包,官网 2.引入less文件 <link rel="stylesheet/les ...

  7. php 接口 implements 使用

    主要对类名,类所拥有的方法,以及所传参数起约束和规范做用,感觉跟php abstract 抽象类又有点像. 一,接口的定义和调用 <?php interface face1 { const pa ...

  8. poj 3304 Segments

    Segments 题意:给你100以内的n条线段,问你是否存在一条直线,使得题给的线段在这条直线上的“投影” 相交于一点: 思路: 1.先要将线段投影相交于一点转变为存在一条直线与所有的线段相交: 很 ...

  9. Uva 1354 Mobile Computing

    题目链接 题意: 在一个宽为r 的房间里, 有s个砝码, 每个天平的一端要么挂砝码, 要么挂另一个天平, 并且每个天平要保持平衡. 求使得所有砝码都放在天平上, 且总宽度不超过房间宽度的最大值. 思路 ...

  10. LightOj_1321 Sending Packets

    题目链接 题意: 给一个数据大小为S的数据包, 每一次发送需要K秒(单向),现在要从节点0 发送到节点 n-1. 其中有n - 1条路径, 每条路径都有一个传输成功率. 问传输成功所需最小时间的期望. ...