客户端架构

Blog2-客户端架构

一.客户端架构简介

   客户端(Client)或称为用户端,是指与服务器相对应,为客户提供本地服务的程序。除了一些只在本地运行的应用程序之外,一般安装在普通的客户机上,需要与服务端互相配合运行。

架构,又名软件架构,是有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。软件架构是一系列相关的抽象模式,用于指导大型软件系统各个方面的设计。软件架构是一个系统的草图。软件架构描述的对象是直接构成系统的抽象组件。各个组件之间的连接则明确和相对细致地描述组件之间的通讯。在实现阶段,这些抽象组件被细化为实际的组件,比如具体某个类或者对象。在面向对象领域中,组件之间的连接通常用接口(计算机科学)来实现。

在“软件构架简介”中,David Garlan 和 Mary Shaw 认为软件构架是有关如下问题的设计层次:“在计算的算法和数据结构之外,设计并确定系统整体结构成为了新的问题。结构问题包括总体组织结构和全局控制结构;通信、同步和数据访问的协议;设计元素的功能分配;物理分布;设计元素的组成;定标与性能;备选设计的选择。”

二.常见的架构方式

针对数据流动的方向而言,分为分层架构,MVC架构,MVVM架构,MVP架构。

1.分层

分层架构是一种常见的软件应用架构,在 Java 程序中可以算是一种应用标准了,通常又叫 N 层架构。

优点:

1、开发人员可以只关注整个结构中的其中某一层;

2、可以很容易的用新的实现来替换原有层次的实现;

3、可以降低层与层之间的依赖;

4、有利于标准化;

5、利于各层逻辑的复用。

缺点:

1、降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。

2、有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码。

1.1三层架构

最常见的是 3 层架构,它从上至下包含如下 3 层:

展示层(Presentation tier),也称为 UI 层,也就是程序的界面部分。

业务层(business logic(domain) tier), 业务层,是最为核心的一层。

持久层(Data tier),数据持久层。

层次

作用

设计原则

表示层(UI)

向用户展现特定业务数据,采集用户的输入信息和操作。

用户至上,兼顾简洁;不包含任何业务相关的逻辑处理。

业务逻辑层(BLL)

从DAL中获取数据, 在UI显示; 从UI中获取用户指令和数据, 执行业务逻辑或通过DAL写入数据源。

作为U层与D层的桥梁,目的在于展现清晰的函数结构, 只负责数据处理传递, 不涉及SQL语句和ADO.NET。

数据访问层(DAL)

直接操作数据库,针对数据的增添 删除 修改 查找; 具体为业务逻辑层或表示层提供数据服务。

专门操作数据库, 不考虑数据合法性. 数据库错误返回-1, 逻辑错误返回0, 并告知错误原因, 成功返回1

 

3 层架构是存在物理上分层概念的,从上往下即展示层、业务层、持久层,也从上往下由上一层依赖下一层。不同层之间也是高内聚低耦合的体现,层内高内聚,层间低耦合,层是层内具体工作的高度抽象。低耦合则是依赖倒转原则体现出来,高层依赖于下层的抽象而不是具体。

1.2四层架构

在三层架构的基础上多了业务规则层,通常的三层是把业务逻辑和业务规则合并为一个层,统称为业务层.业务规则层的提出,既可以及时处理用户输入的不合法信息, 又可以及时处理数据库错误, 增大了业务逻辑层的结构清晰度, 让业务逻辑人员专心致志做逻辑。

从上至下为:

l  表示层

l  业务规则层

l  业务逻辑层或称为领域层

l  数据访问层

层次

作用

设计原则

业务规则层(ECL)        

对于UI层传下来的参数来说,检查合法性。

用户至上,兼顾简洁;不包含任何业务相关的逻辑处理。

1.3引入service层

引入service层的架构和普通的分层架构的不同是: service层内部有数据, 可以单独运行。

从上至下为

l  表现层

l  服务层(service)

l  数据访问层

l  业务逻辑层

层次

作用

表现层    

显示与用户的交互。

服务层

service层提供表现层的业务逻辑入口,通过定义接口服务的形式,通过接口调用来完成。

业务逻辑层

1接收服务层传来的DTO, 然后根据业务规则, 对传入的DTO进行加工, 返回加工后的信息

2 需要为每个对象提供业务行为, 并且这些对象之间是独立的

3 业务对象之间的交互流程通过服务层来组织

数据访问层

本地数据远程数据的访问接口。

 

