【小吉送书—第二期】阿里后端开发:抽象建模经典案例

文章目录

  • 0.引言
  • 1.抽象思维
  • 2.软件世界中的抽象
    • 2.1 命名抽象
    • 2.2 分层抽象
    • 2.3 原则抽象
  • 3. 经典抽象案例
    • 3.1 方案一:战术抽象,多快好省,跑步前进
    • 3.2 方案二:深入分析,透过表象,探寻本质
  • 5. 推荐一本书
  • 🍔彩蛋

在这里插入图片描述

0.引言

在互联网行业,软件工程师面对的产品需求大都是以具象的现实世界事物概念来描述的,遵循的是人类世界的自然语言,而软件世界里通行的则是机器语言,两者间跨度太大,需要一座桥梁来联通,抽象建模便是打造这座桥梁的关键。基于抽象建模,不断地去粗取精,从现实世界到业务模型,从业务模型到设计模型,最终完成现实世界到软件世界的转换。

事实上,服务端开发工程师在大部分工作时间里并不是在写代码,而是在抽象建模。工程师需将业务需求抽象成领域模型、模块、服务和系统,面向对象开发时需抽象出类和对象,面向过程开发时抽象出方法和函数。
某种意义上,软件的本质就是抽象,建模则是系统地实施抽象的过程。作为一种将事物形象化的有效手段,建模可将现实世界中的事物及事物之间的关系准确地表达出来。


1.抽象思维

抽象在中文里可作为动词,也可作为名词。作为动词的抽象是指一种行为,这种行为的结果,就是作为名词的抽象。百度百科对抽象的定义为:人们在实践的基础上,对于丰富的感性材料通过去粗取精、去伪存真、由此及彼、由表及里的加工制作,形成概念、判断、推理等思维形式,以反映事物的本质和规律的方法。

事实上,抽象作为一种高级思维形式,与日常生活关系密切,例如数字,人类初期并没有数字这一概念,原始人类或许能够理解三个苹果和三只鸭子,但不存在数字 “三” 这个概念,在他们的意识里,三个苹果和三只鸭子是没有任何联系的。当人类文明发展到一定阶段,发现了这两者之间存在的一种共性,即 “三”,于是就逐渐形成了数字这个概念。此后,人们就开始用数字对各类事物进行计数。

2.软件世界中的抽象

软件的本质就是抽象,在软件世界里,抽象无处不在,典型如命名抽象、分层抽象、原则抽象。

2.1 命名抽象

作为一名软件工程师,最令你头疼的事情是什么呢?是写代码,看别人的代码,需求评审,还是修 Bug?Quora 和 Ubuntu Forum 曾经针对这个问题进行过广泛地调研,结果显示, 最令软件工程师头疼的事情是命名,没错,就是命名!应用名、包名、类名、方法名、字段名、变量名等等。如果你不曾为命名苦思冥想、反复权衡,也许你还不能算是真正的软件工程师。

关于命名,Stack Overflow 的创始人 Joel Spolsky 曾言:“起一个好名字很难,但这是理所应当的,因为一个好名字需要把要义浓缩在一到两个词(Creating good names is hard, but it should be hard, because a great name captures essential meaning in just one or two words)。” 其实,这个浓缩的过程便是抽象的过程。

很多时候,业务代码的复杂,并非业务本身复杂,而是人为因素造成的,命名混乱就是最常见的因素。虽然不合理的命名并不影响需求的实现,但却加重了认知负荷,随着时间的推移,理解代码的成本会越来越高。同时,命名不合理本质上是抽象不合理,往往影响可复用性。

2.2 分层抽象

在软件开发中,经常会用到各种分层架构,如经典的三层模型(展现层、业务逻辑层、数据层)和 MVC (Model、View、Controller)模型。如图 1 所示为阿里广泛采用四层模型,它包括 View、Service、Manager、DAO 四部分,通过分层将数据访问、通用处理、业务逻辑、终端展示四者解耦,各司其职。View 与用户交互;Service 依赖多个 Manager 和 DAO 实现具体的业务逻辑;Manager 负责通用业务逻辑处理和封装外部服务,它是对 Service 层通用能力的下沉,注重复用性;DAO 负责与底层数据库进行数据交互。分层架构的核心其实就是抽象的分层,每一层的抽象只需要而且只能关注本层相关的信息,从而简化整个系统的设计。
在这里插入图片描述

2.3 原则抽象

