好的提高代码质量的方法有哪些?有什么经验和技巧?
用于确保代码质量的6个高层策略:
1 编写易于理解的代码
考虑如下这段文本。我们有意地使其变得难以理解,因此,不要浪费太多时间去解读。粗略地读一遍,尽可能吸收其中的内容。
〓ts〓取一个碗,我们现在称之为A。取一个平底锅,我们现在称之为B。在B中装满水,置于炉盘上。在A中放入黄油和巧克力,前者100g,后者185g。这应该是70%的黑巧克力。将A放在B之上;等待A的内容物融化,然后将A移到B之外。再取一个碗,我们现在称之为C。在C中放入鸡蛋、糖和香草香精,第一种原料放两个,第二种185g,第三种半茶匙。混合C的内容物。A的内容物冷却后,将其加入C当中混合。取一个碗,我们称之为D。在D中放入面粉、可可粉和盐,第一种原料50g,第二种原料35g,第三种半茶匙。完全混合D的内容物,然后过滤到C中。充分搅拌D的内容物使其完全混合。我们要用这种方法制作巧克力糕饼,我是不是忘记说这个了?在D中加入70g巧克力屑,充分搅拌D的内容物。取一个烘焙模具,我们称之为E。在E中涂上油脂并铺上烘焙纸。将D的内容物放入E中。我们将把你的烤炉称为F。顺便说一句,你应该将F预热到160℃。将E放入F中20min,然后取出。让E冷却几个小时。
现在,我们提出一些问题。
〓● 这段文本说的是什么?
〓● 按照这些指示,我们最终能得到什么?
〓● 我们需要哪些配料?各种配料的分量是多少?
我们可以在这段文本中找到上述问题的答案,但并不容易。这段文本的可读性很差。造成这一结果的问题很多,包括如下。
〓● 没有标题,因此我们不得不通读整段文本,以领会它的意义。
〓● 这段文本没有很好地组成为一系列步骤(或者子问题),而是像一堵长长的文本墙。
〓● 用毫无益处的模糊名称指代事物,如“A”,而不是“装有融化后奶油和巧克力的碗”。
〓● 信息与需要它们的地方相隔甚远:成分与数量相互分离,烤炉需要预热这样的重要指示到最后才提及。
(你可能已经感到厌倦,没有读完这段文本,它是巧克力糕饼的食谱。如果你真想制作这种食物,附录A中有一个更易于理解的版本。)
阅读一段质量低劣的代码并试图领会其含义,与我们刚刚阅读巧克力糕饼食谱的体验没有什么不同。特别是,我们可能很难理解关于代码的如下情况:
〓● 做什么;
〓● 怎么做;
〓● 需要什么成分(输入或状态);
〓● 运行代码后得到什么。
在某个时间,其他工程师很有可能必须阅读并理解我们的代码。如果我们的代码在提交之前必须经过代码评审,那么这种情况几乎是立刻发生的。但即便忽略代码评审,在某个时间,其他人也会查看我们的代码,并试图领会它的作用。这可能发生在需求变化或者代码需要调试的时候。
如果我们的代码可读性很差,其他工程师就不得不花费很多时间来解读它。他们很有可能错误地理解它的作用,或者遗漏一些重要的细节。如果发生这种情况,代码评审期间就不太可能发现缺陷,而在其他人修改我们的代码、添加新功能时,就有可能引入新缺陷。软件的功能都是基于代码来完成的。如果工程师无法理解代码的作用,也就几乎不可能确定软件能否正常工作。正如食谱一样,代码必须易于理解。
在第2章中,我们将了解到,如何通过定义正确的抽象层次来帮助实现可读性。而在第5章中,我们将介绍使代码更易理解的一些具体技术。
2 避免意外
过生日时得到一件礼物,或者彩票中奖,都是意外好事(惊喜)的例子。但是,当我们试图完成一件特定任务时,意外通常不是好事。
想象一下,你饿了,因此决定下单购买一些比萨。你拿出电话,找到比萨店的电话号码,拨通电话。很奇怪的是,电话那端沉默了很长时间,但最终还是接通了,有个声音询问你:想要什么?
“请来一份大的玛格丽塔比萨,外送。”
“好的,你的地址?”
半个小时以后,你收到外卖,打开包装一看却发现图1-3中的情景。