2.MVC

MVC指Model-View-Controller。

层次

作用

设计原则

M(模型层)

封装了应用的一系列数据, 并定义了操作, 处理这些数据的逻辑和计算规则。

通过Notification,KVO对控制器进行反馈

V(视图层)

视图对象是一个应用中, 用户可以看到的对象. 视图对象知道如何绘制自己, 也能够响应用户的操作. 视图对象的主要目的之一是将应用模型对象中的数据显示出来, 并允许用户编辑该数据。

视图通过不能直接操作模型层, 通过target-action, delegate, dataSource和控制器进行反馈

C(控制器层)

控制器层是在视图层和若干个模型层的中间人

c可以直接操作模型层和视图层

 

下图说明了MVC之间的交互。

优点:

(1) 可以为一个模型在运行时同时建立和使用多个视图。变化-传播机制可以确保所有相关的视图及时得到模型数据变化,从而使所有关联的视图和控制器做到行为同步。

(2) 视图与控制器的可接插性,允许更换视图和控制器对象,而且可以根据需求动态的打开或关闭、甚至在运行期间进行对象替换。

(3) 模型的可移植性。因为模型是独立于视图的,所以可以把一个模型独立地移植到新的平台工作。需要做的只是在新平台上对视图和控制器进行新的修改。

(4) 潜在的框架结构。可以基于此模型建立应用程序框架,不仅仅是用在设计界面的设计中。

缺点:

(1) 增加了系统结构和实现的复杂性。对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。

(2) 视图与控制器间的过于紧密的连接。视图与控制器是相互分离,但确实联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。

(3) 视图对模型数据的低效率访问。依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。

(4) 目前,一般高级的界面工具或构造器不支持MVC模式。改造这些工具以适应MVC需要和建立分离的部件的代价是很高的,从而造成使用MVC的困难。

1.1安卓客户端的MVC

V:V在MVC架构中Activity(托管Fragment,View,WebView等)首先充当V的角色。

M:业务逻辑层划分出来专门处理数据。例如:数据的http请求,数据解析和储存等逻辑都封装在这一层。Activity 不直接和Http,Dao(数据访问对象层)直接有联系了,视图数据从此为路人。

C:接受或控制事件或逻辑层的回调响应。

1.2Java Swing的MVC

Swing是一个标准的MVC结构

• ComponentUI代表View,负责描画组件。

• 组件由其Model层,比如JTextField的Document,JTable的TableModel, JTree?的TreeModel等等。

• 而Controller可能不是很明显,我们或许可以简单的将其Event机制看作一个Swing团队开发给开发者的Controller.

3.MVVM

MVVM是在MVC的基础上多了一个View Model: 表示逻辑, 将 model 的数据转换为 view 可以呈现的东西。适合大量展示类的App。

MVVM指Model-View-ViewModel,是一个从 MVC 模式中进化而来的设计模式。

Model,domain model(领域模型)或是数据层代表的数据模型,也可以理解为用户界面需要显示数据的抽象(数据)。

View, 应用的界面

ViewModel,binder 所在之处,是 View 的抽象,对外暴露出公共属性和命令,是 View 与 Model 的(绑定)连接器。

下图是一组MVC,MVP和MVVM的对比图片。

最早于2005年被微软的 WPF 和 Silverlight 的架构师 JohnGossman 提出。

举例来说,在 iOS 开发中实践 MVVM 的话,通常会把大量原来放在 ViewController 里的视图逻辑和数据逻辑移到ViewModel 里,从而有效的减轻了ViewController 的负担。另外通过分离出来的 ViewModel 获得了更好的测试性,我们可以针对 ViewModel 来测试,解决了界面元素难于测试的问题。MVVM 通常还会和一个强大的绑定机制一同工作,一旦ViewModel 所对应的 Model 发生变化时,ViewModel 的属性也会发生变化,而相对应的View 也随即产生变化。

优点:

(1)低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。

(2)可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。

(3)独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xml代码。

(4)可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。

缺点:

一个首要的缺点是,MVVM 的学习成本和开发成本都很高。MVVM 是一个年轻的设计模式,大多数人对他的了解都不如 MVC 熟悉,基于绑定机制来进行编程需要一定的学习才能较好的上手。同时在客户端开发中,并没有现成的绑定机制可以使用,要么使用 KVO,要么引入类似 ReactiveCocoa 这样的第三方库,使得学习成本和开发成本进一步提高。

