Android 下一代架构指南:DDD

news2024/12/24 20:37:13

移动端架构与网站架构的区别是什么?网易新闻客户端的架构演进历程是怎样的?为什么要选择 DDD 思想来指导重构?DDD 落地中应当关注哪些方面?带着这些问题我们来看下文。(节选自网易新闻App架构重构实践)

当前,大多数移动开发团队选择以 MVP 作为业务层的核心架构模型,在此基础上实现了客户端的组件化、插件化、容器化等,但作为业务层核心的 MVP 架构模式至今仍有诸多弊端。网易新闻 App 在领域驱动设计(DDD)思想指导下,对其架构做了整体重构,得到了不错的重构质量与项目收益。

1移动端架构与网站架构的区别

传统意义上的网站架构,通过超文本传输协议,浏览器可以快捷方便地将我们想要访问的页面呈现在眼前。每个网站由多个页面组成,这些页面也都属于 Web Server 的一部分,如图 1 所示。
在这里插入图片描述

图 1 Website 与 Server 抽象模型

网站大多数时候不需要关注离线化,而主要关注负载均衡、高并发和多级缓存等场景,以实时响应大规模流量。

而移动端 App 需要用户先进行安装操作,然后再进行页面访问,其中的高并发网络请求等场景通常交由 Server 端处理,移动端则更关注处理用户交互与界面变化,如图 2 所示。
在这里插入图片描述

图 2 Application 与 Server 抽象模型

所以移动端和网站端的核心关注点不同,也就造成了二者在架构上的历史演进的不同。举一个简单的例子,最初起源于 .NET Framework 3.0 的模型 / 视图 / 视图模型(MVVM)思想,从 WPF 应用过渡到 ASP.NET,用于网页的开发,后来却在移动端成为最流行的架构模式之一。

随着网站端的历史演进,网页的工作量和跨平台的需求增长迅速,使得网站前端开发的重要性日趋明显,网站端已经抽象为了前端和后端,网站前端通过浏览器实现跨平台,与移动端共同组成了大前端。

目前常见的移动端架构设计模式主要包括关注面向接口编程的 MVP(Model-View-Presenter)、关注数据驱动与双向绑定的 MVVM(Model-View-ViewModel)、关注表现层分离的 MVC(Mode-View-Controller)和符合领域驱动设计思想(DDD)的 The Clean Architecture 等。

2 网易新闻客户端的架构演进历程

网易新闻客户端的架构演进主要经历了四个阶段:Static Method、MVP、MVPs 和 VIPER。

为摆脱沉重晦涩的架构模型束缚,网易新闻客户端团队将一些软件设计中的元素抽象为轻松的食品加工中的元素,用蛋糕模型来做示例。

第一阶段:Static Method

从最初的设计阶段开始,为了简单地达到代码的可复用性,新闻客户端采用了一种 Static Method 的设计方式,将业务逻辑按照业务模块转移到一些工具类中,使得开发人员可以用最小成本复用这些业务逻辑。

在 Static Method 的模式中,技术团队将 View 抽象为一块蛋糕,蛋糕上面需要奶油,柠檬,樱桃(Model)等食材,所有负责输送材料的加工厂(Static Method)派工人(而不是厨师)将材料直接运送并摆放在蛋糕上面,如图 3 所示。这使得蛋糕最后拥有了所有他该有的食材成分。但这些食材存在随意摆放,使蛋糕变得混乱的情况,如果再继续这样堆砌食材,它就不再像是一块蛋糕了。
在这里插入图片描述

图 3 Static Method 蛋糕加工模型

所以,随着时间的推进和业务迭代的不断加速,这种丧失了封装、多态和继承的面向对象特性的工具类设计,难以应对业务的变化,过渡到流行的 MVP 模式已成必然趋势。

第二阶段:MVP

传统的 MVP 模式中,一个 View 由一个 Presenter 管理,在这种模式下产生了代码复用的难题。

由于 Presenter 与 View 通过接口协议绑定,通常一个 Presenter 里的业务逻辑只能为一个 View 服务,代码复用性的丧失会导致大量冗余代码的产生。

Presenter 与 View 为一对一的方式,就像一块蛋糕(View),指派给一个厨师(Presenter)去制作,但是厨师一个人需要做的事情太多,他需要亲自加工食材(Model),再将这些材料一一装饰在蛋糕上面,如图 4 所示。如果这时候再告诉他我们的蛋糕还需要添加一些突然增加的装饰和点缀,他可能会面临崩溃。

在这里插入图片描述

图 4 MVP 蛋糕加工模型

第三阶段:MVPs

为了解决 MVP 代码复用的问题,大多数的设计方式都是将 View 与 Presenter 改为多对一的模式,使得一个 Presenter 可以为多个 View 服务,而一个 View 也被多个 Presenter 控制。更多的 Presenter 介入也意味着这些 Presenter 为了适应不同的 View 将产生更多的接口。

