前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >App架构经验总结(二)

App架构经验总结(二)

作者头像
Keegan小钢
发布2018-08-10 14:53:01
6280
发布2018-08-10 14:53:01
举报
文章被收录于专栏:Keegan小钢Keegan小钢

原文链接:http://keeganlee.me/post/architecture/20160303 版权声明:本文刊载在《程序员》杂志2016年3期,版权归《程序员》所有,未经许可不得转载

架构分层

API的设计完成之后,接下来我就会考虑App项目的整体架构了。整体如何架构,我也曾经做过不少尝试。早期的时候,Android就是将所有操作都放在Activity里完成,包括界面数据处理、业务逻辑处理、调用API。后来发现Activity越来越臃肿,代码越来越复杂,很难维护。于是就开始思考如何拆分,如何才能做到松耦合高内聚。

前面也说过,一个App的核心就是数据,那么,从App对数据处理的角色划分出发,最简单的划分就是:数据管理、数据加工、数据展示。相应的也就有了三层架构:数据层、业务层、展示层。它们之间的关系如下图,数据层是三层中的最底层,往下,它接入API;往上,它向业务层交付数据。业务层夹在三层中间,属于数据的加工厂,将数据层提供上来的数据加工成展示层需要展示的数据。展示层处于三层中的最上层,主要就是将从业务层取得的数据展示到界面上。

数据层

数据层是数据管理者,主要任务就是封装API,并将数据结果交付给上层,中间会再加个数据缓存。整个主流程如下图:

  1. 业务层向数据层请求数据;
  2. 数据层检查缓存中有没有请求需要的数据;
  3. 如果有缓存数据,则直接返回缓存数据;
  4. 如果没有缓存数据,则从网络API获取数据,并将数据加入缓存,然后返回数据。

调用网络API时,还要判断网络状态,根据不同状态做不同处理。如果网络不可用,就无需发起请求了。网络可用时,也要区分是连接WIFI还是连接移动网络。连接移动网络时,一般需要限制调用比较耗流量的请求。曾经,我们没有对移动网络状态下的请求进行限制,结果,测试时流量DuangDuangDuang地一下子就不见了十几M。连接WIFI时,则无需设置这种限制,而且还可以预先请求一些接口,比如请求当前分页数据时,可以将下一页的数据也预先请求。

缓存也需要缓存策略,不同的接口需要做不同的缓存处理。首先,缓存只适用于获取数据的接口,对于修改数据的接口则不适用。其次,不同接口缓存时间一般也不同,对于很少变动的数据缓存时间可以设置长一些,而频繁变动的数据缓存时间则比较短,甚至不进行缓存。最后,缓存数据因为比较多,我们一般保存在数据库,而对于调用频率高、最新的数据,还会在内存中也拥有一份缓存,不过缓存时间比较短。请求缓存数据时,会先检查内存缓存中有没有,有则直接将缓存的数据返回,没有才从数据库获取。

那么,如何将数据交付给业务层呢?这是整个数据层模块与外部交互的部分,当与外部交互的时候,一般都要符合面向接口编程的原则,因此只要提供开放的数据接口就可以了。对于接口的参数需要说明一下,上面提到的参数有appKey、version、currentPage这几个,还有签名sign、时间戳time,其实可以分为两类:系统参数和业务参数。像appKey、version、sign、time这些属于系统参数,而currentPage,或username之类的则属于业务参数。数据层开放的数据接口的参数只需要包含业务参数就可以了,业务层并不需要关心系统参数是什么,系统参数在数据层内部封装API时指定就可以了。

业务层

业务层是数据加工者,主要就是从数据层获取数据,然后经过业务逻辑处理后转化成展示层需要的数据。业务层因为夹在数据层和展示层中间,起着承上启下的作用。也因此,业务层很容易沦落为只是一个数据的中转站,主要就是因为对业务层具体的作用和职责没有理解清楚。

这里用一个例子来说明业务层具体的工作吧,就举个用户注册的例子。用户注册时,界面上需要用户提供手机号、短信验证码、密码、确认密码。那么,最简单的操作就是,带上这些参数调用数据层的注册接口。好了,问题来了,注册接口并没有提供确认密码的参数。那好,调用注册接口之前先判断下密码和确认密码是否一致,不一致则返回错误提示给用户,一致了才调用注册接口。好了,第二个问题来了,用户等网络请求等了一段时间后,请求结果返回说手机号少了一位。下一次,又等了一段时间,这次又返回说手机号多了一位。就因为一个小错误要让用户等那么久,用户肯定有意见。后台也有意见,各种非法的请求都发过来,是嫌服务器压力不够大啊。那好,调用接口之前对这些参数做有效性检查吧,手机号要规范,短信验证码只能为六位数字,密码不能少于六位。终于注册成功了,第三个问题又来了,注册接口是没有返回用户的accessToken的,只有登录接口才会返回。让用户手动再登录一下?这用户体验不太好啊。正确的姿势应该是注册成功后再自动调用一次登录接口,如果因为网络问题第一次登录失败,后面还需要再自动调用多一次,如果还是调用失败,才让用户手动登录。

