编写高质量的iOS工程
一、 引言
随着公司的项目越来越多,目前还没有形成统一高效的iOS开发架构来开发项目,如果项目的开发架构和管理策略得不到优化,项目开发效率必定得不到大幅度的提高,项目维护也将变得极其复杂繁琐。
我们需要项目有更快的开发速度、更加易于维护而又不失代码质量等优点。目前的开发架构将达不了我们预期的开发效果。我们需要根据业务需求来细化开发架构。
二、 项目架构
1. 版本管理
使用Git分布式管理项目。
目前的项目管理工具使用了SVN。SVN为集中式管理模式,这种管理方式强调中心服务器,开发人员的操作都是通过中间服务器操作执行任务,开发人员难以离线开发,不利于团队的并行开发。
Git是当前较为优秀的分布式管理工具,每个开发者可以保持中心服务器最新的代码,同时开发者可以随时重本地提交最新代码。这种管理方式强调个体,开发者不需要经常和服务器交互,几乎可以离线工作,版本提交和代码融合非常方便,项目管理灵活自由,利于团的并行开发。
2. 第三方类库管理
使用Cocopods+手动的管理方式。
目前的第三方类库管理方式为Cocopods+手动管理。Cocopods极大方便了第三方类库的使用和更新。手动管理类库方式是管理一些不支持Cocopods管理的类库。
3. 项目分层结构
分层结构开发。
一般,为了避免数据的跨层访问,横向依赖等问题,项目的分层结构的设计非常必要。为了使项目结构更加清晰,业务逻辑更加规律,提高内聚性降低耦合,项目采用分层结构开发。层次之间低耦合,层内高内聚。
数据流从下往上或从上往下通信。
信息系统层:数据流,如数据本地缓存,服务器数据。
数据层:网络数据或本地数据的访问。
业务逻辑层:处理数据逻辑(ViewModel)。
表示层:视图。
4. 开发设计模式
采用MVVM开发设计模式。
目前,公司项目采用主流的MVC的开发模式;
1) MVC
MVC开发模式特点:
优点:
- 代码逻辑清晰,便于维护。
- 可复用性高。
- 可测试性强。
- 代码耦合度低。
缺点:
- 不能很好地表达业务逻辑。
- 代码冗余度较高。
- 业务逻辑臃肿。
2) MVVM
MVVM开发模式特点:
优点:
- 兼容MVC的优点。
- 业务逻辑更加清晰。
- 封装性和重用性更强。
- 代码冗余度更低。
- 代码耦合度更低。
- 可测试性更强。
缺点:
- 局部代码可读性有所降低。
- 局部代码维护将有所降低。
结构简析:
- ViewController:处理业务逻辑以及页面跳转。
- View:页面布局
- ViewModel:主要数据逻辑处理,以及绑定Model和View;
- Model:数据模型
公司的开发的项目大多都是定制化,业务复杂,开发人员交替等因素,MVC的设计模式必定会导致ViewController臃肿,业务逻辑不清晰,层次结构模糊。使用MVVM开发设计模式使ViewController瘦身,提高业务逻辑的内聚,项目的业务逻辑和项目结更加构清晰条理,提高项目的开发效率和开发进度,更加有利于项目的模块化开发。至于局部代码的维护使用技术规范和类库的维护来优化。
5. 模块化开发
无论从开发效率还是项目维护等方面出发,模块开发显得尤其重要,特别是外包的项目。
1) 模块化开发的优点
- 高内聚性。
业务逻辑内聚; - 高封装高复用性。
业务模块封装,几乎没有外部外部依赖,开发时可直接模块移植添加业务需求。 - 业务模块更加清晰话。
业务逻辑集中在模块内,业务逻辑清晰。当开发人员调动时,查看的时相同的代码,可读性不言而喻。 - 业务高定制化。
当定制化界面时,只修改View层代码。 - 超低耦合。
模块内对模块外部几乎没有依赖。 - 高可维护性。
当修改业务需求,业务扩展,更新系统适配,bug修复等维护时,可通过模块批量替换。 - 高稳定性。
模块的统一开发维护,模块代码的开发经验必定会越来越丰富,代码高质量越来越高,模块越来越稳定。 - 模块专业化。
每个模块由专门的人员维护更新,更大程度使技术丰富化,专业化。
2) 模块化封装标准和规则
如果没有统一的封装规则,出现代码冲突的可能性将会提高。制定模块封装规则,可减少模块冲突的可能性,提高代码刻度性。
模块封装主要规则集中在命名,消息传递机制和代码依赖。
1. 高性能
稳定性强,响应速度快,CPU、GPU、内存达到良好效果。
2. 命名规则
命名跪着一般使用主流的骆驼命名法。
3. 接口
接口精炼,参数少,功能齐全。
4. 依赖
主要为模块外部依赖,如宏变量和外部功能性等模块外部依赖尽量减到最少。当功能扩展需求或迫不得已的外部依赖,使用runtime通过绑定类文件进行依赖绑定,一定程度上降低模块的耦合度。
要求:
- 没有外部宏变量或全局变量依赖。
- 没有common、core、public等模块外部公共类方法依赖。
- 模块单独割离出来能够独立运行。
5. 消息传递规则
消息传递主要规范以下几种方式
a) Block
Block的使用使得代码逻辑有迹可循,结构稳定,代码显得清晰调理,对于非必要长期的绑定性的通讯,Block的使用自由灵活,开发方便,对于接口的封装要优于其他的传递方式。
b) 代理
代理为一对一的传递方式,消息需要长期经常性传递使用的,长期数据绑定性传值。代理的可读性较高,结构稳定。如非长期的绑定性的通讯,一般不建议使用。
c) 通知
通知为一对多传递方式,通知的发起者和接收者可分布在不同的类和模块内,这使得通知的可读性较低,结构不稳定,如果不集中管理还可能出现消息传递冲突。一般,对于模块化的封装,不到万不得已,建议不使用通知来进行传值。全局性的接口或消息除外。
d) objc_msgSend
objec-msgSend属于runtime的方法,它用于方法的动态生成和调用。和底层方法的实现。一般,用于工具化消息传递的封装和外部依赖的绑定,减少业务模块的耦合。如一些非必要的业务功能,当模块需要额外的功能扩展时,使用objec-msgSend实现解耦,扩展模块的添加和外部依赖既不影响模块的正常化使用,也提高代码效率和质量。代码可读性较低,结构不稳定。
e) KVO和KVC
KVO和KVC一般用于解决技术性难题的解决,代码的可读性较低。
3) 模块化开发的分类
针对不同模块的模块化开发对项目的依赖程度有所不同,以下我们按功能和业务分类。
1. 非UI类封装
非UI类的封装为高度封装,例如网络模块,数据处理模块,加密模块等不应模块外部依赖,模块单独剥离能够独立运行。
2. UI类封装
a) 公共类模块
不应有模块外部依赖,模块单独剥离能够独立运行。
b) 业务类模块
可有外部依赖宏变量或公共类方法依赖。
4) 模块化开发和维护
模块化开发的特点大大提高项目的开发进度。当我们实现模块化的维护时,修改模块只需要统一替换模块实现统一维护,大大节约维护成本和维护时间。
5) 模块化开发进行技术累积
分配开发人员专门负责一些模块化的开发,使模块业务更加专业,业务累积更加周全丰富,性能更加稳定。
模块化的开发也是公司技术积累的过程。长期的模块化的开发和维护使公司的技术累积更加专业细腻,技术容量更加丰富,技术实力更加宏厚。当培养新人时也显得更加容易简单。
6. 宏和const 使用规范
宏和const的使用确实大大方便了项目的开发,但是大量使用宏会增加编译时间。宏的使用尽量精炼,全部静态的变量尽量使用const代理。
7. 基类
纵向依赖过深会使项目结构和逻辑复杂,不到迫不得已的情况下,不建议创建多个继承于一类的基类。
8. 数据层的封装
一般数据层的功能模块相对稳定,可复用性很强,对数据层模进行高度封装非常利于架构的稳定,模块移植开发非常的方便快捷。
数据层的封装主要包括网络请求模块、数据存储模块、和数据安全模块。这三大模块互相依赖较强。为了实现各个模块的独立封装,实现模块之间的解耦,在每个模块内创建一个通过runtime实现的绑定(bind)类,实现各模块可互相伪依赖,又可割离单独运行。
9. 项目架构搭建
项目开发拥有合理稳定的开发架构,高质量的项目的开发也变得有迹可循,开发流程也变得简单有效。
目前Public中与UI相关封装组件的还比较少,后续将陆续添加。其他一些框架的封装也后续完善。后续将不断完善功能缺陷和优化性能。
项目目录结构:
1) 主要目录
一级目录分5大类:
1. Main(UI类)
所有与UI相关的代码、框架、控件。
a) 业务开发目录
该目录为按业务开发模块。
b) other
存储基类和与UI相关的封装的框架或控件。
2. Expand(非UI类)
所有与UI相关不大的封装框架、工具类、配置、常量等。
a) DataBase
封装完整的与数据存储相关框架。
如包含了FMDB、keychain、NSUserdefault、plist存储方式的封装。
b) Network
封装与通讯相关的框架,如AFNetworking、CocoAsyncSocket、蓝牙等通讯框架。
c) Tool
开发的实用工具类,主要分以下几大类。
- PADataConvert:所有与数据转换或与数据处理相关的类的封装。
- PAUItool:所有与UI适配或计算相关的类的封装
- PAAppUpdate:app的更新的封装。
- PASecurity:所有与数据,app安全相关类的封装。
- PADevice:所有与用户设备的相关信息类的封装。
- PATimer:所有与时间相关的类的封装。
- PAImageTool:图片处理的封装。
d) Category
存放项目公共的类别。
e) Macros
存放使用宏全局配置的相关的代码。
- PAappMacro:App配置,如服务器地址、app版本等。
- PADeviceMacro:全局设备相关参数的配置。
- PAFontMacro:全局字体的规格的配置。
- PAColorMacro:全局颜色的配置。
f) Const
存放全局常量的配置。
3. Vendor(第三方框架)
4. Other (AppDelegate、pch文件)
5. Resource (资源文件)
2) 结构概述
主要功能和业务两大模块,除了Main属于业务开发模块,其他豆薯功能开发模块。
功能开发模块,它组成项目的基本架构模版,一般里面所有的功能模块已被全套封装供项目使用。各个功能的子模块互不依赖,能够单独剥离使用。而极少数子功能模块会通过runtime的绑定文件绑定其他的子模块,例如DataBase模块使用runtime绑定了PASectury模块来实现数据加密存储,如果DataBase单独剥离也可以单独运行,但是树勇与数据加密的api时将会提示开发者拖入PASectury子模块。这样通过runtime绑定其他子模块很好地解决了模块依赖,和代码冗余问题。
业务开发模块,它有开发者自定义开发界面,other为UI相关的基类和与UI相关控件的封装。其他的由开发按业务自定义目录进行开发。
10. 项目统一管理和维护
分配开发人员维护和更新封装框架或组件,当更新系统或出现bug,由分配的开发人员修复框架或组件,再统一更新。
更新中…