为什么会选择clean+mvp架构

前言

在了解代码架构之前,先普及一下软件开发周期,因为有着软件不是一层不变的,它也有着周期的循环,所以作为开发者而言,代码架构的搭建,应该考虑后续的扩展性,易测性等。

常见的软件周期:

瀑布模型、快速原型、迭代开发、螺旋模型

瀑布模型

瀑布模型现在看来是比较老旧的方式了,一条龙下来的模型,是典型的预见性的方法,严格遵循预先计划的需求分析、设计、编码、集成、测试、维护的步骤顺序进行。

image

瀑布模型强调文档的作用,并要求每个阶段都要仔细验证。但是,这种模型的线性过程太理想化,已不再适合现代的软件开发模式,几乎被业界抛弃,其主要问题在于:

  • (1) 各个阶段的划分完全固定,阶段之间产生大量的文档,极大地增加了工作量;

  • (2) 由于开发模型是线性的,用户只有等到整个过程的末期才能见到开发成果,从而增加了开发的风险;

  • (3) 早期的错误可能要等到开发后期的测试阶段才能发现,进而带来严重的后果。

快速原型:

快速原型模型的第一步是建造一个快速原型,实现客户或未来的用户与系统的交互,用户或客户对原型进行评价,进一步细化待开发软件的需求。通过逐步调整原型使其满足客户的要求,开发人员可以确定客户的真正需求是什么;第二步则在第一步的基础上开发客户满意的软件产品。

快速原型的关键在于尽可能快速地建造出软件原型,一旦确定了客户的真正需求,所建造的原型将被丢弃。因此,原型系统的内部结构并不重要,重要的是必须迅速建立原型,随之迅速修改原型,以反映客户的需求。

螺旋模型

螺旋模型由风险驱动,强调可选方案和约束条件从而支持软件的重用,有助于将软件质量作为特殊目标融入产品开发之中。但是,螺旋模型也有一定的限制条件,具体如下:

(1) 螺旋模型强调风险分析,但要求许多客户接受和相信这种分析,并做出相关反应是不容易的,因此,这种模型往往适应于内部的大规模软件开发。

(2) 如果执行风险分析将大大影响项目的利润,那么进行风险分析毫无意义,因此,[螺旋模型]只适合于大规模软件项目。

(3) 软件开发人员应该擅长寻找可能的风险,准确地分析风险,否则将会带来更大的风险

一个阶段首先是确定该阶段的目标,完成这些目标的选择方案及其约束条件,然后从风险角度分析方案的开发策略,努力排除各种潜在的风险,有时需要通过建造原型来完成。如果某些风险不能排除,该方案立即终止,否则启动下一个开发步骤。最后,评价该阶段的结果,并设计下一个阶段。

image

迭代开发

每次只设计和实现这个产品的一部分, 逐步逐步完成的方法叫迭代开发, 每次设计和实现一个阶段叫做一个迭代,第一个增量往往是实现基本需求的核心产品。核心产品交付用户使用后,经过评价形成下一个增量的开发计划,它包括对核心产品的修改和一些新功能的发布。这个过程在每个增量发布后不断重复,直到产生最终的完善产品。

迭代开发模型也存在以下缺陷:

*(1) 由于各个构件是逐渐并入已有的软件体系结构中的,所以加入构件必须不破坏已构造好的系统部分,这需要软件具备开放式的体系结构。

*(2) 在开发过程中,需求的变化是不可避免的增量模型的灵活性可以使其适应这种变化的能力大大优于瀑布模型和快速原型模型,但也很容易退化为边做边改模型,从而使软件过程的控制失去整体性

各自特点:

  • 瀑布模型 文档驱动 系统可能不满足客户的需求

  • 快速原型模型 关注满足客户需求 可能导致系统设计差、效率低,难于维护

  • 迭代模型 开发早期反馈及时,易于维护 。但是需要开放式体系结构,易扩展。可能会导致效率低下

  • 螺旋模型风险驱动 风险分析人员需要有经验且经过充分训练

我们在做app开发的时候,现在大部分的情况都是敏捷性的迭代开发,团队较小沟通效率高,相对灵活,周期也短,从而降低风险,这就要求我们对于框架的选型需要合理,不能为了完成迭代任务而加代码,导致后期的需要一次次的重构。那怎样的架构相对来说比较合理性,现在介绍一种叫clean干净架构的代码特点:

image