在面向对象设计和面向对象编程领域,有一个著名的 SOLID(单一功能、开闭原则、里氏替换、接口隔离以及依赖反转)原则,它是由 Robert Martin 在 21 世纪早期提出。在软件设计和开发中,正确地遵循这些设计原则,有助于提升系统的可维护性和可扩展性。

以依赖倒置原则(Dependency Inversion Principle, DIP)为例,其含义为:抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对抽象(接口)编程,而不是针对实现细节编程。这样做有什么好处呢?一个软件系统通常可划分为多个层次,上层调用下层,上层依赖于下层,如果上层依赖的是下层的具体实现,那么,当下层实现细节发生变化时,上层往往也需要同步修改,这就加重了不同层之间的耦合度。但是,如果上层依赖的只是下层的抽象而不是细节,就完全不同了,抽象变化的频率极低,让上层依赖于抽象,实现细节也依赖于抽象,即使实现细节不断变动,只要抽象不变,上层就不需要变化,如此一来大大降低了耦合度。

Java 的 JDBC 是依赖倒置原则的一个典型应用场景 。如图 2 所示,如果没有 JDBC 这一层抽象,软件系统将直接依赖具体的数据库(如 MySQL、Oracle 等),与实现细节耦合,当需要切换到另一种数据库时,就需要修改大量代码来适应细节的变化。若系统依赖的是抽象的 JDBC 接口,那么通过调用 JDBC 即可完成数据库操作,而无须再关注 JDBC 背后的数据库,因为所有关系型数据库的连接库都实现了 JDBC 接口,当需要换数据库时,作为抽象的 JDBC 并不会变化,系统也就无需感知变化。
在这里插入图片描述


3. 经典抽象案例

如图 3 所示,有这样一个关于 “霸屏” 动效的需求,产品文档(Product Requirement Document,PRD)摘要描述如下:

ZFB 会员与 KA(Key Account) 商家合作,升级会员等级特权,因此在会员频道首页通过 “霸屏” 动效提示用户并引导其进入新等级特权页面;

若用户点击 “看我等级特权” 按钮,则自动跳转到新等级特权页面,引导目标达成,“霸屏” 动效不再出现,以免打扰用户;

若用户未点击 “看我等级特权” 按钮,“霸屏” 动效展示 3 秒自动收起。由于引导目标未达成,需继续引导,同时为了防止过度打扰用户,“霸屏” 动效每月最多出现 N 次,N 需支持灵活配置。

在这里插入图片描述
我们来简单分析一下这个需求,核心业务目标在于引导用户进入新等级特权页面,同时兼顾用户体验,避免 “霸屏” 动效过度打扰用户。对于服务端而言,需要实现 “疲劳度” 控制逻辑,即:

若用户点击按钮:持久化用户点击记录,当用户再次访问该页面时,通过查询点击记录就可以判断该用户是否曾点击按钮。若记录存在,则告知前端不要弹出 “霸屏” 动效。

若用户未点击按钮:持久化 “霸屏” 动效对用户的曝光记录,当用户再次访问该页面时,通过查询曝光记录就可以判断该用户是否满足展示 “霸屏” 动效的条件。若当月曝光次数少于 N,则告知前端可弹出 “霸屏” 动效。

3.1 方案一:战术抽象,多快好省,跑步前进

基于上面的需求分析,稍有经验的服务端开发工程师立马就能想出解决方案,如表 1 所示,为每个用户落一条记录即可实现需求。

表 1:点击、曝光记录模型概要
图片
从实现需求的角度来看,上述设计完全可以满足业务当前的需要。如图 4 所示,曝光、点击记录模型几乎完全是由产品文档(PRD)翻译而来,乍看之下,十分的 “信达雅”,简直不要太完美。
图片

图 4 将 PRD 翻译为模型
我们再来仔细分析一下,上面的模型真的好么???显然很一般!!!该模型局限于实现当前业务需求,几乎没有进行抽象建模,因此,建立的模型不能准确地刻画业务的本质。这样的模型可扩展性极差,基本就是一锤子买卖。

在笔者看来,直接 “翻译” PRD 是一种战术编程,或者说战术抽象。John Ousterhout 在《A Philosophy of Software Design》一书中提到:几乎每个软件开发组织都至少有一个将战术编程发挥到极致的开发人员,可称之为战术龙卷风(Almost every software development organization has at least one developer who takes tactical programming to the extreme: a tactical tornado)。战术龙卷风有以下几个特点。

快速。他们常以腐化系统为代价换取当前最快速的解决方案,几乎没有人能比他们更快地完成任务。

