iOS程序模块化设计
一、模块化设计的概述:
模块化设计(Block-based design):对一定范围内的不同功能或相同功能的不同性能、不同规格的产品进行功能分析的基础上,划分并设计出一系列功能模块,通过模块的选择和组合构成不同的定制产品,以满足市场的不同需求。
模块化设计是绿色设计方法之一,绿色设计是指“在产品整个生命周期内,着重考虑产品环境属性(可拆卸性、可回收性、可维护性、可重复利用性等)并将其作为设计目标,在满足环境目标要求的同时,保证产品应该有的功能、使用寿命、质量等要求”。
绿色设计的原则被公认为“3R”的原则,即Reduce,Reuse, Recycle, 减少环境污染、减小能源消耗,产品和零部件的回收再生循环或者重新利用。
二、 模块化设计的特点:
- 控制了程序设计的复杂性:模块化设计将整体进行切割封装,每一小的功能即可封装成一个小的模块,独立运行,互不影响,控制了整体的复杂性。
- 各模块相对独立、功能单一、结构清晰、接口简单:模块化后的代码相对独立,功能单一,只在外部提供必要的接口供外界调用,内部的实现过程,隐藏在内部,面向对象的接口编程,使得结构清晰,接口简单,能达到高内聚,低耦合的效果。
- 通用性:模块化设计需要保证抽出来的功能无论是在SDK支持的功能上还是屏幕尺寸的适配上都用灵活性的方法来封装,这样才能保证应用能够部署在支持的最低系统版本基础上的同时,适应不同屏幕的适配。
- 避免程序开发的重复劳动:每个项目中,都会或多或少的涉及到相同的功能和UI界面展示,将这些相同的功能或界面UI进行模块化,无疑是能避免程序开发的重复劳动,同时也能够提高编码的质量。
- 缩短了开发周期:将项目中涉及到的功能和UI界面提前进行模块化后,需要用到时直接调用,进行组装,能缩短开发周期,同时也能避免资源浪费。
- 易于维护和功能扩充:因为将整体的功能进行模块化,使得每一个功能只是一个小的功能点,相对来说,更易于维护。有新的需求,需要增加新的功能点,也方便统一扩充,之前模块化好的代码也无需改动,易于维护。
三、模块的划分:
模块的划分可以从架构层面、业务层面或功能层面上进行划分:
(一)架构层面:
每个项目都会有整体的架构,这个架构就像地基一样,只有搭好了架构才能在这个基础上进行相应模块功能的开发。项目架构在搭建的过程中,从层级上来说,可以按以下方式进行搭建(以下为有名服务的架构):
项目目录“UrMingService”,主要开发工作区域下,整体分为“Classes”, “Resources”/ “Tools”和“Supporting Files”三个大的目录:
1、在“Classes”这个目录下每个模块又按MVC的设计模式进行搭建,进行分门别类,方便管理,也增加了代码层级的可读性,我们在“有名服务”的项目中分为“首页”、“消息”、“发布”、“订单”和“我的”五个大模块,搭建架构时,在这几大业务模块的基础上,增设一个“Public”模块,这个模块里面主要是放置一些项目最上层级的基类或公共类,比如导航栏和底部标签栏整体风格的设置等,也可以用MVC的模式进行层级化管理。
2、“Resources”/ “Tools”这个目录下,主要是分门别类按功能进行封装好的工具类和整个项目会用到的图片资源,对于图片资源放置的层级目录可以按大致分为:引导页、导航栏、标签栏和展示类。
3、“Supporting Files”这个目录下,主要用于放置整个项目会用到的本地文件,应用icon和启动页图片管理的“Images.xcassets”,系统全局配置文件,国际化文件等。
(二)业务层面:
业务层面的模块划分跟产品设计的业务模块划分有关,可以将不同业务划分成各个子模块,这是相对整体又独立的划分,比如“有名服务”中我们将业务模块划分为“首页”、“消息”、“发布”、“订单”和“我的”,每一个相对独立的业务模块组装在一起,完成了“有名服务”所要展示的主题与业务。
业务模块的统一与业务模块之下的UI界面风格的统一有利于打造一系列同类风格的产品,这样可以在架构与功能模块化的基础上,将同类产品进行整体的模块化,实行工厂化定制开发。
优点:从业务层面上的划分,会使得各个模块更加独立。
缺点:处理公共的事务将会变得繁琐。
(三)功能层面:
功能层面的模块划分,是为了功能独立,实现高内聚,低耦合。每一个小的功能模块能运行,能调试,能测试,各个功能之间基本是完全独立的,不存在相互依赖的关系。
但是功能是与业务无法分割的,我们在开发时,需要宏观的把控业务与功能之间的关系,对于相似的业务模块,需要统一区别开发,协作完成,防止出现重复做工。
优点:职责独立清晰。
缺点:各司其责,缺少连续性与宏观性。
四、 常见问题及解决方案:
1、问题:相同功能,多处使用。
解决方案:将各个功能按职责剥离出来,各自开发各自的功能模块。
能独立运行,能编译为静态库,有完整的内部接口文档。
符合:可拆卸行、可回收性、可维护性和可重复利用性。
2、问题:如果模块拆分后,各个模块经常会有第三方库的依赖,比如公共库等。如何避免重复引用及引用版本的问题。
解决方案:用CocoaPods软件解决。
第三方的依赖全部由它自带的podfile配置完成,它会根据项目中引用的第三方打包于项目中,如果遇到多个重复引用时,它将会合并引用。我们的各个模块也可以做成独立的podspecs文件,供其他模块引用,这样就可以实现模块的升级与更新。
3、问题:功能模块化后,每个模块的具体功能是怎样的?
将应用程序中的功能分解为独立的模块,这带来了一个新的挑战——我们需要确保这些互不依赖的零件们能够在一起工作。
一个模块系统的另一个特点是外部依赖的声明。很多组件对外部条件有一定需求。使用依赖模式来维持模块系统中组件之间的依赖性有一个大前提,那就是我们必须遵循一系列的规则:
第一个规则是向后兼容性:如果新版本发布,那么所有在之前版本下可建立的契约也必须能够在新版本下工作。
第二个规则是,系统中的组件需要准确的说明它们需要什么。当一个模块的依赖性产生改变的时候,它必须要说出来,这样系统才能够准确的确认这些依赖性是否被满足。
五、模块化设计综述:
模块最重要的属性是它们应该尽可能的独立和自包含;模块应被设计成可以提供一整套功能,以便程序的其它部分与它清楚地相互作用;模块提供的功能必须是完整的,以便它的调用者们可以各取所需。
模块化就是为了减少循环依赖,减少耦合,提高设计和开发的效率。为了做到这一点,我们需要有一个设计规则,所有的模块都在这个规则下进行设计。良好的设计规则,会把耦合密集的设计参数进行归类作为一个模块,并以此划分工作任务。而模块之间彼此通过一个固定的接口(所谓的可见参数)进行交互,除此之外 的内部实现(所谓的隐参数)则由模块的开发团队进行自由发挥。
最后但也是重要的一点:方法命名的规范性很重要,注释很重要,如果没有注释只有开发者心中很清楚,所以必要的注释会给后期的代码维护工作带来便利的同时也提高效率。每个界面的主要是用于做什么的,可以在头文件中适当进行说明,如图:
参考文献:
http://doruby.com/projectmanage/2013/04/12/block-based-design/
http://developer.51cto.com/art/201001/179842_1.htm
http://book.51cto.com/art/201007/212898.htm
http://blog.csdn.net/newjerryj/article/details/7749901
http://blog.csdn.net/optman/article/details/2319450
http://blog.csdn.net/jyc1228/article/details/4636037