> For the complete documentation index, see [llms.txt](https://www.doruby.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.doruby.com/mobile/modularization/mo-kuai-hua-she-ji-ios-tuan-dui-xie-zuo-kai-fa.md).

# 模块化设计-iOS团队协作开发

### 现状&#x20;

当项目发展到一定阶段，功能会变得越来越庞大，修改一个功能可能有牵一发而动全身的感觉，维护变的相当吃力。如果只是扩充项目成员的话，协作也会成为一种障碍，人多反而不能提高生产率。 如果只是一、两个成员开发的项目还好说，之间的沟通与协作更加灵活而松散，也许吼一嗓子就可以完成。 但如果人员也从几个到十几个，甚至几十个。就不能再靠传统流程开发了，需要更深入系统架构层面将大家工作进行规范与限定，制定标准。

这个时候我们就需要更好的架构设计应用，使得开发与协作变得更加高效，功能的耦合性变得更小。在设计领域有一种概念是模块化设计(Block-based design).

按此概念的意思是说 "对一定范围内的不同功能或相同功能不同性能、不同规格的产品进行功能分析的基础上，划分并设计出一系列功能模块，通过模块的选择和组合构成不同的顾客定制的产品，以满足市场的不同需求"。ok, 这正是我们想要的结果.

### 模块化

模块化设计也是绿色设计方法之一,所谓绿色设计是指"在产品整个生命周期内，着重考虑产品环境属性（可拆卸性，可回收性、可维护性、可重复利用性等）并将其作为设计目标，在满足环境目标要求的同时，保证产品应有的功能、使用寿命、质量等要求".绿色设计的原则被公认为“3R”的原则，即Reduce,Reuse,Recycle，减少环境污染、减小能源消耗，产品和零部件的回收再生循环或者重新利用。

无论是从工业设计还是软件设计，实际上都是尊崇以上的原则。注意上面几点，可拆卸性，可回收性、可维护性、可重复利用性. 我们就从这里入手重新设计。(PS:无畏的重复开发也算是一种能源消耗吧，嗯，至少我们也是爱护环保人士)

从以往开发Web应用的经验来说，模块的划分可以从业务层面或功能层面上决定。业务层面上，你可以将不同的业务划分成各个子模块，好比公司的各个职能部门，事业一部，事业二部，后勤部门，人事部门等。从业务的层面上划分，会使得各个模块更加独立，不用和其它的部门打交道也能完成日常的事务。不过缺点是，一些如果处理公共的事务将会变得繁琐。 另外一个选择是从功能层面上，比如资料管理，订单管理，财务管理等,优点是职责清晰，不过缺点就是各管一方，事务缺少连续性。

举个实际的例子，有一个功能需求是查询与记录，查询有食物查询，运动查询，体重查询等等。对应的也会有食物记录，运动记录，体重记录。 如果从业务上划分可以是食物管理，运动管理，体重管理，各自记录各自的信息，各自独立，互不干扰。可在一个地方就完成所有操作。但如果现在我们要收集所有的记录信息，并且各自还需要一些协作完成操作的话，这样各个功能之间的协调就会变得困难。 所以还有一个方法是按功能来划分，查询模块，记录模块， 查询模块只负责查询，查询的类型分为三种，然后需要记录的时候将信息传送到记录模块，进行一并记录。这样的好处是当我们职责各加清晰，信息统一。

无伦从哪个角度来划分模块其实都有各自的优缺点，我们需求上来设计实际的项目，即使他们功能独立，减低耦合，又要使得信息的流转变得简单。 理论讲的差不多了，我们这里除开项目管理的基本要求，比如开发文档，注释规范，各种图等不提，拆分的方式根据你自己的业务需求自行选择拆分方式，这里只讲讲开发中如何协调和整合它们。 好吧。下面上干货了。

### iOS 团队开发实践&#x20;

我们先把现在遇到的问题列出来，然后一一解决。

**问题:** 以往各个模块整合在一起时，功能之间的调用基本是通过 import 某个类的接口头文件完成.这样使得某个功能会非常依赖另一接口的实现，假如有一天，一个专门负责这个接口的人换了实现方法或这个接口就不存在了，而又没通知到引用的人，就会发生错误，你也许会说，可以保留原有接口，加上即将作废的提示，然后用替代方法进行转换。或直接告诉团队的成员，使用新的 sdk 等。 但这些操作如果变得非常频繁或不确定就会成为障碍。

**解决方案:** 在Rails 框架中有一个叫 Routes表的文件，用来将用户的Web请求定位到某个Controller的某个Action. 我们是不是也可以将调用看作是用户的一次 Web 请求呢。只要存在这样一张 routes 表，就可以将这个请求映射到指定的路径。 所以首先想到的是有一个专门的职能模块去构造这张表，然后维护它，相当于cocoa里的 notification center。 不过和 notification center不同的是，我们的这个 routes 表，也可以称为规则表是在应用启动时就已经创建好了的。相当于智能路由器已经配置好不同的路由方向一样。如何构建这张表呢，同样在Rails里也会有引用第三方的 Plugin 概念,我们也可以把各个模块看作 Plugin，Plugin自己定义自己的路由规则，然后由 route center将所有的规则合并在一起，如果其中一个模块发生变化，只需要改写自己的routes即可，不需要通知其它引用的人，除非你的命名规则发生变化。

接下来如何构造这个请求呢？通知机制，也就是 notification , 相当于你吼一嗓子，我要去干嘛干嘛,谁来帮我处理。然后 route center 会接收此请求，根据里面的规则转送到指定的模块中处理，这样就减小了他们之间的相互依赖。

在具体实现时，还会有线程选择、广播或点到点方式、立即返回结果等规则的定义。不过需要注意的是可能发会生的广播风暴。

![one\_block\_based](http://blog.ydio.com/wp-content/uploads/2013/04/one_block_based.png)
