Clprolf를 사용한 클래스 책임 분리
Source: Dev.to
개요
깨끗하고 잘 구조화된 클래스를 설계하는 것은 객체‑지향 프로그래밍에서 핵심 과제입니다.
Clprolf는 declensions(활용형) 를 도입합니다 – 클래스의 성격과 속한 도메인을 간단히 표현하는 방법으로, 기존 아키텍처를 대체하지 않습니다. 레포지토리, 서비스, 컨트롤러, 엔티티, 추상화는 그대로 두고, 활용형을 추가하여 일관성을 보장합니다.
활용형(Declensions)
활용형은 클래스가 비즈니스/도메인 계층(agent)에 속하는지 기술 계층(worker_agent)에 속하는지를 나타냅니다. 이 용어는 자연어에서 단어가 사용에 따라 형태가 변하지만 핵심 정체성은 유지되는 개념을 차용한 것입니다.
주요 활용형
| 활용형 | 전형적인 책임 |
|---|---|
| agent | 비즈니스 로직, 도메인 개념, 추상화, 시뮬레이션 엔티티 |
| worker_agent | 기술 구성 요소: 레포지토리, 화면 로직, 파일 작업, 시스템 상호작용, 실행기 |
동의어
같은 활용형 안에서 동의어는 도메인을 바꾸지 않으면서 의도를 더 명확히 합니다.
- agent 동의어:
abstraction(개념적 또는 구조적 요소, 예:List,Button,Color),simu_real_obj(시뮬레이션 내부 객체) - worker_agent 동의어:
comp_as_worker(시뮬레이션 뉘앙스를 가진 동일 의미)
이 동의어들은 실제 도메인을 변경하지 않으며, 개발자에게 더 명확한 용어를 제공할 뿐입니다.
기존 구성 요소와의 통합
Clprolf는 Service, Repository, Controller 역할을 대체하지 않습니다. 이들 위에 활용형 주석을 추가하여 일관된 경계를 강제합니다.
전형적인 매핑
| 구성 요소 유형 | 활용형 |
|---|---|
| Repository / DAO | worker_agent |
| Service | agent |
| Controller | agent (또는 컨트롤러를 순수 기술 엔드포인트로 간주한다면 worker_agent) |
상속 규칙
Clprolf는 구성 요소 간 상속을 간접적으로 감독합니다:
- worker_agent는 agent를 상속할 수 없습니다 (예: 레포지토리가 서비스에서 상속되는 경우).
- agent는 기술 클래스를 상속할 수 없습니다.
- 같은 활용형을 가진 두 클래스는 상속이 가능하지만, 서로 다른 동의어를 사용할 경우 경고가 발생하여 관점 차이를 알립니다.
이 규칙은 우발적인 교차‑도메인 상속을 방지하고 시간이 지나도 책임을 명확히 유지하도록 돕습니다.
DDD 및 Clean Architecture와의 비교
- DDD는 도메인을 모델링하고 유비쿼터스 언어를 유지하기 위해 관례와 팀 규율에 의존합니다.
- Clean Architecture는 가이드라인, 패턴, 프로젝트 구조를 통해 도메인과 기술 계층을 분리합니다.
- Clprolf는 언어 수준에서 도메인 ↔ 기술 역할을 강제하여, 아키텍처 경계를 컴파일러가 확인하도록 보장합니다.
따라서 Clprolf는 DDD와 Clean Architecture와 함께 작동하며, 이를 대체하지 않고 추가적인 안전성을 제공합니다.
접근 방식 비교
| 접근 방식 | 초점 | 강제 방식 |
|---|---|---|
| DDD | 도메인 모델링, 유비쿼터스 언어 | 관례 및 팀 규율 |
| Clean Architecture | 도메인 ↔ 기술 계층 분리 | 가이드라인, 패턴, 프로젝트 구조 |
| Clprolf | 활용형: 도메인 ↔ 기술 역할 | 컴파일러가 확인하고 언어 차원에서 강제 |
사용 예시 (Java)
// Business logic (agent)
@Agent
public class OrderService {
private final OrderRepository repository = new OrderRepository();
public void validateAndStore(String orderId) {
// Business logic
System.out.println("Validating order " + orderId);
// Technical operation delegated to a worker_agent
repository.save(orderId);
}
}
// Technical work (worker_agent)
@Worker_agent
public class OrderRepository {
public void save(String orderId) {
System.out.println("Saving order " + orderId);
}
}
// Illegal inheritance – compilation error
@Worker_agent
public class WrongRepo extends OrderService {
// ❌ A worker_agent cannot inherit from an agent.
}
// Domain object (agent)
@Agent
public class Animal {
public void eat(String food) {
System.out.println("The animal eats " + food);
}
}
// Service using technical workers
@Agent
public class CheckoutService {
private final OrderRepository orders = new OrderRepository();
private final PaymentRepository payments = new PaymentRepository();
public void checkout(String orderId) {
orders.save(orderId);
payments.process(orderId); // Technical operation
}
}
위 예시들은 다음을 보여줍니다:
- 기존 구성 요소(Service, Repository, Controller)는 그대로 유지됩니다.
@Agent혹은@Worker_agent를 추가함으로써 각 클래스의 도메인이 명확해집니다.- 상속은 비즈니스 ↔ 기술 구분을 존중하여 우발적인 혼합을 방지합니다.
장점
- 비즈니스와 기술 로직의 명확한 분리
- 컴파일러가 확인하는 경계로 우발적인 교차‑도메인 상속 방지
- 활용형 동의어를 통한 일관된 용어
- SOLID 원칙, DDD, Clean Architecture와 호환
- 신규 개발자를 위한 예측 가능하고 가독성 높으며 유지보수 쉬운 코드베이스
추가 자료
전체 Clprolf 매뉴얼, 사양, 프레임워크 소스 코드는 다음에서 확인할 수 있습니다: