Day968.如何开启一个遗留系统现代化项目? -遗留系统现代化实战

news2025/1/17 5:55:44

如何开启一个遗留系统现代化项目?

Hi,我是阿昌,今天学习记录的是关于如何开启一个遗留系统现代化项目?的内容。那如何启动一个遗留系统现代化项目。


一、项目背景

说来有点唏嘘,国内遗留系统的重灾区,恰恰是那些最早拥抱信息化的行业,比如电信、银行、保险、民航等。

它们早年身先士卒,投资金、投人力,建设了信息化系统,没想到多年以后反而成为了限制业务发展的遗留系统。

这些遗留系统都在各方面都存在着许多共性:

  • 代码量巨大且质量不高
  • 前端普遍使用用 ASP、JSP 等服务端渲染技术,在页面中内嵌了大量业务逻辑
  • 数据库中存在大量存储过程和函数
  • 单体“大泥球”架构
  • 系统缺乏文档和知识,新人很难上手
  • 几乎没有 DevOps

虚拟案例是一个车险行业的业务系统,它具备以上所有特点,使用 JSP 技术,数据库是 Oracle,存储过程的代码量占整体代码量的三分之一左右。

那么在开始现代化之前,需要做哪些前期准备呢?


二、业务梳理

作为架构师,可能并不熟悉每一个业务模块的具体内容,但不了解业务是无法设计出合理架构的。

因此,需要先对整体业务进行梳理划分出业务的边界,才能进一步设计组件和服务。还需要沟通好业务方,请他们派出各个业务模块的领域专家跟你一起梳理。也同样需要业务分析师、质量分析师和资深开发人员。

有很多梳理业务的方法和工具,像用户旅程、用户故事地图等,它们可以帮助理解业务流程、梳理业务架构。这其实也是一个降低外在认知负载、提升相关认知负载的过程。

梳理好的投保和理赔业务的用户旅程(这里是一个简化版的用户旅程,忽略了痛点和心情曲线,目标是梳理业务流程,而不是寻找用户痛点)大致如下所示:

在这里插入图片描述

在这里插入图片描述


三、战略建模与架构设计

接下来,需要以用户旅程为蓝本,对整个系统进行战略建模,目的是设计出目标架构。

战略建模同样有很多工具可用,常见的有事件风暴、动名词法,以及刚刚兴起的领域故事会。在这个案例里,使用动名词法。

动名词建模法 是指通过梳理业务需求、识别关键领域名词、识别命令动词,并将名词动词进行关联,从而形成统一语言、提取模型的建模过程。

其中,领域名词是指在业务操作中出现的名词,通常是业务操作的对象,比如“订单”,“商品”等。 而命令动词是指作用于领域名词的动作,使用业务语言描述(区别于 CRUD),比如“下单”,“订购”等。

在实战中,将整个建模过程分为以下七个步骤。

在这里插入图片描述

其中,前四个步骤属于业务梳理,后三个步骤属于架构设计。

步骤一:识别动名词

在这一步中,跟领域专家一起,进一步详细分析用户旅程中的每一个业务阶段。

按照业务时序,讨论业务步骤,以达成一致的理解。

梳理完毕后,将动词和名词按照业务相关性组织到一起。

在这里插入图片描述
在这一过程中,可以和领域专家澄清很多缩略的业务术语。

比如核保,拆分成命令动词和领域名词,应该是审核投保单,承保应该是承接投保单,缴费应该是缴纳保费,报案应该是申报案件申请,结案应该是结束案件……澄清这些术语很重要。

比如核保和承保,字面上理解是审核和承接保单,但实际业务中却是投保单。

通过和领域专家的沟通,才会明白,保单才是保险公司和投保人之间的合同,而投保单只是一个投保申请。

因此,保单和投保单很明显是两个领域名词,建立的模型也肯定是不一样的。

再比如缴费这个术语,在投保上下文里代表的是缴纳保费,但在其他上下文里,可能是缴纳其他费用。

越早澄清这些容易引起歧义的名词,就越容易形成统一语言,避免误解。


步骤二:识别角色

角色 是命令动作的发起者,比如“代理人”、“承保岗”、“查勘岗”,也可以是一个系统,比如微信小程序、支付宝等。

通过识别角色,可以进一步了解命令动作是如何参与到业务中的。

另外,不同角色的需求和变化频率往往不同,这有助于设计边界更加合理的架构。


步骤三:寻找缺失概念

缺失的概念是 指业务人员没有明确提到的概念,但是缺失后很可能影响业务的完整性和可追溯性。

缺失的可能是名词,比如已经识别出来了某个动词,但却没有找到与之对应的名词,需要找到这个名词,并补充到模型中;

缺失的也可能是动词,业务人员没有明确提到,但缺失了某一动词后,名词的生命周期就不完整,这样的动词也需要补充到模型中。

比如在步骤一提到的投保和缴费,就都是行为,没有对应的名词,找到投保单和保费的概念,就弥补了缺失的名词。

再比如赔款这个名词,只有“支付”这一个动词与之对应,显然生命周期是不完整的,应该补充“生成赔款”这一动作。


步骤四:去除噪音

与前一步“寻找缺失的概念”相反,这一步是要去除或忽略无用的信息(噪音)。

通常需求⽂档或者业务人员的描述会涉及到很多细节,但并不是所有的内容都和建模相关。在实施过程中需要有针对性地甄别,避免噪音对模型的干扰,降低后续设计过程的复杂度。在建模时不需要关注的噪音通常包括:

  • 无需记录的线下操作:有些行为并不会影响系统的数据或状态,因此不需要被系统记录。比如投保人提供投保单材料、上级人工核保、打印保单、清分单据等。
  • 查询操作:和数据查询相关的操作,如数据展示、数据导出、数据过滤查询等。
  • 字段说明:业务验证错误时的提示语、出错信息等。

经过这四个步骤,完成了业务梳理,部分的领域名词和命令动词如下所示:

在这里插入图片描述


步骤五:区分基础能力与运营能力

对于一个大型的复杂系统,需要将它分解成更小、更简单的部分。

借鉴 Unix 操作系统“分离策略与机制”的设计原则和 DDD 战略设计方法,将业务能力分为基础能力和运营能力。

基础能力通常提供原子能力,它们不依赖于编排能力,且变化的频率很低;

运营能力是在基础能力之上,企业想要健康运作而需要的能力,它们的变化频率很高。

在这一步中,要区分已经汇总的动名词对儿,并将它们按照基础能力和运营能力分成两层。

在这里插入图片描述


步骤六:识别核心基础能力

对于像保险业务系统这样的大型复杂系统,其基础能力可能仍然过大,需要进一步分解。

按照 Gartner 的 PACE Layered Application Strategy,对于基础能力里稳定性(或变动频率)不同的部分,可以再次划分,识别出核心基础能力。

核心基础能力是指反映业务本质,实现业务价值所必须的最小能力集合。

在识别核心基础能力的时候,可以遵循这样三个原则:

  • 稳定性原则:即找出反映业务本质的部分。业务本质通常是最稳定的,而与用户的交互通常是不稳定的。
  • 最小化原则:即尽可能做减法,非必要不做加法。
  • 完备性原则:即核心基础能力应该是完备的,能够独立实现业务价值。

以保险业务为例,不论其渠道端(柜台、互联网、移动端)怎么变化,不论实现技术怎么变化,其业务本质仍然围绕保单展开的,包括保单的费用和服务(案件、赔款)。

在识别出业务本质后,业务名词就可以分解为这样的三层。

在这里插入图片描述


步骤七:设计分层架构

当把业务名词分层之后,就可以着手设计目标架构了。

在这里,把这些业务名词理解为一个业务模块或组件中的核心模型,并以这些名词作为模块或组件的名称。

对于企业的业务系统,可以粗略地设计为三个层次:接入层、运营作业层和核心能力层。

  • 接入层 一般为 UI 系统、API Gateway 或 BFF 等,比如手机 App、微信小程序等。
  • 运营作业层是指围绕业务价值所展开的运营活动和作业管理。在这里把前面的运营能力层和基础能力层合并,来作为运营作业层。
  • 核心能力层是实现业务价值所必须的最小能力集合,是企业运营的本质。比如保险行业就是保单和保费,而银行则是围绕账户所展开的金额和状态的管理。
  • 除此之外,业务系统还需要对接一些企业已有的公共服务,比如产品中心、银行对接、客户管理、权限管理等,也需要与一些外部系统进行交互。最终的目标架构如下图所示:

在这里插入图片描述