另一个缺点是,数据绑定使 Debug 变得更难了。数据绑定使程序异常能快速的传递到其他位置,在界面上发现的 Bug 有可能是由 ViewModel 造成的,也有可能是由 Model 层造成的。传递链越长,对 Bug的定位就越困难。

同时还必须指出的是,在传统的 MVVM 架构中,ViewModel 依然承载的大量的逻辑,包括业务逻辑,界面逻辑,数据存储和网络相关的逻辑,使得 ViewModel 仍然有可能变得和 MVC 中 ViewController 一样臃肿。

3.1安卓客户端的MVVM

目前 Android 的 data binding 还是 beta,还只是 one-way 单向绑定,功能上还有所欠缺、控制性也还不强,但是把它写出来还是没问题的。对于 Activity、Fragment 而言仅仅是作为 Java View 看待,与 XML 对应,所以里面只有 View 的展现逻辑,此外没有其它代码。一个Activity 或 Fragment(一般都 with XML) 对应一个 ViewModel,对于一个基础 View(XML)可以通过继承对应的 ViewModel 实现重用,本文的代码也有体现。对于 Activity 和 Fragment 的View 状态保存恢复也通过 ViewModel 处理。因为 binding 的入口在 Activity 或 Fragment 中,所以为了方便写个基类处理ViewModel 和 Binding 的初始化,然后在对应的 XML 里加上 ViewModel 的 variable, XML 里不再有其它数据对象的 variable。

ViewModel 中通过ObservableField 来达到细粒度的控制,绑定操作都放在ViewModel 里,然后 ViewModel 里可以有多个 domain 中的Interator(UseCase) 来得到 View 需要渲染的数据 Model。对于 ObservableField 的绑定操作和命令操作(Command)都是暴露的,也易于测试。binding现在缺少手动在 Java 代码中注册通知事件的功能,比如有些 model 的渲染必须通过 Java 代码来操作的话就需要了,在 Activity(Java View)中通过向 Binding 注册通知回调,而目前只能在 XML 中知道,当然目前也可以自己实现,方法也有多种:接口回调、EventBus、RxBus。

下图是MVVM的架构图。

4.MVP

Model-view-presenter (MVP) 是使用者界面设计模式的一种,被广范用于便捷自动化单元测试和在呈现逻辑中改良分离关注点(separation of concerns)。

Model定义使用者界面所需要被显示的资料模型,一个模型包含着相关的业务逻辑。View视图为呈现使用者界面的终端,用以表现来自Model 的资料,和使用者命令路由再经过Presenter对事件处理后的资料。Presenter包含着元件的事件处理,负责检索Model取得资料,和将取得的资料经过格式转换与View进行沟通。

优点:

(1)模型与视图完全分离,我们可以修改视图而不影响模型。

(2)可以更高效地使用模型,因为所有的交互都发生在一个地方----Presenter内部。

(3)我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。

(4)如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑

缺点:

由于对视图的渲染放在了Presenter中,所以视图和Presenter的交互会过于频繁。还有一点需要明白,如果Presenter过多地渲染了视图,往往会使得它与特定的视图的联系过于紧密。一旦视图需要变更,那么Presenter也需要变更了。比如说,原本用来呈现Html的Presenter现在也需要用于呈现Pdf了,那么视图很有可能也需要变更,可修改性下降。

4.1安卓客户端的MVP

很多时候视图层面还是充斥中很多复杂的逻辑,例如UI事件的响应处理,网络响应的回调等等,充斥着各种监听器的回调。我们期望视图V便当更简单、更纯粹,V只负责绘制和刷新其他逻辑都不用管了,也不想和M有直接的联系。从MVC的VC(Activity)中我们分离一层出来叫做Presenter,由它来负责调度UI何时刷新、由它来接受UI的事件响应并传达指令给M。从此V和M是路人,V和数据的距离更远了。

V:Activity为代表,这时候的Activity更为简单了,只负责UI的绘制和刷新。

P:负责传达指令。向上接收V的事件指令并需要的时候传达给M,向下接收M的指令并通知V刷新UI。

M:只负责出来数据逻辑。其实还可以细分一些东西,比如Http请求,很多时候Http框架都是用的第三方开源框架,如果有一天更优秀的框架出现了,要更换,怎么才能做到不影响其他层次?如果做了分层隔离那么,可以很轻松的换掉,如果没有做分层隔离,那么可能要在每一个功能模块的M中修改代码,修改代价是巨大的,所以一般第三方开源框架都不会直接使用而是在业务上做一层抽象隔离。同理,本地数据的存储,也有必要做响应的封装或隔离,可能今天是用Litepal,也许某一天想用GreenDao了,只需要修改封装类的代码就好了。