图1-3 如果你以为是在和一家比萨店通话,实际上却是一家墨西哥餐厅,那么你的订单仍然有意义,但送来的可能是意外的东西
哇,这真是意外。显然,有人将“margherita”(一种比萨的名称)误听成“margarita”(一种鸡尾酒的名称)。但这是件怪事,因为这家比萨店没有提供鸡尾酒。
原来,你手机上使用的定制拨号应用添加了一个新的“智能”功能。应用开发者发现,当用户拨打一家餐厅的电话却遇到忙线的情况时,80%的人会立刻致电另一家餐厅,因此,他们创建了一个节约时间的方便功能:当你拨打一个应用识别为餐厅的电话号码且遇到忙线,该应用将无缝地拨打电话簿中下一家餐厅的电话号码。
在这个例子中,下一家餐厅恰好是你最喜欢的墨西哥餐厅,而不是你以为正在拨打的比萨店。墨西哥餐厅肯定提供玛格丽塔鸡尾酒,而不是比萨。应用开发者的意图很好,也认为这种功能可以方便用户的生活,但他们创建了一个会带来某种意外的系统。我们依赖自己对电话的心理模型,根据听到的声音确定发生的事情。重要的是,如果我们听到语言应答,心理模型就会告诉我们已经接通刚刚拨打的电话号码。
定制拨号应用的这个新功能改变了应用的表现,超出我们的预期。它打破了我们的心理模型假设,即语音应答意味着我们已经接通刚刚拨打的电话号码。这个功能或许很有用,但因为其行为超出普通人的心理模型,就必须明确告知人们发生的情况,例如用语音信息告诉人们拨打的电话号码正忙,询问是否愿意拨打另一家餐厅的电话号码。
可以将这个定制拨号应用类比为一段代码。其他工程师在使用我们的代码时将名称、数据类型和常见约定作为线索,以构建一个心理模型,用于预测我们的代码以什么为输入、完成什么功能、返回什么结果。如果我们的代码行为超出这个心理模型,就很有可能导致软件潜藏缺陷。
在致电比萨店的例子中,即便在发生意外情况之后,一切似乎仍正常运转:你点了一个玛格丽塔比萨,餐厅也乐于效劳。直到很久以后,错误已无法纠正,你才发现无意间点了一杯鸡尾酒而不是一份比萨。这与软件系统中的代码完成意外工作时常常发生的情况很类似:因为代码调用者没有预料到这种意外,这些代码将一无所知地继续执行。在一段时间里,一切看起来都很正常,但随后出现可怕的错误,程序处于无效状态,或者将一个奇怪的值返回给用户。
即便有着最好的意图,编写提供一些有用或者“聪明”功能的代码仍有造成意外的风险。如果代码做了某些意外的事情,使用代码的工程师不会知道也不会思考处理那种情况的方法。这往往会导致系统“跛行”,直到在远离问题代码的地方出现明显的古怪表现。或许,这只会产生一个有些恼人的缺陷,但也可能造成破坏重要数据的灾难性问题。我们应该提防代码中的意外情况,并尽可能避免。
在第3章中,我们将看到,代码契约是一种有助于解决这个问题的基础技术。第4章在介绍软件错误时提到,如果不能正确提示或处理这些错误,就可能导致意外情况。第6章将关注避免意外的一些更具体的技术。
3 编写难以误用的代码
在电视机的背部,我们可能会看到如图1-4所示的接口。我们可以在这些接口里插入不同的线缆。重要的是,电视机厂商通过将不同的接口设计成不同的形状,可以防止用户将电源线插进HDMI接口中。