当然,这只是一个假想的保险业务系统,仅仅做了其中部分业务的粗略梳理,并不是什么行业标准。


四、选择试点

有了战略模型和架构设计后,接下来要选择一个试点进行遗留系统现代化。

在做数字化转型时,常常会选择一个**精益切片(Thin Slice)**作为试点,而不是全盘地转型。

遗留系统现代化同样可以借鉴这种方法,对架构进行垂直的切割,将业务的所有元素整合成一个价值交付部分,能够提供完整的价值。

除了业务价值,还需要考虑试点的复杂度。可以使用一些工具,全盘分析整个遗留系统,一方面可以得出一些质量指标,比如缺陷数、坏味道数等,评估代码质量。

另一方面也能得出模块间的依赖关系,了解系统的复杂度。对于代码质量,推荐你使用流行的 SonarQube。

对于架构,推荐公司的开源工具 ArchGuard。

什么样的切片才适合做试点呢?这需要权衡业务价值和复杂度。

业务价值高的,往往很复杂,不好做;而简单的,又可能没有价值。

所以要尽量选择既能提供一定业务价值复杂度又不是很高的切片

因为复杂度太高的话,进展会很慢,容易让团队和各方干系人失去信心和耐心。

相对简单的模块则更容易成功,可以给业务带来实惠,给团队增加信心,同时可以总结出来各种经验和套路,供下一个切片使用。

在综合评估了业务价值和复杂度这两个维度后,选择核保模块作为试点

下图中阴影覆盖的部分,就是一个切片。

在这里插入图片描述


五、以假设驱动为指引选择现代化方向

选择完试点,你还需要选择要对试点所采取的遗留系统现代化方向。

是重构代码,还是添加测试?是拆分模块,还是拆分服务?这些都是可行的方向,需要选择的是最可能实现更大业务价值的那些。

这时候需要以假设驱动为指引,找到价值最大的方向。比如从业务敏捷这个维度,需要缩短需求交付周期、扩大需求吞吐量。

以前 30 人天开发完成的需求,能否缩短到 20 天?以前一个迭代交付 5 个需求,能否再增加 1 个?如果业务方更关注业务响应力,可能需要将这个模块拆分成相对独立的服务

另一方面,如果平时这块业务 Bug 比较多,需求方更希望改善它的质量,那可能需要对代码添加各种级别的测试。

指标的重要性和优先级确立以后,需要与业务方达成一致,并选择可以支撑这些指标的工作。

就本案例而言,业务方更关注业务响应力,因此选择将核保模块拆分为微服务


六、确定目标架构

对于试点的目标架构,其实无需关注太多细节。虽然通过战略建模,梳理出了整个系统的大致架构分层,但这其实还是对于问题域(Problem Space)的分析。

具体解决方案域(Solution Space),这些模块是微服务,还是几个模块合并成基于服务的架构,其实都不需要在现阶段给出答案。

遗留系统是复杂的,架构应该是慢慢演进的。一个负责任的架构师,是不可能仅仅在几天的业务梳理和战略建模之后,就给出最终的确切架构的。

对于核保模块这个试点,目标架构十分简单,就是把它拆分出来,形成一个微服务

在这里插入图片描述


七、制定架构演进计划

虽然目标架构的形态十分直观,但演进计划却并不简单。

这是一个将遗留系统的微服务拆分这个复杂问题,拆解成多个简单问题的过程,最终让任何一个普通的开发人员,都能够胜任其中的一个简单任务。