高产。他们是高产的程序员,代码量极高,堪称 “卷王”。

坑多。他们往往倾向于简单地进行功能堆积,忽视抽象建模,将成本放到未来,由后来人买单。

从战术龙卷风的特点可以看出,战术编程(抽象)是缺乏或者说忽视抽象建模和系统设计的,聚焦于快速交付,系统能用就行,注重短期收益而非长期价值。当然,这并非完全是软件工程师的问题,不合理的评价体系和行业特点亦难辞其咎。

3.2 方案二:深入分析,透过表象,探寻本质

方案一中 “草率” 地进行抽象建模是不可取的,于开发者自身而言,是一种苟且,无能力提升;于软件项目而言,随意堆积一次性代码,将成本放到未来,是一种不负责任的行为。

如果我们深入分析业务,我们会发现,其实有更好的方案,而且并不复杂。如图 5 所示:首先,忽略 PRD 描述中那些无关紧要的细节,可以发现,PRD 涉及两种场景;然后,针对两种场景,进一步抽取共同特征——场景 S : N 次/周期 Q;最后,洞见共同特征背后的本质——周期维度记账。
图片

图 5 基于业务抽象建立模型

基于【周期维度记账】这一需求本质,我们建立的模型不仅可以满足当前业务的需要:

用户点击按钮:DB 里面落一条记录,其中 scene 可设为 “CLICK”。当用户再次进入对应页面时,先根据 userId 和 scene 查询记录,若存在,则说明用户已经点击过按钮,告知前端无需展示“霸屏”动效。

用户未点击按钮:DB 里面落一条记录,其中 scene 可设为 “EXPOSE”。当用户再次进入对应页面时,先根据 userId 和 scene(CLICK)查询、判断用户是否点击过按钮,如果没有点击,则根据 userId 和 scene(EXPOSE)查询、判断并更新曝光次数 count。

与此同时,基于【周期维度记账】这一需求本质,我们建立的模型具有更好的可复用性、可扩展性。举两个例子:

多周期:基于字段 quantum 和 bizDt,可以支持终身、年、月、周、日等时间维度记账。满足不同业务场景的需要。

多场景:基于字段 scene,可以实现不同业务场景的数据隔离,同时支持多个场景,以及数据分析等附加需求。

  1. 抽象并非一蹴而就!需要不断假设、验证、完善
    如图 6 所示,在人类文明早期,人们基于直观地观测,认为地球是宇宙的中心,因此抽象出了 “地心说” 模型。随着时间的推移和观测手段的进步,人们观察到的天文现象越来越多,逐渐意识到 “地心说” 模型与观测结果存在矛盾,于是,人们开始对 “地心说” 模型进行修正(像极了程序员重构模型),典型如 “本轮-均轮” 模型。

然而,随着更多的天文现象被发现,在 “地心说” 模型的大框架下,无论如何修正都无法自圆其说。在 “地心说” 模型统治人类 “天文世界观” 很长一段时间后,勇敢的先行者推翻了 “地心说” 模型,并提出了在当时看来离经叛道的 “日心说” 模型。

在这里插入图片描述

从 “地心说” 模型被提出,到 “日心说” 模型被广泛接受,跨越了 1400 多年的时间。这一史实表明,人们对事物本质的探索是一个过程,而非一蹴而就!!!对于服务端开发而言,我们对需求的认知也是如此,初见之下,我们往往很难直接洞见其本质,而需要不断假设、反复推演,最终才能抽象出较好的模型。

你可能会问——抽象建模如此麻烦,开发时间往往又不充裕,何必苦苦探寻所谓的本质呢?能用不就行了么?

如果你确有上述疑问,不妨换个角度,想一下 “核心竞争力” 的内涵。很多时候,我们并不缺乏解决问题的办法、能力和资源,而缺乏的是对问题的识别、理解、抽象。当一个问题被抽象为足以刻画业务本质的模型,并拆解到软件项目维度的时候,面对确定的任务、清晰的目标,可以解决问题的人就非常多了。

某种程度上,解决问题的能力是重要的基础,但若仅仅是解决问题还远远不足以称为核心竞争力。对于服务端开发工程师而言,抽象建模能力比编程落地能力更重要,因为编程解决问题只是一种普通技能而已,而对具象事物(如业务需求)的高度抽象,探索事物的本质,需要我们从新的角度审视旧的问题,需要有创造性的想象力,这才是真正的难点,当然也是核心竞争力所在。

