通用详情页的打造

背景介绍

图片

大家都知道,详情页承载了站内的核心流量。它的量级到底有多大呢?

我们来看一下,日均播放次数数亿次,这么大的流量,其重要程度可想而知。

在这样一个页面,每一个功能都是大量业务的汇总点。

作为用户核心消费场景,详情页不仅需要承接各种业务的转化,还要负责展示各业务在播放页的功能。

可以说,播放页的代码复杂度属于客户端最高的代码之一,这不仅因为播放页本身的功能复杂,还因为它需要融合大量外部业务功能。

复杂的功能自然会带来较高的代码复杂度,而高代码复杂度往往意味着高代码维护成本。

明确需求

图片

我们来看一下没有做这个项目之前的状态。如图所示,他们分别为三个业务团队各自维护。页面间相互独立。能力无法复用。

图片

通过这个项目,我们要将他们融合成了一个页面。产品的诉求就是将他们融合为一个,来达到多业务形态统一的目标。

图片

但是,这三个详情页并不像产品想象的那么简单。

每个业务都有自己的特殊形态,如大型活动态、主客态、播单态、PUGV/OGV态等一系列业务形态。

每种形态都有自己的特殊逻辑,而且这些业务形态间还可以互相切换。

需求分析

为了更好地达成目标,我们需要进行如下思考:

  • 从业务角度:

要解决多业务形态不统一的问题。例如,产品既想要UGC大型活动的能力,又想要OGV的多视角功能。

但这两个能力在之前分别是两个业务团队各自开发的,无法复用,产品在业务选择上无法兼得。

  • 从效率角度:

要解决迭代方式不统一的问题。例如,进度条体验优化需求,产品在给UGC团队提需求的同时,还要复制一份给OGV团队。

两个业务方的开发和测试都需要进入这个项目,并且双方的开发进度和排期可能不一致。如果产品强烈要求同一版本上线,还需要协调各方资源。

  • 从质量角度:

要解决如何保障稳定性的问题。例如,多团队协作,之前都是组内同事协作开发,现在融入了两个新的业务团队,我们该如何保障稳定性。

  • 从团队角度:

要解决如何让新人快速上手的问题。正常情况下,新人想要进入开发必须对这个系统足够了解后才行。

更何况现在变成了三个业务融合的页面。有没有一种手段,让新人无需关心复杂的业务形态和业务逻辑,只需要关注自己的需求?

具体方案

针对以上问题,我们可以总结出通用详情页框架必须满足以上三点,分别为:复用性,灵活性,稳定性

图片

接下来我们继续对多业务形态进行分析。

首先我们从横向上进行拆解,通过对比,我们可以发现

多业务形态间其实有很多的相同模块。如互动,弹幕发送框,相关推荐等。

从纵向上进行拆解,我们也可以发现很多相同模块,如弹窗管理器,主题组件,转场组件等。

那么从横向和纵向上我们发现,多种业务形态间其实有很多可以复用的能力。

图片

基于前面的思考,我们设计了一套通用详情页的框架。将其分为三层:

  1. 业务层:将业务模块分为两类,能够在多业务间复用的模块抽象到通用业务,业务独有模块则由各业务自行负责。

  2. 组件层:抽象出各种通用组件,业务方可自由选取和组装。

  3. 框架层:抽象生命周期管理、数据管理等核心逻辑,以此来保证整个详情页的稳定性。

这样我们就初步解决了复用性的问题,但是随之而来的就是灵活性问题。

图片

我们以实际场景为例,相关推荐模块在课堂态不展示,但是在ugc和ogv下需要展示,另外他的点击事件在ugc和ogv下还会出现差异。

同时相关推荐模块还强依赖简介模块。因为简介模块也是一个通用组件,业务方可以自由替换。

如果哪天业务方替换了了简介模块,那相关推荐模块将无法正常运行。