在制定计划时,需要考虑以下几个方面:

  • 首先,代码如何拆分。在遗留系统中,各个业务模块的边界是否清晰?是否可以使用基于组件的分解?或者是一个结结实实的大泥球,只能使用战术分叉?最终决定采用战术分叉方式

  • 其次,数据如何拆分。是暂时不拆分,和遗留系统共享单体数据库?还是使用单体封装的数据库服务?或者变更数据所有权,并在应用中同步数据?关于这部分,你可以复习第十五节课的内容。本案例最终选择的是拆分数据。

  • 第三,如何增量迭代。按照增量演进原则,不能采取长期改造、一次性上线的交付方式,而应该是每个迭代都交付一部分增量。那么对于服务拆分,应该如何迭代?是按页面交付?还是按 API 交付?在这个案例里,考虑到页面过于复杂,包含很多按钮,而每个按钮都对应一个后端 API,选择按 API 交付,这样粒度更小。

  • 第四,组建拆分小组。你需要和项目负责人沟通好资源,给你一个 5~9 人的开发团队。如果遗留系统的团队结构是业务组件团队,则最好就是从维护核保这个组件的团队中抽调一些人。如果是特性团队,则最好是经常做核保特性的团队。最糟的情况是技术组件团队,你需要选择一些对核保业务比较熟悉的开发人员。另外,一定要配备一到两名专职测试拆分结果的测试人员,不要给他们分配其他测试工作。我们在第十八节课中介绍过,这样会让测试人员在不同上下文之间频繁切换,增加他们的认知负载。

  • 第五,干系人如何管理。需要与业务方、项目负责人、业务分析师、其他架构师、核心开发人员、测试人员建立紧密的联系,获得他们的支持和帮助。做好这几个方面,你就可以开始按迭代增量演进了。


八、按迭代增量演进

迭代 0 是增量演进中最重要的迭代,有很多事情要在这个迭代完成。

  • 第一,创建全新的核保代码库。按照战术分叉的方法,将遗留单体的代码全量复制到核保代码库中,并将与核保无关的代码删除。
  • 第二,创建全新的核保数据库。对于数据,也可以使用战术分叉方法,将全量数据复制过来再删除掉无关的表,或者利用 Oracle 的特性,使用 DB Link,先远程访问单体数据库中的内容。具体方法我们后面的课程再展开。
  • 第三,搭建核保服务的持续集成流水线。如果遗留系统已经有了持续集成流水线,可以复用。如果没有,可以只搭建一个最简单的流水线,只包含构建和打包功能。
  • 第四,将持续集成流水线打出来的包部署到各个环境中。部署完之后,可以通过 API 工具测试部署是否成功。
  • 第五,建立开关机制。将流量引流到新的服务中,以验证真实场景下的连通性。
  • 第六,计划迭代 1 要改造的 API。从迭代 1 开始,增量演进就将进入一个稳定的交付阶段,你需要在每个迭代结束前,计划好下个迭代要完成的工作。
  • 第七,制定开发工序。要将复杂的任务简单化,你需要制定一个普通开发人员可以遵循的开发清单。

比如用活文档工具进行业务梳理、添加 API 的开关并验证、在单体中的老 API 上添加 @Deprecated 注解、Java 代码怎么拆分、存储过程怎么拆分、JSP 中的代码如何处理、如何测试、如何寻求帮助等等。开发工序应该尽可能详细,以降低普通开发人员的认知负载。

由于迭代 0 的工作量巨大,可以相对延长迭代 0 的时间。比如一个迭代是两周,可以把迭代 0 延长到一个月,以确保这些内容顺利完成和交付。

从迭代 1 开始,就可以按增量来演进了。


九、关于估算

在改造时,一个绕不过去的话题就是需要多长时间。对于正常的功能开发,工作量的估算可能还比较准确,但是对于遗留系统现代化,想准确估算出具体的时间节点是难上加难。

因为遗留系统现代化是一个复杂问题,会有很多不确定的东西时不时冒出来,比如人员变动、临时添加的紧急需求、代码和架构本身未知的复杂度等等。不过,这和业务方的诉求是矛盾的,业务方想知道到底需要多少预算,来评估风险、衡量 ROI。

然而,如果迫于业务方的压力而随意拍脑袋给一个人天(比如 10 人天就是 1 个人工作 10 天,或者 2 个人工作 5 天),反而是不专业的。

这时最好的答案就是坦诚地说:我还不知道。

正因为如此,才更应该选取一个小的精益切片,并且将功能开关锁定在一个小的 API 上。因为开发的规模变小了,估算可能还相对容易一些。你应该快速做出一个小的增量,证明这是可行的,给团队、领导和业务方以信心。

然后根据做出的这个增量的工作量去估算其他增量。也可以让业务方来比较一下,希望开发给出一个一年的承诺,最后一次性上线全部承诺,还是不做出具体承诺,但是一年内每个月都能看到一个具体的进展,并且随时可以中止(因为是增量且可回退的)。

如果业务方选择后者,那么他们就不会再纠结于一次性知道全部费用了。


十、总结

讨论了如何开启一个遗留系统现代化项目。

花了不少篇幅去梳理开启项目的步骤,需要先对不熟悉的业务进行梳理,得到初步的用户旅程或用户故事地图;

