随着移动互联网时代的到来,移动技术也随之飞速发展。如今,APP已然成为绝大多数互联网企业用来获取用户的核心渠道。与此同时,伴随着业务量的高速增长,APP会面临多重挑战,如庞大的用户群体,高频高并发的业务等等,不断直面挑战的过程,同时也是其架构在不断演进和优化的过程,好的技术架构才能够持续支持伟大的商业梦想。
首先介绍一下软件架构,根据SEI的定义,软件架构是整个程序或系统的结构(Structure),包含程序的元素(Software Elements)和外部能看见的元素属性(Properties)和元素之间的关系(Relationship)。进一步探究可以得出,架构定义了结构,组件接口,组件之间的交流和依赖以及组件的职责。
从整体上来看,架构可以分为四个部分,分别是业务架构、应用架构、数据架构和技术架构,这其中,业务架构是业务的细分,应用架构是业务的实现蓝图,数据架构是数据的应用目标而技术架构则是基础装备。这四个部分的架构是随着移动互联网应用规模的不断扩大而衍变产生的,每一个架构都有其特定的职责。业务架构,单独的分析各个业务之间可能存在的逻辑上的联系,尽量保证各个业务模块内部高聚合,模块之间低耦合。应用架构就相当于为具体的业务架构提供技术支持,数据架构是单独将应用的数据拆分出来,进行数据分析、数据清洗等用来为应用提供更好的服务保障。 技术架构相当于最底层的基础技术保障,提供诸如安全、通讯等基础服务。 一个业务庞杂的App通过这四个架构的相辅相成,为用户带来良好的使用体验。
在架构过程中,应该从一开始就对需要满足的质量属性保持高度的重视,通常在设计应用架构时需要考虑的质量属性包括可用性、性能、伸缩性、互操作性、安全性等等。其中大型移动互联网应用重点考虑的是性能、伸缩性和可用性。性能意味着应用要做到以用户为中心,提供快速的访问体验,衡量应用性能的主要参数有较短的响应时间,较大的并发处理能力,较高的吞吐量与稳定的性能参数。可用性代表移动互联网应用应该在任何时候都可以被正常访问,正常提供对外服务。伸缩性代表移动互联网应用可以在不改变原有架构设计的基础上,通过添加/减少硬件(服务器)的方式,适时地提高/降低系统的处理能力。
好的架构源于不断的衍变而不是设计,从来没有一个完美的架构能够一直支撑下去,架构是动态、实时变化的,在不断的变化过程中因为量变而发生质的变化,不同的阶段需要不同的架构。架构同样也是一个不断演进的过程,在我们这篇报告中,接下来将要介绍在各种应用背景下,为了应对各种不同的挑战而提出的各种移动互联网应用客户端架构。这其中包括MVC架构、MVP架构、MVVM架构等等。其中MVC架构是大部分移动互联网应用早期的选择,因为MVC架构“短平快”的开发优势,有助于帮助App快速占领市场,在MVC的体系架构中,Controller层负责整个APP中主要逻辑功能的实现;Model层则负责数据结构的描述以及数据持久化的功能;而View层作为展现层负责渲染整个APP的UI。分工清晰,简洁明了。然后,这种架构在开发的后期会由于其超高耦合性,造成Controller层庞大,而这也是一直被人们所诟病。最终的MVC都从Model-View-Controller走向了Massive-View-Controller的终点。这时就产生了MVP架构,将Activity复杂的逻辑处理移至另外的一个类(Presenter)中时,Activity其实就是MVP模式中的View,它负责UI元素的初始化,建立UI元素与Presenter的关联(Listener之类),同时自己也会处理一些简单的逻辑(复杂的逻辑交由 Presenter处理)。MVP架构相对于MVC架构,做到了模型与视图的完全分离,可以更高效的使用模型,同时可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。但MVP架构的代码还是不够优雅简洁,这时又产生了MVVM架构,其中的VM是ViewModel的缩写,ViewModel可以理解成是View的数据模型和Presenter的合体,ViewModel和View之间的交互通过Data Binding完成,而Data Binding可以实现双向的交互,这就使得视图和控制层之间的耦合程度进一步降低,关注点分离更为彻底,同时减轻了Activity的压力。在这里只是对这几种架构进行了一个简要的介绍,接下来,我们的报告中将会详细的对每一种架构的优缺点、适用场景等做一个完整的介绍与对比。
MVC是随着GUI开发的发展而出现的架构,由Model(数据读写、封装、存储、操作)、View(展示与交互)、Controller(转发与返回)三部分组成。
在MVC的实现中,view接受用户请求并将请求传递给controller,controller再调用某个model来处理用户的请求。在controller的控制下,将处理后的结果交给某个view进行格式化输出给用户。另外,View可以直接访问Model来进行数据的处理,这种操作可以通过观察者模式实现,即在view里设置listener,通过监听model里的逻辑操作来改变相应的数据展示。
MVC模式的出现极大便利了GUI软件的开发,但是由于移动互联网开发的特殊性,Android中的MVC仍然存在许多不足,主要体现在activity的臃肿和M&V之间的耦合性,需要进一步的改善。
MVC与三层架构的区别:
从根本目的上看,分层是为了解决整个应用程序中各个业务操作过程中不同阶段的代码封装的问题,为了使程序员更加专注的处理某阶段的业务逻辑;而MVC 主要是为了解决应用程序用户界面的样式替换问题,把展示数据的页面尽可能和业务代码分离。
从各层与各模块对比来看,分层模式的model主要是实体类,而mvc的model则包含了对数据的逻辑操作;分层模式的中间层logic负责业务逻辑,presenter负责界面展示,而mvc的controller既含有部分逻辑操作,也含有部分界面展示功能。
从层与层、模块与模块之间的交互来看,分层只能逐级调用,在mvc中view可以不通过controller直接访问model;如果修改接口,分层模式中只会逐级影响自己的直接上层,在mvc中model会同时影响controller和view;在分层模式中,各模块之间由上层持有下层的引用,而mvc中各模块相互持有。
本次课所讲的MVC是GUI开发中的MVC,要注意与服务端的MVC的区分。MVX框架都致力于解决V与M的交互问题,例如V向M请求数据,与M同步数据更新等,而X(MVC中为Controller)正是解决这一问题的方案。把握住这一点,就能理解MVC是应用于图形界面开发,而与服务端开发不同了。
MVP是对MVC的改良,由Model(数据读写、封装、存储、操作)、View(展示与交互)、ViewInterface(V的抽象接口)与Presenter(连接M与V)组成。
MVP的实现:声明一个由view来实现的接口,再将其注入到presenter中,然后将逻辑全部转移到presenter中,从而使view不再和model耦合,实现了控制逻辑和UI分离。从view接收到的请求传递给presenter,由presenter进行逻辑处理并转发至model,再将返回的结果交给view进行反馈。其中,Presenter可以不等待view的请求而主动调用view,从而实现异步交互。
在MVP里,Presenter完全把Model和View进行了分离,主要的程序逻辑在Presenter里实现。而且,Presenter与具体的View是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更View时候可以保持Presenter的不变。
优点:模块职责划分明显,层次清晰,也有利于数据的隐藏和测试驱动的开发;降低耦合度,实现了Model和View真正的完全分离,可以修改View而不影响Model;同时使View从特定的业务场景中脱离出来,只需提供接口,可以对业务完全无知,这样就可以使view组件高度可复用,进行界面开发时也可以专注于UI而无需考虑逻辑;由于对提供了view的抽象接口,Presenter也可以实现复用,一个Presenter可以用于多个View,而不需要更改Presenter的逻辑,提高了代码的灵活性。
缺陷:Presenter中除了应用逻辑以外,还有大量的View->Model,Model->View的手动同步逻辑,造成Presenter比较笨重,维护起来比较困难。由于对视图的渲染放在了Presenter中,视图和Presenter的交互会过于频繁,如果Presenter过多地渲染了视图,往往会使得它与特定的视图的联系过于紧密,一旦视图需要变更,那么Presenter也需要随之变更。此外相对于MVC,额外的接口也会带来更大的工作量与学习成本。
关于MVC与MVP的区别,除了最一目了然的M与V解耦,还要从controller与presenter的在功能实现上的不同来理解。并不是删除了V对M的直接调用,MVC就变身成MVP了。在MVC中, View捕获到用户交互操作后会直接转发给Controller,由后者完成相应的UI逻辑。如果需要涉及业务功能的调用,Controller会直接调用Model。在完成UI处理之后,Controller会根据需要控制原View或者创建新的View对用户交互操作予以响应。而在MVP中,Presenter包含了根据用户在视图中的行为去更新模型的逻辑。视图仅仅只是将用户的行为告知Presenter,而Presenter负责从视图中取得数据然后发送给模型。同时presenter也可以自主调用view的方法传递数据,从而使异步交互成为可能。
包括简易计数器的demo在内,多数MVP项目都是使用fragment与activity作为View,同时单独设置Presenter。但是activity和fragment的生命周期都很复杂,而且包含着一部分逻辑。GUI软件开发最理想的结果是将逻辑与展示层彻底分离,使界面只关注界面,而不关注任何底层实现。因而通用的MVP并不完美。所以一种新的想法出现了,即把UI的逻辑从上述两类中抽取出来,只剩下其他逻辑,然后将这两个类作为presenter使用。这种做法实现了视图层的进一步解耦,值得关注。
MVP模式在MVC模式的基础上,改善了模块间耦合的问题,提高了模块的独立性、可重用性、易修改性,给前后端的开发人员的独立工作带来了极大的便利。但是随着功能简化的activity变得轻便,逻辑与交互集中的presenter又开始变得臃肿与繁重。
本次使用的demo——简易计数器,由于逻辑简单,可以用简洁的代码将MVP的结构展示得一目了然,有利于同学们对MVP的代码实现的学习。同时也加入异步调用,展示了MVP的一些特性。但是由于demo功能过于简单且只有单一界面,其实并不能很好地体现出MVP相较于MVC的优越之处。如果使用一个有多界面且包含复杂的数据请求、更新等逻辑的app源代码,应当能更好地展示出MVC的缺陷与MVP的优势。
在课程报告中提出了MVC、MVP设计模式中可能存在的问题,由此引出了MVVM(Model–view–view model)软件架构设计模式。
MVVM组成部分包括模型(Model)、视图(View)、视图模型(View Model)。模型(Model)指的是代表真实状态内容的领域模型(面向对象),或指代表内容的数据访问层(以数据为中心),视图(View)就像在MVC和MVP模式中一样,视图是用户在屏幕上看到的结构、布局和外观,视图模型(View Model)是暴露公共属性和命令的视图的抽象。
MVVM的设计思想是利用WPF(Windows Presentation Foundation,微软推出的基于Windows 的用户界面框架)下的数据绑定(Data Binding)、依赖属性(Dependency Property)、命令(Command)、路由事件(Routed Event)等新特性,打造了一个更加灵活高效的架构。
最后我们为一个MVC模式的计数器Demo重新设计为MVVM模式,以此清晰地展示MVVM的数据绑定的特点。
MVVM旨在利用WPF中的数据绑定函数,通过从视图层中几乎删除所有GUI代码(代码隐藏),更好地促进视图层开发与模式其余部分的分离,使MVVM设计模式下的应用程序具有层次性。因此,应用程序的层次可以在多个工作流中进行开发以提高生产力。角色的分离使得交互设计师可以专注于用户体验需求,而不是对业务逻辑进行编程。用户体验(UX)开发人员不需要编写GUI代码,他们可以使用框架标记语言(如XAML),使UI与应用程序开发人员编写和维护的视图模型的数据绑定起来。即使一个开发人员在整个代码库上工作,视图与模型的适当分离也会更加高效,因为基于最终用户反馈,用户界面通常在开发周期中经常发生变化,而且处于开发周期后期。
WPF中的依赖属性有别于.NET中的属性,因为在WPF中有几个很重要的特征都需要依赖项属性的支持,例如数据绑定、动画、样式设置等。WPF绝大多数属性都是依赖项属性,只不过它是用了普通的.NET属性过程进行了包装,通过这种包装,就可以像使用属性一样使用依赖项属性。
命令是 Windows Presentation Foundation (WPF) 中的输入机制,它提供的输入处理比设备输入具有更高的语义级别。Commands 可以很好地与 MVVM 模式 (Model- View-ViewModel)结合在一起。视图(view)通过使用WPF 命令( Commands )来得知并调用与其绑定的视图模型(ViewModel),这是视图更新模型的一种机制。
为了降低由事件订阅带来的耦合度和代码量,WPF推出了路由事件机制。WPF把消息机制封装成了更容易让人理解的事件模型,一个事件包含3个关键点:事件的拥有者、事件的响应者、事件的订阅关系。路由事件与传统的直接事件的区别在于,直接事件激发时发送者直接将消息通过事件订阅交送给事件响应者,事件响应者使用其事件处理器方法対事件的发生做出响应、驱动程序逻辑按客户需求运行,而路由事件的事件拥有者与事件响应者之间没有直接显示的订阅关系,事件的拥有者只负责激发事件,事件将由谁响应它并不知道,时间的响应者则安装有事件侦听器,针对某类事件进行侦听,当有此类事件传递过来,事件响应者就使用事件处理器来响应事件并决定事件是否可以继续传递。简单地说,路由事件的原理是: 舍弃直接事件响应者,让不同的控件变成监听者。 而事件拥有者,只负责发出事件。
MVVM具有良好的可测试性。通常来说, 要进行界面测试比较困难, 比如在MVC架构中,我们不得不实例化一个完整的 Controller 以及伴随的 View , 然后去测试View 中的值。现在在MVVM的架构下,展示逻辑移入了View Model,表示逻辑与实际表示分离,然后对View Model的展示逻辑进行测试。
对MVVM模式优缺点的一些讨论
- 由于展示逻辑被抽取到了视图模型中,所以 视图的代码将会变得轻量级。
- 在可复用性方面,一个视图模型可以复用到多个视图中,同样的一份数据,可以用于不同的界面展示。
- 在可修改性方面,如果一个model 封装了大量业务逻辑,那么改变它可能会比较困难,并且存在一定的风险。在这种场景下,View Model 可以作为 model 的适配器使用,从而避免对 model 进行较大的改动。
- MVVM模式中,View Model只负责处理和提供数据,不涉及界面。 如果是MVP模式,遇到需要更改界面的场景,就可能需要改变接口。
- 数据绑定使得一个位置的 Bug 被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。 看到界面出现异常,有可能是 View 的代码有问题,也可能是 Model 的代码有问题 。
- 一个大的模块中,model也会很大,当时长期持有时,不释放内存,就造成了更多的内存花销。
- MVVM的创造者John Gossman本人对这种模式的批评指出,实现MVVM的开销对于简单的UI操作是“过度的”。他说,对于更大的应用来说,推广ViewModel变得更加困难。而且,他说明了非常大的应用程序中的数据绑定会导致相当大的内存消耗。
FRP(Functional Reactive Programming)作为一种编程风格或范式,与传统的event callback的方式在许多地方都有着不一致。对于高度复杂的业务逻辑,基于控制流来编写代码可能会非常的复杂且难以维护,而基于数据流就成为了一个新的角度,降低了编写复杂且容易变化的业务的困难性。
FRP的具体使用场景(Flicker,拖动,酒店价格计算)描绘了在FRP这样一种操作理念是如何在现实中被使用的,相关的流操作(merge, map, filter)相互组合,将复杂的需求转化为了对于一个或多个事件/数据流的操作。Filcker例子中的需求变更体现了FRP事件流操作面对需求时的灵活性,拖动图标的例子与事件回调机制形成对比,体现出了FRP的流操作在特定场景的优势,酒店价格计算的例子介绍了FRP在实际场景中的复杂运用。
限于课程时间,有一些额外的内容没有涉及,在此补充。
关于FRP和传统callback方式的优缺点对比并未详细提及,只介绍了对于那些适合流式建模的现实需求,用FRP可以展现优势。
更详细的说,在FRP的编程模型里,基本信号可以在不做任何修改的情况下被转换或者组合成新的复杂信号,而新的复杂信号又可以在不做任何修改的情况下被转换或者组合成更复杂的信号,就像乐高积木的搭建,这个过程可以一直进行下去,直到构建出足够复杂的信号以满足系统的需求。这是一种强大的组合能力(Composability)。
程序中注册的事件回调处理函数的返回值一般都是void或者是一个表示执行状态的状态码。不太可能让返回值可以随意使用各种数据类型,这是因为一个事件驱动框架要通用地处理各种callback,就只能让它的返回值类型足够通用,void便是首选。因此,回调与回调之间是无法直接传递类型丰富的数据的,它们只能通过修改应用程序的共享状态来间接地通讯,这迫使程序员不得不把应用逻辑分割得支离破碎,从而丧失了核心的组合能力。这便是callback风格程序的最大问题。
Callback模型关注控制流,但它对控制流的描述不具有很好的组合性。FRP模型换了一个视角,关注数据流,且数据流的组合能力极佳,使得代码更接近于只描述做什么(what)的声明式(declarative)代码,而不是描述怎么做(how)的命令式(imperative)代码,相当简洁和直观,更符合人的自然思维。
课上介绍的内容还是十分充实的,有丰富的例子,和传统情况下event callback的对比也能让同学们有共鸣感,不至于觉得FRP是一项遥远而无关的技术。并且FRP本身算是较为新鲜的技术,比较能吸引同学们的兴趣。
但是最需要修改的是FRP这一块的课后作业。FRP虽然有优势,但是并非绝对优于事件回调机制,某些场景并不适用FRP,所以课后作业的需求设计应该要足够适合FRP,让同学们在实践中体会FRP的操作方式与event callback的不同点。
围绕我们的计数器,我觉得比较好的一个作业需求是:修改计数器逻辑,200ms内连按两次ADD键才将数字加一,连按两次SUB键才将数字减一。这样的话,在做这可课后作业的时候,最起码要将事件流中的buffer, map, filter操作体现出来,这样才能让同学们真正用FRP的写法来实现一个需求,而不是单纯的修改某处的逻辑代码。
当我们使用上面所说的各种架构模式来帮助我们分解逻辑简化代码的时候,仿佛一切都变的简单起来,界面只用关注界面元素的布局,数据只需关注数据的内容,控制只需要将界面和数据之间对应关系搞清楚就好,一个团队可以很容易的合作编写代码。代码编写之后却会出现一个麻烦的事情:不同人的代码如何组合在一起?
无论是采用工厂类还是初始化的时候构建,复杂的对象之间的引用让再熟练的工程师也变得头疼起来,如何管理对象之间的关系以及对象的创建和回收变得极其重要。为了防止循环构建和引用传递的复杂性以及对象生命周期管理的问题、最小化代码合并所做的额外的工作,一个依赖注入框架必不可少。
依赖注入是实现控制反转的方式,通过控制反转,将成员对象的生命周期从调用方独立出来。此时调用方可以通过依赖来获取对象实例,并且加以使用,而不用关心对象怎么来的,使用完之后是否销毁等操作。基于这个思想,实现依赖注入的框架有很多,比如Spring,Guice等等,但是他们却因为配置文件复杂或者运行时对性能要求极高而不能在移动应用开发中加以使用,而基于编译时运行的Dagger框架完美解决了这个情况。
Dagger2是一个基于JSR-330标准的依赖注入框架,在编译期间自动生成代码,负责依赖对象的创建。它前期是基于Square开发的Dagger框架,相比较Dagger1,他取消了反射机制在图的验证、配置和预先设置都在编译的时候执行(Dagger1还是使用到了一部分反射,如图的这块),牺牲少量灵活性的基础上,使用Builder模式,Factory模式变得更加容易调试和可跟踪,有更好的性能。Dagger2目前成为客户端代码使用依赖注入的主流选择。
Dagger2中主要是用两个注解来进行定位:@Component和@Inject来定义依赖关系,可将注解配置到方法或者成员变量来说明如何使用。这点在课上已经通过代码来进行了讲解,并且给出了使用和未使用框架的代码对比。这两个注解是对Dagger2框架的最基本的使用,Dagger2框架还提供了其他的注解来实现更多的功能。下面对Dagger2框架的其他功能进行详解。
-
@Provides 和 @Module
我们在使用第三方插件的时候,我们需要在代码中引入相关类,但是第三方封装好的实现,我们并不能在其源码上进行修改添加@Component注解,这是我们需要这两个组件来辅助我们创建对象。使用@Module描述类来声明模块,在模块内部使用@Provides声明方法来提供对象,此时被声明的方法中需要返回相关类的实例。@Module在使用时,需要在@Component的注解中添加module这个参数来绑定Component和Module的对应关系
-
SubComponent
面向对象的特点之一便是继承,我们可以用@SubComponent中声明依赖的Component来进行扩展重用。但是笔者认为组合优于继承,不建议大家使用
-
@Singleton
顾名思义,@Singleton注解是声明一个单例,可以保证对象在整个运行期间是保证唯一的:比如数据库连接类,网络控制服务类。使用的时候用 @Singleton 标注在目标单例上,然后用 @Singleton 标注在 Component 对象上。
-
@Scope
Scope 的字面意思是作用域,也就是表达一种能力的范围。@Scope用来对对象的生命周期来进行限制,可以用@Scope来自定义注解,在声明注解的时候加上生命周期的现实。@Singleton就是@Scope注解的一个特殊实例,能够起作用是因为它被 @Scope 注解。
-
@Qualifiers 和 @Name
在我们的Module中的@Provides 提供的依赖是由返回值决定的,但是对于同一种类型不同实例,我们就需要用@Name来给类型的不同实例提供别名。使用Name之后我们调用的时候调用类型的时候,如果有多个实例,会根据Name的不同属性来确定具体返回哪一个对象。而使用@Qualifier可以来自定义注解,用自定义注解可以将Name的属性值独立出来统一管理,避免在代码中编写过多的Name的属性值,难以管理,修改。
Dagger2框架在2012年诞生之后,伴随着Google推广的MVP+Dagger2的架构组合,Dagger2开始被广大程序员所青睐。尤其是在近两年,Android应用的结构越来越复杂、功能越来越多,模块开发已经成为不可阻挡的趋势,使用Dagger来松耦合模块也被更多的使用。Dagger2在Google公司的努力下,更加适配Android系统的Dagger Android也出现了,让依赖注入在Android开发生态中扮演着不可缺少的一环。相信在未来,Dagger会被越来越多的公司和开发者来使用。
万丈高楼平地起。在架构演进的过程中,小到核心模块代码,大到核心架构,都会不断演进,这个过程值得我们去深入学习和思考。下面以两个亿万级APP为例介绍大型项目构是如何进行优化和演进的。
一个典型的Android应用在从小到大的成长过程中的“踩坑”与“填坑”的历史。
微信1.0 for Android的测试版本于2011年1月发布。这是微信Android客户端的第一个版本,软件架构采用早期标准的Android系统应用设计。
微信的快速增长,从2.0版本开始第一次爆发。从语音版,到附近的人、漂流瓶,再到摇一摇。3.0之后的每一个小版本都处在一到两周的高速迭代过程中。
代码、内存、apk大小都在膨胀,这其中,内存对消息收发的影响很关键。如何解决?微信选择的,是轻重分离的思路。通过在微信3.5版本时候做的架构重构,实现了不受功能增长、系统缺陷影响的稳定推送方案。
微信在高速发展过程当中,到5.0的时候已经有很多功能,而其中一些功能,随着用户群体、产品设计等因素变化,用户使用的频率在改变。之前试错的一些功能,也大量存留在微信版本中。这些不常使用的功能不应该始终占用程序资源,从架构上进行纵向分离,保证主要场景的体验,是这一时期的主要设计思路。
进入到2015年后,微信在软件架构上逐渐趋于平稳。内部也放弃了沿用许久的ant + eclipse,全面转向gradle + Android Studio的分布式构建思想。通过内部开源,微信内的公共组件已经可以通过maven在不同的开发团队中共享并随时使用。
阿里巴巴打造的不是一个软件系统平台,而是一个电子商务操作系统。这样的电商操作系统,支撑了过去10年的快速发展。同样,阿里在移动端也在重新思考如何继续升级,如何在手机APP中完成生态建设。
从2009年开始,DAU从100万增长到超过1亿,面临的问题、包括研发支撑所需要解决的事情各不相同。在用户量和业务复杂度的线性递增下,架构也进行了相应的演进。如下图所示,具体可以分为四个阶段:
随着应用数量的增多,每个应用分别暴露的API出口很多,修改的话逻辑很复杂,这时候应该引入一个统一的网关。
下图是现在手机淘宝上关于HTML5的整体框架图。手机淘宝上的方案大致分为两部分,中间那一部分是手机淘宝自己开发的HTML5的运行容器,它负责在上面跑各种各样的WebApp,在线上有一个统一发布管理系统。
跟之前最大的区别就是让用户感知不到前面同步下载的过程,大概的做法是:把HTML5以及WebApp在发版之前先做一些预知放到客户端里面,前面会做两件事情,首先按照原来的逻辑运行,其次就是在右侧的蓝图里面。