Presenter 与 View 为多对一的方式,就像一块蛋糕(View),指派给多个厨师(Presenters)在共同加工。而每个厨师可能会处理多块蛋糕,他们同时还要做好手上的装饰品(Model),再亲自将其放在每个蛋糕上。在这期间,厨师们直接接触每块蛋糕时,还加入了很多他们擅长的但是蛋糕不需要的手艺。多个厨师围着一块蛋糕转,蛋糕有了很多他原本不想拥有的东西,而这些厨师们也难以管理,他们直接操控蛋糕,没人能够合理控制他们,如图 5 所示。所以,新闻客户端过渡到了符合 DDD 的 VIPER 模式下。

在这里插入图片描述

图 5 MVPs 蛋糕加工模型

第四阶段:符合 DDD 的 VIPER

在符合领域驱动设计的 VIPER 架构设计模式下,一块蛋糕(View)只由一个主厨(Presenter)进行装饰摆放,但是蛋糕上所有的饰品食材,都由这位主厨指派给多个不同的厨师(Interactor)进行加工(Entity)。当这些厨师加工完毕后,再把材料送过来,通知主厨,由主厨亲自进行摆放。

那些负责加工的厨师没有机会再直接接触到蛋糕,蛋糕只有它原本应有的样子,变得更加利于加工制作。更美好的是,以往蛋糕需要每个厨师亲自配送到它需要被送达的地方,现在厨师只需要打个电话,一切配送工作都将由快递员(Router)去完成,如图 6 所示。

在这里插入图片描述

图 6 VIPER 蛋糕加工模型

3基于 DDD 的短视频架构优化

以网易新闻客户端的视频详情页为例,新闻客户端的视频详情页结构可以抽象为图 7。初期设计的视频详情页,所承载的业务并不多,界面也较为简单,Holder、子页面和适配器等都在 Fragment 类中定义实现。但是随着短视频风口的到来,业务加速迭代,视频的业务需求急剧增加,视频详情页所需要承载的业务也越来越多,Fragment 类从最初的几百行,急速扩张到两千多行。基于旧有的视频详情页设计,加入新的业务,使得维护成本变得越来越高,类也变得越来越大,臃肿膨胀的类已经变为了“面条代码”。

在这里插入图片描述

图 7 视频详情页抽象结构

基于 DDD 的思想,新闻客户端实现了一套包含 UseCase 的基础框架,划分出了领域模型,由于视频详情页由多 Fragment 组成,技术团队还加入了共享变量层,使拥有统一生命周期的组件之间能解耦传递数据,重构后的视频详情页整体架构如图 8 所示。

在这里插入图片描述

图 8 视频详情页重构后的架构设计图

4 DDD 的选型与实践

选型背景

新闻客户端的多数业务模块在设计初期的时候,承载的业务都不是很多。当某些业务模块的需求逐渐增加,开发人员为了快速完成迭代工作,代码经常会冲刺堆积在一起,久而久之,业务模块之间的边界变得越来越不清晰,耦合也变得越来越严重。

DDD 的限界上下文可以帮助技术团队定义出清晰的领域模型边界,以达到解耦的目的。VIPER 是符合 DDD 理念的架构模型,VIPER 曾一直流行于 iOS 端,在 Android 端的应用案例非常少,但其实 VIPER 的核心思想是 The Clean Architecture,所以它同样适用于 Android 端,是一个通用的解决方案。

落地难题

在将 DDD 落地的过程中,团队遇到的比较困难的问题大致是两方面,一方面在于优化工作流程,另一方面在于转变编码思想。

在工作流程方面,大多数互联网公司都会有需求评审会,其中会有产品经理、项目经理、软件工程师、UI 交互设计师等参与。但传统形式的需求评审主要关注点还是在整体的业务本身,在事件划分上是非常模糊的,这与确定限界上下文的事件风暴相差一段距离,推动多个团队变更评审方式的难度比较大。所以,开发团队内部在编码阶段开始前,还会进行一次技术评审,由准领域专家们参与到其中,与开发人员共同分析讨论界限上下文。

在编码思想方面,需要团队成员接受 DDD 的思想,转变为领域驱动思维,技术团队在内部进行了一系列相关的分享,通过编程中的“隐喻”,让大家循序渐进地建立对 DDD 的认知,逐步加深了解。

重构效果

在基于 DDD 的架构重构初期,新闻客户端选取了视频详情、视频列表和图集三个业务模块使用 VIPER 重构,对 DDD 进行尝试性探索。

在重构质量上,由于先确定了领域模型,代码整体解耦符合预期,三个模块重构后上线均未产生严重线上问题。

