Clprolf와 `indef_obj`를 사용한 클래스 리팩토링

발행: (2025년 12월 25일 오후 11:51 GMT+9)
6 분 소요
원문: Dev.to

Source: Dev.to

Charles Koffler

대부분의 개발자는 **단일 책임 원칙 (SRP)**에 동의합니다.
실제 어려운 점은 무엇을 해야 하는지가 아니라 언제 해야 하는지입니다.

실제 프로젝트에서는 보통:

  • 작동하는 코드를 작성하고,
  • 시간이 지나면서 코드를 더 잘 이해하고,
  • 책임이 명확해질 때 리팩터링합니다.

Clprolf는 리팩터링을 통해 미뤄진 아키텍처 결정을 지원함으로써 이 워크플로우에 자연스럽게 맞습니다.

1️⃣ 클래식 OOP 클래스에서 시작하기

아주 흔한 예제로 시작해봅시다. 특이한 건 없고, 단지 동작하는 클래스입니다.

public class OrderManager {

    public void processOrder(Order order) {
        if (order.getTotal() <= 0) {
            throw new IllegalArgumentException("Invalid order");
        }

        saveToDatabase(order);
        logOrder(order);

        String message = formatConfirmation(order);
        sendEmail(message);
    }

    private void saveToDatabase(Order order) {
        System.out.println("Saving order " + order.getId());
    }

    private void logOrder(Order order) {
        System.out.println("Order processed: " + order.getId());
    }

    private String formatConfirmation(Order order) {
        return "Order #" + order.getId() + " confirmed";
    }

    private void sendEmail(String message) {
        System.out.println("Sending email: " + message);
    }
}

이 클래스는:

  • 비즈니스 규칙을 포함하고,
  • 영속성을 처리하며,
  • 로깅을 수행하고,
  • 메시지를 포맷하며,
  • 이메일을 보냅니다.

누구나 이런 코드를 작성해 본 적이 있을 것입니다.

2️⃣ 역할에 대해 고민하지 않고 Clprolf 사용하기

Clprolf에서는 똑같은 방식으로 시작할 수 있습니다. 사전에 아무것도 결정할 필요가 없으며, 단지 아키텍처상의 역할이 아직 명확하지 않음을 인정하면 됩니다.

public indef_obj OrderManager {

    public void processOrder(Order order) {
        if (order.getTotal() <= 0) {
            throw new IllegalArgumentException("Invalid order");
        }

        saveToDatabase(order);
        logOrder(order);

        String message = formatConfirmation(order);
        sendEmail(message);
    }

    private void saveToDatabase(Order order) { }
    private void logOrder(Order order) { }
    private String formatConfirmation(Order order) { return ""; }
    private void sendEmail(String message) { }
}

이 단계에서는:

  • 강제되는 것이 없고,
  • 아키텍처상의 약속도 없으며,
  • 코드는 잠시 이렇게 유지될 수 있습니다.

indef_obj는 고전적인 OOP와 하지만 의식적으로 동작합니다.

3️⃣ 코드 이해 후 SRP 적용

Later—exactly like in a classic SRP refactoring—you realize that this class mixes different responsibilities.

ConcernNature
Business decisionBusiness
PersistenceTechnical
LoggingTechnical
Formatting / I/OTechnical

This is where Clprolf가 유용해집니다.

4️⃣ 명시적 책임으로 리팩터링

Before (indef_obj)

OrderManager
 ├─ business rule
 ├─ persistence
 ├─ logging
 └─ notification

After (SRP made explicit)

OrderProcessor (agent)
 ├─ business decision

OrderRepository (worker_agent)
 └─ persistence

OrderNotifier (worker_agent)
 ├─ logging
 └─ messaging

🎯 비즈니스 책임 → agent

public agent OrderProcessor {

    private final OrderRepository repository;
    private final OrderNotifier notifier;

    public OrderProcessor(OrderRepository repository,
                          OrderNotifier notifier) {
        this.repository = repository;
        this.notifier = notifier;
    }

    public void process(Order order) {
        if (order.getTotal() <= 0) {
            throw new IllegalArgumentException("Invalid order");
        }

        repository.save(order);
        notifier.notify(order);
    }
}

agent는:

  • 비즈니스 의도를 표현하고,
  • 행동을 조정하며,
  • 기술적인 세부 사항을 포함하지 않는다.

⚙️ 기술 책임 → worker_agent

public worker_agent OrderRepository {

    public void save(Order order) {
        System.out.println("Saving order " + order.getId());
    }
}
public worker_agent OrderNotifier {

    public void notify(Order order) {
        log(order);
        String message = format(order);
        send(message);
    }

    private void log(Order order) {
        System.out.println("Order processed: " + order.getId());
    }

    private String format(Order order) {
        return "Order #" + order.getId() + " confirmed";
    }

    private void send(String message) {
        System.out.println("Sending email: " + message);
    }
}

워커는 기술적인 관심사를 자유롭게 혼합할 수 있다:

  • I/O,
  • 포맷팅,
  • 로깅,
  • 인프라스트럭처.

이는 비즈니스 의미가 agent에 남아 있기 때문에 허용된다.

5️⃣ 변경된 점 — 그리고 변하지 않은 점

변경되지 않은 항목

  • 알고리즘,
  • 동작,
  • 성능,
  • 표현력.

변경된 항목

  • 책임이 명시적으로 되었다,
  • 아키텍처 의도가 가시화되었다,
  • 미래의 진화가 쉬워졌다.

이는 단순히 구조적으로 적용된 SRP이다.

🧩 결론

Clprolf는 개발자에게 더 열심히 생각하라고 요구하지 않으며— 특히 더 일찍 생각하라고 요구하지도 않습니다.
그들은 준비가 되었을 때 생각할 수 있게 해줍니다.

당신은:

  • 먼저 코드를 작성하고,
  • 나중에 이해하고,
  • 필요할 때 책임을 리팩터링할 수 있습니다.

indef_obj목표가 아니라 — 실제 개발을 지원하는 임시 상태입니다.

그 의미에서, Clprolf는 단순한 언어가 아닙니다.
이는 아키텍처 명료성을 위한 리팩터링 도구입니다.

Back to Blog

관련 글

더 보기 »