领域驱动设计(DDD)模式深度剖析与 C# 实践

news2024/11/30 18:39:14

一、DDD 模式概述

领域驱动设计(Domain-Driven Design,简称 DDD)是一种软件开发方法论,旨在应对复杂业务领域的软件系统构建挑战。它强调以领域模型为核心,围绕业务领域中的关键概念、规则以及它们之间的关系来组织软件架构与设计,使软件系统能够更紧密地贴合业务需求,提高可维护性、可扩展性与可理解性。

在传统软件开发过程中,常出现业务逻辑分散于不同技术层面(如数据库操作层、用户界面层)的问题,导致系统牵一发而动全身,代码变更困难。DDD 则通过划分清晰的分层架构与明确界定领域对象职责,将复杂业务领域分解为多个界限明确的子领域,各子领域聚焦自身业务逻辑,协同工作以支撑整体业务运转。

二、DDD 核心概念

(一)领域与子领域

领域是指业务所涉及的整个范围,涵盖业务操作、规则、流程等方方面面。例如,电商领域包含商品管理(上架、下架、库存盘点等)、订单处理(下单、支付、发货、退款)、客户服务(用户注册、信息修改、咨询处理)等复杂业务活动。为便于管理与设计,会依据业务关联性与功能独立性,将大领域切分为多个子领域,像电商领域可细分为商品子领域、交易子领域、客户子领域等,各子领域相对自治又协同配合。

(二)限界上下文

限界上下文(Bounded Context)是 DDD 中至关重要的概念,它界定每个子领域的边界,明确其中通用语言(Ubiquitous Language)适用范围与领域对象含义。在不同限界上下文里,相同术语可能有不同语义,例如电商 “商品”,在商品管理上下文中侧重于属性编辑、分类设定;在订单处理上下文中则侧重商品规格、价格用于订单金额计算,借助限界上下文避免语义混淆,确保领域模型准确性。

(三)实体

实体(Entity)是具有唯一标识的领域对象,其标识在生命周期内保持不变,即便对象属性值变更。以电商订单为例,订单号作为唯一标识,无论订单状态(待支付、已发货、完成等)、商品详情、收货地址如何改变,订单实体凭借订单号可被精准追踪与操作,实体承载业务规则与行为,像订单可执行取消操作(需校验支付状态、库存回滚等规则)。

(四)值对象

值对象(Value Object)无自身唯一标识,通过属性值组合确定自身特征,多个属性共同描述一个完整概念且不可变(若需变更则创建新值对象)。如电商收货地址是值对象,包含省、市、区、街道、邮编等属性,当地址信息修改,等同替换整个地址值对象,它用于传递数据、参与运算且简化实体间关联,增强领域模型内聚性。

(五)聚合与聚合根

聚合(Aggregate)是一组紧密关联的领域对象集合,遵循一致性边界规则,确保数据完整性与业务规则一致性。聚合根(Aggregate Root)是聚合的入口点,外部对象只能通过聚合根访问聚合内其他对象,维护聚合内对象间层级与协作关系。例如电商订单聚合,订单实体作为聚合根,关联订单项(包含商品、数量、单价等)、收货地址等值对象,订单取消时,聚合根协调各对象按规则执行库存回补、状态更新等系列操作。

(六)领域事件

领域事件(Domain Event)是领域内发生的有意义事情的记录与通知机制,反映业务流程关键节点变化,如 “订单已支付”“商品库存不足” 事件。它解耦不同限界上下文或业务模块,发布订阅模式下,相关方监听感兴趣事件触发后续业务逻辑,像支付成功事件触发物流系统启动发货准备、积分系统给予用户积分奖励。

(七)通用语言

通用语言是团队(包含业务人员、开发人员、测试人员等)在 DDD 项目沟通中统一使用的业务术语集合,确保各方对领域概念、规则理解一致,融入代码实现(类名、方法名、注释等),使代码 “可读”“可沟通”,如 “确认收货” 在业务流程与代码方法命名保持一致,减少歧义、提升协作效率。

三、DDD 分层架构

(一)用户界面层(User Interface Layer)