上面的例子中,对参数的有效性检查,注册成功后的自动登录,都属于业务逻辑的处理,也就是说都是业务层的工作。

业务层交付给展示层的数据也是通过接口的方式,不过,和数据层交付给业务层时不同的是:交付给展示层的数据应该是通过异步回调返回的。因为获取数据是一个比较耗时的任务,通过异步回调才不会阻塞UI主线程。

展示层

展示层作为数据展示者,它只要关心数据如何展示就可以了。不过,数据如何展示却不是那么简单。展示层是三层架构中最复杂的一层了,要考虑的东西远远多于其他两层,涉及的东西包括但不限于界面布局、屏幕适配、图片资源、文本资源、颜色资源等等。在开发一段时间后,展示层出现代码混乱是最常见的。因此,做好展示层,就需要保持高质量的代码。要保持高质量代码,我觉得至少应该遵循几条基本的原则:

  1. 保持规范性:定义好开发规范,包括书写规范、命名规范、注释规范等,并按照规范严格执行;
  2. 保持单一性:布局就只做布局,内容就只做内容,各自分离好,每个方法、每个类,也只做一件事情;
  3. 保持简洁性:保持代码和结构的简洁,每个方法,每个类,每个包,每个文件,都不要塞太多代码或资源,感觉多了就应该拆分。

所谓无规矩不成方圆,展示层的设计,要从开发规范开始。一份好的开发规范,是保证代码有较高的可读性的基础。iOS方面,苹果已经有一套Coding Guidelines,主要属于命名方面的规范。当我们制定自己的开发规范时,首先就要遵守苹果的这份规范,在此基础上再加上自己的规范。Android方面,我也在我的博客中分享过一套(Android技术积累:开发规范),主要分为书写规范、命名规范、注释规范三部分。

最重要的不是开发规范的制定,而是开发规范的执行。如果没有按照开发规范去执行,那开发规范就等于形同虚设,那代码混乱的问题依然得不到解决。

说到单一性,面向对象设计中,有一个基本原则就是单一职责原则,它规定一个类应该只有一个发生变化的原因。保持单一性是减低耦合度的关键标准,其目的就是各方面的解耦。而我这里说的单一性不只是规定类的单一,也包括界面的单一、方法的单一、资源文件的单一等。

界面的单一,首先是界面的布局和界面的数据应该分离。另外,界面数据的获取和展示也应该分离。一句话,保持界面的单一性就是要保持界面上每个维度都做好分离,从界面的布局,到数据的获取,数据的检查,数据的展示。

方法的单一,则表现为一个方法是对一个行为的封装。行为又可以拆分为多个步骤,每个步骤其实也是更细化的行为。因此,方法嵌套方法是一种常态。那么,保持方法的单一性,关键不在于怎么定义这个方法的行为,而在于这个行为要怎么拆分成更细的行为。举个例子,通常在Activity的onCreate方法,做初始化操作,细分出来就分为了:控件的初始化、逻辑变量的初始化、数据的初始化。数据的初始化又可以再细分:数据的获取、数据的展示。每个细化的行为都应该封装为一个独立的方法,这样,才真正符合方法的单一性。

资源文件的单一,主要是指Android的各类资源文件,包括存放字符串的strings.xml,存放字符串数组的arrays.xml,存放颜色值的colors.xml,存放尺寸值的dimens.xml,等等。资源文件的单一,是说所有相关的资源信息要在资源文件里定义并引用到代码或布局文件里,而不是在代码或布局文件里直接定义。这样做,可以很方便地做各种适配和修改,比如支持国际化,比如不同分辨率的屏幕用不同尺寸值。iOS则没有提供和Android一样的资源文件分离的机制,但可以参考Android的做法自己去实现。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-03-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Keegan小钢 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 架构分层
相关产品与服务
短信
腾讯云短信(Short Message Service,SMS)可为广大企业级用户提供稳定可靠,安全合规的短信触达服务。用户可快速接入,调用 API / SDK 或者通过控制台即可发送,支持发送验证码、通知类短信和营销短信。国内验证短信秒级触达,99%到达率;国际/港澳台短信覆盖全球200+国家/地区,全球多服务站点,稳定可靠。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档