MVP的依赖关系:

MVP类图:

把每一层都抽象成一个接口,例如V层,我们定义一个接口为View(不要和Android API里的View弄混了),让后Activity为这个View的具体实现。每一层对另一层的依赖都是接口依赖,并不关心另一层的具体实现,每一层我们都可以写不同的实现,随时切换,这就意味着,有一天如果有一层不好用了,可以轻松的重写另一个实现来替换掉,而不是如履薄冰的修改。

5. HMVC

Hierarchical MVC, 把客户端应用程序分解为有层次的父子关系的MVC, 反复应用这个模式, 形成结构化的客户端架构. 适合重型B/S架构的WebApp。

一个MVC模块由应用程序的一个模块抽象而成. 其中很重要的一个概念就是 Parent MVC , 它可以对应界面上的实体, 也可以是一个抽象的对象. 设想一个app 有标签栏, 工具栏, 导航栏, 主工作区, 对应到HMVC上就是这个app最底部的标签栏是 Layer1, Layer2 导航栏,主要工作区, 工具栏. 如果觉得 Layer2 太复杂可以吧主要工作区放到 Layer3, 依次类推.

Controller 是功能模块的总控室, 它负责和子Controller或父Controller通信,并通知它的 View 处理改变界面显示, Model 处理一些业务逻辑或数据库访问操作. 如刚才的例子里, 点击了工具栏里的一个按钮, 工具栏的Controller 响应这个event, 发现是要切换主工作区, 工具栏做不了,就传递他的父Controller处理(如果父Controller也处理不了, 就继续往上传递)然后标签栏的Controller处理切换主工作区.

优点:

(1)把程序分成了几个部分, 降低了依赖性

(2)支持鼓励重用代码, 组件或者模块。

(3)在今后的维护中, 提高了可扩展性。

缺点:

不利个案创作、独立创作、难艺术化、难个性化。

6. VIPER

VIPER,通过把APP架构划分为线框、视图、展示、交互、实体、数据六个层次,使得开发工作可以在最早的时候就参与进来,并且完全可以开发出后面无须改变的整体架构代码。

使用VIPER架构,可以在AppDelegate里通过唯一的一个实例对象管理整个APP的依赖,并且非常直观地管理整个APP的实例对象关系。

通过视图、事件、交互三组协议的协议对象,使得视图显示、事件处理、交互数据这三块的类可以得到彻底分离。未来面对APP功能修改或增加时,将会变得非常容易,代码变化被约束到了最小的范围。

 

三.如何评估架构

正如同软件本身有其要达到的目标,软件架构设计要达到如下的目标:

1.可靠性(Reliable)。软件系统对于用户的商业经营和管理来说极为重要,因此软件系统必须非常可靠。

2.安全性(Secure)。软件系统所承担的交易的商业价值极高,系统的安全性非常重要。

3.可扩展性(Scalable)。软件必须能够在用户的使用率、用户的数目增加很快的情况下,保持合理的性能。只有这样,才能适应用户的市场扩展的可能性。

4.可定制化(Customizable)。同样的一套软件,可以根据客户群的不同和市场需求的变化进行调整。

5.可伸缩 (Extensible)。在新技术出现的时候,一个软件系统应当允许导入新技术,从而对现有系统进行功能和性能的扩展。

6.可维护性(Maintainable)。软件系统的维护包括两方面,一是排除现有的错误,二是将新的软件需求反映到现有系统中去。一个易于维护的系统可以有效地降低技术支持的花费。

7.客户体验(Customer Experience)。软件系统必须易于使用。

8.市场时机(Time to Market)。软件用户要面临同业竞争,软件提供商也要面临同业竞争。以最快的速度争夺市场先机非常重要。

四.框架

1. volley

特点:

(1) JSON,图像等的异步下载;

(2) 网络请求的排序(scheduling)

(3) 网络请求的优先级处理

(4) 缓存

(5) 多级别取消请求

(6) 和Activity和生命周期的联动(Activity结束时同时取消所有网络请求)

2. android-async-http

特点:

(1) 在匿名回调中处理请求结果

(2) 在UI线程外进行http请求

(3) 文件断点上传

(4) 智能重试

(5) 默认gzip压缩

(6) 支持解析成Json格式

