小程序开发商有哪些/seo站外优化平台

小程序开发商有哪些,seo站外优化平台,移动终端开发是学什么,乔拓云微信小程序官网文章目录 1.认识领域驱动设计1.1 简介1.2 发展历史1.3 DDD 的兴起 2.从一个简单案例2.1 转账需求2.2 设计的问题2.3 违反的设计原则 3.使用 DDD 进行重构抽象数据存储层抽象第三方服务抽象中间件封装业务逻辑重构后的架构 4.小结参考文献 1.认识领域驱动设计 1.1 简介 领域驱…

文章目录

  • 1.认识领域驱动设计
    • 1.1 简介
    • 1.2 发展历史
    • 1.3 DDD 的兴起
  • 2.从一个简单案例
    • 2.1 转账需求
    • 2.2 设计的问题
    • 2.3 违反的设计原则
  • 3.使用 DDD 进行重构
    • 抽象数据存储层
    • 抽象第三方服务
    • 抽象中间件
    • 封装业务逻辑
    • 重构后的架构
  • 4.小结
  • 参考文献

1.认识领域驱动设计

1.1 简介

领域驱动设计(Domain-Driven Design,DDD)是一种复杂软件系统建模与设计方法论。

领域驱动设计最早由程序员 Eric Evans 于 2003 年在他的同名书籍《Domain-Driven Design: Tackling Complexity in Software》中提出。

领域驱动设计可以指导我们将复杂系统进行拆分,拆分出各个子系统间的关联以及是如何运转的,帮助我们解决大型的复杂系统在落地中遇到的问题。

1.2 发展历史

在复杂软件系统设计的领域,有许多重要的著作和方法论,它们提供了设计模式、架构风格、领域驱动设计、微服务等,为软件开发人员和架构师提供丰富的理论和实践指导。

  • 94 年 GoF 的 《Design Patterns》

这本书介绍了23种设计模式,为面向对象设计提供了标准化的解决方案。

  • 99 年 Martin Fowler 的 《Refactoring》

本书强调通过重构来改善代码的结构和可维护性,提供了多种重构技术和实例。

  • 02 年 Martin Fowler《Patterns of Enterprise Application Architecture》

该书介绍了企业级应用程序的架构模式,帮助开发人员设计可扩展和可维护的企业应用程序。

  • 03 年 Gregor Hohpe, Bobby Woolf 的 《Enterprise Integration Patterns》

这本书专注于企业应用中的集成模式,提供了大量的消息传递解决方案和设计模式。

后来软件设计理论逐渐开始注重业务,从业务角度给出架构设计理论。

  • 03 年 Eric Evans 的《Domain Driven Design》

这本书是领域驱动设计(DDD)的奠基之作,Eric Evans 在书中提出了一系列概念和原则,旨在帮助开发人员解决复杂软件系统中的业务问题。书中强调了与业务专家的紧密合作、领域模型的创建,以及通过聚合、实体和值对象等概念来管理复杂性。

DDD 提供了一种将业务逻辑与技术实现分离的方法,使得软件设计更具灵活性和可维护性。这本书极大地影响了软件开发领域,特别是在设计复杂系统时。

  • 13 年 Vaughn Vernon 的《Implementing DDD》

这本书基于 Eric Evans 的 DDD 理论,提供了更详细的实施指南。Vaughn Vernon 结合了实际案例和代码示例,介绍了如何在真实项目中应用 DDD 的原则和模式,包括聚合、领域事件、命令查询职责分离(CQRS)等。

重要性: 本书为开发人员提供了实际的、可操作的建议,帮助他们在项目中有效地实施 DDD。它也涵盖了现代软件架构的相关主题,如微服务架构和事件驱动设计。

  • 17 年 Uncle Bob 的《Clean Architecture》

这本书讨论了软件架构的基本原则,强调了如何构建可维护、可测试和可扩展的系统。Uncle Bob 提出了“清洁架构”的概念,强调应当将业务逻辑与外部系统(如数据库、用户界面等)分离,以便于维护和测试。