负责与用户交互,接收输入、展示输出,涵盖 Web 页面、桌面客户端、移动端界面等形式,是系统对外 “窗口”。在 C# Web 应用中,ASP.NET Core MVC 或 Blazor 框架负责渲染视图、处理用户请求(如用户在电商页面点击下单,接收表单数据传递给下一层),应保持简洁,避免业务逻辑嵌入,仅做数据展示与请求转发。

(二)应用层(Application Layer)

编排领域对象协作完成业务用例,类似 “指挥官” 角色,不包含核心业务规则。它接收界面层请求,调用领域层方法、协调多个聚合操作、处理事务、发布领域事件等。以电商下单流程为例,应用层方法PlaceOrder接收订单数据,验证参数合法性后,通过仓储接口获取商品库存、客户信息,指挥订单聚合根创建订单、扣减库存、关联支付信息等系列操作,确保业务流程连贯、原子性。

public class OrderApplicationService
{
    private readonly IOrderRepository _orderRepository;
    private readonly IProductRepository _productRepository;
    private readonly IUnitOfWork _unitOfWork;

    public OrderApplicationService(IOrderRepository orderRepository, IProductRepository productRepository, IUnitOfWork unitOfWork)
    {
        _orderRepository = orderRepository;
        _productRepository = productRepository;
        _unitOfWork = unitOfWork;
    }

    public async Task<OrderDto> PlaceOrder(OrderCreateDto orderCreateDto)
    {
        // 验证订单数据合法性
        if (!ValidateOrderData(orderCreateDto))
        {
            throw new ApplicationException("订单数据无效");
        }

        // 获取商品信息
        var productList = await _productRepository.GetProductsByIds(orderCreateDto.ProductIds);
        // 创建订单聚合根
        var order = new Order(orderCreateDto.CustomerId);
        foreach (var item in orderCreateDto.OrderItems)
        {
            var product = productList.FirstOrDefault(p => p.Id == item.ProductId);
            if (product == null)
            {
                throw new ApplicationException($"商品{item.ProductId}不存在");
            }
            order.AddOrderItem(product, item.Quantity);
        }
        // 保存订单
        _orderRepository.Add(order);
        await _unitOfWork.CommitAsync();
        return MapToDto(order);
    }
}

(三)领域层(Domain Layer)

是 DDD “心脏”,包含实体、值对象、聚合、领域服务、领域事件等核心元素,封装复杂业务逻辑与规则。如订单实体类中Cancel方法实现取消订单逻辑,检查支付状态、解锁库存、记录取消日志等操作都依循严谨业务规则,领域层独立于技术框架,专注业务本质表达,保证高内聚、低耦合,提升复用性与可维护性。

public class Order : AggregateRoot
{
    public Guid Id { get; private set; }
    public Guid CustomerId { get; private set; }
    public OrderStatus Status { get; private set; }
    private readonly List<OrderItem> _orderItems = new List<OrderItem>();

    public Order(Guid customerId)
    {
        Id = Guid.NewGuid();
        CustomerId = customerId;
        Status = OrderStatus.Created;
    }

    public void AddOrderItem(Product product, int quantity)
    {
        var orderItem = new OrderItem(product, quantity);
        _orderItems.Add(orderItem);
    }

    public void Cancel()
    {
        if (Status == OrderStatus.Paid)
        {
            // 执行库存回滚等复杂逻辑
            foreach (var item in _orderItems)
            {
                item.Product.ReleaseStock(item.Quantity);
            }
        }
        Status = OrderStatus.Cancelled;
        // 记录取消日志等业务逻辑
    }
}

(四)基础层(Infrastructure Layer)

提供通用技术能力支撑,涵盖数据库持久化(EF Core 实现仓储接口与数据库交互)、消息队列集成(发送接收领域事件)、缓存机制等,实现领域层抽象接口,为上层屏蔽技术细节,保障领域层纯净业务性,像仓储接口IOrderRepository在基础层用 SQL Server 数据库操作实现增删改查订单实体功能。

public class OrderRepository : IOrderRepository
{
    private readonly MyDbContext _dbContext;