图1-4 电视机厂商有意将电视机背部的接口做成不同形状,以避免用户插入错误的线缆
想象一下,如果电视机厂商没有这么做,而是将每个接口做成相同的形状,将会出现什么情况。你认为会有多少人在电视机背部摸索的时候不小心将线缆插进错误的接口里?如果将HDMI线缆插到电源接口里,电视机可能无法工作,虽然让人烦恼,但也不算太可怕。但如果有人将电源线插进HDMI接口里,就会烧毁电视机的电路板。
我们所写的代码常常被其他代码调用,这有点像是一台电视机的背部。我们预计其他代码会“插入”某种东西,比如输入参数,或者在调用前将系统置于某个状态。如果将错误的东西“插入”代码,就可能造成某些破坏:系统崩溃、数据库永久性损坏或者丢失某些重要数据。即便没有造成破坏,代码也很有可能无法正常工作。我们的代码被调用是有原因的,插入不正确的内容,可能意味着一项重要的任务没有执行,或者某些古怪的行为没有引起注意。
通过编写很难或不可能被误用的代码,我们可以最大限度地提高代码持续正常工作的概率。针对这个问题,有许多实用的解决方法。第3章介绍的代码契约(类似于避免意外)是有助于编写难以误用的代码的基础技术。第7章将介绍编写难以误用的代码的一些更为具体的技术。
4 编写模块化的代码
模块化意味着一个对象或系统由可独立替换的更小的组件组成。为了说明这个概念以及模块化的好处,我们考虑图1-5中的两个玩具。

图1-5 模块化的玩具很容易重新配置,而缝合起来的玩具则极难重新配置
图1-5左侧的玩具是高度模块化的。头部、手臂、手掌和腿都很容易独立替换,而不会影响到玩具的其他部分。相反,图1-5右侧的玩具是非模块化的。没有轻松的方法可以替换头部、手臂、手掌或腿。
模块化系统(如图1-5左侧的玩具)的特征之一是,不同组件有明确定义的接口,相互作用的点尽可能少。如果我们将一只手掌当成组件,那么左侧的玩具只有一个交互点和一个简单的接口:一根钉子,以及一个与之适配的小孔。而右侧的玩具在手掌和身体其他部位之间有一个极其复杂的接口:手掌和手臂上有20多圈相互交织的线。
现在想象一下,如果我们的任务是维护这些玩具,某天经理告诉我们一个新需求:手掌上要有手指。我们更愿意应对哪一个玩具/系统?
对于左侧的玩具,我们可以制造一只新设计的手掌,轻松地替换现有的手掌。如果两周以后,经理改变了主意,我们可以恢复玩具原来的配置,而不会产生任何麻烦。
至于右侧的玩具,我们可能不得不拿出剪刀,剪掉那20多圈线,然后直接将新的手掌缝到玩具上。在这个过程中,我们可能会损坏这个玩具,如果两周后经理改变主意,我们就要同样费尽力气将玩具恢复成原有配置。
软件系统和代码库与这些玩具非常相似。将代码分解为独立模块,其中两个相邻模块的交互发生在单一位置、使用明确定义的接口,往往是很有好处的。这有助于确保代码更容易适应变化的需求,因为一项功能的变化不需要对所有地方进行大量修改。
模块化系统通常也更容易理解和推演。因为系统被分解为容易控制的小功能块,各功能块之间的交互有明确的定义和文档。这增加了代码一开始就能正常工作,并在未来持续工作的可能性——因为工程师更不容易误解代码的作用。
在第2章中,我们将了解如何创建清晰的抽象层次,这是引导我们编写出更具模块化特性的代码的一种基础技术。在第8章中,我们还将了解一系列使代码更加模块化的具体技术。
5 编写可重用、可推广的代码
可重用性和可推广性这两个概念很类似,但略有不同。
〓● 可重用性的含义是某个系统可在多种场景下用于解决同一个问题。手钻是一种可重用工具,因为它可以在墙、地板和天花板上钻孔。问题是相同的(需要钻一个孔),但场景不同(钻墙、钻地板和钻天花板)。
〓● 可推广性的含义是某个系统可用于解决多个概念相近但有细微差异的问题。手钻也是具有可推广性的工具,因为它可以用于钻孔,也可以将螺钉固定到某个物体上。制造商认识到,旋转是适用于转孔和固定螺钉的通用问题,因此它们造出可通用于这两个问题的工具。
在手钻的例子中,我们能立刻认识到这两个特性的好处。想象一下,如果我们需要4种不同的工具。
〓● 只能在平举状态工作的钻孔机——只能用于钻墙。
〓● 只能垂直向下工作的钻孔机——只能用于钻地板。
〓● 只能垂直向上工作的钻孔机——只能用于钻天花板。
〓● 用来固定螺钉的电动螺丝刀。
我们必须花很多钱购买这一套4种工具,将更多的东西带在身上,给4组电池充电——这都是浪费。幸亏有人发明了既可重用又可推广的手钻,我们只需要一种工具就能完成上述所有工作。不用猜也知道,手钻在这里又是对代码的一种类比。
创建代码需要花费时间和精力,一旦创建完毕,还需要持续投入时间和精力进行维护。创建代码也并非没有风险:尽管我们小心翼翼,编写的一些代码仍会包含缺陷,写得越多,出现缺陷的可能性越大。重点在于,我们在代码库中留下的代码行数越少越好。这听起来可能有些奇怪,我们不是通过写代码得到报酬的吗?但实际上,我们得到工资,是因为能够解决某个问题,代码只是一种手段。如果我们可以解决问题,同时花费更少的精力,降低我们不小心引入缺陷而导致其他问题的概率,就太好了。
编写可重用、可推广的代码,我们(和其他人)就可以在代码库的多个地方和场景中使用它们,解决不止一个问题。这能节约时间和精力,并使我们的代码更加可靠,因为我们往往重用已在外部经过考验的逻辑,其中的缺陷可能已经被发现和修复。
更具模块化特性的代码往往也有更好的可重用性和可推广性。与模块化相关的章节与可重用性和可推广性的主题关系紧密。此外,第9章将介绍一些提高代码可重用性、可推广性的专用技术和考虑因素。
6 编写可测试的代码并适当测试
正如我们在前面的软件开发与部署过程(见图1-2)中所见到的,在确保最终不会将有缺陷和不完善的功能投入运行的过程中,测试是至关重要的一环。它们往往是这一过程中两个关键点的主要保障(见图1-6)。
〓● 防止有缺陷或者不完善的功能提交到代码库。
〓● 确保阻止有缺陷或不完善的功能发行并投入运行。
因此,测试对确保代码可用并持续正常工作是必不可少的。

