我们经常在感叹,技术更新换代太快,但是不管怎么变,永远不变的一个核心思想就是“调用更加方便、更加安全、架构清晰,代码简洁、反对臃肿、代码之间的耦合度更低”,这是一个好的软件永远追求的目标。
本文出自门心叼龙的博客,属于原创类容,转载请注明出处。https://blog.csdn.net/geduo_83/article/details/88937994
忙了将近两个月,也算告一段落,一直打算写一篇关于项目架构方面的文章,也是对这段时间工作的一个归纳总结,正好清明节放了三天假,难得有时间...
一周科技杂谈:
上个周,王兴团长在接受境外媒体参访的时候,旧事重提了当年支付宝独立的陈芝麻烂谷子的事儿,指责马云有诚信问题,这件事儿其实和美团一点关系都没有,这事儿还不够,又发了一个朋友圈对阿里的人事进行指手画脚,给阿里指定“太子”。去年还是东哥的舆论场,如今却变成了王兴舆论场,众所周知,东哥由于明尼苏达事件已经是身败名裂,现在是彻底退居二线了,东哥现在确实低调了很多,微博个性签名都改成了,“低调,低调,在低调”。
我们还记得在2017年乌镇世界互联网大会上东哥和王兴组了声势浩大晚宴“东兴”局,照片一出,马云腾C位正襟危坐,左右分别是刘强东和王兴,其他各互联网大佬都列作于此,唯独不见马云,明眼人都能看出来,这就是要孤立马云,随后刘强东参加了“共享红利--互联网精准扶贫”的论坛,刘强东讲到:“有人说一个月赚几十亿已经成为让人痛苦的事情,在我国还有几千万的生活在极端贫困的状态,这是中国已经富起来的这些人的耻辱”,很明显这话是在怼马云。
事后,马云在接受媒体采访时说“我马云岂能是一场饭局就能击垮的,我可以把世界级的大佬邀请来,也搞一个有必要吗?没有”,这就是马老师的格局,随后刘强东异常高调,但是还不到一年的时间,就出了刘强性情事件的丑闻,估计马云听到这事情会大笑三天三夜。现在东哥消停了,王团长又来了,不管是蹭热度还是有其他什么目的,但是在公开场合作为企业创始人公开怼别人,这就是你的不对了,俗话说:“凡事留一线,日后好见面”,刘强东的事儿虽然没有触犯法律,但是却彻底失声了,自己也是身败名裂,企业形象严重受损,有人说被人“做局了”,我想无论是有没有被“做局”,但是事情你终归还是做了,就是被人做局,也是别人抓住了你的人性的弱点。用当年上大学时宿舍里面经常说的一句陕西口头禅:“娃是好娃,女人把娃害了”。
企业之间竞争不可避免,搞团团伙伙,拉帮结派,公开怼,这就有些太小肚鸡肠,小人形象暴露无遗,刘强东彻底消停了,王兴又来了,我想这小子会不会是下个东哥?平日除了研究技术,最大的爱好就是写毛笔字练书法,最爱写的八个字就是,“上善若水”、“厚德载物”,水利万物而不争,君子以厚德载物,如果德不配位,早晚遭殃。
项目架构的重要性:
好了,我们言归正传,我们在前面几篇文章谈到了一些项目架构的问题,年前写了一篇“Android组件化最佳实践”,年后写了一篇“浅谈单一结构体项目的组件化改造”,我们提到了单一结构项目里,结构混乱,层次不清,有些模块同一功能解决方案不统一、有了新需求只是在原有项目上不断的砌代码罢了。长此以往,整个项目就是铁板一块,为后期的项目维护和扩展造成了极大的困难。
我们在软件开发的时候,在做一个项目之前,架构师做工作就是搭项目框架,这是一个前提工作,给整个项目制定开发标准,开发规范,如果没有规范,项目可以搞起来吗?当然可以,就是个开发人员各行其是,最后的结果就是,项目做完了,整个项目结构混乱,层次不清。反之,一旦形成自己的一套框架体系,就可以长期使用,甚至成为整个公司的一套开发标准,大大提高后期的项目开发效率,来了新项目就直接可以在新项目中使用,而把主要的精力放在业务功能的实现上。
架构的变:
前阵子在一个技术群里面,有人说他们现在还用的是传统的架构MVC的架构,觉得挺好,甚至还在用ListView,我只能说,你感觉良好就行,有这种情况吗?肯定有,以前的一些老技术,老方案,能实现吗?当然可以,可以实现具体的开发要求,就好比你去理发店理发,你进店之后,前台就会问你,你要找那个老师给你理?我们这里有20块的,也有50块,最高是200块的,问你要选一种?20块也能做,200块也能做,价格却整整差了10倍,为什么?这就是不同老师他们水平不一样,做法不一样罢了,你20元有20元的做法,你200元当然有200元的做法,我们做软件开发也一样,同一个项目,你给两千元有两千架构的做法,你给二十万也有二十万元的架构的做法,最终功能都能实现,只是软件质量不同罢了。
架构的不变:
在后移动时代我的一些思考的这篇文章里,我们谈到这是一个知识爆炸的时代,尤其是做技术这一行业的,不像一些传统的行业,例如医生、律师这些知识结构相对稳定的行业,做技术的我们时常会深深的体会到技术更新换代太快了,我们一项新技术还没有研究透彻,就又有新的技术来替代它了,但是不管技术怎么变,但是永远不变的一个核心思想就是“调用更加方便、更加安全、代码之间的耦合度更低”,这是一个好的软件永远追求的目标。
代码质量问题:
同样的一个功能初级工程师能实现吗?可以,高级工程师可以做吗?当然也可以,有何不同?可能高级工程师1个小时就能实现的功能,作为一个初级工程师可能需要1天时间才能完成,一个高级工程师可能需要50行代码实现的问题,初级工程师可能花了两三百行才能搞定,高级工程师实现的功能bug率很低,而初级工程师可能一测试到处都是bug,这就是区别,这就是软件的质量不同。
当然,在实际工作当中有很多时候,项目需要赶进度,领导看的是结果,就看你功能实现了没有?你没有办法,只能选择做20元了,因为你想要做好,你就需要花更多的时间了,而现在没有人给你这个时间去做这个工作。
代码简洁之道:
在唐代有一位大诗人叫白居易,他每作一首诗,都要给不识字的老太太念念,老太太能听懂的,就要,听不大懂的,就改,这也是为什么他的诗一直在民间广为流传,而且还流传到了日本,而我们写代码也是一样的道理,越简单也好,我曾经看过别人写的一个关于app应用市场下载的功能,一个简单的功能搞了十几个类,各个类之间层次不清,引用关系混乱,实在让人看不下去,一个好的工程师,不在于你写了多么复杂的功能,而在于你写了一个多么好的功能,代码简洁,结构清晰,人人都能看懂,这才是好代码,反对臃肿,真正的做到了简约而不简单,这才是编码高手。
Android应用架构发展史:
一代MVC架构:
- Model: 用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法
- View: 渲染页面
- Controller: 控制器,他是M和V之间的连接器,处理相关的业务逻辑
标准的MVC架构它的工作流程:
- View接受用户的交互请求
- View将请求转交给Controller
- Controller操作Model进行数据更新
- 数据更新之后,Model通知View数据变化
- View显示更新之后的数据
MVC工作流程图:
在最早从事android开发这批人员,最早使用的是都是MVC架构,这是一种非标准的MVC架构,因为Activity及承担Controller的角色,又承担了View的角色。Activity 和 Fragment 越来越多的同时承担了 Controller 和 View 的职责,导致他们变得及其臃肿且难以维护,由于 Controller 和 View 的揉合,回调嵌套太多,代码逻辑不清晰,难以理解且不利于后期维护,各层次模块之间职责不清晰等等。
二代MVP架构:
在2016年,Google 推出的基于 MVP 架构的 Demo 后,我们发现 MVP 架构能解决现在所面临过的很多问题
MVP工作流程图:
- View接受用户的交互请求
- View将请求转交给Presenter
- Presenter操作Model进行数据库更新
- 数据更新之后,Model通知Presenter数据发生变化
- Presenter更新View的数据
MVP架构图如下:
- View Layer: 负责绘制UI元素、与用户进行交互,对应于xml、Activity、Fragment、Adapter,包含一些自定义的 UI 组件
- Model Layer: 负责检索、存储、操作数据,包括来自网络、数据库、磁盘文件和SharedPreferences的数据
- Presenter Layer: 作为 View Layer 和 Module Layer 的之间的纽带,它从 Model 层中获取数据,然后调用 View 的接口去把数据显示在View上
- Contract: 参照 Google 的 Demo 加入契约类 Contract 来统一管理 View 和 Presenter 的接口,使得某一功能模块的接口能更加直观的呈现出来,这样做是有利于后期维护的。
尽管这样,MVP模式也有不足之处,不然也不会推出MVVM了,缺点如下:
- Presente层与View层是通过接口进行交互的,View层可能会有大量的接口,因为有可能好几个Activity都是去实现同一个View接口,那么所有用到的Activity都要去实现所有的方法(不管你是否用到),而且如果后面有些方法要删改,Presenter和Activity都要改动,比较麻烦;
- MVP把Activity相当的一部分责任放到了Presenter来处理,复杂的业务同时也可能会导致P层太大,一旦业务逻辑越来越多,View定义的方法越来越多,会造成Activity和Fragment实现的方法越来越多,依然臃肿。
三代MVVM架构:
相对于 MVC 的历史来说,MVVM 是一个相当新的架构,MVVM模式不是四层,任然是3层,分别是Model、View、ViewModel,MVVM 在使用当中,通常还会利用双向绑定技术,使得 Model 变化时,ViewModel 会自动更新,而 ViewModel 变化时,View 也会自动变化。所以,MVVM 模式有些时候又被称作:model-view-binder 模式。
MVVM 在实际使用中,确实能够使得 Model 层和 View 层解耦,但是如果你需要实现 MVVM 中的双向绑定的话,那么通常就需要引入更多复杂的框架来实现了。
- View:视图层,采用XML文件进行界面的描述
- Model:模型层,通过网络和本地数据库获取视图层所需数据
- ViewModel:视图-模型层,负责View和Model之间的通信,以此分离视图和数据
工作流程:
- View中使用DataBinding的Command来绑定事件和响应事件,触发网络请求
- ViewModel进行分析处理,调用Model的方法去请求数据
- Model将收到的请求参数等信息封装,调用网络请求库
- 服务器将数据返回Retrofit等网络库,再返回到Model层中
- ViewModel在回调中收到返回的实体类对象
- 因为xml与实体类对象实现了双向绑定,实体类更新,使得UI更新
MVVM也存在着自己的一些缺点:
- 数据绑定使得 Bug 很难被调试。你看到界面异常了,有可能是你 View 的代码有 Bug,也可能是 Model 的代码有问题。数据绑定使得一个位置的 Bug 被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了
- 对于过大的项目,数据绑定需要花费更多的内存
某种意义上来说,我认为就是数据绑定使得 MVVM 变得复杂和难用了
四代架构MVP+组件化
前面讲的这三种android开发中常用的项目架构,不管是哪一种架构,它始终是一个单一结构体项目,各个模块之间还是以传统的包名来区分的,其各个模块还是强耦合在一的,自然而然组件化的方案就出现了,组件化有开发模式和发布模式之分,在开发模式下每个业务模块都是都是一个独立的apk,在发布模式打包的时候,每个业务模块都变成了一个个独立的组件library,这就完成了各个模块之间的彻底解耦。
今年开年以来公司就上了一个新项目Vcars,就采用了MVP + 组件化的解决方案,现在通过文字的形式把它记录下来,也是对这段时间工作的一个归纳总结。
Vcars组件化架构图:
- 集成模式:所有的业务组件被“app壳工程”依赖,组成一个完整的APP;
- 组件模式:可以独立开发业务组件,每一个业务组件就是一个APP;
- app壳工程:负责管理各个业务组件,和打包apk,没有具体的业务功能;
- 业务组件:根据公司具体业务而独立形成一个的工程;
- 功能组件:提供开发APP的某些基础功能,例如打印日志、下拉刷新控件等;
- Main组件:属于业务组件,指定APP启动页面、主界面;
- Common组件:属于功能组件,支撑业务组件的基础,提供多数业务组件需要的功能
Vcars项目类图
-
Activity关系图:
-
Fragment类关系图:
-
BaseRefreshActivity类图:
-
BasePresenter类关系图:
-
BaseModel类关系图:
总结:
整体来看MVVM 比MVC/MVP精简了很多,不仅仅简化了业务与界面的依赖,在MVVM中,View不知道Model的存在,ViewModel和Model也察觉不到View,这种低耦合模式可以使开发过程更加容易,提高应用的可重用性。
不管是MVC,MVP还是MVVM,他们都属于项目的编码架构,而组件化是整个工程的工程架构,它的主要意义在于,对原来以包来区分的各个模块进行完全的解耦,但是不管技术怎么怎么更新换代,但是永远不变的一个核心思想就是“调用更加方便、更加安全、代码之间的耦合度更低”,这是一个好的软件永远追求的目标。