yii模块可以处理两种问题
当yii 核心开发组开发模块时总是会兼顾这两个目标。更普遍地,社区开始使用模块来归组功能而不是隔离(这个比较好理解,因为合适的隔离很难做到)。如果模块是隔离的,它从不会使用它之外的东西,如果需要一些功能,它会提供一个让使用它的模块实现的接口。也同样适用其他方面 比如,模块之外使用模块内部功能被习惯性地严格限制为通过模块的接口访问。
对于模块耦合 通过接口作为协议。比如 在article模块 每个post有一个作者,我们在文章后想显示作者名字。因为我们不想耦合到特定的用户实现上,此时引入article模块提供的接口:
interface ArticleInterace
{
public function getAuthorName();
// ...
}
inteface ArticleRepositoryInterface
{
public function getById($id);
public function getPage($page);
}
之后在本模块 我们只使用接口并提供一种在模块配置中设置ArticleRepositoryInterface的方式。 当模块被使用时,开发者必须实现这些接口,这经常比较简单,直接。并且如果接口设计的比较好 。 会提供很出色的灵活性 。
译自Modules in Yii -- by samdark
本文由 yiqing 创作,采用 知识共享署名 3.0 中国大陆许可协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。
翻译过来 的 有些不太好理解 ,实际就讲了两个问题:
模块的用途
如何使用模块 两种用法:
把相似函数 聚集起来 形成一个名空间 抱成一个模块
跨项目重用 做为微系统重用 比如用户 评论模块 这些经常每个项目都用的
模块间依赖 通过接口解耦 基本思想就是模块间引入接口来解耦模块的互相访问 不要直接粗暴的使用另一个模块内部的功能 所有功能应该在模块边界完成( 通过模块配置注入 , 或者通过模块自身提供接口供别的模块使用) 你把模块看做是一个对象 对象具有隐藏 封装 (继承可以先不考虑)特征 所以对象内部的东西你需要使用公共方法来访问(最好定义接口 接口是契约 是应该长期稳定的东西 不应该经常变动 如果不提供接口 其他模块访问本模块 是零散的直接访问 而随着时间的变化 这种公共方法会因为需求而变化(比如 参数类型 名称 个数 返回类型 抛出的异常等等 都会变化) 所以有必要先定义接口 这样先使通信协定稳定下来 不要经常变动 。 这样要求你在设计模块对外的方法时需要仔细斟酌(模块也有一些是给内部用的属性和方法) 而不是拍脑袋乱写,这也就是 接口即契约的思想--共识达成不到万不得已就不要瞎变 给你提供了一个警戒线)
@yiqing 来个完整的module代码,带有接口契约的demo。
talk is cheap show me the code please !
文章原文:基本思想就是模块间引入接口来解耦模块的互相访问 不要直接粗暴的使用另一个模块内部的功能
@yiqing
个人理解如下: 我认为这句话有错误歧义,可能,yiqing的意思是:先定义好接口方法,然后实现接口方法,然后A去实现的接口方法拿数据。而不是,A直接做了一个提供数据的方法,B直接调用A提供的方法。
下面我发表一下个人的认知:A的行为 依赖于B的一些方法,但是B还没有开始做,所以,我们先通过接口实现定义各个空的方法,用来拿数据,大致的意思,我用一个比喻形容:A和B是革命党,A是军方,需要用服装,B是生产方,必须等B生产好了,B告知A到哪里拿服装,哪里拿鞋子,A的服装队伍才能去拿衣服,也就是A依赖于B的信息,现在有了契约,A直接告诉B衣服放到哪里,鞋子放到哪里,而且还有相应的生产尺码,A到时候去拿,等B生产好衣服鞋子的时候,按照契约C,直接把衣服和鞋子放到相应的地方,对于A来说,有点皇帝的味道,到了时间,直接去拿衣服鞋子,另外一个比喻:税收就像接口,定义好了大家都要交税,国家就是定义接口的主体,原来是农民B生产了粮食,A去拿粮食,A有点要饭的味道,因为A依赖于B,现在通过税收契约,直接规定B必须上交,不按照接口规定就办了你(报错退出),A有了皇帝的味道。通过这个例子我们可以看到,原来是A依赖B,变成了,A定义C契约(接口),B依赖C,这样由A依赖B,间接实现了B依赖A。这就是接口的作用。在产品设计方面可以颠倒主从依赖关系,有点控制反转的味道。
也就是让两个彼此影响的个人,通过接口,让其依赖相互颠倒
通过调用接口有什么好处呢?看似很啰嗦。我认为好处有如下几点: 1.在程序设计,尤其是产品,如果A依赖于B,A是产品的一部分,譬如用户组件(user component),B是用户自定义(譬如user,User extends ActiveRecord implements IdentityInterface),按照常理,需要B先行,然后A在行动,但是呢?在产品中,我们需要A先行动,B在行动,这就需要A行动的时候,告诉B,你如何如何,这就是接口,告诉B要实现那些方法,A在B没有的情况下直接使用B的方法,然后强制B实现这些方法(通过接口),这样通过契约接口颠倒了依赖,在程序实现上,完成了解耦, 也就是说,接口是使用方定义的,而不是提供方定义的,这个有点像客户让工厂加工某些东西,提供了图纸一样,如果B不按照图纸,A就不验收,就报错退出。 2.个人认为接口一旦存在,就是强制执行,除非法律更改(接口改变),在工作当中,为了扩展,经常的对某些方法进行修改,譬如 方法的参数增加了个数,由于php不想java那样,还可以限制传入的参数类型和返回的类型,所以php的接口限制要弱一些。不过还是比较有效,可以限制开发者脑门一热,方法增加参数,或者把这个函数名改变了。
总结:接口的作用,1:可以解耦,我个人认为更确切的是,接口可以让依赖关系颠倒,原来是a和b的关系(a依赖b),变成了a和c(a定义c),b和c的关系(b依赖c),其中c是接口,通过中间层c,间接让b依赖a,有点控制反转的味道。 2.接口,定义类的某些方法不能更改方法名和方法传入的参数。
工作顺序的颠倒: 两个人合作做一个功能,A和B分别做2个模块,A是消费方,B是生产方,原来的先后顺序为: B生产出来一个方法,告诉A调用这个方法,来消费B生产的方法,
变成了:A定义个接口C,然后A使用C接口里面的方法实现了自己的功能,然后把C接口扔给B,让B去实现这个接口。
由生产方做主导的工作顺序,转变成消费方做主导的工作顺序。