在项目收益上,一方面,DDD 帮助团队加速了迭代的开发效率,另一方面,代码的可维护性也有了比较大的提高,同时,模块错误率也约降低了约 50%。

新闻客户端以半年为一个维度,统计出模块重构前半年和重构后半年的系统故障率(主要指程序开发期间产生的问题),得出了如图 9 所示的信息。数据发现,越是业务变化很频繁的模块(如视频),通过 DDD 获得的模块稳定性收益就越大。

在这里插入图片描述

图 9 DDD 重构前后系统故障率统计图

5 DDD 落地面面观

DDD 从 2003 年被提出来以后,得到了软件学术界的高度认可,但由于国内外开发环境和开发人员思想理念不同等多种影响,导致 DDD 在国内的实践并不是很理想。从 2013 年开始,微服务架构和中台化在国内逐渐盛行,而 DDD 可以作为其指导思想,帮助微服务架构进行清晰的领域和子域划分,DDD 逐渐在企业应用实践上获得理想的成果,这正是 DDD 在国内突然变得流行的最主要原因之一。

对于开发团队来说,实践 DDD 最重要的一步就是通过事件风暴来进行领域分析建模,但这对于带头发起人的领域素养要求较高,需要团队内有一位布道师开路,担任领域专家的职责。

针对移动端来说,目前最合适的、符合 DDD 的架构模型就是 The Clean Architecture,Google 官方推出的安卓蓝图项目也针对 MVP 提供了一套符合 The Clean Architecture 的 MVP-Clean 项目,开发者可以由此为起点进行逐步探索和尝试。

由于国内外软件工程师职业环境和所承受的压力有所不同,在很多突发性的业务需求的冲击下,使得开发者只能对代码做疯狂堆叠,导致开发者不得已放弃 DDD 的设计,而期间发生需求变更就很容易导致风险。

当风险变为危险后,发生各种互相推诿的现象,其问题本质归结起来无非是两方面,一方面是组织结构和环境所影响,另一方面是边界划分不明确。

对于组织和团队方面,前期无需变动,也可以满足向 DDD 转型的条件,也为后期再建设微服务和中台化提供了便利。但需要注意的是,改变团队成员的固有开发思维也是十分重要的一个环节,团队内应该定期组织关于 DDD 的分享,有利于使大家对 DDD 的观念潜移默化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/440015.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kafka吞吐量

目录 kafka的架构和流程 小文件对HDFS影响: 解决办法: kafka的架构和流程 ⾸先Kafka从架构上说分为⽣产者Broker和消费者,每⼀块都进⾏了单独的优化,⽐如⽣产者快是因为数据的批量发送,Broker快是因为分区,分区解决了并发度的问题,⽽且⽂…

媒体宣传的优势与重要性

传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 媒体宣传日益成为企业和品牌宣传推广的重要手段,媒体的宣传报道更有权威性,能够帮助品牌进行背书,更有权威性,另外媒体的报道在搜索引擎中…

基于GPS/北斗卫星技术的无盲区车辆调度系统

基于GPS/北斗卫星技术的无盲区车辆调度系统 现代车辆调度系统是一种集全球卫星定位技术(GPS)、地理信息技术(GIS)和现代通信技术于一体的高科技项目。它将移动目标的动态位置(经度与纬度)、时间和状态等信息…

linux环境搭建jmeter、ant、git、Jenkins、jdk、Tomcat

我在搭建环境时,将jmeter、ant、jdk、Tomcat都放在陆opt文件夹下 1.下载jmeter、ant、Jenkins(Jenkins.war包)、jdk、Tomcat Linux环境下安装Jenkins,需要jdk版本大于11 2.环境配置 jdk配置 vim /etc/profile 添加配置信息&am…

飞书接入ChatGPT - 将ChatGPT集成到飞书机器人,直接拉满效率 【飞书ChatGPT机器人】

文章目录 前言环境列表视频教程1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10. 机器人测试 前言 在飞书中创建chatGPT机器人并且对话,在下面操作步骤中,使…

LBS找外贸客户 外贸怎么找客户

随着全球贸易的不断发展,越来越多的企业开始寻找更多的客户和销售机会。而随着移动互联网的普及,LBS已经成为了人们生活和工作中不可或缺的一部分。在商业领域中,LBS被广泛应用于定位、导航、营销等方面,为企业提供了更加便捷、精…

如何在Mac VM Fusion上安装和使用Plan 9

我在 Mac 上使用 VM Fusion 安装 Plan 9 的时候遇到了很多问题,官方文档和有些前两年的国外的一些博客并没有写清楚,甚至出现了“误导”的情况(有些情况变了)。所以来写本文帮助其他也遇到的问题的人。 如果你能看到这篇博客&…

上传ChatGPT相关资源,瓜分¥5000元奖金池