(7) 可将Cookies持久化到SharedPreferences

3. Afinal

主要有四大模块:

(1) 数据库模块:android中的orm框架,使用了线程池对sqlite进行操作。

(2) 注解模块:android中的ioc框架,完全注解方式就可以进行UI绑定和事件绑定。无需findViewById和setClickListener等。

(3) 网络模块:通过httpclient进行封装http数据请求,支持ajax方式加载,支持下载、上传文件功能。

(4) 图片缓存模块:通过FinalBitmap,imageview加载bitmap的时候无需考虑bitmap加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象。

FinalBitmap可以配置线程加载线程数量,缓存大小,缓存路径,加载显示动画等。FinalBitmap的内存管理使用lru算法,

没有使用弱引用(android2.3以后google已经不建议使用弱引用,android2.3后强行回收软引用和弱引用,详情查看android官方文档),更好的管理bitmap内存。

FinalBitmap可以自定义下载器,用来扩展其他协议显示网络图片,比如ftp等。同时可以自定义bitmap显示器,

在imageview显示图片的时候播放动画等(默认是渐变动画显示)。

4.xUtils框架

主要有四大模块:

(1) 数据库模块:android中的orm框架,一行代码就可以进行增删改查;

l  支持事务,默认关闭;

l  可通过注解自定义表名,列名,外键,唯一性约束,NOT NULL约束,CHECK约束等(需要混淆的时候请注解表名和列名);

l  支持绑定外键,保存实体时外键关联实体自动保存或更新;

l  自动加载外键关联实体,支持延时加载;

l  支持链式表达查询,更直观的查询语义

(2) 注解模块:android中的ioc框架,完全注解方式就可以进行UI,资源和事件绑定;

l  新的事件绑定方式,使用混淆工具混淆后仍可正常工作;

l  目前支持常用的20种事件绑定,参见ViewCommonEventListener类和包com.lidroid.xutils.view.annotation.event。

(3) 网络模块:支持同步,异步方式的请求;

l  支持大文件上传,上传大文件不会oom;

l  支持GET,POST,PUT,MOVE,COPY,DELETE,HEAD,OPTIONS,TRACE,CONNECT请求;

l  下载支持301/302重定向,支持设置是否根据Content-Disposition重命名下载的文件;

l  返回文本内容的请求(默认只启用了GET请求)支持缓存,可设置默认过期时间和针对当前请求的过期时间。

(4) 图片缓存模块:加载bitmap的时候无需考虑bitmap加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象;

l  支持加载网络图片和本地图片;

l  内存管理使用lru算法,更好的管理bitmap内存;

l  可配置线程加载线程数量,缓存大小,缓存路径,加载显示动画等…

5.ThinkAndroid

主要有以下模块:

(1) MVC模块:实现视图与模型的分离。

(2) ioc模块:android中的ioc模块,完全注解方式就可以进行UI绑定、res中的资源的读取、以及对象的初始化。

(3) 数据库模块:android中的orm框架,使用了线程池对sqlite进行操作。

(4) http模块:通过httpclient进行封装http数据请求,支持异步及同步方式加载。

(5) 缓存模块:通过简单的配置及设计可以很好的实现缓存,对缓存可以随意的配置

(6) 图片缓存模块:imageview加载图片的时候无需考虑图片加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象。

(7) 配置器模块:可以对简易的实现配对配置的操作,目前配置文件可以支持Preference、Properties对配置进行存取。

(8) 日志打印模块:可以较快的轻易的是实现日志打印,支持日志打印的扩展,目前支持对sdcard写入本地打印、以及控制台打印

(9) 下载器模块:可以简单的实现多线程下载、后台下载、断点续传、对下载进行控制、如开始、暂停、删除等等。

(10) 网络状态检测模块:当网络状态改变时,对其进行检测

6.LoonAndroid

主要有以下模块:

(1) 自动注入框架(只需要继承框架内的application既可)

(2) 图片加载框架(多重缓存,自动回收,最大限度保证内存的安全性)

(3) 网络请求模块(继承了基本上现在所有的http请求)

(4) eventbus(集成一个开源的框架)

(5) 验证框架(集成开源框架)

(6) json解析(支持解析成集合或者对象)

(7) 数据库(不知道是哪位写的忘记了)

(8) 多线程断点下载(自动判断是否支持多线程,判断是否是重定向)

(9) 自动更新模块

(10) 一系列工具类