本书提供了一种清晰的架构设计思路,强调了关注点分离和依赖倒置等原则,适用于各种规模的项目。它是软件架构师和开发人员在构建复杂系统时的重要参考。

1.3 DDD 的兴起

DDD 在 03 年问世,一直没有火起来,最近开始流行的原因,主要是借着微服务的东风。

Martin Fowler 于 2014 详细阐述了微服务架构,随后微服务架构逐渐兴起。

DDD 随着微服务架构的流行而火起来,主要是因为两者在设计理念、服务划分、复杂性管理、团队协作等方面存在天然的契合。DDD 提供的业务驱动设计和领域建模方法论为微服务架构的有效实施提供了理论支持,使得开发团队能够更好地管理复杂性,快速响应业务变化。

随着企业对灵活性和可扩展性的需求不断增长,很多大型互联网企业已经将 DDD 设计方法作为微服务的主流设计方法了。

后面伴随微服务逐渐进入大家的视野。

2.从一个简单案例

2.1 转账需求

举一个转账的业务场景。

用户可以通过 APP 转账给另一个账号,且支持跨币种转账。同时因为监管和对账要求,需要记录本次转账活动。

具体的实现步骤如下:

  1. 查询账户信息: 从数据库中获取涉及的账户信息,包括转出账户和转入账户。

  2. 获取汇率信息: 从第三方服务(如 Yahoo、XE 或其他汇率提供者)获取当前汇率,通过开放的 HTTP 接口进行调用。

  3. 计算转账金额: 根据获取的汇率计算需要转出的金额,检查转出账户的余额是否足够,并确认转账金额不超过每日限额。

  4. 执行转账操作: 完成转账,扣除相应的手续费,并将更新后的账户信息保存到数据库中。

  5. 发送审计消息: 通过消息队列(如 RabbitMQ)发送审计消息,以便后续进行审计和对账。

伪代码实现如下:

class TransferService {private yahooRateService;private rabbitMqClient;private mysqlClient;public func transfer(srcAccId, tgtAccId, amount, currency) error {// step 1 从 db 获取数据(账户与余额信息)// step 2 获取外部数据// step 3 根据获取到的数据进行业务参数校验// step 4 计算账户余额// step 5 变更账户余额至 DB// step 6 发送审计消息return nil}
}

一段业务代码里经常包含了参数校验、数据读取存储、调用外部服务、业务计算、发送消息等多种逻辑。

2.2 设计的问题

这种是很常见的实现代码,短时间并没有什么问题,并且可以满足业务需求,快速上线但长久以往有如下几个问题。

(1)可维护性差

可维护性 = 依赖变化时有多少代码需要随之改变。

应用程序的生命周期通常包括开发阶段和维护阶段,其中维护阶段的成本往往占据了更大的比例。

开发阶段: 通常占据整个生命周期成本的 20% - 30%。

维护阶段: 通常占据整个生命周期成本的 70% - 80%。

依赖的变更可能会有如下情况:

  • 数据结构的不稳定性

账户表对应在代码中会有一个类与之对应,比如 AccModel。这里的问题是数据库的表结构和设计是应用的外部依赖,长远来看都有可能会改变,比如数据库要做分片,或者变更表字段名等。

还有可能依赖的 ORM 库的升级或者迁移至新的 ORM 库,都会有维护成本。

  • 第三方服务依赖的不确定性

第三方服务,比如汇率服务的变更。轻则API签名变化,重则服务不可用需要寻找其他可替代的服务。在这些情况下改造和迁移成本都是巨大的。同时,外部依赖的兜底、限流、熔断等方案都需要随之改变。

  • 中间件更换

加入今天使用 RabbitMQ 发消息,明天如果要上腾讯云用 RabbitMQ 该怎么办?后面如果消息的序列化方式从String改为Binary又该怎么办?如果需要消息分片该怎么改?

(2)可扩展性差

可扩展性 = 新增/变更功能时需要新增/修改多少代码。

虽然如果业务逻辑简单,那么面向过程的代码实现也非常高效简单,但是当业务功能变多时,其扩展性会变得越来越差。

如果之后要加一个转账到外部银行,原来的代码还可以复用吗?

原来的实现面对扩展需求时,有如下问题:

  • 数据来源被固定、数据格式不兼容

原有的 AccModel 是从 DB 获取的,而跨行转账的数据可能需要从一个第三方服务获取,而服务之间数据格式不太可能是兼容的,导致从数据校验、数据读写、异常处理到金额计算等逻辑都要重写。

  • 业务逻辑无法复用

数据格式与数据源的不同,导致核心业务逻辑无法复用。主流程代码会出现很多 if-else 分支,导致代码逻辑混乱,难以维护。

  • 业务逻辑和数据存储的相互依赖

当业务逻辑增加变得越来越复杂时,新加入的逻辑很有可能需要对数据库schema或消息格式做变更。而变更了数据格式后会导致原有的其他逻辑需要一起跟着动。

在最极端的场景下,一个新功能的增加会导致所有原有功能的重构,成本巨大。

(3)可测试性差

可测试性 = 单个测试用例执行时间 * 每个需求所需要增加的测试用例数量。

根据这个定义,上面的实现方便做单元测试嘛?

  • 业务逻辑与基础设施耦合严重

当代码中强依赖了数据库、第三方服务、中间件等外部依赖之后,想要完整跑通一个测试用例需要确保所有依赖都能跑起来,这个在项目早期是及其困难的。在项目后期也会由于各种系统的不稳定性而导致测试无法通过。

  • 测试用例运行耗时长

大多数的外部依赖调用都是I/O密集型,如跨网络调用、磁盘调用等,而这种I/O调用在测试时需要耗时很久。当一个测试用例需要花超过10秒钟,会降低测试用例的执行频率,这回降低代码可靠性。

  • 业务逻辑复杂

假如一段代码中有A、B、C三个子步骤,而每个步骤有N个可能的状态,当多个子步骤耦合度高时,为了完整覆盖所有用例,最多需要有N * N * N个测试用例。当子步骤越多时,需要的测试用例呈指数级增长。

2.3 违反的设计原则

Uncle Bob 在其著作《Agile Software Development, Principles, Patterns, and Practices》提出了面向对象设计的 SOLID 原则。

这里至少违背了如下三个原则:

  • 单一职责原则

一个类应该仅负责一个功能或任务,避免承担多个职责,以便于维护和理解。

但是在这个案例里,类 TransferService 的设计包含了多个功能,查询数据库,调用第三方服务,向中间件发送消息,一个类承担多个职责会导致类变得复杂,难以理解和维护。

  • 开放封闭原则

软件实体应对扩展开放,但对修改封闭,即可以通过扩展现有代码而不是修改它来增加新功能。

在这个案例里的金额计算属于可能会被修改的代码,这个时候该逻辑应该需要被包装成为不可修改的计算类,新功能通过计算类的拓展实现。