一、活动时间 资源类型时间上传地址上传【ChatGPT的原理分析】资源4月17日-4月30日https://upload.csdn.net/creation/uploadResources?taskId643925fde212675bb64a3984&utm_sourceblog上传【Chatgpt的多种使用方法】资源4月15日-4月30日https://upload.csdn.net/creatio…

介绍NPOI 的颜色卡、名称以及索引

文章目录 前言 遍历NPOI颜色 前言 使用NPOI的颜色时,一些颜色类的名称很难想象出具体对应的颜色,所以有了下面的对照表,方便使用。 NPOI 颜色的索引范围是 8~64,超出范围无效。 色彩类名索引Index名称#000000HSSFColor.Black8黑色#ffffffH…

【C++ 一】C++ 入门、数据类型、运算符

C 入门、数据类型、运算符 文章目录 C 入门、数据类型、运算符前言1 C 初识1.1 第一个C程序1.1.1 创建项目1.1.2 创建文件1.1.3 编写代码1.1.4 运行程序 1.2 注释1.3 变量1.4 常量1.5 关键字1.6 标识符命名规则 2 数据类型2.1 整型2.2 sizeof 关键字2.3 实型(浮点型…

【最详细最完整】windows 安装 Oracle Java环境

windows 安装Oracle Java环境 一、安装教程二、验证Java环境 前言:公司有个app的项目,我是打算使用uniapp来实现,那么调试是需要使用到java环境,所以我本地就得安装java环境,接着我找了好多文章发现没有相对完整的&…

在头部大厂做了13年云计算后,这次他想系统地聊聊FinOps!

随着企业上云战略的深入普及,越来越多的企业开始关注云成本优化。伴随着企业对IT资源的投入不断增加,企业迫切需要解决成本与效率,以及如何将云成本优化落到实处的问题。 FinOps是将财务和业务整合到一起的变革,可以帮助企业更好…

抖音数字人主播app

抖音数字人主播app是指一款利用计算机生成的虚拟数字人,在抖音平台上进行实时音视频传输和互动的应用程序。该软件可以让用户创建自己的虚拟数字人,并在抖音平台上进行实时互动和交流。 抖音数字人主播app通常需要包含以下功能: 3D建…

本地JAR打镜像,并启动

1.准备好jar,和Dokerfile文件。 2.使用命令打镜像 docker build -t wstest . 3. 查看镜像 4. 由于服务是两个端口。使用以下命令 5.优化怎么随着docker的开启而启动 docker run --restartalways -p 8089:8089 -p 8069:8069 wsserver docker run --restartalways -…

C++基础入门——语法详解篇(下)

文章目录 一、缺省参数 1、1 缺省参数的概念 1、2 缺省参数的分类 1、2、1 全部缺省 1、2、2 半缺省参数 二、引用 2、1 引用的概念 2、2 引用特征 2、3 引用的使用场景 2、3、1 引用做参数 2、3、2 常引用 2、3、3 引用做返回值 2、4 引用总结 三、内联函数 3、1 内联函数的引…

谷歌浏览器的跨域设置、配置、新老版本Chrome

文章目录 1、个人开发中的使用习惯2、老版本Chrome浏览器(版本号49之前)3、新版本Chrome浏览器(版本号49之后) 1、个人开发中的使用习惯 下载好谷歌浏览器以后,快捷方式一份放在桌面上,一份放在开始菜单栏,桌面的重命名为dev(可以随意命名)&a…

【09 cookie and session】

cookie and session 一、cookie1. 会话技术2. 什么是cookie3. cookie的属性4. cookie方法5. cookie添加和获取6. 需求案例7. cookie的细节 二、session1. HttpSession介绍2. HttpSession常用方法3. HttpSession获取4. HttpSession使用5. HttpSession使用细节 一、cookie cooki…

【MongoDB】什么是MongoDB?MongoDB有什么特点?MongoDB的适用场景?

什么是MongoDB数据库? MongoDB是一个开源、高性能、支持海里数据存储的文档型数据库。 MongoDB是一个高效的非关系型数据库(不支持表关系:只能操作单表) MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系…

postman安装

目录 下载、安装 Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。 Postman原是Chrome浏览器的插件,可以模拟浏览器向后端服务器发起任何形式(如:get、post)的HTTP请求 使用Postman还可以在发起请求时,携带一些请求参数、请求头等信息…

debezium docker订阅oracle 11g

debezium 依赖于kafka,kafka依赖于zookeeper。 zookeeper实现了kafka消息的一致性,debezium 把订阅的数据推送到kafka dockerFile FROM debezium/connect:1.6 ENV KAFKA_CONNECT_JDBC_DIR$KAFKA_CONNECT_PLUGINS_DIR/kafka-connect-jdbc ENV INSTANT_C…