    public OrderRepository(MyDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task Add(Order order)
    {
        await _dbContext.Orders.AddAsync(order);
    }

    public async Task<Order> GetById(Guid id)
    {
        return await _dbContext.Orders.FindAsync(id);
    }

    // 其他查询、更新、删除方法实现
}

四、DDD 实践步骤

(一)领域建模启动

项目伊始,业务专家与技术团队紧密合作,梳理业务流程、挖掘领域概念,绘制业务流程图、用例图勾勒业务场景与操作,提炼实体、值对象、聚合关系形成初步领域模型草图,例如电商项目初期确定商品、订单、客户为核心实体及关联关系,勾勒出商品聚合(含分类、属性等值对象)、订单聚合框架。

(二)限界上下文划分

依据业务功能模块独立性、语义一致性细分领域为限界上下文,绘制上下文映射图展示交互关系(合作、共享、防腐层隔离等),像电商分商品管理、订单交易、物流配送限界上下文,商品管理上下文为订单交易提供商品详情,借助防腐层转换适配避免直接依赖、保证各自演进。

(三)领域对象精化与代码实现

在各限界上下文内,详细设计实体属性、行为,值对象结构,聚合层次,用 C# 类、接口精准编码实现,遵循领域层业务聚焦、应用层编排协调、基础层技术支撑分层原则,持续迭代优化领域模型,应对业务变化,如订单实体随支付规则调整完善支付相关方法逻辑、仓储接口适配新数据库架构优化查询性能。

(四)集成与演进

完成各模块开发后,通过依赖注入、接口适配集成各层组件,搭建完整系统,上线运行后依据业务反馈、性能瓶颈监测,持续回溯优化领域模型、调整分层架构、升级技术选型,如电商流量增长时优化数据库索引、引入分布式缓存提升订单查询效率、拓展领域事件应用于大数据分析场景。

五、DDD 优势与挑战

(一)优势

  1. 紧密贴合业务:通用语言与领域建模保障软件与业务同频,业务变更能高效映射到代码,降低需求理解偏差。
  2. 架构清晰可维护:分层架构、限界上下文隔离,职责明确,修改局部代码不牵全局,长期维护成本低。
  3. 复用与扩展:领域对象高内聚、通用业务逻辑复用,新业务拓展可在既有模型、架构添模块,如电商拓展跨境业务复用基础商品、订单模型修改适配海关规则。

(二)挑战

  1. 学习成本高:复杂概念多,团队需深入理解掌握 DDD 理念、实践,前期投入大。
  2. 初期建模难度大:精准勾勒领域模型、划分限界上下文依赖深厚业务洞察、经验,易返工调整。
  3. 团队协作要求高:业务、开发、测试围绕通用语言协同,跨职能沟通不畅会致模型 “走样”、功能偏离。

六 、DDD开源项目

1. Axon Framework(Java)

  • 项目概述
    • Axon Framework 是一个用于构建基于事件驱动的微服务和应用程序的框架,它紧密遵循领域驱动设计(DDD)原则。这个框架提供了一系列工具和库,帮助开发者轻松地实现事件溯源、命令查询职责分离(CQRS)以及领域模型的构建。
  • 功能特点
    • 事件溯源:Axon 支持事件溯源,这意味着它可以记录领域对象的所有状态变化历史。例如,在一个财务系统中,每一笔账目交易都可以被看作是一个事件,通过事件溯源,系统能够重现账户在任何时间点的状态。它通过存储事件流,并根据这些事件重新构建对象状态。
    • CQRS 架构实现:Axon 能够很好地实现 CQRS 模式。在这种模式下,命令(用于修改状态)和查询(用于获取数据)被分离到不同的模型和处理路径中。这样可以优化系统的性能,提高可扩展性,并且使得系统更容易维护。例如,在一个电商系统中,下单操作(命令)和查询订单详情(查询)可以通过不同的方式处理,互不干扰。
    • 聚合管理:Axon 提供了强大的聚合管理功能。聚合是 DDD 中的核心概念之一,它代表了一组相关的领域对象,这些对象应该作为一个整体来处理。Axon 通过提供注解和接口,方便开发者定义和管理聚合,确保聚合的一致性和完整性。例如,在一个物流系统中,一个 “运输任务” 聚合可能包含货物信息、运输车辆信息、司机信息等,Axon 帮助管理这些对象之间的关系和操作。
  • 应用场景示例
    • 金融交易系统:可以利用 Axon 的事件溯源功能记录每一笔交易,如股票交易、转账等操作。通过存储这些事件,系统可以方便地进行审计、风险评估和历史数据查询。例如,当需要查询某个账户在过去一个月内的所有交易记录时,Axon 可以快速地根据事件流重建账户状态并提供准确的信息。
    • 供应链管理系统:在供应链中,从订单处理、库存管理到物流配送都涉及大量的事件和复杂的业务逻辑。Axon 可以帮助构建一个基于事件驱动的系统,使得各个环节之间能够通过事件进行通信和协调。例如,当库存水平低于某个阈值时,库存管理模块可以发布一个 “库存不足” 的事件,触发采购模块进行补货操作。

2. Eventuate Tram(Java)

