iOS-设计模式之胖瘦Model

作者: 有毒的程序猿 | 来源:发表于2017-02-16 18:33 被阅读539次

    前言

    之前在自己公司开发过程之中,一直就是想办法把代码写的漂亮,可复用度高,就是不断地稠代码,分模块.具体怎么做
    写出比较完美的代码,自己也不知道,现在有时间整理一些自己学习的心得,废话不多说,先飞一波!

    这个问题,下次见面再回答你.jpg

    在开始之前还是想讲一下,代码的规范

    • 先是life cycle,即controller的生命周期等一些方法如:
    #pragma  mark - lifecycle
    - (void)viewDidLoad 
    
    • 然后是 private method,一些私有方法(虽然说好的代码,控制器里面没有私有方法,不过毕竟不是超级大神),即你自己封装的一些功能类方法
    #pragma  mark - private method
    - (void)setupRefreshView 
    
    • 然后是Delegate方法实现,先系统代理,然后自己写的代理
    #pragma  mark - UITableViewDataSource
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    
    #pragma  mark - SegmentCellDelegate
    - (void)segmentClickedWithIndex:(NSInteger)selectedIndex
    
    • 然后是event response,所有button、gestureRecognizer的响应事件都放在这个区域里面,不要到处乱放。
    #pragma mark - event response
    //点击空白处释放键盘
    - (void)tap 
    //点击退出按钮
    -(void)existButton:(UIButton *)button
    
    • 然后才是getters and setters,和 懒加载
    #pragma mark - Getters and Setters
    - (NSMutableArray *)searchSections {
        if (!_searchSections) {
            _searchSections = [[NSMutableArray alloc] init];
        }
        return _searchSections;
    }
    

    为什么要这样要求?

    我见过无数ViewController,代码布局乱得一塌糊涂,这里一个delegate那里一个getter,然后ViewController的代码一般都死长死长的,看了就让人头疼。
    定义好这个规范,就能使得ViewController条理清晰,业务方程序员很能够区分哪些放在ViewController里面比较合适,哪些不合适。另外,也可以提高代码的可维护性和可读性。

    好了,希望以上可以帮到大家,这也是我看了一些文章整理出来常用 mark分类方法.下面开始主题了,一直听别人说关于胖瘦Model的事,也不是很了解,下面我们
    来扒一下他们的老底.是不是有些期待呢....

    一 丶关于胖Model和瘦Model

      1. 什么叫胖Model?

    胖Model包含了部分弱业务逻辑。胖Model要达到的目的是:Controller从胖Model这里拿到数据之后,不用额外做操作或者只要做非常少的操作,就能够将数据直接应用在View上.

    FatModel:
    @property (nonatomic, copy) NSString *calId;            //日程id
    @property (nonatomic, copy) NSString *title;              //日程标题
    /*
     *  判断自己是否是该日程参与者
     */
    + (BOOL)isCalendarActory:(NSString *)doneUsers;
    
    Controller:
        BOOL ret = [FatModel isCalendarActory:@“”];
    
    其优点是:

    这属于业务代码,算是弱业务。FatModel做了这些弱业务之后,Controller就能变得非常skinny,Controller只需要关注强业务代码就行了。众所周知,强业务变动的可能性要比弱业务大得多,弱业务相对稳定,所以弱业务塞进Model里面是没问题的。

    另一方面,弱业务重复出现的频率要大于强业务,对复用性的要求更高,如果这部分业务写在Controller,类似的代码会洒得到处都是,一旦弱业务有修改(弱业务修改频率低不代表就没有修改),这个事情就是一个灾难。如果塞到Model里面去,改一处很多地方就能跟着改,就能避免这场灾难。

    其缺点是:

    胖Model相对比较难移植,虽然只是包含弱业务,但好歹也是业务,迁移的时候很容易拔出萝卜带出泥。另外一点,MVC的架构思想更加倾向于Model是一个Layer,而不是一个Object,不应该把一个Layer应该做的事情交给一个Object去做。最后一点,软件是会成长的,FatModel很有可能随着软件的成长越来越Fat,最终难以维护。

    • 2.什么叫瘦Model?

    瘦Model只负责业务数据的表达,所有业务无论强弱一律扔到Controller。ThinModel要达到的目的是,尽一切可能去编写细粒度Model,然后配套各种helper类或方法来对弱业务做抽象,强业务依旧交给Controller。举个例子:

    ThinModel:
    @property (nonatomic, copy) NSString *calId;            //日程id
    @property (nonatomic, copy) NSString *title;              //日程标题
    
    ThinHelper:
    /*
     *  判断自己是否是该日程参与者
     */
    + (BOOL)isCalendarActory:(NSString *)doneUsers;
    
    Controller:
        BOOL ret = [ThinHelper isCalendarActory:@“”];
    
    其优点是:

    由于ThinModel跟业务完全无关,它的数据可以交给任何一个能处理它数据的Helper或其他的对象,来完成业务。在代码迁移的时候独立性很强,很少会出现拔出萝卜带出泥的情况。另外,由于ThinModel只是数据表达,对它进行维护基本上是0成本,软件膨胀得再厉害,ThinModel也不会大到哪儿去。

    其缺点是:

    缺点就在于,Helper这种做法也不见得很好,这里有一篇文章批判了这个事情。另外,由于Model的操作会出现在各种地方,ThinModel在一定程度上违背了DRY(Don't Repeat Yourself)的思路,Controller仍然不可避免在一定程度上出现代码膨胀。

    二丶MVC

    M应该做的事:
    1. 给ViewController提供数据
    1. 给ViewController存储数据提供接口
    2. 提供经过抽象的业务基本组件,供Controller调度
    C应该做的事:
    1. 管理View Container的生命周期
    1. 负责生成所有的View实例,并放入View Container
    2. 监听来自View与业务有关的事件,通过与Model的合作,来完成对应事件的业务。
    V应该做的事:
    1. 响应与业务无关的事件,并因此引发动画效果,点击反馈(如果合适的话,尽量还是放在View去做)等。
    1. 界面元素表达

    三丶MVCS

    苹果自身就采用的是这种架构思路,从名字也能看出,也是基于MVC衍生出来的一套架构。从概念上来说,它拆分的部分是Model部分,拆出来一个Store。这个Store专门负责数据存取。但从实际操作的角度上讲,它拆开的是Controller。

    这算是瘦Model的一种方案,瘦Model只是专门用于表达数据,然后存储、数据处理都交给外面的来做。MVCS使用的前提是,它假设了你是瘦Model,同时数据的存储和处理都在Controller去做。所以对应到MVCS,它在一开始就是拆分的Controller。因为Controller做了数据存储的事情,就会变得非常庞大,那么就把Controller专门负责存取数据的那部分抽离出来,交给另一个对象去做,这个对象就是Store。这么调整之后,整个结构也就变成了真正意义上的MVCS。

    TCStore:
    //主要为本地数据查询,删除,跟新  提供接口
    - (NSMutableArray *)fetchLocalFavoritesWithType:(NSString *)type
    Controller:
    self.dataSource = [[TCStore sharedInstance] fetchLocalFavoritesWithType:@“”];
    

    四丶MVVM

    1.纯属打酱油

    MVVM去年在业界讨论得非常多,无论国内还是国外都讨论得非常热烈,尤其是在ReactiveCocoa这个库成熟之后,ViewModel和View的信号机制在iOS下终于有了一个相对优雅的实现。MVVM本质上也是从MVC中派生出来的思想,MVVM着重想要解决的问题是尽可能地减少Controller的任务。

    2.看着好看有分割线

    不管MVVM也好,MVCS也好,他们的共识都是Controller会随着软件的成长,变很大很难维护很难测试。只不过两种架构思路的前提不同,MVCS是认为Controller做了一部分Model的事情,要把它拆出来变成Store,MVVM是认为Controller做了太多数据加工的事情,所以MVVM把数据加工的任务从Controller中解放了出来,使得Controller只需要专注于数据调配的工作,ViewModel则去负责数据加工并通过通知机制让View响应ViewModel的改变。

    3.卧槽怎么还有

    MVVM是基于胖Model的架构思路建立的,然后在胖Model中拆出两部分:Model和ViewModel。关于这个观点我要做一个额外解释:胖Model做的事情是先为Controller减负,然后由于Model变胖,再在此基础上拆出ViewModel,跟业界普遍认知的MVVM本质上是为Controller减负这个说法并不矛盾,因为胖Model做的事情也是为Controller减负。

    另外,我前面说MVVM把数据加工的任务从Controller中解放出来,跟MVVM拆分的是胖Model也不矛盾。要做到解放Controller,首先你得有个胖Model,然后再把这个胖Model拆成Model和ViewModel。

    4.马上完了

    前面扯了那么多,其实归根结底就是一句话:在MVC的基础上,把C拆出一个ViewModel专门负责数据处理的事情,就是MVVM。然后,为了让View和ViewModel之间能够有比较松散的绑定关系,于是我们使用ReactiveCocoa,因为苹果本身并没有提供一个比较适合这种情况的绑定方法。iOS领域里KVO,Notification,block,delegate和target-action都可以用来做数据通信,从而来实现绑定,但都不如ReactiveCocoa提供的RACSignal来的优雅,如果不用ReactiveCocoa,绑定关系可能就做不到那么松散那么好,但并不影响它还是MVVM。

    在实际iOS应用架构中,MVVM应该出现在了大部分创业公司或者老牌公司新App的iOS应用架构图中,据我所知易宝支付旗下的某个iOS应用就整体采用了MVVM架构,他们抽出了一个Action层来装各种ViewModel,也是属于相对合理的结构。
    所以Controller在MVVM中,一方面负责View和ViewModel之间的绑定,另一方面也负责常规的UI逻辑处理。

    viewCell
    @property (nonatomic, strong) viewModel *model; 
    
    
    Model
    @property (nonatomic, copy) NSString *title;              //标题
    
    viewModel
    @property (nonatomic, strong) Model *model; 
    /**
     * 头像frame
     */
    @property (nonatomic, assign, readonly) CGRect headerFrame;        
    +(void)caluCellHightWith:(RHFlowCategoryCellType)type;
    
    Controller
    viewCell.model = self.dataSource[index.row];
    

    五丶VIPER

    VIPER(View,Interactor,Presenter,Entity,Routing)。VIPER我并没有实际使用过,我是在objc.io上第13期看到的。

    但凡出现一个新架构或者我之前并不熟悉的新架构,有一点我能够非常肯定,这货一定又是把MVC的哪个部分给拆开了(坏笑)。事实情况是VIPER确实拆了很多很多,除了View没拆,其它的都拆了。

    这个我就不讲了,不怎么用,如果有想了解的,请去网站了解.

    参考资料:
    http://casatwy.com/iosying-yong-jia-gou-tan-viewceng-de-zu-zhi-he-diao-yong-fang-an.html
    (objc.io)
    https://www.objc.io/issues/13-architecture/viper/

    相关文章

      网友评论

        本文标题:iOS-设计模式之胖瘦Model

        本文链接:https://www.haomeiwen.com/subject/zpuhwttx.html