作为一个移动端开发我员就知道移动端很少有架构师这个职业,很少有公司会招移动端架构师。移动端开发并不像后端开发那样久远,它的发展也是由 Android、iOS 的出现才兴起的,也没有什么高并发、高可用之类的术语。一直以来,除了大厂,大部份移动端关注更多的是UI、UX方面的问题。
一、移动端架构的发展
在早些年的时候,移动端是没有所谓的架构可言,很大的原因是因为移动端开发刚刚兴起,刚刚兴起意味着“代码存量少”,意味着软件复杂度相对于传统的服务端开发更低。但随着越来越多的大型 APP 的出现,业务越来越复杂。为了更好的组织移动端的代码,才将传统的软件架构移到了移动端开发上面。
一个 APP 的初始阶段,必然是先满足各种业务需求。然后,经过多次版本迭代之后,先前的由于急于满足需求而导致的杂乱代码则会充斥整个项目。而此时,项目有了一定的规模,有了一定数量的开发人员,那么为了达到快速迭代版本的需求,则是需要有一个强大的架构来支撑。
为什么需要架构:
- 一个 Activity 走天下,包含各种模块和功能
- 不同功能,不同层次拎不清楚,混合在一起
- 臃肿类太多,重复代码太多,复用性为差
- 耦合严重,无法协作开发,Bug 太多
车轮滚滚,到如今,移动端架构百花齐放,那么我们要思考,是否每个产品都需要架构吗? 每个产品都有自己不同的定位,“ 一个好的 APP 就是需要有好的架构,如果没有一个好架构,那么这个 APP 就会让人感觉很 Low”,这句话显然抛开产品的业务需求去谈如果给它们设计一个良好的架构,这纯属无稽之谈。
二、移动端架构师的职责
2.1 移动架构师职位描述
通过搜索各招聘平台上对移动端架构师的要求,列出了一些:
- 参与需求分析,设计和搭建移动项目架构
- 负责移动应用客户端总体架构、组件设计和技术路线确定,及核心业务模块的研发和技术攻关
- 负责移动应用客户端相关业务架构、应用架构、数据架构、技术架构设计
- 负责移动应用客户端交互架构设计和实施,含通信、安全、风控、流控、客户端灰度发布、ABTest方案、策略下发、数据埋点/采集/分析等
- 提升移动应用客户端的速度、稳定性和研发效率,解决各类潜在系统技术风险加固系统,保证系统的安全、稳定、快速运行
- 研究业界的技术发展、评估外部技术与解决方案
概括起来就是:改进过去架构,设计当前架构,前瞻未来架构。
架构师不仅仅是写代码、设计优化架构,还需要对老板汇报技术规划、对团队宣讲,打造技术氛围、提升团队整体技术水平,打造团队技术影响力,甚至负责招聘吸引更多的人加入团队等。
2.2 移动架构师任职要求
- 本科及以上学历,5年以上移动端研发经验,有2年以上移动端架构设计经验,具有良好的英文阅读能力
- 熟悉objective-C、Java语言,对面向对象的开发有深刻认识,有多个完整的 Android/ios 项目经验
- 熟悉iOS、Android开发模式,掌握相关框架及原理,对UI,网络,数据库,XML/JSON解析及功能的实现方式了解
- 熟悉常用软件设计模式,熟悉各种算法与数据结构,多线程,网络编程(socket、http/web service)等
- 注重细节,有独立解决问题的能力,有责任心
- 较强的表达和沟通能力,工作认真、严谨、敬业,能够带领团队
架构师立命的根本还是技术,所以在移动开发技术上研究的事情都要尝试去做。
2.3 移动架构师任职要求素质
2.3.1 技术能力方面
不管是移动端架构师还是传统的架构师,首先必须是技术方面的专家兼全才。专家和全才如果不能兼得,那更偏重于全才一些。只有有了对全局的把握,才能更好的制定整体的框架。比如,2个开发语言选哪个更加好,只有2种语言都有一定的了解,才能做出明智的选择。所以,架构师必须懂得很多,而且每个方面,虽然不要求很熟悉,但是必须有相当的了解,而不能泛泛而谈。
2.3.2 沟通能力方面
作为架构师,绝不是一个人在战斗,所以沟通能力也是必须的。沟通能力包括表达能力和理解能力。与客户沟通,确认需求,理解能力很重要。与底下的工程师沟通,用工程师能理解的语言,说清楚需求、方向,直接关系到项目技术上的成败。与上级领导沟通,让领导时刻了解情况,给予必要的支持,这也是架构师的重要工作内容。
三、架构的进化
在自已的职业生涯中,有看到有的人在开发伊始就开始想着后期要怎么扩展,设计无比复杂的架构,最终导致开发起来非常痛苦,为了实现一个功能,写各种各样冗余的类,做各种各样重复的事情,导致效率低下,“过度设计” 是架构设计可能犯下的第一个错误。那如何做恰当的架构设计?第一步先不用去考虑需要什么架构,而是应该思考你这个项目的核心业务是什么,再考虑为了实现这个核心业务,最大最重要的技术点是什么? 所谓 “业务即架构”。
架构就像是一场进化史,根据不同时期的需求,演变出不同的架构。从最开始的 MVC 到 MVP、MVVM,以及综合各种概念的 CLEAN 架构。
3.1 MVC(Model-View-Controller)
- Model(数据层):负责处理数据逻辑
- View(视图层):负责处理视图显示
- Controller(控制层):负责处理业务逻辑
人们刚接触编程,相信第一个遇到的框架就是 MVC,不管你经意还是不经意写出来的 Android 程序他就是 MVC 框架,只不过是 MVC 框架的某一个变种(最混乱的那种)。Android 系统本身就根据 MVC 建造的。
- XML 的 View 层
- Activity/Fragment 的 Controller 层
- 数据 Model 层
优点:
由于 MVC 很好的分离了视图层和业务层,所以它具有以下优点
- 耦合性低
- 开发速度快
- 可维护性高
- 易于理解
缺点:
由于 MVC 的设计思想是从 Model 出发,而没有考虑到 View 端的复杂性,这样导致的问题是 Model 难以符合复杂多变的 View 端变化。导致 Model 的作用很小,而很多 View 层的职责也转移到了 Controller 层。Controller 变得臃肿不堪。耦合性也变高了。另外,测试困难。
3.2 MVP(Model-View-Presenter)
MVP(Model-View-Presenter)是 MVC 进一步演化出来的,由 Microsoft 的 Martin Fowler 提出。
- Model(数据层):负责处理数据逻辑
- View(视图层):负责处理视图显示
- Presenter:负责连接 Model 层和 View 层,是这两层的中间纽带,负责处理业务逻辑
大家都在 Activity 里面处理逻辑因为太方便了,但是这样之后,我们 Activity 的职责太多了,耦合也严重,所以就想着怎么能给 Activity 减负,同时把耦合也降下来,所以就想找个人来替 Activity 分担的责任,大家最后都只有一个责任,各层关系也相对好理解,大家照着这个方式写。所以引入了 Presenter 来处理事务,有啥事都找 Presenter,MVP 是一个真正意义上的隔离 View 的细节和复杂性的模式。Model 层和 View 层之间不能有交互,要通过 Presenter 层进行交互。
优点:
- 模型与视图完全分离
- 可以更高效地使用模型,因为所有的交互都发生在一个地方—— Presenter 内部
- (Presener的复用)一个Presener可以用于多个视图(View),而不需要改变 Presenter 的逻辑。视图(View)的变化比模型(Model)的变化更频繁的多 ,所以这样就很方便
- (View的复用)View 可以进行组件化。在 MVP 当中,View 不依赖 Model。这样就可以让 View 从特定的业务场景中脱离出来,可以说 View 可以做到对业务逻辑完全无知。它只需要提供一系列接口提供给上层操作。这样就可以做高度可复用的 View 组件
- 更容易单元测试
缺点:
- Presenter 中除了业务逻辑以外,还有大量的 View -> Model,Model -> View 的手动同步逻辑,造成 Presenter 比较笨重,维护起来会比较困难
- 由于对视图的渲染放在了 Presenter 中,所以视图 View 和 Presenter 的交互会过于频繁。特别是需要修改视图的时候,Presenter 也需要跟着修改,很麻烦
- 其实总的来说就是结构很清晰,业务逻辑也很明白,耦合低,但是就是自己写的麻烦,Presenter 不好维护,工作量太大,太笨重,有点像 MVC 中的 Activity 了,职责太多了
3.3 MVVM(Model-View-ViewModel)
MVVM(Model-View-ViewModel)是 MVP 进一步演化出来的,它也是由 Microsoft 的 Martin Fowler 提出。
- Model(数据层):负责处理数据逻辑
- View(视图层):负责处理视图显示
- ViewModel:负责连接 Model 层和 View 层,是这两层的中间纽带,负责处理业务逻辑,View 层和 ViewModel 层是双向绑定的,View 层的变动会自动反映在 ViewModel 层,ViewModel 层的变动也会自动反映在 View 层
MVVM 模式中,一个 ViewModel 和一个 View 匹配,它没有 MVP 中的 IView 接口,而是完全的和 View 绑定,所有 View 中的修改变化,都会自动更新到 ViewModel 中,同时ViewModel 的任何变化也会自动同步到 View 上显示。这种自动同步的原因其实就是是 ViewModel 中的属性都实现了 observable 这样的接口,也就是说当使用属性的 set 的方法,都会同时触发属性修改的事件,使绑定的 UI 自动刷新。
在 Andndroid 中 DataBinding 帮助我们实现 MVVM,在 XML 进行数据绑定,增加了 XML 的重量,不再像以前那样仅仅是布局,均衡了各部分的职责。所以 MVVM 比 MVP 更升级一步,在 MVP 中,V 是接口 IView, 解决对于界面 UI 的耦合; 而 MVVM 干脆直接使用 ViewModel 和 UI 无缝结合, ViewModel 直接就能代表 UI。
优点:
解决了 MVP 大量的手动 View 和 Model 同步的问题,提供双向绑定机制。提高了代码的可维护性
简化测试
响应式编程更方便
缺点:
- 过于简单的图形界面显得大材小用
- 视图状态较多,ViewModel 的构建和维护的成本都会比较高
- 数据绑定的声明是指令式地写在 View 的模版当中的,这些内容是没办法去打断点 debug 的
3.4 CLEAN
Google 官方的话说来就是:独立
- 独立于框架。该体系结构不依赖于某些特征库软件库的存在。这允许您将此类框架用作工具,而不必将您的系统塞入其有限的约束中。可测试。可以在没有UI,数据库,Web服务器或任何其他外部元素的情况下测试业务规则
- 独立于 UI。UI可以轻松更改,而无需更改系统的其余部分。例如,可以使用控制台 UI 替换 Web UI,而无需更改业务规则
- 独立于数据库。您可以换掉 Oracle 或 SQL Server,用于 Mongo,BigTable,CouchDB 或其他东西。您的业务规则未绑定到数据库
- 独立于任何外部机构。事实上,您的业务规则根本不了解外部世界
Clean将核心业务(Domain 层)、UI相关(Presenter 层)以及数据加载(Data 层)彼此独立开来,不同的层之间由接口依次连接起来,但却又彼此不了解彼此的具体实现。
优点:
- 代码复用性更高
- 更易于测试
- 耦合度更小
缺点:
- 学习难度大
- 代码量大
Clean 架构为什么知道的人少,即用得少呢,因为太复杂了,把 Java 那套全部搬到移动端。
3.5 MVX总结
从 MVC-> MVP -> MVVM -> MVP -> Clean 后者解决了前者遗留的问题,把前者的缺点优化成了优点。一代更比一代强,但是都是需要代价的,学习成本更高,更加规范,但是并不一定就谁比谁更好,只有谁更适合你的项目,都有优劣,怎么选择需要靠自己了。其实 MVX 系列的本质一直未变:
- 关注点分离原则
- 高内聚低耦合原则
四、移动架构师的扩展
移动架构设计和选型应该遵守以下几个原则:
- 优先保证业务逻辑
- 架构设计遵循简洁的原则
- 架构的学习成本不要太高,需要符合当前技术团队内开发人员的能力范围
- 架构是在开发过程中不断扩充和维护的,代码重构也是架构的核心之一
同样道理,围绕着最核心的业务、最核心的技术点去设计架构才是最重要的。
- 对于一个以 H5 为主的 APP,最重要的架构设计是设计好 H5 和原生的交互方式,如何快速的加载出 H5 页面
- 对于一个以主要以图片加载为主的 APP, 最重要的核心技术点就是大量图片的加载,好的图片加载框架,项目已经成功了一半
- 对于一个本地数据库为主的 APP,如何设计好本地数据库的读取和存储,如何选择一个适合的轮子去处理好数据库存在的问题,才是最根本的架构设计
最简单的就是最好的,最简单的东西往往最有力量。越是简单的架构设计,越容易学会,合作的同事越容易接受,就像代码设计,自解释的代码比写满了注释的代码设计的要更好。
五、总结
移动架构师是一个充满挑战的职业,移动端涉及的语言多、领域广,知识面的宽窄往往决定着一个架构师的架构能力。架构师从来都不是看书看来的,需要长久的实践与累积。最好的方式就是在工作中累积。需要有耐心,不断学习,拓宽自己的视野。
思考:
- 这个项目是为了解决什么问题而生的,提供了什么样的功能?
- 它是如何实现的?有哪些小的功能模块组成?它们是怎样解耦的?如果我有扩展需求,我该如何改?
- 为什么会这样来实现?有没有更好的方案?
六、扩展
6.1 Android 架构师技术介绍
架构与设计 | 设计模式 |
---|---|
重构 | |
网络编程框架 | HttpClient |
HttpURLConnection | |
Volley | |
OkHttp | |
Retrofit | |
UI架构模式 | MVC |
MVP | |
MVVM | |
版本控制系统 | SVN |
Git | |
Gitlab | |
Github | |
调试工具 | ADB |
DDMS | |
Stetho | |
LeakCanary | |
ClassyShark | |
Postman | |
性能优化 | 启动优化 |
代码优化 | |
内存优化 | |
电量优化 | |
布局优化 | |
网络优化 | |
CodeReview工具 | Gerrit |
Phabricator | |
构建工具 | Gradle |
Buck | |
移动安全 | 代码和资源混淆 |
反编译 | |
密钥管理 | |
安全编码 | |
应用加固 | |
专项技术 | APP 瘦身 |
MultiDex | |
插件化 | |
推送技术 | |
Crash 统计 | |
函数式编程 | |
在线热修复 | |
AOP | |
依赖注入 | |
SDK化 | |
跨平台 | Flutter |
React Native | |
单元测试 | JUnit |
Robolectric | |
Mockito | |
UI自动化测试 | Monkey |
MonkeyRunner | |
UIAutomator | |
Robotium | |
Espresso | |
Appium | |
持续集成 | Jenkins |
Travis CI | |
fastlane | |
静态代码扫描 | CheckStyle |
FindBugs | |
PMD | |
Android Lint | |
Infer | |
编程语言 | Java |
C | |
C++ | |
Javascript | |
Groovy | |
Kotlin | |
持续学习 | 周边技术 |
产品交互设计 | |
后端技术 | |
HTML5 | |
iOS | |
移动测试 | |
跨平台 | Flutter |
React Native | |
项目管理 | 边界思维 |
过程思维(WBS) | |
风险思维 | |
干系人思维 | |
整合沟通 | |
团队管理 | 招聘面试 |
梯队培养 | |
技术规划 | |
团队规范 | |
个人管理 | 技术博客 |
技术分享 | |
会议演讲 | |
领导力 |