近几年,业内一些知名度较高的应用都分享了各自的应用架构,微信和淘宝只是其中之二。做架构之前,要想清楚这样设计的目的是什么,通过架构设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合,做到基本符合迪米特、依赖倒置、里氏替换、接口隔离等原则。这样做的好处是使得程序在开发的过程中,开发人员只需要专注于一点,提高程序开发的效率,并且更容易进行后续的测试以及定位问题。但设计不能违背目的,对于不同量级的工程,具体架构的实现方式必然是不同的,切忌为了设计而设计,为了架构而架构。
缺少从微信和淘宝的例子中以小见大,总结出如今成功App的演进规律、新开发的技术和遵循的法则。架构是非常值得分享和讨论的,好的技术架构能够持续支持伟大的商业梦想。但是无论什么优秀的可扩展性好的技术架构,都不能脱离于业务而存在,最终都会随着业务的不断发展,而同时其架构也在进行不同程度的演进与优化。一个好的架构首先是必须是能解决公司遇到的现实技术问题和符合满足公司目前架构技术现状,其次能带来技术性的革新从而引领业务的发展。
本次报告围绕着移动应用的发展描述了应用架构的特点,MVC、MVP等设计模式的演变,架构开发用到的方法、编程原则和一些大型App的架构演进史。以小见大,见微知著,好的架构决定好的产品,而大型架构也是遵循着“面向接口编程”,“单一职责”,“高内聚低耦合”等原则构建模块,一砖一瓦堆砌成的。对架构的学习和思考告诉我们不论工作、生活中都要学着将复杂的事情分离,减少每项任务间的交叉,要不断的更新对自己的认识,做出更加合适的决策。 反思:在多人报告中缺乏每个人内容上的承接和整体的把握;在内容上可以有更加丰富的扩展而不是概念的陈述。