其中的 volley扩展性非常好,个人比较喜欢的风格。其他如 android-async-http、Afinal 也相当不错。

7.AndroidAnnotations

主要有以下特点:

l  使用依赖注入(DI)、控制反转(IOC)来简化开发过程

l  简化的线程模型(Simplified threading model)

l  事件绑定(Event binding)

l  REST Client

l  No Magic

五.非功能指标

代码整齐,分类明确

代码整齐是每一个工程师的基本素质。因为代码不仅需要给他人阅读,自己在今后的编程过程中也可能会阅读。如果哪一天架构有修改,正好修改到此处,很容易自己都无法理解。另外,根据“破窗理论”,如果代码不整齐分类不明确,整个架构会随着一次一次的拓展而越来越混乱。

分类明确的意思是:不要让一个类或者一个模块做两种不同的事情。如果有类或某模块做了两种不同的事情,一方面不适合未来拓展,另一方面也会造成分类困难。

不用文档,或很少文档,就能让业务方上手。

业务方由于事务繁忙,很少会留意文档。所以需要尽可能让API的名字可读性强。函数名称长一点没有关系,更重要的是便于理解。

思路和方法要统一,尽量不要多元。

解决一个问题会有很多种方案,但是一旦确定了一种方案,就需要在其他地方保持方案的一致性。记录设立某个模块的想法和原因,记录下解决思路,避免之后引入了其他方案,从而导致异构。

没有横向依赖,万不得已不出现跨层访问。

跨层访问是指数据流向了跟自己没有对接关系的模块。有的时候跨层访问是不可避免的,比如网络底层里面信号从2G变成了3G变成了4G,这是有可能需要跨层通知到View的。但这种情况不多,一旦出现就要想尽一切办法在本层搞定或者交给上层或者下层搞定,尽量不要出现跨层的情况。跨层访问同样也会增加耦合度,当某一层需要整体替换的时候,牵涉面就会很大。

对业务方该限制的地方有限制,该灵活的地方要给业务方创造灵活实现的条件。

架构师必须要有能力区分哪些情况需要限制灵活性,哪些情况需要创造灵活性。比如对于Core Data技术栈来说,ManagedObject理论上是可以出现在任何地方的,那就意味着任何地方都可以修改ManagedObject,这就导致ManagedObjectContext在同步修改的时候把各种不同来源的修改同步进去。这时候就需要限制灵活性,只对外公开一个修改接口,不暴露任何ManagedObject在外面。

如果是设计一个ABTest相关的API的时候,我们又希望增加它的灵活性。使得业务方不光可以通过Target-Action的模式实现ABtest,也要可以通过Block的方式实现ABTest,要尽可能满足灵活性,减少业务方的使用成本。

易测试易拓展

老生常谈,要实现易测试易拓展,那就要提高模块化程度,尽可能减少依赖关系,便于mock。另外,如果是高度模块化的架构,拓展起来将会是一件非常容易的事情。

保持一定量的超前性

保持适度的技术上的超前性,能够使得架构更新变得相对轻松。

另外,超前性不仅仅是技术上的,还有产品上的。了解产品未来走向,就可以在合理的地方为未来留下可拓展的空间。同时,在创业公司的环境下,很多产品需求其实只是为了赶产品进度而产生的妥协方案,最后还是会转到正轨的。这时候业务方可以不实现转到正规的方案,但是架构这边,是一定要为这种可预知的改变做准备的。

接口少,接口参数少

越少的接口越少的参数,就能越降低业务方的使用成本。当然,充要条件还是要满足的,需要能够在满足充要条件的情况下尽可能地减少接口和参数数量。

高性能

对应每层架构都需要做每层架构的不同优化方案。

 

 

参考资料:

1. 《iOS应用架构谈 开篇》

http://www.cocoachina.com/ios/20150414/11557.html

2.《ANDROID应用开发架构概述》

http://www.liuguangli.win/archives/299

3.架构百度百科

http://baike.baidu.com/link?url=S0PcGElJ48on43vxXb9d8y3HR3T_kUQ1bRXHAliX4NrFDvVeA-ARyV1T5wRSOSEkvcwhFR9VHuadIPAT_LejwMiswdr1wJGrIWM2oetLwKq

4.《移动App架构设计》

http://blog.csdn.net/uxyheaven/article/details/38041091

5.《值得推荐的android开源框架》

http://www.ezlippi.com/blog/2014/10/android-opensource.html

 

 

 

你可能感兴趣的:(客户端架构)