最后,不要苟且,不要应付。我们每一次对事物的深入思考、对表象背后本质的探寻,都是一次自我提升。

5. 推荐一本书

PS:本文内容节选自业界首部体系化、全景式解读服务端开发的著作——《服务端开发:技术、方法与实用解决方案》。

在这里插入图片描述

《服务端开发:技术、方法与实用解决方案》一书取材自阿里和蚂蚁集团的精品内训课程,由资深服务端技术专家、技术讲师、阿里第二届技术讲师课程大赛年度冠军得主、CSDN 博客专家撰写。该书理论与实践结合,全景式、体系化地阐述了服务端开发,核心内容包括以下两个部分。

第一部分:服务端开发的技术和方法

首先介绍服务端开发的职责、技术栈、核心流程和进阶路径;然后从需求分析、抽象建模、系统设计、数据设计和非功能性设计 5 个方面展开,结合案例深入讲解了服务端开发的实操方法和重难点,为读者呈现服务端开发的全景图,帮助读者快速、体系化地掌握服务端开发的知识和方法。

第二部分:服务端典型问题的解决方案

针对高并发、高性能、高可用、缓存、数据一致性、幂等、秒杀等服务端开发实践中的典型问题,给出了对应的解决方案和开发规范,同时还结合案例深入分析了不同方案的优缺点。此外,还总结了接口设计、日志打印、异常处理、代码编写、代码注释等落地层面的行业案例和规范。

读者对象

IT 从业人员:服务端开发工程师、客户端开发工程师、产品经理、测试开发工程师等。

高校学生:计算机、软件、自动化、电气、通信等专业有志于进入 IT 行业的在校学生。

在这里插入图片描述

目前,本书已经在京东、淘宝、当当、拼多多等电商平台发售。在电商 APP 搜索关键词 “服务端开发”、“服务端开发技术”,即可搜索到该书。

🍔彩蛋

⭐ 《阿里后端开发:抽象建模经典案例》免费包邮送3本!
⭐活动时间:截止到 2023-09-15 20:00:00
⭐ 抽奖方式:利用程序进行抽奖。
⭐参与方式:关注博主、点赞、收藏、评论区进行高质量评论(不少于10个字),即可参加抽奖活动
⭐本次活动一共赠3本,评论区抽取3位小伙伴免费送出!!

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

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

相关文章

Mac专用投屏工具AirServer 7 .27 for Mac中文免费激活版

AirServer 7 .27 for Mac中文免费激活版是一款Mac专用投屏工具,能够通过本地网络将音频、照片、视频以及支持AirPlay功能的第三方App,从 iOS 设备无线传送到 Mac 电脑的屏幕上,把Mac变成一个AirPlay终端的实用工具。 目前最新的AirServer 7.2…

Redis:分布式锁误删原因分析

一、线程阻塞 例如,线程一获取分布式锁,但是线程一阻塞时间过长,导致锁超时释放。此时线程二获取分布式锁。当线程一阻塞结束后,释放分布式锁,但是释放的却是线程二的锁。此时线程二就不安全了,线程三也可…

destoon关于archiver归档的性能优化

今天在处理一个项目时候发现archiver单个模块归档超过百万数据,打开速度就特慢,所以打开archiver下index.php文件进行分析,发现有句sql作怪,查询需要三四分钟,所以要修改这个。 $result $db->query("SELECT …

【Linux】Linux工具

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员,2024届电子信息研究生 目录 一、Linux安装软件: 1.yum安装 2.Linux和Windows文件互传 问题: 3.yum卸载软件 二、vim编辑器 1.命令模式 2.vim配置项说明 3.vim操作总结 一、Linux安装软件&#…

【Vue】快速入门案例与工作流程的讲解

🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚 🌟在这里,我要推荐给大家我的专栏《Vue快速入门》。&#x1f…

win部署CRM

win部署crm) 1.phpstudy2.composer3.代码4.其他配置 周末锴哥让我帮他部署了一个CRM,写个教程,方便之后他用。锴哥用的是 NxCrm,先把代码下下来。 1.phpstudy 1.首先是下载小皮面板,配置php的环境。这里面下载了php8…

UML类图

优质博客:IT-BLOG-CN UML(Unidied Modeling Language)统一建模语言:用来设计软件的可视化建模语言,能够表达软件设计中的动态与静态信息。UML定义了用例图、类图、对象图、状态图、活动图、时序图、协作图、构件图、部…

外星人入侵游戏-(创新版)