  • 项目概述
    • Eventuate Tram 是一个用于构建微服务架构的开源框架,它强调事件驱动和 DDD 理念。这个框架提供了一套简单而强大的工具,用于在微服务之间进行异步通信、数据一致性维护以及领域事件的处理。
  • 功能特点
    • 事件驱动通信:Eventuate Tram 支持微服务之间通过事件进行通信。这使得各个微服务可以解耦,它们只需要关注自己感兴趣的事件,而不需要直接依赖其他微服务的接口。例如,在一个电商系统中,用户服务可以发布 “用户注册成功” 的事件,而营销服务可以订阅这个事件,以便向新用户发送欢迎邮件或优惠券。
    • 数据一致性保障:在分布式系统中,数据一致性是一个关键问题。Eventuate Tram 提供了机制来确保跨多个微服务的数据一致性。它通过使用事件溯源和分布式事务处理技术,保证在复杂的业务操作中,各个微服务的数据状态能够保持一致。例如,在一个在线预订系统中,当用户预订一个酒店房间时,预订服务、支付服务和酒店库存服务之间需要保持数据一致,Eventuate Tram 可以帮助协调这些服务之间的操作。
    • 领域事件处理:框架提供了方便的方式来处理领域事件。开发者可以轻松地定义事件处理器,对不同类型的事件进行相应的业务逻辑处理。例如,在一个物流系统中,当收到 “货物已发货” 的事件时,可以触发通知用户的操作,同时更新运输状态的记录。
  • 应用场景示例
    • 微服务架构的电商平台:包括用户服务、商品服务、订单服务、支付服务等多个微服务。Eventuate Tram 可以用于在这些微服务之间传递事件,如订单创建事件、支付完成事件等。当订单服务创建一个新订单时,它可以发布一个订单事件,商品服务和支付服务可以订阅这个事件并进行相应的处理,如扣除库存和处理支付。
    • 物联网应用场景:在物联网环境中,有大量的设备产生数据并需要进行处理。Eventuate Tram 可以用于在不同的物联网服务之间传递设备事件,例如传感器数据更新事件、设备状态变化事件等。这些事件可以被不同的服务用于监控、分析和决策,如能源管理系统根据设备能耗数据进行节能策略调整。

3. NestJS(TypeScript/JavaScript)

