基于自行车销售场景的模块化单体DDD代码组织方案问询
自行车销售领域Modular Monolith代码结构方案
基于你定义的Offering限界上下文(核心域:订阅,支撑域:发布、折扣),结合选定的领域模式,下面是适配Modular Monolith架构的代码结构方案,兼顾模块独立性与业务逻辑的合理分层:
核心目录结构
BikeSales.ModularMonolith/ ├── src/ │ ├── BikeSales.Shared/ # 共享基础组件(工具类、通用DTO、配置基类等) │ ├── BikeSales.Offering/ # Offering限界上下文根模块 │ │ ├── Subscription/ # 核心域:订阅模块(Domain Model模式) │ │ │ ├── Domain/ # 领域层:封装核心业务规则 │ │ │ │ ├── Entities/ │ │ │ │ │ ├── Subscription.cs │ │ │ │ │ ├── SubscriptionPlan.cs │ │ │ │ ├── ValueObjects/ │ │ │ │ │ ├── SubscriptionPeriod.cs │ │ │ │ │ ├── BillingCycle.cs │ │ │ │ ├── Services/ │ │ │ │ │ ├── SubscriptionManagementService.cs │ │ │ ├── Application/ # 应用层:处理命令/查询,协调领域与基础设施 │ │ │ │ ├── Commands/ │ │ │ │ │ ├── CreateSubscriptionCommand.cs │ │ │ │ │ ├── CancelSubscriptionCommand.cs │ │ │ │ ├── Queries/ │ │ │ │ │ ├── GetSubscriptionByIdQuery.cs │ │ │ │ ├── Services/ │ │ │ │ │ ├── SubscriptionAppService.cs │ │ │ ├── Infrastructure/ # 基础设施层:实现仓储、数据持久化 │ │ │ │ ├── Repositories/ │ │ │ │ │ ├── SubscriptionRepository.cs │ │ │ │ ├── Persistence/ │ │ │ │ │ ├── SubscriptionDbContext.cs │ │ ├── Publishing/ # 支撑域:发布模块(Active Record模式) │ │ │ ├── Models/ # Active Record实体:融合数据持久化与简单业务逻辑 │ │ │ │ ├── BikeOfferListing.cs │ │ │ │ ├── PublishingSchedule.cs │ │ │ ├── Services/ # 辅助服务:做简单流程编排 │ │ │ │ ├── ListingPublishingService.cs │ │ ├── Discount/ # 支撑域:折扣模块(Transaction Script模式) │ │ │ ├── Scripts/ # 事务脚本:按业务流程组织逻辑方法 │ │ │ │ ├── ApplyDiscountForSubscription.cs │ │ │ │ ├── CalculateDiscountAmount.cs │ │ │ ├── Models/ # 数据载体:仅存储数据,无业务逻辑 │ │ │ │ ├── DiscountRule.cs │ │ │ │ ├── DiscountApplicationResult.cs │ │ ├── OfferingApi/ # 限界上下文统一对外API入口 │ │ │ ├── Controllers/ │ │ │ │ ├── SubscriptionController.cs │ │ │ │ ├── PublishingController.cs │ │ │ │ ├── DiscountController.cs │ ├── BikeSales.Web/ # 前端Web应用(可选,用于用户交互) │ ├── BikeSales.Tests/ # 测试集合 │ │ ├── UnitTests/ │ │ │ ├── SubscriptionDomainTests.cs │ │ │ ├── PublishingModelTests.cs │ │ │ ├── DiscountScriptTests.cs │ │ │ ├── IntegrationTests/ │ │ │ │ ├── OfferingApiIntegrationTests.cs ├── README.md ├── BikeSales.ModularMonolith.sln
各模块模式落地细节
订阅模块(Domain Model模式)
- 领域层是核心:
Subscription实体封装状态转换(激活、取消)、周期验证等核心业务规则;SubscriptionPeriod值对象处理周期合法性校验,避免业务逻辑散落在应用层 - 应用层仅做协调:负责接收外部请求,调用领域服务完成业务操作,不包含具体业务规则
- 基础设施层解耦持久化:仓储接口定义在领域层,实现放在基础设施层,支持切换ORM或存储方式
发布模块(Active Record模式)
BikeOfferListing等模型直接继承ORM基类(比如EF Core实体),同时嵌入简单业务逻辑(如验证发布时间范围、状态转换)- 服务层仅做轻量编排:比如调用模型的方法完成发布、下架操作,不承载复杂逻辑
折扣模块(Transaction Script模式)
- 按业务流程组织脚本:比如
ApplyDiscountForSubscription方法完整实现"查询订阅→匹配折扣规则→计算折扣金额→更新订阅费用"的事务流程 - 模型仅做数据载体:
DiscountRule、DiscountApplicationResult仅存储数据,所有业务逻辑集中在脚本方法中,适合规则相对固定、流程线性的场景
模块化约束实践
- 模块依赖规则:仅允许子模块依赖
BikeSales.Shared,OfferingApi依赖所有子模块;禁止子模块之间直接依赖(比如订阅模块不能直接调用折扣脚本) - 跨模块交互:通过领域事件或应用服务接口实现。例如订阅创建后触发
SubscriptionCreatedEvent,发布模块监听事件同步发布对应报价;折扣逻辑通过DiscountAppService接口调用,避免硬耦合 - 数据层隔离:每个模块可使用独立数据库上下文或表前缀,避免数据层交叉依赖
- 统一对外入口:所有外部请求通过
OfferingApi控制器接入,内部模块不直接暴露服务
内容的提问来源于stack exchange,提问作者Maciej MJ Jedrzejewski
相关产品推荐
相关产品推荐

