面试中经常会有一些问题,相信大家也都遇到过
例如:
看你重构过代码,问你如何重构的,为什么要重构
你知道什么是mvc、mvp等业务架构,你的项目中使用的是哪一个
你觉得技术重要还是业务重要
不仅只在面试中,在实际工作中,相信大多数的Android程序员也都在迷失在浩瀚的业务中,在一次次和产品的battle以及需求的deadline中丧失了对一个好的业务架构的思考,什么扩展性、通用性、解耦都不重要了,重要的是明天提测.
做技术方向的和做业务方向的,哪个更加“高大上”呢
我们也常常听到类似的话,一直写业务代码技术水平是不可能提高的,也常常对基础架构组的同学充满了仰望,觉得他们都是大神。
是的,曾经我的想法也是这样,经常看很多技术视频,想着提高技术,逃离无聊的业务。
提高技术当然没有错,其实业务也没有低人一等,在大多数公司或者说所有的情况下,业务才是根本,业务才是一个公司是否可以长期发展的筹码。对于个人来说,纯技术大神很多,但是具有良好的业务思维,能写出优秀的业务架构代码的人,很少。
这种业务能力强的人,才是公司真正大量需要的,也应该是一个程序员的应该具备的基本。
再说一个“题外话”,“年少无知”的我们只单纯的羡慕基础架构组的技术,却不知道他们压力。做业务的同学,大都是产品经理喂饭吃,不怕“饿死”,只怕工作量太大。而纯做技术的同学呢,大多数都是自己找饭吃,尤其是在今天Android应用在各个方向的优化都已穷尽,想再找一个优化点去突破,很难,所以现在出现了很多黑科技,甚至是对虚拟机的hook,种种的黑科技看似是一种高大上的技术追求,实际上是一种压力、无奈,要不没饭吃,没绩效
那如果写好业务代码,培养业务思维呢
抛砖引玉,希望看到此文章的同学,能给出更多有价值的思考或自身的体会
大致可以从以下几个方面去思考
-
mvc、mvp、mvvm、mvi等业务架构的选择
这些业务构架其实都是在想要解决日渐增长的复杂的业务需求与如何更好的更新界面(view)之间的矛盾
-
View的组织形式
何为view的组织形式呢,简单点解释也就是用一种什么样的方法将各个view组合成一个完整的页面,当然把所有的view都堆积在一个 xml里面,也是一种方法,只不过这样的话你的xml会超过几千行哦
-
如何优雅的进行数据通信
数据通信主要包含两个方面,如何给view传递数据,更新view,这块其实和(mvc、mvp等架构的想解决的问题是一样的); 另一方面就是模块间或者类与类之间的数据传输了
-
继承与组合
本来想从设计模式的角度去写,又感觉设计模式太大了。业务的增长离不开继承,但是一味的用继承真的好吗,可以尝试下组合,会有很好的效果
-
业务思维
这个业务思维怎么说呢,一些招聘简章上有这个词【业务 sense】,我是认为这个很重要,不管是在解决问题和分析问题上面,还是在需求评审、测试用例评审,还是在实实在在编写代码的逻辑性上面都会发挥很大的作用。用一句话总结就是有业务 sense的人,会让人感觉沟通很顺畅,思路很清楚,考虑很全面
下面将会从以下方面逐个展开来说说什么样的代码是好代码
(本文不会纠缠于技术细节,仅从一个比较大的一个角度去表达些什么)
业务架构 mvc、mvp、mvvm、mvi 到底如何选择
我习惯上先说结论,再基于结论去展开
当然这个结论仅仅是我个人的一个思考,因为好的程序,好的架构有千千万
一个综合大型的app,例如抖音、小红书等这些业务架构(mvc、mvp、mvvm 甚至mvi),肯定都在用,不会单单选其中一个,比如A模块的B业务用的是mvc,相同模块的C业务就用的mvvm,这些架构思想的合理混合使用才是一个更好的选择。
那对于某一个业务或模块如何进行选择呢
那就需要先大致说说每个架构的使用场景(本文不纠结太细的实现,只基于其思想去展开)
android业务代码一般分为4个部分 : View的更新、纯业务代码逻辑、View的点击滑动等事件的分发(用户操作)、网络请求逻辑
这些业务架构基本围绕着如何更好的解耦、扩展而去去编排这些模块的编写以及之间的通信。就像我们在写需求时,经常会自言自语,我的这个逻辑应该怎么写,写到哪里比较好呢.....
mvc
结论 : 在我看来mvc在Android上的应用,都不应该算作一个架构思想。
在Android的业务中,一般Activity或者Fragment充当多个角色,View的更新逻辑,业务代码的处理逻辑以及View的点击等用户操作的逻辑,有的甚至网络请求也都会在里面。
这其实就是mvc的基本思想,就像东北乱炖、大锅菜。
优点:
代码编写很方便,几乎所有的逻辑代码都写在一个类中(Activity或Fragment),不用关心类之间、模块之间的数据通信,可以直接更新view,很方便
缺点:
Activity或Fragment代码量会暴增,后续有bug很难排查、想优化无法下手、想增加需求只能继续堆积
那什么场合适合用它呢 ,我认为
-
有些专门在debug包下用来测试的页面,可以用这种。
测试页面一般业务比较简单,和业务耦合几乎没有,后续的代码扩张也应该比较清楚。
-
如果某个业务模块划分的很独立,为加快代码编写、减少无用的数据通信,其实也可以直接用mvc
当然业务模块的独立,可能不单单指的是产品或需求逻辑上的独立,更多的是整体的代码架构,一个好的整体的代码架构可以使每个业务代码都在不经意间保持一定的距离,距离产生美嘛~
至于怎么设计这个“好架构”,会在下节的【View的组织形式】中阐述。当view组织的很好时,mvc也可以经常用
但是现实情况是什么呢,我想大家都知道,看看自己的某个类,某个Fragment 的代码量,有的都超过了5000行!
mvp
mvp的使用还是比mvc更加广泛的,如果要在mvc和mvp中一定要选其一使用,一定是mvp
在Android业务中,mvp思想相对mvc来说,多了一层P层,也就是接口以及其实现层,正是因为这个接口层,将View的更新逻辑与繁杂的业务代码的处理逻辑分开了
这就是mvp的基本思想(接口思想),为了解决mvc大乱炖的乱象,mvp将业务处理代码放到了实现层,减轻了view的主类(Activity或fragment)的负担。
优点:
通过增加接口,实现了责任分离,易于模块化,可有效应用对需求的快速增长,可维护性,扩展性都很好。
缺点:
-
正是因为多了接口层,代码量和开发时间可能会增加,需要处理view与业务的数据的通信。
-
当然等需求大爆发时,接口数量、接口的实现以及接口的“递归”调用深度也会越多,在排查问题时,想要找个某个具体实现和调用顺序就会变的相当困难了
不过相对古代Android开发,现代Android开发对于view的更新处理很少用mvp思想了,因为有了更先进的更新 mvvm(mvi)。不过对于sdk,aar等独立模块的开发,还是需要通过接口的方式,因为接口更加通用。
现实情况是什么呢,有同学已经有意识到mvc不适用于复杂的大型页面,开始用mvp重构,单纯的将繁杂的业务剥离出去,目的不是为了模块化,而仅仅是为了减少主类(Activity或fragment 的负担,当作了对主类的一个代理 ,这种其实不能算作一个合适的mvp改造。
mvvm
在Android业务中,一直在探索如何更加优雅的更新view,随着响应式编程思想的逐渐在Android业务中生根,很多优秀的框架被引入到Android,比如Rxjava。这种思想可以使得view的更新和响应可以摆脱接口的束缚,view可以主动通知业务层,也可以很方便的收到其数据的改变
LiveData诞生了!
-
有面试题会问:LiveData为什么只能运行在主线程中,因为LiveData的出现就是单纯的为了更新ui,而更新ui只有在有在主线程中进行才是合法的。
-
当然现在也出现了很多LiveDataBus进行数据通信,好像像是针对 EventBus。
-
有的直接用LiveData来进行数据通信,而非用于ui更新。但是有一个问题需要注意,原生的LiveData是具有粘性的,在某些非ui更新的场合,可能会收到历史脏数据,导致业务bug的问题,所以有同学认为这是LiveData的bug。
而我认为(也不能说是我认为,应该说是谷歌的目的),LiveData的目的就是单纯的来保障ui界面的正确、实时性,包括Activity销毁重建时,也要保证UI 不会出现异常。LiveData和ViewModel的配合就可以完美的做到这个。
这就是MVVM,通过响应式编程思想 来使得View的更新逻辑和业务逻辑处理解耦
优点:
响应式的架构优点很明显,就不说了
缺点:
缺点也是有的,我这里说两点(我也只会这些了)
-
如果使用LiveData和ViewModel的架构,如果view的状态比较复杂,ViewModel中的LiveData数量可以会很多
-
每对于一个View状态,可能需要两个LiveData,一个用来写,一个用来读。这样可以保证view状态的变化源单一,可控。
当然,现实情况下,大家都会觉得麻烦,直接用一个public 的可读可写的 LiveData,其实我觉得勉强也可以吧
虽然响应式思想不算是一个新鲜事,但是我相信,很多同学对此还不是很清楚,不管怎么样,先用起来,用上它,不用太费心就能写出比mvc、mvp更加优秀的代码。
MVI
MVI与MVVM相对比就比较暧昧了,它是在MVVM的基础上改造的。只不过多了一个状态机器的概念。
将View的点击滑动等事件的分发(用户操作)转化成一个意图(其实也是把动作封装到一个类中),把View的更新逻辑设计一个状态。
标准的demo型的MVI代码我还没写过,这个东西相对mvvm还是比较新的。不过类MVI还是经常写的,我相信很多同学也写过。就是当一个View的状态比较多时,如果单纯用mvvm,livadata确实会比较多,如果把view状态的枚举全都归于一个State,然后机遇这个State,去更新view,那么需要一两个livadata就可以了。
同样的
这些业务架构,我们也不必须拘于其教科书式的写法去写代码, 只需要去抓住其核心思想,灵活应用,再加上对业务未来的一个预判以及后续的调用方式,相信写出来的代码不会很差。
除去这些业务架构,我们还应该关注View的组织形式。如果说mvc、mvp、mvvm等架构的重点都在于繁琐的业务代码应该写在哪里,那么View的组织形式更多在于如何再view层次去再次解偶业务逻辑,可能说的比较抽象。下一节将详细对其解释。
View的组织形式
下期见
数据通信如何选择 LiveData,LiveData 配合ViewModel、EventBus、接口、单例(静态)方法传递、Rxjava、flow
下期见
继承 VS 组合
下期见
业务思维
下期见