ios之良好的代码/工程架构牛人解析

良好的代码
a.为整个工程创建worksapce。
 
b.按照权责分门别类存放资源文件:每种类型的资源存放于独立的目录下:图片,声音,配置文件等等。而图片又可以按照类型分别存放在不同的子目录下:全局类型,背景图,logo,登录等等。
 
c.合理的代码结构。推荐如下的工程目录结构
 

 
 
Core:工程内一些通用的机制实现类:统一的任务管理,模块管理,服务管理。
 
General:公用类和方法,包括工程内ViewController,UITableViewCell基类(Base),公用Category(Category),公用UI组件(CustomUI),公用辅助方法(Helper)和宏定义(Marco)。
 
Model:公用数据模型
 
Sections:不同程序单元。如登录,设置等等。其下又可以按照功能分成不同的子目录:当前单元使用的自定义UI组件,管理类,数据模型和ViewController等等。
 
Vendors:第三方库。
 
合适的框架
一个合适的框架不是银弹,在我看来框架要解决的问题从来不是:有了框架之后,工程就能无比正确地进行下去。好的框架能够做到的事仅仅只是:降低通用问题的复杂度和减少发生错误的可能性。个人认为一个良好iOS App框架应该是有如下特点:  
 
1. 定义清晰的层次结构。横向上,各模块互相独立,仅通过有限的几个接口进行通讯。最理想的状态是除核心模块外,其他模块都是可拔插。纵向上,各层次间依赖关系清晰,基本不出现逆向依赖的情况。
 
横向模块一般依赖于业务需求,常被定义成各种Service或Manager。一种好的做法是有个统一的Service管理器负责相应Serivce的加载,卸载,监听和分发App级别的通知给相应Service,如前后台切换,收到内存警告等。这样做一方面容易实现上面说的模块的可插拔化,另一方面也保证了公用特性处理的一致性。在这方面微信就做得不错,基本所有的模块都是从MMService继承而来,由MMServiceCenter进行管理。当然从dump出来的头文件也可以发现一些管理上的紊乱,比如一些ViewController都是继承自MMService。
 
纵向的层次划分基本各个App不会有太大区别,一般可以分为三个层次:
a.展现层(Presentation layer),负责管理UI和UIViewController
 
b.逻辑层(Business/Service Layer),负责逻辑数据的定义和转发,起到承上启下的作用。
 
c.数据访问层(Data Access Layer),负责具体API构造,网络请求,数据持久化等。
 
各层根据业务逻辑的复杂性内部又会使用单层或者多层结构。以数据访问层为例,一般又可以细分为网络层,持久化层。而一般而言,展现层(UIView和UIViewController)都是直接使用逻辑层提供的Model进行展现,但是某些场景下往往需要不同的Model有相同的界面展示(如我们的App易信中,会话界面,收藏界面,问一问功能都需要进行图片的展现,但这三个模块下的Model定义并不一致),这就需要增加额外的ViewModel层用于粘合展现层和逻辑Model。
 
2. 遵守SOILD原则和慎用各种设计模式。这是个老生常谈的话题了,并不是iOS开发独有,展开讲可以讲上几天几夜,不赘述。
 
3. 定义自己的UI基类:UIView,UIViewController,UITableviewCell。这一点的好处不言而喻,所有的子View,Controller,Cell都能够很方便的继承基类的共有的行为,样式。但也会引进很大的管理风险:组内成员总会经不起诱惑往基类塞各种并不普适的特性,引起基类权责的无限膨胀。大基类不仅增加组内成员对代码的理解难度,同时也增加出现问题时的排查难度。从这方面讲,微信的UIViewController基类设计就极端失败:MMUIViewController的属性和方法数几乎过百。
 
4. 提供方便好用的工具类。一些好用的工具类往往会成为框架重要的有机组成部分,方便快捷地解决局部问题,同时又步引入过多的复杂度。NSTimer的retain cycle是个很容易掉去的坑,那么提供一个基于Block或者weak delegate的NSTimer的封装就是不错的选择。使用KVO容易发生add和remove的不配对调用,那么就引入THObserversAndBinders或者FB的KVOContorller。某些核心模块需要被多个模块依赖时,引入类似XMPP的GCDMulticastDelegate就能够方便地进行解耦。
 
5. 好的范例。在前几年使用C++的那段暗无天日的日子里,我常想的一个问题是:如何在API层面去限制和规避一些错误。比如往线程池里面扔的task必须是堆上分配的对象,那么如何去强制传入的指针指向的是堆地址而不是栈地址呢?这种傻问题大部分情况下是无解的,有时候有解却是个异常别扭的解。而现在我更相信破窗理论所提供的可能性:做好示范,接下来的一切都会水到渠成。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值