소프트웨어 설계에서 명령(Command)과 조회(Query)의 역할을 분리하는 것은 유지보수성과 가독성을 높이는 데 중요한 원칙입니다.
CQS(Command Query Separation)는 이와 같은 설계 원칙을 정의하고 있으며, 이 포스트에서는 CQS의 개념, 예시, 장단점에 대해 알아보겠습니다.
CQS는 Bertrand Meyer가 제안한 원칙으로, 프로그래밍에서 명령(Command)과 조회(Query)를 분리하는 것을 강조합니다. 이 원칙은 단일 책임 원칙(SRP)과 유사하게, 각 메서드가 하나의 책임만을 가질 것을 요구합니다. 즉, 하나의 메서드는 상태를 변경하는 명령을 수행하거나, 상태를 조회하는 작업을 해야 하며, 두 가지를 동시에 할 수는 없습니다.
하나의 메서드가 commend 면서 동시에 query일 수 없다.
즉, 하나의 메서드 안에서 상태변경/상태반환 동시 작업을 지양하라는 뜻 인것 같다.
CQS 원칙: 하나의 메서드가 상태를 변경하는 동시에 값을 반환해서는 안 된다.
Command는 시스템의 상태를 변경하는 메서드로, 반환값이 없습니다. 예를 들어, 새로운 사용자를 추가하는 로직은 Command로 구현될 수 있습니다.
public class AddUserCommand {
private String username;
private String password;
public AddUserCommand(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
}
public class UserCommandHandler {
public void handleAddUserCommand(AddUserCommand command) { // 사용자를 추가하고 상태를 변경
System.out.println("User added: " + command.getUsername());
}
}
public class Main {
public static void main(String[] args) {
UserCommandHandler commandHandler = new UserCommandHandler();
AddUserCommand addUserCommand = new AddUserCommand("john123", "password");
commandHandler.handleAddUserCommand(addUserCommand);
}
}
Query는 시스템의 상태를 조회하고, 이를 반환하지만 상태를 변경하지 않습니다. 예를 들어, 특정 사용자의 정보를 조회하는 로직은 Query로 구현될 수 있습니다.
public class GetUserQuery {
private String username;
public GetUserQuery(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
}
public class UserQueryHandler {
public String handleGetUserQuery(GetUserQuery query) { // 사용자 세부 정보를 검색하고 상태를 반환
String userDetails = "User details for username: " + query.getUsername();
System.out.println(userDetails);
return userDetails;
}
}
public class Main {
public static void main(String[] args) {
UserQueryHandler queryHandler = new UserQueryHandler();
GetUserQuery getUserQuery = new GetUserQuery("john123");
String userDetails = queryHandler.handleGetUserQuery(getUserQuery);
System.out.println(userDetails);
}
}
CQS는 명령과 조회의 책임을 분리함으로써 코드의 명확성과 가독성을 향상시킵니다. 이는 단일 책임 원칙(SRP)과도 일맥상통하며, 각 메서드가 하나의 역할만 수행하도록 유도합니다.
명령과 조회를 분리하면 각각의 메서드를 독립적으로 테스트할 수 있어, 테스트 코드 작성이 쉬워집니다. 이는 전체 코드베이스의 유지보수성을 높이는 데 기여합니다.
CQS는 읽기 작업과 쓰기 작업을 분리하여, 각각의 작업을 독립적으로 최적화할 수 있는 가능성을 제공합니다. 이는 성능 향상으로 이어질 수 있습니다.
CQS를 엄격히 적용하려면 명령과 조회를 위한 별도의 모델과 핸들러를 구현해야 하며, 이는 코드의 복잡성을 증가시킬 수 있습니다.
명령과 조회를 별도로 구현할 때, 비슷한 로직이 두 곳에서 중복될 수 있습니다. 이로 인해 코드베이스가 방대해지고, 관리가 어려워질 수 있습니다.
CQS(Command Query Separation)는 소프트웨어 개발에서 중요한 설계 원칙 중 하나입니다. 이 원칙을 통해 코드의 가독성, 유지보수성, 그리고 테스트 가능성을 크게 향상시킬 수 있습니다. 하지만 복잡성과 코드 중복 문제를 고려해야 하며, 상황에 맞게 적절히 적용하는 것이 중요합니다.