图1-6 为了最大限度地防止有缺陷和不完善的功能进入代码库,并确保它们不会对外发行,测试至关重要
在软件开发中,测试的重要性如何强调都不为过。你以前肯定多次听到这一说法,很容易将其视为老生常谈,但它确实重要。正如我们在本书的很多地方看到的那样。
〓● 软件系统和代码库往往太过庞大和复杂,一个人不可能了解所有细节。
〓● 人(即便是智力超群的工程师)都会犯错。
这或多或少都是生活中的事实。除非我们用测试来锁定代码的功能,否则这些功能就会习惯性地与我们(以及我们的代码)纠缠在一起。
代码质量的这一支柱包含两个重要的概念:“编写可测试的代码”以及“适当测试”。测试和可测试性相关,但考虑的因素不同。
〓● 测试——顾名思义,这与测试我们的代码或者软件有关。测试可能是人工进行,也可能是自动进行。作为工程师,我们通常努力编写测试代码来执行“真实”代码,并检查一切表现是否如同预期。测试有不同级别。你可能使用的3种最常见的测试级别如下。(请注意,这并不是完整的列表。测试有许多分类方法,不同组织往往使用不同的术语。)
〓❏ 单元测试——这种测试通常测试代码的小单元(如单个函数或类)。单元测试是测试工程师在日常编程中最经常使用的测试级别,也是本书唯一详细介绍的测试级别。
〓❏ 集成测试——系统通常由多个组件、模块或子系统组成。将这些组件和子系统连接到一起的过程称为集成。集成测试试图确保这些集成正常工作,而且一直保持正常。
〓❏ 端到端(E2E)测试——测试整个软件系统从头至尾的典型流程。如果待测软件是一个在线购物系统,E2E测试的一个例子是自动驱动浏览器,确保用户能够完成一次购物流程。
〓● 可测试性——这指的是“真实代码”(相对于测试代码),并描述该代码在测试中的表现。某个事物“可测试”的概念在子系统或系统级别上也适用。可测试性往往与模块化高度关联,模块化程度越高的代码(或系统)越容易测试。想象一下,某汽车制造商正在开发一种紧急行人防撞制动系统。如果该系统的模块化程度不高,测试它的唯一方式可能是将其安装在真实的汽车上,将车开到一个真人面前,检查车辆是否会自动停下。如果情况果真如此,那么该系统所能测试的场景有限,因为每次测试的成本非常高:制造一辆整车,租用一条测试道路,并让一个真人冒险扮演路上的行人。如果这种紧急制动系统是一个单独的模块,可在真实车辆之外运行,可测试性就更高了。现在测试可以通过如下方式进行:向该系统提供预先录制的行人走出的视频,检查它是否为紧急制动系统输出正确的信号。这样的测试非常简易、经济且安全,可以对成千上万种不同的行人状况进行测试。
如果代码不可测试,也就不可能对其进行“适当”测试了。为了确保我们编写的代码是可测试的,最好在编写代码时不断地问自己一个问题:“我们将如何测试这些代码?”因此,测试不应该是“马后炮”,而应该是编写代码各个阶段不可分割的基本组成部分。
推荐书籍
好代码 ,坏代码