再通过动名词法等工具,对系统进行战略建模,并设计出目标架构;

然后选择一个端到端的业务进行试点,并以假设驱动的方式寻找合适的现代化方案;

确定目标架构以及制定演进计划,并按照计划逐个迭代地增量演进;

最后,每个迭代都需要得到充分验证。

目标很明确,就是要把核保业务从单体大泥球架构中拆分出来,形成具有独立数据库的微服务。这已经是个非常艰巨的任务了。

因此一定要记住,一次只做一件事。有时候你可能既想拆分微服务,又要进行代码重构,或者既要拆分数据,又想重新设计不合理的数据库,这些都是我不推荐的。

可以把它们排进计划,等一件事彻底做完再做另一件,而不要企图并行完成

因为认知负载太高了,什么都想做,最终什么也做不成。


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

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

相关文章

MongoDB概念和操作

一、相关概念 在mongodb中最基本的概念为:文档、集合、数据库 SQL术语/概念MongoDB术语/概念解释/说明databasedatabase数据库tablecollection数据库表/集合rowdocument数据记录行/文档columnfield数据字段/域indexindex索引table joins表连接,MongoDB不支持prima…

Cordova webapp实战开发:(5)如何写一个Andorid下自动更新的插件?

在 《Cordova webapp实战开发:(4)Android环境搭建》中我们搭建好了开发环境,也给大家布置了调用插件的预习作业,做得如何了呢?今天我们来学一下如何自己从头建立一个Andorid下的cordova插件。 本次练习你能…

【大腹太卷】一篇文章带你了解校招的神秘面纱

校招求职复盘 写在前面方向确定前置工作就业信息获取简历制作简历投递 笔面试工作测评笔试面试八股文自我介绍项目相关HR面试反问环节 Offer选择写在后面 写在前面 2023届应届生,去年的时候参加了校招,一路走来,感慨良多,特此记录…

蚊香液、蚊香片、蚊香盘的优缺点

夏天来了,蚊子也出来活动了,又到了消灭蚊子的季节。     蚊子是凭借人所呼出的二氧化碳和带气味的气体,来定位人的位置,进而叮咬人的皮肤。     蚊子吸人血,主要是利用血液里的胆固醇、B族维生素,促进蚊…

OSPF综合实验(第一部分)

目录 要求 确定广播域的个数 分配网段 配置路由器IP地址-优先公网配通 配置MGRE部分 拓扑结构: 要求 1、R4为ISP,其上只能配置IP地址,R4与其他所有直连设备间使用公有IP 2、R3~R5/6/7为MGRE环境,R3为中心站点 3、整个OSPF环境I…

《编程思维与实践》1072.下一位妙数

《编程思维与实践》1072.下一位妙数 题目 思路 思路与最小不重复数基本一致,从最高位开始找到第一个出现9的位置,让其加1,后面全变为0即可. 只需要再加一个判定条件:不能被9整除. 由数学知识,一个数不能被9整除当且仅当各位数之和不能被9整除. 这里给出简单的证明: 不妨以三位…

Linux-初学者系列7_shell编程

在进行服务器集群管理时,需要编写shell程序来进行服务器管理。 shell是一个命令行解释器,他会为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户用shell启动、挂起、停止和编写一些程序。 Linux-初学者系列7_shell编程…

简单记录一下spi的四种mode

0 前言 最近在学习SPI&#xff0c;刚开始接触四种mode的时候&#xff0c;还有点懵&#xff0c;也是搜了好几个博客&#xff0c;才算搞懂&#xff0c;特此记录下&#xff0c;防止下次又要翻好几篇博客才找到答案 >_< 1 四种mode的组成单元 这四种mode是由时钟极性和时钟…

Leetcode刷题之反转链表Ⅱ

业精于勤而荒于嬉&#xff0c;行成于思而毁于随。 ——韩愈目录 前言&#xff1a; &#x1f341;一.反转链表Ⅱ &#x1f352;1.left和right中间链表反转&#xff0c;再把反转链表和剩下的链接起来 &#x1f5fc;2.left和right中间链表头插 题目描述…

「实验记录」MIT 6.824 Raft Lab2A Leader Election

