接口隔绝原则(ISP)

接口隔离原则(ISP)

接口隔离原则(ISP

应当为客户端尽可能小的单独的接口,而不要提供大的总接口。

总觉得这个和“单一职责原则”很像,很多人都把它们分开来讲,我不想把它们分的太清楚,就当一种说法对另一种说法的诠释好了。

         个原则比较简单易懂,就是应该把接口细粒化,单位化,避免接口污染。这样做的好处也很明显,接口就相当于对外界的承诺,你愿意对外界承诺的更多还是更少呢?其次,从美学上讲,这是一个污染问题,虽然不可能将美学纳入设计原则中,但是鄙人就喜欢做什么都干干净净、优雅利落,是个典型的完美主义者。

         虽然ISP很好理解,但是实际中却常常被忽略,我经常会在公司里的代码中看到一个总的大接口,更要命的是它是从很多单位化细粒化接口继承过来的,而往往消费这个接口需要实现它所有的方法,这就诱发程序员偷懒行为:将不需要实现的方法置为真空状态(即里面什么都不写)

         定义接口通常我们会以职责来划分,一个职责一个借口,不要将多种职责放在同一个接口里,评判的标准是:你的接口是否仅仅因为一种原因而改变?但是“职责”是一个没有标准化的术语,实际项目中,100个人可能有98个人都有不同的职责看法(另外两个人看了此文章)。下面我举几个简单的例子来展示当我们遇到问题时,接口隔离原则为我们带来的好处。

第一,             如果我将两种或两种以上的职责都放在一个大的接口里,如果有一天我发现只需要其中的一种职责就可以了,那我们难道就强制它实现这个接口,然后将它不关心的职责真空化吗(就像上面说的,将不需要实现的方法置为真空状态,那就只能说明你这个接口包含了过多的职责)?

第二,             如果哪天我们发现其中有一个职责改变了,那么我们是不是要忍着牵一发而动全身的悲剧而修改这个接口呢?比如考虑手机通信这个接口,它有拨打电话和挂电话等操作,姑且我们把它看做协议职责,它还有通话,回应等操作,姑且我们把它看做数据传输职责,现在我们的手机都是2G的,哪天换成了3G的,视频通话的,那不仅仅是语音数据的传输,还包括视频数据的传输,那是不是我们必须要改动这个接口了呢?想想一下,有多少个类实现了这个接口我们就相应的修改这些类,如果我们开始的时候就定义为两个接口,两个职责,这个时候是不是就只需修改实现了数据传输接口的类就行了呢?

第三,             如果你在写一个API组件,需要对外界提供一个借口供二次开发人员使用,我想,你肯定不想对外界做出更多的承诺吧,那么,就把你的接口单一职责化吧。

总的来说,我觉得有一句话概括很帅气:“我单纯,所以我快乐”。简简单单,清晰明了,分工明确,细粒度低,何尝不好。这句话不仅仅适用于接口,对类和方法也适用,当然,具体情况视具体项目而定。比如考虑一个修改用户信息的方法,它根据传入的type不同,分为修改用户名,用户密码,用户。这种方法细粒度怎样?如果这个方法出问题了,受影响的功能会波及修改用户名,修改用户密码,修改如果你所有对用户信息的修改都放在了此方法里,那么所有的用户信息修改都将会受到影响,这不是开玩笑的。而且,这样的代码不是自解释性的,可读性也不好,也不够复用性。

举一个亲身经历的例子,我有一个需求,判断当前的设备实际类型(你可以认为是电信设备)和当前用户配置的网元类型是否一样,相信很多人都会去写一个返回truefalse的方法,这是不恰当的。因为你这个方法包含了两个职责:1.得到设备实际类型2.比较当前的实际类型和用户配置的类型是否一样。所以应该只需定义一个方法即可,它仅仅是得到当前设备的实际类型,然后返回给你,你在主程序中再去判断。这样做的好处是,如果有一天,我需要在程序的另一个地方得到当前设备的实际类型,那么你写的这个方法就不能复用,必须再写一个这样的方法才行。这是多么的纠结啊,所以,我单纯,我快乐。

原则是死的,人是活的,凡事适当就好。