🌈write in front🌈 🧸大家好,我是Aileen🧸.希望你看完之后,能对你有所帮助,不足请指正!共同学习交流. 🆔本文由Aileen_0v0🧸 原创 CSDN首发🐒 如…

Improving 3D Imaging with Pre-Trained Perpendicular 2D Diffusion Models

使用预先训练的垂直 2D 扩散模型改进 3D 成像 论文链接:https://arxiv.org/abs/2303.08440 项目链接:https://github.com/hyn2028/tpdm Abstract 扩散模型由于其众多的优点已经成为一种流行的图像生成和重建方法。然而,大多数基于扩散的逆…

YOLOv8学习

1 YOLOv8训练自己的数据集 1.1 部署和运行 1.1.1 第一步,下载代码 源码地址 1.1.2 第二步,创建环境 默认已经安装好conda conda create -n yolopy38 python3.8conda activate yolopy38安装所需要的包,先cd到代码目录下 pip install -r…

基于Java的养老院管理系统的设计与实现(亮点:多角色、登录验证码、留言反馈)

养老院管理系统 一、前言二、我的优势2.1 自己的网站2.2 自己的小程序(小蔡coding)2.3 有保障的售后2.4 福利 三、开发环境与技术3.1 MySQL数据库3.2 Vue前端技术3.3 Spring Boot框架3.4 微信小程序 四、功能设计4.1 主要功能描述 五、系统实现5.1 养老院…

Linux底层基础知识

一.汇编,C语言,C,JAVA之间的关系 汇编,C语言,C可以通过不同的编译器,编译成机器码。而java只能由Java虚拟机识别。Java虚拟机可以看成一个操作系统,Java虚拟机是由汇编,C&#xff0c…

【深度学习实验】线性模型(三):使用Pytorch实现简单线性模型:搭建、构造损失函数、计算损失值

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入库 1. 定义线性模型linear_model 2. 定义损失函数loss_function 3. 定义数据 4. 调用模型 5. 完整代码 一、实验介绍 使用Pytorch实现 线性模型搭建构造损失函数计算损失值 二、…

idea创建springboot项+集成阿里连接池druid

创建项目并集成流程 1:前提准备2:创建springboot项目流程3:集成阿里连接池步骤4:集成swagger方便测试5:书写增删改查进行测试6:项目gitee地址 1:前提准备 准备开发工具:idea java环…

nginx知识点详解:反向代理+负载均衡+动静分离+高可用集群

一、nginx基本概念 1. nginx是什么,做什么事情? Nginx是一个高性能的HTTP和反向代理服务器,特点是占有内存少,并发能力强。Nginx转为性能优化而开发,能经受高负载考验。支持热部署,启动容易,运…

linux内核分析:线程和进程创建,内存管理

lec18-19:进程与线程创建 lec20-21虚拟内存管理 内核代码,全局变量这些只有一份,但是内核栈有多份,这可能就是linux线程模型1对1模式的由来。通过栈来做的 x86 CPU支持分段和分页(平坦内存模式)两种 分段,选择子那里就有特权标记了

Linux多线程【线程控制】

✨个人主页: 北 海 🎉所属专栏: Linux学习之旅 🎃操作环境: CentOS 7.6 阿里云远程服务器 文章目录 🌇前言🏙️正文1、线程知识补充1.2、线程私有资源1.3、线程共享资源1.4、原生线程库 2、线程…

GIS跟踪监管系统单元信息更新

GIS跟踪监管系统单元信息更新 单元信息更新。① 新增单元。② 编辑单元。③ 删除单元。物资查询(1)物资查询与展示。① 几何查询。• 单击查询:• 拉框查询:• 多边形查询:② 物资定位。• 多个物资定位: 单…

Visual Studio2019报错

1- Visual Studio2019报错 错误 MSB8036 找不到 Windows SDK 版本 10.0.19041.0的解决方法 小伙伴们在更新到Visual Studio2019后编译项目时可能遇到过这个错误:“ 错误 MSB8036 找不到 Windows SDK 版本 10.0.19041.0的解决方法”,但是我们明明安装了该…

智慧公厕:不放过任何“卫生死角”,为公共厕所装上“净化系统”。

#智慧公厕[话题]# #智慧公厕系统[话题]# #智慧公厕管理系统[话题]# #智慧公厕设备[话题]# #智慧公厕厂家[话题]# 在社会活动中,公共厕所是我们经常使用和停留的场所。然而,由于传统公共厕所的粗放式管理,导致卫生情况差、设备不齐全、配置破…