  • 依赖倒置原则

高层模块不应依赖于低层模块,二者应依赖于抽象,从而减少模块间的耦合,提高系统灵活性。

在这个案例里外部依赖都是具体的实现,比如 yahooRateService 虽然是一个接口类,但是它对应的是依赖了 Yahoo 提供的具体服务,所以也算是依赖了实现。同样的 mysqlClient 和 rabbitMqClient 实现都属于具体实现。

3.使用 DDD 进行重构

下面是重构前的架构:

在这里插入图片描述

抽象数据存储层

新建一个 Account 实体类。

一个实体(Entity)是拥有ID的域对象,除了拥有数据之外,同时拥有行为。

class Account{private id;private user_id;private card_no;private daily_limit;
}

Account 实体类和 AccountModel 数据类的区别:

AccountModel 是单纯和数据库表做映射的数据类,每个字段对应数据库表的一个列。这种对象叫 Data Object(贫血模型)。

Account 是领域逻辑的实体类,包含属性,同时也包含行为,属于实体(充血模型)。

新建账户存储接口类 AccRepo,只负责实体的存储和读取,而 AccRepo 的实现类完成数据库存储的细节。通过加入 AccRepo 接口,底层的数据库连接可以通过不同的实现类来替换。

interface AccRepo {func getById(id) Account;func saveToDb(Acc) error;
}// 具体实现
class AccRepoImpl implements AccRepo {func getById(id) Account {// ...}func saveToDb(Acc) error {// ...}
} 

DAO 和 AccRepo 类的区别:

DAO 对应的是一个特定的数据库类型的操作,相当于 SQL 的封装。所操作的对象都是 Data Object 类,所有接口都可以根据数据库实现的不同而改变。比如,insert 和 update 属于数据库专属的操作。

AccRepo 对应的是实体对象读取/储存的抽象,在接口层面做统一,不关注底层实现。比如,通过 save 保存一个 Entity 对象,但至于具体是 insert 还是 update 并不关心。

通过 Account 类,避免了其他业务逻辑代码和数据库的直接耦合,避免了当数据库字段变化时,大量业务逻辑也跟着变的问题。

通过 AccRepo 接口类,改变业务代码的思维方式,让业务逻辑不再面向数据库编程,而是面向领域模型编程。实现了实体与 DB 的解耦。

通过 AccRepoImpl 实现类,由于其职责被单一出来,只需要关注 Account 到 AccountModel 的映射关系和 AccRepo 方法到 DAO 方法之间的映射关系。

抽象第三方服务

可以新建一个汇率类 ExRate,汇率接口类 ExRateService 和具体实现类 ExRateServiceYahoo。

// 汇率类
class ExRate {private srcCurrency;private tgtCurrency;private rate;// 根据汇率 rate 将金额转为 tgtCurrency 币种的金额public func exchangeTo(amount) float64;
}// 汇率接口类
interface ExRateService{func getExchangeRate(srcCurrency, tgtCurrency) ExRate;
}// 汇率实现类
class ExRateServiceYahoo implements ExRateService {//...
}

这是一种常见的设计模式叫做防腐层(Anti-Corruption Layer,ACL)。

防腐层是依赖倒置原则的一种体现:高层模块不应该依赖底层模块,二者都该依赖于抽象。

很多时候我们的系统会去依赖第三方系统,而被依赖的系统会有不兼容的协议或技术实现,如果对外部系统强依赖,如果第三方放生变更,我们的系统也会收到影响,那么会导致我们的系统被“腐蚀”。

这个时候,通过在系统间加入一个防腐层,能够有效的隔离外部依赖和内部逻辑,无论外部如何变更,内部代码可以尽可能的保持不变。

ACL 有如下好处:

  • 适配器。

防腐层可以充当适配器,将不同系统的接口和数据格式转换为适合当前系统的格式,降低了系统间的耦合度。

  • 缓存

防腐层可以实现缓存机制,减少对外部服务的频繁调用,从而提高系统性能和响应速度。

  • 兜底

防腐层提供了兜底机制,能够处理外部系统的异常和错误,确保当前系统的稳定性和可靠性。

  • 功能开关

防腐层可以实现功能开关,允许动态启用或禁用某些功能,从而灵活应对需求变化和系统演进。

