中小型App的架构

3,416 阅读6分钟

引言

个人对于架构比较感兴趣,平时有事没事的都会逛逛博客,看看书。然后组长要我分享下关于架构的知识。先来写一份博客捋捋思绪吧。 MVC模式,个人觉得是架构模式里最强大的模式!能给予很多的架构启发(包括后面出现的MVP,MVVM)。对于中小型App,简单的MVC或者MVPC模式会更合适点。本文是基于MVC的思想去写的。

Model还有胖瘦?

早在几年前吧,国外对于胖瘦model这个概念,争执了很久,最后的结果还是不了了之。。。因为无论是胖model还是瘦model,都各自具有各自的优缺点。那么什么是胖瘦model呢? 所谓的胖model就是说,你的Model层上包含了部分弱业务,瘦Model就是单纯的Model,只有属性的映射。 举个🌰: 比如说你的UserModel里有性别这个熟悉,但是后台返回或者数据库存储的字段是0和1,你需要根据这个字段去判断男和女。如果是胖Model选手呢,很简单啊,我在我的Model层里就做好这些简单业务的判断,到时候ViewController需要用到的时候直接用就好了。但是胖Model比较难移植,而且修改或许会造成某些不必要的麻烦。而瘦model选手就不同,我的Model可以非常方便的直接ORM映射,我在我的ViewController里需要用的时候去判断下。不过这样的结果就是违法了DRY原则(don't repeat yourself)。因为很多冗余的代码没有抽象出来,这样的VC层看起来很臃肿。

至于我的态度,我更倾向于胖Model。传统的MVC模式,会让VC层非常的臃肿,早之前就很多人提出要给VC层瘦身。于是乎就把部分弱业务写在model里了,胖Model因此诞生了。至于后来的MVP,MVVM什么的就更加抽象了。

什么是架构

什么是架构,可能很多人上来就是MVVM,MVC,然后罗列出一系列的优缺点巴拉巴拉。。。我个人觉得架构就是架构师根据当前业务复杂度和业务工程师去设计框架,目的就是让业务工程师在写业务的时候统一,方便,明白。而且可以比较简单的上手,迁移,包括之后的演化也需要考虑到。 对于中小型的App来说,业务工程师不会很多,业务也不会很复杂。所以可以基于MVC做一些简单的拆分(抽象)。

整体架构

基础架构.png

总体是基于MVC,多加了一层Reformer。作用是将胖Model中的若业务部分抽出来,ViewController中的部分业务抽出来,放在Reformer中。所以我们的网络层的接口可以这样设计

+ (void)requestBubleList:(BaseReFormer *)reformer
                     xxx:(NSString *)xxx
                callBack:(void (^)(int code))callback;

业务程序猿只需要关注自己需要做什么数据处理,业务逻辑,在Reformer中写好。然后传入这个Reformer和请求需要的参数就可以了,至于网络层做了什么,其实并不需要了解。 Reformer用于处理业务和数据,Model用于数据管理,View用于数据展示,ViewController用于协调Model和View,并且响应交互(可能会涉及到部分业务)。

总体来说,弱化了原先在MVC中C层的作用,并且在设计过程中,少用继承,多用组合,将能够复用的代码用管理类管理起来。我把这个叫做MRVC框架(O(∩_∩)O哈哈~)

整体代码框架

image.png

框架又基于业务去设计和区分,为了可以更好的分工合作,更好的迁移代码。 第一个Util里放公共的代码,和业务无关的工具类。比如说各种第三方的封装,分类。 第二个'Dao'里放的是和整体业务相关的工具类,比如说公共数据库,公共网络接口API。 第三个就是App涉及到的业务。 Lib是没有pod库导入的第三方库。 Res就是资源库,放图片,Assets。 外面就是Base类,Base类里不要放业务相关的代码,就放基础配置和基本API。

业务代码层框架

image.png

当具体到某个业务里的框架设计呢,我们会将网络层也做业务区分,并且散落到各个业务模块中。可以看到最上面是数据来源(无论后台返回还是数据库都是数据的来源)。中间的Mediator层是用于业务跳转的,我们大部分时候写页面跳转都是这样写的:

XXXViewController *controller = [XXXViewController new];
[self.navigationController pushViewController:controller animated:YES];

这样的坏处是A程序猿需要跳转到B程序猿负责的已经完成的某一个业务页面,但是A不熟悉B的代码,就要去问B,如果B不在的话,就要找,可能会很久,如果需要带参数就更加尴尬了。所以我们可以添加个B业务的Mediator层的,用于跳转。跳转的接口都设计好,举个🌰:

UserMediator.h

/**
 跳转到个人详情页面

 @param from 跳转的页面
 @param user_id 用户ID
 @param nickName 用户昵称
 */
+ (void)pushUserInfoContoller:(UIViewController *)from
                       userID:(long)user_id
                     nickName:(NSString *)nickName;

当我们需要用到的时候,就调用[UserMediator pushUserInfoContoller:self userID:10086 nickName:@"中国移动"]。对于A来说去看看Mediator层的文档就可以使用了。

image.png

所以说业务层的框架设计可以如下图所示:

总结

这个架构的好处 1.整体是分业务模块设计的,业务与业务之间没有直接的耦合,因为中间多了层Mediator层。所以说业务的复用和迁移相对来说比较简单,对于今后如果想要模块化也可以进一步迭代。如果还需要解耦合,就用runtime和dictionary传参的方式,但是这样的成本相对较高,对于API直观程度不够。 2.整体是MRVC设计,所以是轻量级的V层和映射级的Model层,中间业务都基本处于Reformer层。如果需要响应式编程的话,可以在Reformer层进行设计修改。 3.少用继承,多用组合。对于代码迁移有很大的方便性,拔出萝卜带出泥的这种现象会很少。 4.网络层接口的分模块可以和后台架构保持一致,对于整体架构都比较好。