项目模块拆分总结

最近负责完成了公司项目中一个模块的拆分,在此做一个简单的总结,只总结从项目中把某个模块拆分出去的一点经验,不涉及整个项目的模块化工作。

主要步骤:

  1. 确认模块的范围。
  2. 将模块与项目中其它部分解耦。
  3. 将模块拆分出去,并作为一个独立pod,通过cocoapods引入项目。
  4. 为拆分出去的模块创建一个可供独立开发的demo。

确认模块的范围

要将一个模块拆分出去,首先应该明确这个模块的范围,它应该包含哪些功能、组件,这样才能将一个模块真正有效地拆分出去。如果一个模块拆分出去的范围太小,包含的功能或者组件不完整,会导致无法有效地独立开发,这就失去了一个模块化的意义。而如果拆分出去的范围太大了,这样又会带来不必要的冗余代码,甚至影响主项目的开发。

如果在之前的项目开发中,就已经有了模块化的意识,有意识的将各个模块之间的文件进行隔离,那这一步就会非常轻松,否则模块的代码分散在各处,这时要来理清这些文件的关系会有不小的麻烦。

解耦

发现依赖

确认了一个模块的范围后,接下来最重要的一件事就是要把它和项目其它模块解耦,而要实现解耦,第一步就是找出它对项目中其它文件的依赖。

找依赖关系比较有效的一种方式就是写一个脚本,分析引入的头文件,找出既不属于本模块,又不属于第三方库的头文件,这样用脚本跑一遍就能找出所有用#import方式引入的外部头文件。

但这里有两个坑,因为我们项目中并不是所有的头文件都是通过#import方式引入的,有两种特例。

  • 一种是是在oc文件中,通过Project-Swift.h文件引入的依赖,这个文件引入的主要是对Swift文件的依赖,但也有可能夹带oc文件的依赖。
  • 另一种情况是这个模块中的Swift文件中的依赖。Swift文件中的依赖,并不是通过import方式来引入的,所以比较难发现。这里又有两种依赖,一种是通过桥接文件对oc的依赖,还有一种是直接对Swift文件的文件。

以上两种特例,目前我也是通过手动去找依赖关系的。如果Swift文件比较多的话,会相当麻烦。

思考:如果以后大规模使用Swift开发,如何来管理Swift的依赖关系。

清理依赖

有以下几种方式:

  1. 如果依赖链很短,可以直接将依赖的文件放入模块中。比如模块依赖了外部的一个a.h文件,而a.h没有其它的依赖,就可以直接将a.h文件放入模块中。
  2. 如果依赖链很短,但有不方便将文件移入模块中,比如会有其它模块依赖它的情况,那可以将这个文件放入一个公共基础库,或者直接拷贝一份放入模块中。
  3. 依赖链很复杂的情况。就可能需要考虑通过中间组件来解耦,比如依赖了某个外部控制器,就可以使用类似FRDIntent的组件来解耦。
  4. 通过参数或方法让外部调用者来配置。

拆分、pod引入

创建pod

解耦之后,接下来就是把这个模块拆分出去,然后通过pod引入。
新建一个独立的pod,可以参照cocoapods的官方教程

按照教程,我们建了一个pod,并带有一个example的demo,这时运行这个demo发现,有极大的概率会编译不过。会有以下几个问题:

  1. 如果原项目中使用了pch文件,则会带来隐性依赖问题。接下来可能会出现某些类、方法、宏没有定义的错误。因为项目中我们使用了pch文件引入了一些依赖,并定义了几个宏。这个问题有两个解决方式,一种是在pod中也创建一个pch文件,方法是设置prefix_header_contents属性。但并不推荐在pod中使用pch,最好还是在各个文件中手动添加。
  2. 如果出现了libwebp的文件找不到的情况,可以在podspec文件中加上 s.xcconfig = { 'USER_HEADER_SEARCH_PATHS' => '$(inherited) $(PODS_ROOT)/libwebp/src' }
  3. 如果出现了其它文件找不到的情况,有两种办法,一种是在podfile文件中,设置CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = 'YES'。如果这样还不行,可以把找不到的文件放入私有头文件,当然前提是外部不需要使用这个文件。具体做法是在podspec中设置private_header_files属性。
  4. 另外如果pod是oc、swift混编的,oc要使用Swift的代码,可以通过#import <PodName/PodName-Swift.h>来引入swift代码。
  5. 资源文件的问题,cocopods推荐的做法是在podspec中通过resource_bundles属性,pod.bundle来管理资源文件。采用这种方式,在pod中使用这些资源文件会稍微麻烦点。

pod引入Frodo中

如果拆分出去的模块,在pod中已经能独立编译运行,那大部分工作基本已经完成。这时候就是通过cocoapods将它引入项目中。这时需要做的就两件事:

  1. 修改项目中对这个模块文件的引用方式,之前是#import "xxx.h",现在需要改成#iport <Pod/xxx.h>
  2. 如果Project-Bridging-Header.h文件有引用这个模块的文件,需要删掉,并在使用到的swift文件中,通过import pod引用。

Demo

最后一步就是建立一个可以供独立开发的demo。

  1. 项目基础配置,比如apiKey之类的基础配置。
  2. 如果有登录,因为登录模块还没有拆分出去,所以如果需要登录,需要自己写。或者把登录模块拆分出去。

各个项目可能会有不同的架构,涉及的具体步骤可能会略有不同,这个可以具体情况具体分析。

坚持原创技术分享,您的支持将鼓励我继续创作!