从相关推荐这个例子我们可以得出如果想让业务模块复用,必须满足两个条件。

  1. 支持业务异化,即允许业务能插入自定义逻辑,否则现在抽象的通用模块在迭代的过程一定会变成非通用,或者里面掺杂各种if else逻辑来支持异化。

  2. 必须保证模块间相互独立,因为所有业务逻辑在此框架下都变成了模块,模块是可以由业务方自由选择的。

图片

引入依赖注入

因此,我们需要在流程和模块中加入依赖注入的能力,用于业务方实现差异化逻辑。

业务方可自行插入自己的业务逻辑,并选择或替换业务模块。来解决模块间的耦合。

定义依赖注入容器

public class BlocStore {typealias StoreLock = RecursiveLocktypealias StoreTable = [String: BlocTable]private let lock: StoreLock = StoreLock()private lazy var storeTable: StoreTable = [:]
}extension BlocStore {public func register<Service>(service: Service.Type = Service.self, to: Bloc.Type) {let key = "\(service)"lock.lock()defer { lock.unlock() }serviceTable[key] = to}@discardableResultpublic func optional<Service>(service: Service.Type = Service.self) -> Service? {let key = "\(service)"lock.lock()defer { lock.unlock() }let service = resolve(bloc)return s}
}// Bind and unbind
extension BlocStore {public func bindBloc(bloc: Bloc) {}public func unbindBloc<T: Bloc>(_ blocType: T.Type) {}
}// BlocLifeCycle
extension BlocStore {func onStart(bloc: Bloc?) {bloc?.onStart()}func onPause(bloc: Bloc?) {bloc?.onPause()}func onResume(bloc: Bloc?) {bloc?.onResume()}func onStop(bloc: Bloc?) {bloc?.onStop()}
}

组件注册

// 业务方根据业务逻辑可以注入不同的实现
register(service: XXXProtocol.self, to: ABloc.self) // A业务形态
register(service: XXXProtocol.self, to: BBloc.self) // B业务形态

组件解析

let s: XXXProtocol = store.optional()

引入scope

scope分为页面级和业务级两种scope:

class VDScope {public static let core = "store.core.scope"public static let biz = "store.biz.scope"
}

定义 Scope 管理来管理模块的生命周期:

  • Page scope的生命周期与页面保持一致,Biz scope与业务形态的生命周期保持一致。

  • 即在页面形态发生变化时,框架层会自动将bizscope下的所有模块进行销毁。