  • 易于测试

防腐层通过隔离外部依赖,使得单元测试和集成测试变得更加简单和高效。

抽象中间件

同样的,我们可以将具体的中间件实现与业务逻辑解耦。

可以新建一个审计消息类 AuditMsg,审计消息发送接口类 AuditMsgProducer 和具体实现类 AuditMsgProducerRabbit。

// 审计消息类
class AuditMsg {private srcAccId;private tgtAccId;private moneyAmount;public func serialize() string;public func deserialize(msg) AuditMsg;
}// 审计消息生产接口
interface AuditMsgProducer {func send(AuditMsg msg);
}// 审计消息生产接口实现类
class AuditMsgProducerRabbit implements AuditMsgProducer{// ...
}

通过对中间件抽象,使得业务逻辑依赖于抽象,而不是具体的中间件。

因为中间件通常需要有通用型,中间件的接口通常是 string 或 byte[] 类型的,导致序列化/反序列化逻辑通常和业务逻辑混杂在一起,造成胶水代码。通过中间件的 ACL 抽象,可以减少重复的胶水代码。

封装业务逻辑

金额没有 ID,是一个属性的集合,可以设计为一个值对象(Value Object)。

class Money {private amount;private currency;
}

账户有 ID,有属性,也有行为,转入和转出,可以设计为一个实体(Entity)。这个在上文已经完成设计,这里补充上方法。

我们发现这两个账号的转出和转入实际上是一体的,也就是说这种行为应该被封装到一个对象中去。

class Account{private id;private user_id;private card_no;private daily_limit;// 转出func withdraw();// 存入func deposit();
}

因为未来可能有功能上的扩展:比如增加一个扣手续费的逻辑。

这个时候在原有的 TransferService 中做并不合适,在任何一个域对象都不合适,需要有一个新的类去包含跨域对象的行为。这种对象叫做领域服务(Domain Service)。

我们可以新建一个 AccTransferService 接口,并给出一个具体的实现 AccTransferServiceImpl。

interface AccTransferService {function transfer(srcAcc, tgtAcc, money, exchageRate);
}class AccTranferServiceImpl implements AccTransferService{public func transfer(srcAcc, tgtAcc, money, exRate) {tgtMoney = exRate.exchangeTo(money);srcAcc->withdraw(money);tgtAcc->deposit(tgtMoney);}
}

原有的 TransferService 将变成:

class TransferServiceNew {private accRepo;private exRateService;private auditMsgProducer;private accTransferService;public func transfer(srcAccId, tgtAccId, amount, tgtCurrency) {// 读取数据accRepo.getById(srcAccId)accRepo.getById(trgAccId)// 获取外部数据exRate = exRateService.getExchangeRate()// 校验参数// ...// 业务逻辑:转账accTransferService.transfer()// 发送审计消息accTransferService.send(AuditMsg)}
}

重构后的架构

按照 DDD 的理论进行重构。

重构后最底层不再是数据库,而是领域对象:实体(Entity)、值对象(Value Object)和领域服务(Domain Service)。

这些对象不依赖任何外部服务和框架,而是纯内存中的数据和操作,打包为领域层(Domain Layer)。领域层没有任何外部依赖关系。

再其次的是负责组件编排的应用服务(Application Service),归到应用层(Application Layer)。

但是这些服务仅仅依赖了一些抽象出来的 ACL 类和 Repository 类,而其具体实现类是通过依赖注入注进来的。Application Service、Repository、ACL 等我们归属为应用层。

应用层依赖领域层,但不依赖具体实现。

最后是 ACL,Repository 等的具体实现,这些实现通常依赖外部具体的技术实现和框架,所以统称为基础设施层(Infrastructure Layer)。Web 框架里的对象如 Controller 之类的通常也属于基础设施层。
在这里插入图片描述

如果一开始使用 DDD 作为理论指导,重新写这段代码,考虑到最终的依赖关系,我们可能先写 Domain 层的业务逻辑,然后再写 Application 层的组件编排,最后才写每个外部依赖的具体实现。

这种架构思路和代码组织结构就叫做 领域驱动设计(Domain Driven Design)。

4.小结

DDD 是一种软件开发方法论,旨在通过深入理解业务领域,并将其与软件设计相结合,来解决复杂系统的开发问题。

DDD 强调在软件设计中聚焦于领域模型和领域逻辑,以便更好地满足业务需求。

以 DDD 作为理论指导,我们可以设计出具有如下优点的软件系统:

  • 高可维护性

业务代码与外部依赖解耦,当外部依赖变更时,业务代码只用变更跟外部对接的模块,其他业务逻辑不变。

  • 高可扩展性

DDD 鼓励将系统划分为多个聚合和模块,便于对系统进行扩展和重构。开发者可以在不干扰其他模块的情况下添加新功能。

  • 高可测试性

每个拆分出来的模块都符合单一性原则,绝大部分不依赖框架,可以快速的单元测试,做到100%覆盖。