介绍意思是大体的源码依赖项只能向内指向,内环里的所有项不能了解外环所发生的东西,然后clean架构的目的是:

  • 框架独立,不依赖其他库包,以免受到约束

  • 可测试。可以在没有UI,数据库,Web服务器或任何其他外部元素的情况下测试业务规则。

  • UI独立。UI可以轻松更改,而无需更改系统的其余部分。例如,可以使用控制台UI替换Web UI,而无需更改业务规则。

  • 数据源独立,业务规则未绑定到数据库。

  • 外部代理模块独立,即框架内部不了解外部的情况

image

以下内容是来自该作者的翻译文档:
https://zhuanlan.zhihu.com/p/20001838

以下是更好地理解和熟悉本方法的一些相关词汇:

  • Entities:是指一款应用的业务对象

  • Use cases:是指结合数据流和实体中的用例,也称为Interactor

  • Interface Adapters: 这一组适配器,是负责以最合理的格式转换用例(use cases)和实体(entities)之间的数据,表现层(Presenters )和控制层(Controllers ),就属于这一块的。

  • Frameworks and Drivers: 这里是所有具体的实现了:比如:UI,工具类,基础框架,等等。

Android应用架构

这一对象遵循关注分离原则,也就是通过业务规则让内环操作对外环事物一无所知,这样一来,在测试时它们就不会依赖任何的外部元素了。

要达到这个目的,我的建议就是把一个项目分成三个层次,每个层次拥有自己的目的并且各自独立于堆放运作。

值得一提的是,每一层次使用其自有的数据模型以达到独立性的目的(大家可以看到,在代码中需要一个数据映射器来完成数据转换。如果你不想把你的模型和整个应用交叉使用,这是你要付出的代价)。

以下是图解,大家感受下:

image

表现层 (Presentation Layer)

表现层在此,表现的是与视图和动画相关的逻辑。这里仅用了一个Model View Presenter(下文简称MVP),但是大家也可以用MVC或MVVM等模式。这里我不再赘述细节,但是需要强调的是,这里的fragment和activity都是View,其内部除了UI逻辑以外没有其他逻辑,这也是所有渲染的东西发生的地方。
本层次的Presenter由多个interactor(用例)组成,Presenter在 android UI 线程以外的新线程里工作,并通过回调将要渲染到View上的数据传递回来。

image

领域层 (Domain Layer)

这里的业务规则是指所有在本层发生的逻辑。对于Android项目来说,大家还可以看到所有的interactor(用例)实施。这一层是纯粹的java模块,没有任何的Android依赖性。当涉及到业务对象时,所有的外部组件都使用接口。

image

数据层 (Data Layer)

应用所需的所有数据都来自这一层中的UserRepository实现(接口在领域层)。这一实现采用了Repository Pattern,主要策略是通过一个工厂根据一定的条件选取不同的数据来源。

比如,通过ID获取一个用户时,如果这个用户在缓存中已经存在,则硬盘缓存数据源会被选中,否则会通过向云端发起请求获取数据,然后存储到硬盘缓存。

这一切背后的原理是由于原始数据对于客户端是透明的,客户端并不关心数据是来源于内存、硬盘还是云端,它需要关心的是数据可以正确地获取到。

image

最后附上另外一个博客地址,也写的挺好
https://www.jianshu.com/p/66e749e19f0d

好了,总结一下:不管项目采取什么形式的架构,都是一种代码的规范的基本原则前提下,寻找一种对于业务实现的最优解,如java中代码设计原则主要有单一职责、开闭原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特法则。目的也是提高程序的可维护性,扩展性,实现高内聚,低耦合结果。

比如说,最开始前后端是一个系统的时候就已经强调ui分离了,现在前端可通过npm独立搭建前端项目了,在在这个前端项目本身也不仅仅是ui了,也包含了前端的业务,同时也应该用上诉的代码设计原则,对代码进行调整而达到可维护,解耦的可测性的效果。

app的项目调整也是如此,考虑到不同基础功能的复用,也依然可以用组件化的形式搭建项目,类似后台系统的组件化,微服务的发展。到一定程度app也可以用插件化进行扩展。所以怎么说呢,最重要的还是代码设计的规范吧。

最后附上自己的clean+mvp的“番茄工作”项目地址

https://github.com/liangzs/tomatoTodo

免费获取安卓开发架构的资料(包括Fultter、高级UI、性能优化、架构师课程、 NDK、Kotlin、混合式开发(ReactNative+Weex)和一线互联网公司关于android面试的题目汇总可以加:936332305 / 链接:点击链接加入【安卓开发架构】

猜你喜欢

转载自blog.csdn.net/Coo123_/article/details/88700041