public class BlocStore {typealias ScopeTable = [String: String]...func bizTypeDidChanged() {// 销毁上一个bizscope下所有模块xxxx// 初始化新bizscope下模块xxx}
}

这样,新人进入开发时无需关注当前业务形态或业务形态切换的问题,达到快速上手的目的。

如何保障吞吐速度和质量稳定?

在开发资源和测试资源不变的情况下,业务范围扩大了,我们该如何保障吞吐速度和质量的稳定呢?

图片

我们可以将策略分为三个阶段:

1.开发阶段:

对于核心流程添加全链路日志,如果发现不符合预期的数据则直接抛出异常。

同时进行技术埋点上报。如果是对于核心流程的修改,强制添加AB降级方案。

2.测试阶段:

有些bug非常隐蔽,在用户体验上可能没有任何差异,但内部流程或数据可能已经发生异常。

对于类似问题,测试根本无法发现。导致此类问题流入线上的风险。我们可以通过添加监控和告警,让我们及时发现问题。

3.灰度/线上阶段:

我们可以通过添加监控和告警,让我们及时发现问题。

具体实施方案:

首先,我们对通用详情页里核心流程添加了全链路日志,并为日志服务添加了两项额外能力:

如果发现日志类型为Error,内部自动触发DEBUG弹窗提醒,并上报技术埋点,达到对线上稳定性的监控。

图片

同时,搭建离在线数据报表和异常告警,进一步保障稳定性。

至此,搭建了通用详情页从发现问题到定向拉取再到快速定位的闭环。

-End-

作者丨凉茶

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django 删除单行数据

1&#xff0c;添加模型 from django.db import modelsclass Post(models.Model):title models.CharField(max_length200)content models.TextField()pub_date models.DateTimeField(date published)class Book(models.Model):title models.CharField(max_length100)author…

苹果电脑压缩软件哪个好用一些? mac电脑用什么压缩软件 mac电脑压缩文件怎么设置密码

压缩软件是Mac电脑必不可少的工具&#xff0c;虽然Mac系统自带了一款“归档实用工具”&#xff0c;但是其功能实在匮乏&#xff0c;若你需要加密压缩文件或者把文件压缩成指定格式&#xff0c;那么该工具无法满足你的需求。Mac用户应该怎么选择压缩软件呢&#xff1f;本文就来告…

自动驾驶算法———车道检测(一)

“ 在本章中&#xff0c;我将指导您构建一个简单但有效的车道检测管道&#xff0c;并将其应用于Carla 模拟器中捕获的图像。管道将图像作为输入&#xff0c;并产生车道边界的数学模型作为输出。图像由行车记录仪&#xff08;固定在车辆挡风玻璃后面的摄像头&#xff09;捕获。…

一图展示免费开源的分布式版本控制系统​Git

文章目录 前言一、安装Git二、Git配置三、git命令 前言 Git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理。也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。 一、安装Git Windows操作系统…

MFC扩展库BCGControlBar Pro v35.0 - 可视化管理主题等全新升级

BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中&#xff0c;并为您节省数百个开发和调试时间。 BCGControlBar专业版 v35.0已全新发布了&#xff0c;这个版本改进类Visual Studio 2022的视觉主题、增强对多个…

大模型时代的目标检测

https://zhuanlan.zhihu.com/p/663703934https://zhuanlan.zhihu.com/p/6637039341.open set/open word/ood 这个任务是指在实际应用上可以检测任何前景物体&#xff0c;但是有些不需要预测类别&#xff0c;只要检测出框就行。在很多场合也有应用场景&#xff0c;有点像类无关…

ASP.NET MVC Lock锁的测试

思路&#xff1a;我们让后台Thread.Sleep一段时间&#xff0c;来模拟一个耗时操作&#xff0c;而这个时间可以由前台提供。 我们开启两个或以上的页面&#xff0c;第一个耗时5秒(提交5000)&#xff0c;第二个耗时1秒(提交1000)。 期望的测试结果&#xff1a; 不加Lock锁&…

短视频矩阵搭建,用云微客获客更方便

你的同行都爆单了&#xff0c;你还在问什么是矩阵&#xff1f;让我来告诉你。短视频矩阵是短视频获客的一种全新玩法&#xff0c;是以品牌宣传、产品推广为核心的一个高端布局手段&#xff0c;也是非常省钱的一种方式。 1.0时代&#xff0c;一部手机一个账号&#xff1b;2.0时代…

nx上darknet的使用-目标检测-自定义训练与制作预训练模型

目录 1 训练yolov4-tiny 1.1 文件准备 1.1.1 Annotations 1.1.2 JPEGImages 1.1.3 labels 1.1.4 trained_models 1.1.5 classes.name 1.1.6 create_labels_txt.py 1.1.7 custom_training.data 1.1.8 get_labels.py 1.1.9 get_train_val.py 1.1.10 train…

鼠标怎么挑选

我们平时工作中经常要用到鼠标&#xff0c;那么哪种鼠标比较好。我们今天就来研究下。 手感要好 鼠标最重要的就是手感。这个看参数看不出来。最好能到实体店里面去体验一下&#xff0c;自己上手试一下。 如果现在都是在网上买了&#xff0c;去实体店过于麻烦&#xff0c;并且…

【系统架构设计】计算机组成与体系结构(三)

计算机组成与体系结构&#xff08;三&#xff09; 计算机系统组成存储器系统主存储器辅助存储器Cache存储器Cache 基本原理映射机制直接映射全相联映射组相联映射 替换算法写操作 流水线&#xff08;计算&#xff09;流水线周期流水线执行时间流水线的吞吐率流水线的加速比 计算…

暑期备考美国数学竞赛AMC8和AMC10:吃透1850道真题和知识点

距离接下来的AMC8、AMC10美国数学竞赛还有几个月的时间&#xff0c;实践证明&#xff0c;做真题&#xff0c;吃透真题和背后的知识点是备考AMC8、AMC10有效的方法之一。 通过做真题&#xff0c;可以帮助孩子找到真实竞赛的感觉&#xff0c;而且更加贴近比赛的内容&#xff0c;…

python自动化之用flask库写一个登陆接口(代码示例)

用到的库&#xff1a; 1、flask&#xff08;写接口&#xff09; 2、cerberus&#xff08;校验数据&#xff09; 实现效果&#xff1a;输入账号和密码&#xff0c;校验数据类型是否是字符串&#xff0c;如果是&#xff0c;返回登陆成功&#xff1b;如果不是&#xff0c;返回数…

apache:the requested operation has failed使用httpd -t

Apache24\bin cmd 回车 httpd -t 因为我重新压缩了&#xff0c;记住&#xff0c;重新压缩要使用原路径&#xff0c; 因为你安装的 时候使用的是原路径 还是不行就改个端口&#xff0c;切记修改配置文件httpd.conf先把Tomcat停了 Define SRVROOT "F:\Apache\Apache24&q…

Electron运行报错:Error Cannot find module ‘node_moduleselectroncli.js‘

Electron运行报错&#xff1a;Error: Cannot find module ‘node_modules\electron\cli.js’ 顾名思义&#xff0c;命令行执行Electron .时候&#xff0c;会优先从项目目录查找对应依赖&#xff0c;如果是报错显示是找不到项目目录下的依赖&#xff0c;我们可以从安装在全局的…

【活动预告】Apache IoTDB TsFile 智慧能源应用“上会”啦!

2024 年&#xff0c;站在中国数字经济产业升级和数据要素市场化建设的时代交汇点上&#xff0c;为进一步推动全球数据库产业进步&#xff0c;由中国通信标准化协会、大数据技术标准推进委员会主办的“2024 可信数据库发展大会”将于 2024 年 7 月 16-17 日&#xff0c;在北京朝…

【运维】项目运维方案(word原件)

1. 文档介绍 2. 人员与责任 3. 运维过程内容 4. 运维资源 5. 运维服务规划保障 6. 事件处置 7. 质量改进 8. 运维边界及内容 获取方式&#xff1a; 本文末个人名片直接获取。

安装jenkins最新版本初始化配置及使用JDK1.8构建项目详细讲解

导读 1.安装1.1.相关网址1.2.准备环境1.3.下载安装 2. 配置jenkins2.1.安装插件2.2.配置全局工具2.3.系统配置 3. 使用3.1.配置job3.2.构建 提示&#xff1a;如果只想看如何使用jdk1.8构建项目&#xff0c;直接看3.1即可。 1.安装 1.1.相关网址 Jenkins官网&#xff1a;https…

了解并缓解 IP 欺骗攻击

欺骗是黑客用来未经授权访问计算机或网络的一种网络攻击&#xff0c;IP 欺骗是其他欺骗方法中最常见的欺骗类型。通过 IP 欺骗&#xff0c;攻击者可以隐藏 IP 数据包的真实来源&#xff0c;使攻击来源难以知晓。一旦访问网络或设备/主机&#xff0c;网络犯罪分子通常会挖掘其中…

Mac M1安装配置Hadoop+Flink SQL环境

Flink 1.18.1 Hadoop 3.4.0 一、准备工作 系统&#xff1a;Mac M1 (MacOS Sonoma 14.3.1) JDK&#xff1a;jdk1.8.0_381 &#xff08;注意&#xff1a;尽量一定要用JDK8&#xff0c;少用高版本&#xff09; Scala&#xff1a;2.12 JDK安装在本机的/opt/jdk1.8.0_381.jdk/C…