本书介绍专业软件工程师经常用于编写可靠的、易于维护的代码的关键概念与技术。本书并不是简单列举“该做”和“不该做”的事项,而是旨在解释每个概念和技术背后的核心理论,以及需要权衡的因素。这应该能够帮助读者对如何像一位经验丰富的软件工程师那样思考和编程有基本的理解。
本书分享了编写鲁棒、可靠且易于团队成员理解和适应的代码的实用技巧。内容涉及如何像高效的软件工程师一样思考代码,如何编写读起来像一个结构良好的句子的函数,如何确保代码可靠且无错误;如何进行有效的单元测试,如何识别可能导致问题的代码并对其进行改进,如何编写可重用并适应新需求的代码,如何提高读者的中长期生产力;同时还介绍了如何节省开发人员及团队的宝贵时间,等等。
本书文字简洁、论述精辟、层次清晰,适合零基础的开发人员阅读,对于高等院校计算机及相关专业的学生,也具有很高的参考价值。
相关文章:
好的提高代码质量的方法有哪些?有什么经验和技巧?
用于确保代码质量的6个高层策略: 1 编写易于理解的代码 考虑如下这段文本。我们有意地使其变得难以理解,因此,不要浪费太多时间去解读。粗略地读一遍,尽可能吸收其中的内容。 〓ts〓取一个碗,我们现在称之为A。取一…...
yum保留安装包
一. 用downloadonly下载 1.1 处理依赖关系自动下载到/tmp/pages目录,pages这个目录会自动创建 yum install --downloadonly --downloaddir/tmp/pages ceph-deploy注意,如果下载的包包含了任何没有满足的依赖关系,yum将会把所有的依赖关系包下…...
ERP系统哪家比较好?
ERP系统哪家好?在选择ERP系统时,我们可以按照这三个维度,然后再按照需求去选择ERP系统。 市面上ERP软件大概可以分为三大类: ① 标准ERP应用:功能比较固定,难以满足个性化需求,二次开发难度很高…...
Python读写mdb文件的实战代码
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…...
MAC和IP地址在字符串形式、数字形式和byte数组中的转换
MAC地址 mac地址作为网卡的物理地址,有6个byte的长度。在实际表示形式上,以每个字节的16进制,中间用冒号隔开,比如:“01:02:03:04:05:06”。这就是mac地址的字符串形式 而在网络通信传输中,需要对mac地址从字符串形式转换为数字形式或byte数组形式发送。并且网络上传输…...
时间轮来优化定时器
在raft协议中, 会初始化三个计时器是和选举有关的: voteTimer:这个timer负责定期的检查,如果当前的state的状态是候选者(STATE_CANDIDATE),那么就会发起选举 electionTimer:在一定时…...
《和AI交朋友》教学设计——初识人工智能
创新整合点 (1借助编程软件的机器学习扩展,使学生初步体验建立训练模型,让电脑进行学习的过程,进而感受人工智能的核心技术之一。 (2)借助编程软件的人工智能服务, 在编写程序时使用语音交互模块…...
机载雷达的时间简史
从地基起步 蝙蝠,虽然像人一样拥有双眼,但它看起东西来,用到的却不是眼睛。蝙蝠从鼻子里发出的超声波在传输过程中遇到物体后会立刻反弹,根据声波发射和回波接收之间的时间差,蝙蝠就可以轻易地判断出物体的位置。这一工…...
2018年MathorCup数学建模A题矿相特征迁移规律研究解题全过程文档及程序
2018年第八届MathorCup高校数学建模挑战赛 A题 矿相特征迁移规律研究 原题再现: 背景材料: 球团矿具有含铁品位高、粒度均匀、还原性能好、机械强度高、微气孔多等特性, 是高炉炼铁的重要原料之一。近年来国内外普遍认识到球团矿高温状态下冶金性能是评价炉料…...
如何在 Python 中创建对象列表
Python 中要创建对象列表: 声明一个新变量并将其初始化为一个空列表。使用 for 循环迭代范围对象。实例化一个类以在每次迭代时创建一个对象。将每个对象附加到列表中。 class Employee():def __init__(self, id):self.id idlist_of_objects []for i in range(5…...
Canny算法原理和应用
Canny算法的原理使用高斯滤波器滤波使用 Sobel 滤波器滤波获得在 x 和 y 方向上的输出,在此基础上求出梯度的强度和梯度的角度edge为边缘强度,tan为梯度方向上图表示的是中心点的梯度向量、方位角以及边缘方向(任一点的边缘与梯度向量正交&am…...
数据挖掘(2.2)--数据预处理
目录 二、数据描述 1.描述数据中心趋势 1.1平均值和截断均值 1.2加权平均值 1.3中位数(Median)和众数(Mode) 2.描述数据的分散程度 2.1箱线图 2.2方差和标准差 2.3正态分布 3.数据清洗 3.1数据缺失的处理 3.2数据清洗 二、数据描述 描述数…...
JVM堆与堆调优以及出现OOM如何排查
调优的位置——堆 Heap,一个JVM只有一个堆内存,堆内存的大小是可以调节的。 类加载器读取了类文件后,一般会把什么东西放到堆中?类,方法,常量,变量~,保存我们所有引用类型的真实对象; 堆内存中…...
Springboot——自定义Filter使用测试总结
文章目录前言自定义过滤器并验证关于排除某些请求的方式创建测试接口请求测试验证异常过滤器的执行流程注意事项资料参考前言 在Java-web的开发领域,对于过滤器和拦截器用处还是很多,但两者的概念却极易混淆。 过滤器和拦截器都是采用AOP的核心思想&am…...
软件测试(进阶篇)(1)
一)如何根据需求来设计测试用例? 1)验证功能的正确性,合理性,无二义性,逻辑要正确 2)分析需求,细化需求,从需求中提取出测试项,根据测试项找到测试点,根据测试点具体的来进行设计测试…...
(七十三)大白话深入探索多表关联的SQL语句到底是如何执行的?(1)
今天我们来继续跟大家聊聊多表关联语句是如何执行的这个问题,上次讲了一个最最基础的两个表关联的语句和执行过程,其实今天我们稍微来复习一下,然后接着上次的内容,引入一个“内连接”的概念来。 假设我们有一个员工表࿰…...
SYSU程设c++(第三周) 对象类、类的成员、类与结构体的区别、类的静态成员
对象&类 类用于指定对象的形式,它包含数据的表示方法和用于处理数据的方法。 • 类中的数据和方法称为类的成员。 • 函数在一个类中也被称为类的成员。 定义一个类,其效果是定义一个数据类型的蓝图。它定义了类的对象包括了什么,以及可…...
Redis管道
目录 1、什么是管道? 2、案例演示 3、注意事项 4、面试题 1、什么是管道? 管道(pipeline)可以一次性发送多条命令给服务端,服务端依次处理完,通过一条响应一次性将结果返回,减少 IO 的次数&…...
conda的共用package[硬链接]@pytorch和tensorflow装在同一个环境里好不好?
文章目录refpackage复用(指定同版本)conda install 比pip install 更可能节省空间pytorch和tensorflow装在同一个环境里?导入依赖导入依赖试验ref python - Can packages be shared across Anaconda environments? - Stack OverflowManaging environments — conda 23.1.0.p…...
「Vue面试题」动态给vue的data添加一个新的属性时会发生什么?怎样去解决的?
一、直接添加属性的问题 我们从一个例子开始 定义一个p标签,通过v-for指令进行遍历 然后给botton标签绑定点击事件,我们预期点击按钮时,数据新增一个属性,界面也 新增一行 <p v-for"(value,key) in item" :key&q…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...
对象回调初步研究
_OBJECT_TYPE结构分析 在介绍什么是对象回调前,首先要熟悉下结构 以我们上篇线程回调介绍过的导出的PsProcessType 结构为例,用_OBJECT_TYPE这个结构来解析它,0x80处就是今天要介绍的回调链表,但是先不着急,先把目光…...