#Lab2A - Leader Election I. SourceII. My CodeIII. MotivationIV. SolutionS1 - 角色转换S2 - 发起 RequestVote 拉票请求S3 - 收到 RequestVote 的不同反应S4 - 发送 AppendEntries 心跳包S5 - 收到 AppendEntries 的不同反应S6 - defs.go约定俗成和GetState() V. Result I.…

The service already exists!

文章目录 项目场景&#xff1a;原因分析&#xff1a;解决方案&#xff1a; 项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 在给一位同学安装MySQL时报了这个错&#xff0c;我知道是她之前安装过但是没删干净的原因 但是我把Everything和注册表都查…

五、RGB实验(正点原子达芬奇Pro代码>>ZYNQ 7020代码移植)

RGB实验(正点原子达芬奇Pro代码&#xff1e;&#xff1e;ZYNQ 7020代码移植) 文章目录 RGB实验(正点原子达芬奇Pro代码&#xff1e;&#xff1e;ZYNQ 7020代码移植)前言一、本文目标二、移植步骤1.建立文件2.建立v文件1.lcd_rgb_colorbar2.lcd_driver3.rd_id4.clk_div5.lcd_dis…

单调队列算法模板及应用

文章和代码已经归档至【Github仓库&#xff1a;https://github.com/timerring/algorithms-notes 】或者公众号【AIShareLab】回复 算法笔记 也可获取。 文章目录 队列算法模板例题&#xff1a;滑动窗口code 队列算法模板 // hh 表示队头&#xff0c;tt表示队尾 int q[N], hh 0…

使用Advanced Installer软件将winform程序打包成exe安装文件

在使用vs编写c#代码时&#xff0c;一般都是在debug文件中双击exe文件就可以执行&#xff0c;但是有时候需要将这个exe文件发给别人使用&#xff0c;在自己的电脑上exe文件可以执行&#xff0c;但是在别人的电脑上有时候打开后会报错&#xff0c;提示缺少.neta运行环境&#xff…

AUTUSAR通信篇 - CAN网络通信(一)

第一篇从全局角度出发&#xff0c;简单介绍了AUTOSAR的结构&#xff0c;从本篇开始我们一起详细了解一下AUTOSAR软件架构下内部的组成部分。下面&#xff0c;我们首先介绍第一个模块-通信。在AUTOSAR BSW中通信由三个部分组成&#xff0c;分别是&#xff1a;通信驱动、通信抽象…

【计算机视觉 | Pytorch】timm 包的具体介绍和图像分类案例(含源代码)

一、具体介绍 timm 是一个 PyTorch 原生实现的计算机视觉模型库。它提供了预训练模型和各种网络组件&#xff0c;可以用于各种计算机视觉任务&#xff0c;例如图像分类、物体检测、语义分割等等。 timm 的特点如下&#xff1a; PyTorch 原生实现&#xff1a;timm 的实现方式…

Java之线程池

目录 一.上节复习 1.阻塞队列 二.线程池 1.什么是线程池 2.为什么要使用线程池 3.JDK中的线程池 三.工厂模式 1.工厂模式的目的 四.使用线程池 1.submit()方法 2.模拟两个阶段任务的执行 五.自定义一个线程池 六.JDK提供线程池的详解 1.如何自定义一个线程池? 2.创…

【计网】第三章 数据链路层(3)信道划分介质访问控制

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 3.5-1 信道划分介质访问控制&#xff08;播报信道中应用&#xff09;一、传输数据使用的两种链路二、介质访问控制 三、信道划分 介质访问控制&#xff08;静态划分…

协程切换原理与实践 -- 从ucontext api到x86_64汇编

目录 1.协程切换原理理解 2.ucontext实现协程切换 2.1 实现流程 2.2 根据ucontext流程看协程实现 2.3 回答开头提出的问题 3.x86_64汇编实现协程切换 3.1libco x86_64汇编代码分析 3.2.保存程序返回代码地址流程 3.3.恢复程序地址以及上下文 4.实现简单协程框架 1.协程…

《编程思维与实践》1071.猜猜猜

《编程思维与实践》1071.猜猜猜 题目 思路 对于首字符而言,如果后一位字符与之相同,则首位选法只有1种,不同则2种; 对于最后一位字符而言,如果前一位字符与之相同,则末位选法只有1种,不同则2种; 对于中间的字符而言,有以下几种可能: 1.中间字符与前后字符均不同且前后字符不同…