You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DDD技术疑问:Process Manager与Domain Service的区别是什么?

Process Manager vs Domain Service: Clarifying the Differences (With Navigation Examples)

Great question—this is a super common point of confusion when first implementing DDD alongside CQRS and Event Sourcing, especially for workflow-heavy domains like navigation. Let’s break down their core identities, responsibilities, and how to pick the right one for your use case.

Core Purpose & Scope

First, let’s anchor each component to its core job:

Domain Service

  • Single, stateless domain logic unit: It exists to handle domain logic that doesn’t fit naturally into any single Aggregate Root, Entity, or Value Object. Think of it as a "logic helper" for one-off, self-contained domain tasks.
  • No long-term state: Once it finishes its task, it’s done—no need to persist any information about the operation.
  • Example for navigation: Calculating the shortest path between two points (considering real-time traffic or vehicle restrictions) is a classic Domain Service job. It takes input (start, end, vehicle type) and returns a route, with no need to track what happens after that calculation.

Process Manager

  • Long-running workflow coordinator: It’s a stateful orchestrator that manages end-to-end business processes spanning multiple aggregates and time. Think of it as a "traffic controller" for your domain’s multi-step workflows.
  • Stateful & event-driven: It persists its own state to track where the process is (e.g., "user is en route", "arrived at waypoint") and reacts to domain events to trigger the next steps in the flow.
  • Example for navigation: Managing the full lifecycle of a user’s trip—from initiating navigation, updating guidance as the user moves, logging waypoints, triggering a trip report on arrival, and prompting a post-trip review. This requires coordinating multiple aggregates (navigation, location tracking, user profiles) over time, which is exactly what a Process Manager is built for.

State Management

This is one of the clearest distinguishing factors:

Domain Service

  • Stateless (or transient state only): Every call is independent. The same input will always produce the same output (assuming no external state changes like real-time traffic, which you’d handle via input parameters).
  • For example: A RouteCalculationService.CalculateOptimalRoute(start, end) method doesn’t remember the last route it calculated—it just does the work and returns the result.

Process Manager

  • Persisted state is mandatory: It needs to track the process’s current stage, associated aggregate IDs, completed tasks, and pending actions. This ensures if the system restarts or the process is paused, it can pick up exactly where it left off.
  • For example: A TripOrchestrationManager would store data like tripId, userId, currentLocation, completedWaypoints, and nextGuidanceStep to keep the workflow on track.

Interaction Pattern

How each component interacts with the rest of your domain also sets them apart:

Domain Service

  • Synchronous, direct calls: Application Services (or even other domain components) call it directly to get a result immediately. It doesn’t initiate further actions unless the logic itself requires emitting a single domain event (e.g., RouteCalculationFailedEvent if no valid route exists).

Process Manager

  • Asynchronous, event-driven coordinator: It doesn’t get called directly—instead, it subscribes to domain events from various aggregates. When an event is received, it updates its state and sends commands to other aggregates to move the workflow forward.
  • For example: When the Process Manager receives a UserReachedWaypointEvent, it updates its state to mark that waypoint as complete, then sends an UpdateRealTimeGuidanceCommand to the navigation aggregate and a LogWaypointVisitCommand to the trip history aggregate.

Let’s tie this to your specific navigation use case with two concrete examples:

When to Use a Domain Service

Suppose you need to validate if a proposed route complies with local trucking restrictions (height limits, weight restrictions). This is a self-contained, one-off check that doesn’t require tracking any ongoing workflow. You’d implement this as a RouteComplianceService with a ValidateRouteForVehicle(route, vehicleType) method. It takes inputs, runs the validation logic, and returns a pass/fail result (plus any violation details). No state needs to be saved after this.

When to Use a Process Manager

Suppose you need to manage the entire user navigation experience:

  1. User initiates navigation → NavigationInitiatedEvent is emitted.
  2. Process Manager subscribes to this event, initializes the trip state, and sends a StartLocationTrackingCommand to the location service.
  3. As the user moves, UserLocationUpdatedEvent is emitted repeatedly. The Process Manager checks if the user is deviating from the route, and if so, sends a RecalculateRouteCommand to the navigation aggregate.
  4. When UserReachedDestinationEvent is emitted, the Process Manager updates the trip state to "completed", sends a GenerateTripReportCommand to the reporting aggregate, and a RequestTripReviewCommand to the user profile aggregate.

This multi-step, cross-aggregate workflow is exactly what Process Managers are designed for—you couldn’t handle this with a stateless Domain Service, since you need to track the trip’s progress over time and coordinate multiple components.

Quick Rule of Thumb

  • Use a Domain Service when you have a single, self-contained domain logic task that doesn’t fit into an aggregate and doesn’t require tracking ongoing state.
  • Use a Process Manager when you need to orchestrate a multi-step, cross-aggregate business process that spans time and requires tracking workflow state.

内容的提问来源于stack exchange,提问作者Guigui

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:50:38