  • 项目概述
    • NestJS 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架。它借鉴了许多其他流行框架的优秀设计理念,包括 Angular,并很好地支持 DDD 原则,使得开发者能够以模块化、层次化的方式构建应用。
  • 功能特点
    • 模块化架构:NestJS 采用模块化的设计,这与 DDD 中的模块划分理念相契合。每个模块可以看作是一个独立的领域单元,它包含了自己的控制器(用于处理 HTTP 请求)、服务(包含业务逻辑)、存储库(用于数据访问)等组件。例如,在一个博客系统中,可以有用户模块、文章模块和评论模块,每个模块都有自己的功能和职责范围。
    • 依赖注入系统:NestJS 拥有强大的依赖注入系统,这有助于实现组件之间的解耦和可测试性。通过依赖注入,对象之间的依赖关系可以在外部进行配置,而不是在对象内部硬编码。在 DDD 中,这对于管理领域对象之间的关系非常有用。例如,在一个电商应用中,订单服务可能依赖于商品服务和用户服务,通过依赖注入可以方便地替换这些服务的实现,用于测试或者适应不同的业务场景。
    • 中间件支持:框架提供了中间件机制,用于在请求处理管道中添加各种预处理和后处理逻辑。这在 DDD 中可以用于处理跨领域的横切关注点,如日志记录、权限验证等。例如,在一个企业资源规划(ERP)系统中,可以通过中间件对所有的业务请求进行权限验证,确保只有授权用户能够访问相应的领域功能。
  • 应用场景示例
    • 企业级后台管理系统:构建一个用于企业内部资源管理的系统,包括员工管理、项目管理、财务管理等模块。NestJS 的模块化架构可以很好地组织这些领域模块,每个模块可以独立开发、测试和维护。例如,员工管理模块可以处理员工信息的增删改查、工资计算等业务逻辑,项目管理模块可以负责项目的创建、进度跟踪等功能。
    • 实时应用程序:如在线聊天应用或者实时数据监控系统。NestJS 结合 WebSockets 等技术可以实现实时通信功能,同时利用其 DDD 友好的架构来处理聊天消息的领域逻辑、用户状态管理以及数据持久化等任务。例如,在聊天应用中,消息模块可以处理消息的发送、接收和存储,用户模块可以管理用户的在线状态和聊天权限。

4. SimpleCQRS(C#)

  • 项目概述
    • SimpleCQRS 是一个用 C# 编写的简单的命令查询职责分离(CQRS)和事件溯源示例项目。它通过一个小型但完整的应用场景展示了如何在.NET 环境中应用 DDD 的一些关键原则,特别是 CQRS 和事件溯源的实现方式。
  • 功能特点
    • CQRS 实现示例:SimpleCQRS 清晰地展示了命令和查询的分离。它定义了不同的命令对象用于修改领域状态,以及查询对象用于获取数据。例如,在一个库存管理系统的示例中,有 “调整库存数量” 的命令对象,它包含了要调整的产品 ID 和调整的数量等信息,用于修改库存数据;同时有 “查询库存水平” 的查询对象,用于获取指定产品的当前库存数量。
    • 事件溯源基础展示:项目展示了事件溯源的基本原理。所有对领域状态的修改都会产生相应的事件,这些事件被存储起来。系统可以通过重新播放这些事件来重建领域对象的状态。以库存管理为例,每次库存的增加或减少都会产生一个库存变更事件,通过这些事件的历史记录,可以追溯库存的变化情况。
    • 简单易懂的架构:SimpleCQRS 的代码结构简单,易于理解。它没有过多复杂的框架依赖,对于初学者来说是一个很好的学习 DDD 相关概念的示例。它展示了如何在一个相对简单的 C# 应用程序中构建领域模型、处理命令和查询,以及如何利用事件来维护领域状态。
  • 应用场景示例
    • 小型业务系统学习案例:作为一个学习工具,SimpleCQRS 可以用于教学或者个人学习 DDD 和 CQRS 概念。例如,在一个小型的学生成绩管理系统中,可以应用其理念。“更新成绩” 命令用于修改学生的成绩信息,产生相应的成绩变更事件,“查询成绩” 查询对象用于获取学生的成绩列表。通过这种方式,学生可以直观地理解 DDD 相关概念在实际系统中的应用。
    • 快速原型开发:在开发一些小型的、对架构灵活性有一定要求的项目原型时,SimpleCQRS 可以作为一个基础框架。例如,在一个活动报名系统的早期原型阶段,利用其命令和查询分离的思想,快速实现活动报名(命令)和活动参与人数查询(查询)等功能,并且通过事件溯源来记录报名信息的变化历史,为后续系统的完善提供基础。

七、总结

DDD 模式为复杂业务软件系统构建提供有力范式,以领域模型锚定业务核心,借分层架构、限界上下文等机制解耦复杂性、保障系统演进。虽面临学习、建模、协作挑战,但长期收益可观,C# 生态凭借丰富框架(ASP.NET、EF Core 等)适配 DDD 实践各环节,助力开发者打造高质量、可扩展、贴合业务 “灵动” 软件系统,持续赋能业务创新与数字化转型。随着业务场景愈发复杂、技术迭代加速,DDD 将在软件开发领域持续深耕拓展,融入微服务、云原生架构,绽放更大价值。

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

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

相关文章

VSCode修改资源管理器文件目录树缩进(VSCode目录结构、目录缩进、文件目录外观)workbench.tree.indent

文章目录 方法点击左下角小齿轮点击设置点击工作台&#xff0c;点击外观&#xff0c;找到Tree: Indent设置目录树的缩进 方法 点击左下角小齿轮 点击设置 点击工作台&#xff0c;点击外观&#xff0c;找到Tree: Indent设置目录树的缩进 "workbench.tree.indent"默认…

Transformer.js(七):ONNX 后端介绍 - 它是什么、如何将pytorch模型导出为ONNX格式并在web中使用

在前面的文章中&#xff0c;我介绍了关于transformer.js的一些内容&#xff0c;快速连接&#xff1a; 1. 运行框架的可运行环境、使用方式、代码示例以及适合与不适合的场景2. 关于pipe管道的一切3. 底层架构及性能优化指南4. 型接口介绍5. Tokenizer 分词器接口解析 6. 处理工…

玄机应急:linux入侵排查webshell查杀日志分析

目录 第一章linux:入侵排查 1.web目录存在木马&#xff0c;请找到木马的密码提交 2.服务器疑似存在不死马&#xff0c;请找到不死马的密码提交 3.不死马是通过哪个文件生成的&#xff0c;请提交文件名 4.黑客留下了木马文件&#xff0c;请找出黑客的服务器ip提交 5.黑客留…

消息队列详解:从基础到高级应用

本文主旨 撰写这篇文章的目的在于向读者提供一个全面理解消息队列概念及其在实际应用中重要性的指南。通过从RocketMQ的基础组件如生产者、消费者、主题等的介绍到更高级的概念&#xff0c;比如集群消费与广播消费的区别、顺序消息的重要性等&#xff0c;我们希望能够帮助开发…

qt QGraphicsRotation详解

1、概述 QGraphicsRotation 是 Qt 框架中 QGraphicsTransform 的一个子类&#xff0c;它专门用于处理图形项的旋转变换。通过 QGraphicsRotation&#xff0c;你可以对 QGraphicsItem&#xff08;如形状、图片等&#xff09;进行旋转操作&#xff0c;从而创建动态和吸引人的视觉…

20241129解决在Ubuntu20.04下编译中科创达的CM6125的Android10出现找不到库文件

20241129解决在Ubuntu20.04下编译中科创达的CM6125的Android10出现找不到库文件libtinfo.so.5的问题 2024/11/29 20:41 缘起&#xff1a;中科创达的高通CM6125开发板的Android10的编译环境需要。 [ 11% 15993/135734] target Java source list: vr [ 11% 15994/135734] target …

云轴科技ZStack助力 “上科大智慧校园信创云平台”入选上海市2024年优秀信创解决方案

近日&#xff0c;为激发创新活⼒&#xff0c;促进信创⾏业⾼质量发展&#xff0c;由上海市经济信息化委会同上海市委网信办、上海市密码管理局、上海市国资委等主办的“2024年上海市优秀信创解决方案”征集遴选活动圆满落幕。云轴科技ZStack支持的“上科大智慧校园信创云平台”…

【ArcGIS Pro】实现一下完美的坐标点标注

在CAD里利用湘源可以很快点出一个完美的坐标点标注。 但是在ArcGIS Pro中要实现这个效果却并不容易。 虽然有点标题党&#xff0c;这里就尽量在ArcGIS Pro中实现一下。 01 标注实现方法 首先是准备工作&#xff0c;准备一个点要素图层&#xff0c;包含xy坐标字段。 在地图框…

聚云科技×亚马逊云科技:打通生成式AI落地最后一公里

云计算时代&#xff0c;MSP&#xff08;云管理服务提供商&#xff09;犹如一个帮助企业上云、用云、管理云的专业管家&#xff0c;在云计算厂商与企业之间扮演桥梁的作用。生成式AI浪潮的到来&#xff0c;也为MSP带来全新的生态价值和发展空间。 作为国内领先的云管理服务提供…

brew安装mongodb和php-mongodb扩展新手教程

1、首先保证macos下成功安装了Homebrew&#xff0c; 在终端输入如下命令&#xff1a; brew search mongodb 搜索是不是有mongodb资源&#xff0c; 演示效果如下&#xff1a; 2、下面来介绍Brew 安装 MongoDB&#xff0c;代码如下&#xff1a; brew tap mongodb/brew brew in…

图像显示的是矩阵的行和列,修改为坐标范围。

x 3; y 3; f1x x^2 y^2; guance1 f1x; F (x, y) sqrt((x.^2 y.^2 - guance1).^2); % 使用点乘 [x, y] meshgrid(0:1:5, 0:1:5); Z F(x, y); figure; imagesc(Z); % 由于 imagesc 使用矩阵索引作为坐标&#xff0c;我们需要手动添加刻度 % 这里我们假设 x 和 y 的范围…

深入理解Redis线程模型

前置目标&#xff1a;搭建一个Redis单机服务器。搭建过程参考前面的文档&#xff08;https://blog.csdn.net/Zhuxiaoyu_91/article/details/143904807&#xff09;。 建议调整的redis核心配置&#xff1a; daemonize yes # 允许后台启动 protected‐mode no #关闭保护模…

机器学习实战:泰坦尼克号乘客生存率预测(数据处理+特征工程+建模预测)

项目描述 任务&#xff1a;根据训练集数据中的数据预测泰坦尼克号上哪些乘客能生存下来 数据源&#xff1a;csv文件&#xff08;train.csv&#xff09; 目标变量&#xff1a;Survived&#xff08;0-1变量&#xff09; 数据集预览&#xff1a; 1、英文描述&#xff1a; 2、…

人工智能之数学基础:欧式距离及在人工智能领域中的应用

本文重点 欧式距离,也称为欧几里得距离,是数学中用于衡量多维空间中两点之间绝对距离的一种基本方法。这一概念最早由古希腊数学家欧几里得提出,并以其名字命名。欧式距离的计算基于勾股定理,即在一个直角三角形中,斜边的平方等于两直角边的平方和。在多维空间中,欧式距…

logminer挖掘日志归档查找问题

--根据发生问题时间点查找归档文件 select first_time,NAME from gv$archived_log where first_time>2016-03-15 17:00:00 and first_time<2016-03-15 21:00:00; 2016-03-15 17:23:55 ARCH/jxdb/archivelog/2016_03_15/thread_1_seq_41588.4060.906577337 2016-03-15 17:…

洛谷 P1747 好奇怪的游戏 C语言 bfs

题目&#xff1a; https://www.luogu.com.cn/problem/P1747#submit 题目描述 爱与愁大神坐在公交车上无聊&#xff0c;于是玩起了手机。一款奇怪的游戏进入了爱与愁大神的眼帘&#xff1a;***&#xff08;游戏名被打上了马赛克&#xff09;。这个游戏类似象棋&#xff0c;但…

【c++篇】:解读Set和Map的封装原理--编程中的数据结构优化秘籍

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;c篇–CSDN博客 文章目录 前言一.set和map的初步封装1.树的节点封装修改2.Find()查找函数3.红…

字符型注入‘)闭合

前言 进行sql注入的时候&#xff0c;不要忘记闭合&#xff0c;先闭合再去获取数据 步骤 判断是字符型注入 用order by获取不了显位&#xff0c;select也一样 是因为它是’)闭合&#xff0c;闭合之后&#xff0c;就可以获取数据了 最后就是一样的步骤

电脑启动需要经历哪些过程?

传统BIOS启动流程 1. BIOS BIOS 启动&#xff0c;BIOS程序是烧进主板自带的ROM里的&#xff0c;所以无硬盘也可以启动。BIOS先进行自检&#xff0c;检查内存、显卡、磁盘等关键设备是否存在功能异常&#xff0c;会有蜂鸣器汇报错误&#xff0c;无错误自检飞快结束。 硬件自检…

PYNQ 框架 - OV5640驱动 + Linux 驱动分析

目录 1. 简介 1.1 博文要点 1.2 V4L2 2. 极简 Char 驱动 2.1 源码 2.2 Makefile 2.3 加载驱动 2.4 设备文件 2.5 测试驱动程序 2.6 卸载驱动程序 2.7 自动创建设备文件 2.8 日志等级 3. 极简 V4L2 驱动 3.1 源码 3.2 Makefile 3.3 设备节点类型 3.4 测试 V4L2…