分离业务和控制逻辑

2025.05.15 · 4 minute read

核心逻辑是,将程序中业务,领域知识的部分(domain or business logic)与负责流程控制、协调和决策的部分(control logic)分开,提高代码的可维护性,可测试性和复用性。

在 DDD 中,业务逻辑对应着领域逻辑,控制逻辑对应着「应用层」或「服务层」。

Business Logic

  • 内容:业务规则、验证数据、计算公式
  • 职责:确保系统行为符合业务需求和规范
  • 示例:
    • 计算订单的总价
    • 判断用户的权限
    • 业务状态的转换

Control Logic

  • 内容:流程控制、调用顺序、条件判断
  • 职责:组织和管理业务逻辑的执行,保证系统流程正确
  • 示例:
    • 处理多步骤业务流程的状态切换
    • 事务开始和提交控制

示例

用 Python

普通写法

class UserService:
 def __init__(self):
 self.users = []

 def register_user(self, username, password):
  # 1. validate username
  if username in self.users:
   return {"success": False, "message": "Username already exists"}

  # 2. validate password length
  if len(password) < 6:
   return "Password too short"

  # 3. store user
  self.users.append(username)
  return {"success": True, "message": "User registered successfully"}

分离后写法

class UserRepository:
    def __init__(self):
        self.users = {}

    def exists(self, username):
        return username in self.users

    def save(self, user):
        self.users[user["username"]] = user


# Domain Logic
class UserDomainService:
    def __init__(self, user_repository):
        self.user_repository = user_repository

    def is_username_available(self, username):
        # Check if the username is already taken
        return self.user_repository.exists(username)

    def validate_password(self, password):
        # Validate the password according to your criteria
        return len(password) >= 6

    def create_user(self, username, password):
        user = {"username": username, "password": password}
        self.user_repository.save(user)
        return user


# Application Logic
class UserApplicationService:
    def __init__(self, user_domain_service):
        self.user_domain_service = user_domain_service

    def register_user(self, username, password):
        # 1. Check if the username is available
        if self.user_domain_service.is_username_available(username):
            return {"success": False, "message": "Username already taken."}

        # 2. Validate the password
        if not self.user_domain_service.validate_password(password):
            return {"success": False, "message": "Password does not meet criteria."}

        # 3. Create the user
        user = self.user_domain_service.create_user(username, password)
        return {"success": True, "user": user}


repo = UserRepository()
domain_service = UserDomainService(repo)
app_service = UserApplicationService(domain_service)

print(app_service.register_user("john_doe", "password123"))  # Should succeed
print(
    app_service.register_user("john_doe", "pass")
)  # Should fail due to password criteria
print(
    app_service.register_user("john_doe", "newpassword")
)  # Should fail due to username already taken
  • UserDomainService 只关注业务规则(用户名是否存在、密码校验、创建用户)。
  • UserApplicationService 负责流程控制(调用顺序、返回结果)。

用 Java

普通写法

import java.util.HashSet;
import java.util.Set;

public class UserService {
    private Set<String> users = new HashSet<>();

    public Result register(String username, String password) {
        // 1. Check if the username is available
        if (users.contains(username)) {
            return new Result(false, "Username is already in use");
        }
        // 2. Validate the password
        if (password.length() < 6) {
            return new Result(false, "Password must be at least 6 characters");
        }

        // 3. Create the user
        users.add(username);

        return new Result(true, "success");
    }

    public static class Result {
        private boolean success;
        private String message;

        public Result(boolean success, String message) {
            this.success = success;
            this.message = message;
        }
        public boolean isSuccess() {return success;}
        public String getMessage() {return message;}
    }
}

分离后写法

import java.util.HashMap;
import java.util.Map;

// Domain Logic
class UserDomainService {
    private UserRepository userRepository;

    public UserDomainService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public boolean isUsernameTaken(String username) {
        return userRepository.exists(username);
    }

    public boolean validatePassword(String password){
        return password != null && password.length() >= 6;
    }

    public void createUser(String username, String password) {
        User user = new User(username, password);
        userRepository.save(user);
    }
}

// Persistence Layer
class UserRepository{
    private Map<String, User> users = new HashMap<>();

    public boolean exists(String username){
        return users.containsKey(username);
    }

    public void save(User user){
        users.put(user.getUsername(), user);
    }
}

// User Entity
class User {
    private String username;
    private String password;

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
    public String getUsername() {
        return username;
    }
}


class Result {
    private boolean success;
    private String message;

    public Result(boolean success, String message) {
        this.success = success;
        this.message = message;
    }
    public boolean isSuccess() {return success;}
    public String getMessage() {return message;}
}

// Application Logic
class UserApplicationService {
    private UserDomainService userDomainService;

    public UserApplicationService(UserDomainService userDomainService) {
        this.userDomainService = userDomainService;
    }

    public Result register(String username, String password) {
        if(userDomainService.isUsernameTaken(username))
            return new Result(false, "Username taken");

        if(!userDomainService.validatePassword(password))
            return new Result(false, "Invalid password");

        userDomainService.createUser(username, password);

        return new Result(true, "success");
    }
}

public class scratch_46 {
    public static void main(String[] args) {
        UserRepository userRepository = new UserRepository();
        UserDomainService userDomainService = new UserDomainService(userRepository);
        UserApplicationService userApplicationService = new UserApplicationService(userDomainService);

        Result r1 = userApplicationService.register("alice", "12345");
        System.out.println(r1.getMessage());
        Result r2 = userApplicationService.register("alice", "123456");
        System.out.println(r2.getMessage());
        Result r3 = userApplicationService.register("alice", "1234567");
        System.out.println(r3.getMessage());
    }
}
  • UserDomainService 负责业务规则(用户名是否存在、密码校验、创建用户)。
  • UserApplicationService 负责控制流程(调用顺序、返回结果)。
  • UserRepository 模拟数据存储。
  • User 领域实体。

提示与建议

  1. 从简单方法开始构思
  2. 简单方法转换到逻辑控制层
  3. 分离出业务逻辑

感谢您的阅读!您的支持是我的动力。

如果您喜欢这篇文章,不妨请我喝杯咖啡。 ☕️