  • 代码结构清晰

统一语言(Ubiquitous Language):DDD 强调开发团队与业务专家之间使用统一的语言,确保代码与业务概念一致,从而使代码更易于理解。

合理的分层架构:DDD 通常采用分层架构,如表示层、应用层、领域层和基础设施层,这种结构使得各个层次的职责分明,便于维护和开发。

当团队形成规范后,可以快速的定位到相关代码。


参考文献

DDD 概念参考 - 领域驱动设计

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

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

相关文章

nuxt3网站文章分享微信 ,QQ功能

1.安装 npm install qrcode --save-dev 2.组件使用 <div class"share"><div style"line-height: 69px; color: #fff;width: 100px;"><p style"text-align: center;">分享:</p></div><div click"shareToMi…

VMWare Ubuntu 详细安装教程

VMWare Ubuntu 详细安装教程 一、下载安装VMware二、下载 Ubuntu 镜像文件三、安装 Ubuntu四、开启虚拟机 一、下载安装VMware 官网下载地址https://www.vmware.com/products/desktop-hypervisor/workstation-and-fusion知乎大佬的博客原文&#xff0c;含下载地址https://zhua…

SCI英文论文Accepted后的第一步——Rights and Access

SCI英文论文Accepted后的第一步——Rights and Access 目录 SCI英文论文Accepted后的第一步——Rights and AccessBased on information provided the embargo period/end date is 24 months. 因为选择闭源**Rights and Access(版权与访问权限)**环节是关键第一步,具体操作流…

Qt文件管理系统

引言 今天我将使用model/view模型视图框架来完成一个简单的Qt文件管理系统&#xff0c;主要使用到了QTreeView、QTabelView视图和QFileSystemModel文件系统模型。 界面设计 使用Qt创建项目并勾选创建ui文件&#xff0c;打开ui文件&#xff0c;使用Tree View、Table View、St…

《可爱风格 2048 游戏项目:HTML 实现全解析》

一、引言 在如今的数字化时代&#xff0c;小游戏以其简单易上手、趣味性强的特点深受大家喜爱。2048 游戏作为一款经典的数字合并游戏&#xff0c;拥有庞大的玩家群体。本文将详细介绍一个用单文件 HTML 实现的可爱风格 2048 游戏项目&#xff0c;它不仅具备传统 2048 游戏的基…

C语言 —— 此去经年梦浪荡魂音 - 深入理解指针(卷四)

目录 1. 回调函数 2. qsort函数 2.1 使用qsort函数排序整型数据 2.2 使用qsort排序结构数据 2.3 使用冒泡排序模拟实现qsort函数 1. 回调函数 回调函数其实就是一个通过函数指针调用的函数&#xff0c;如果你把函数的指针作为参数传递给另一个函数&#xff0c;当这个指针被…

Shiro框架漏洞攻略

漏洞原理&#xff1a;服务端在接收到⼀个Cookie时&#xff0c;会按照如下步骤进⾏解析处理&#xff1a;1.检索RememberMe Cookie的值 2.进⾏Base64解码 3.进⾏AES解码 4.进⾏反序列化操作 在第4步中的调⽤反序列化时未进⾏任何过滤&#xff0c;进⽽可以导致出发远程代码执⾏漏…

Ceph集群2025(Squid版)导出高可用NFS集群(下集 )

本次主要对接K8S和传统的一样而已,比较简单&#xff0c;不再过多讲解 官网 https://github.com/kubernetes-csi/csi-driver-nfs/tree/master/chartshelm repo add csi-driver-nfs https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/charts helm pull c…

Off-Road-Freespace-Detection配置pytorch2.0.0

一、概述 在github上进行开源代码搜索&#xff0c;发现了Off-Road-Freespace-Detection&#xff08;链接如下所示&#xff09;。这是对越野环境可通行区域的检测&#xff0c;在经过测试之后&#xff0c;发现对自己有益。 GitHub - chaytonmin/Off-Road-Freespace-Detection: O…

ChatGPT降低论文AIGC重复率的提示词合集(高效降重方法)

&#x1f4a1; 问题&#xff1a;写完毕业论文后&#xff0c;查AIGC率过高&#xff0c;手动降重后仍然很高&#xff0c;该怎么办&#xff1f; &#x1f4cc; 解决方案&#xff1a; 1️⃣ 先查AIGC率&#xff08;找出AI生成的部分&#xff09; 2️⃣ 用ChatGPT优化&#xff08;使…

fastapi+angular评论和回复

说明&#xff1a;fastapiangular评论和回复 效果图: step1:sql show databases; DROP TABLE users; SHOW CREATE TABLE db_school.users; show tables; use db_school; SELECT * FROM db_school.jewelry_categories; CREATE DATABASE db_school; select *from users -- 用户…

AI医疗革命:英伟达GTC 2025医疗健康与生命科学会议全分析

AI医疗革命:英伟达GTC 2025医疗健康与生命科学会议全分析 一、GTC 2025:AI 医疗的算力与生态双突破 1.1 黄仁勋演讲核心:从训练到推理的代际跨越 在科技界瞩目的英伟达 GTC 2025 大会上,英伟达 CEO 黄仁勋的主题演讲成为全场焦点,为 AI 医疗领域带来了极具变革性的消息。…

Apache Spark - 用于大规模数据分析的统一引擎

Apache Spark - 用于大规模数据分析的统一引擎 下载运行示例和 Shell使用 Spark Connect 在 Anywhere 上运行 Spark 客户端应用程序 在集群上启动从这里去哪里使用 Spark Shell 进行交互式分析基本有关数据集作的更多信息缓存 自包含应用程序从这里去哪里 Apache Spark 是用于大…

餐饮管理系统的设计与实现(代码+数据库+LW)

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差&#…

【C#】Winform调用NModbus实现Modbus TCP 主站通讯

一、前言 Modbus是一种串行通信协议&#xff0c;是工业领域全球最流行的协议之一。 1.1 环境 系统&#xff1a;Win11 工具&#xff1a;Visual Studio 2022 .Net 版本&#xff1a;.Net Framework4.6.0 依赖库&#xff1a;NModbus 3.0.81 1.2 协议类型 Modbus RTU&#xff1a;一…

【leetcode题解】贪心算法

目录 贪心算法 柠檬水找零 将数组和减半的最少操作次数 最大数 摆动序列 最长递增子序列 递增的三元子序列 最长连续递增序列 买卖股票的最佳时机 买卖股票的最佳时机 II K 次取反后最大化的数组和 按身高排序 优势洗牌 最长回文串 增减字符串匹配 分发饼干 最…

Apache Doris

Apache Doris介绍 Apache Doris 是一个基于 MPP 架构的高性能、实时的分析型数据库&#xff0c;以极速易用的特点被人们所熟知&#xff0c;仅需亚秒级响应时间即可返回海量数据下的查询结果&#xff0c;不仅可以支持高并发的点查询场景&#xff0c;也能支持高吞吐的复杂分析场…

VLAN间通信

目录 第一步&#xff1a;配vlan 第二步&#xff1a;配置核心vlanif,MAC地址信息。 第三步&#xff1a;ospf协议 三层交换机&#xff08;汇聚层&#xff09;: 对于交换机、路由器、防火墙等网络设备而言&#xff0c;接口类型一般存在两种&#xff1a;二层接口&#xff0c;三…

LeetCode热题100精讲——Top2:字母异位词分组【哈希】

你好&#xff0c;我是安然无虞。 文章目录 题目背景字母异位词分组C解法Python解法 题目背景 如果大家对于 哈希 类型的概念并不熟悉, 可以先看我之前为此专门写的算法详解: 蓝桥杯算法竞赛系列第九章巧解哈希题&#xff0c;用这3种数据类型足矣 字母异位词分组 题目链接&am…

基于python+django的图书借阅网站-图书借阅管理系统源码+运行步骤

该系统是基于pythondjango开发的在线图书借阅管理系统。系统适合场景&#xff1a;大学生、课程作业、系统设计、毕业设计。 演示地址 前台地址&#xff1a; http://book.gitapp.cn 后台地址&#xff1a;http://book.gitapp.cn/#/admin 后台管理帐号&#xff1a; 用户名&…