묻지 말고 시켜라

옹심이·2024년 12월 16일
0
post-thumbnail

시작하며

어떻게 하면 객체 지향적으로 사고할 수 있을까?

가장 쉬운 방법으로는 TDA가 있다. TDA는 “Tell, Dont Ask”를 의미한다.

이번 포스트는 객체에게 물어보지 않고 일을 시키는 방법에 대해 다룬다.

TDA

우선 TDA 원칙을 따르지 않는 코드를 보자

public class Shop {
    public void sell(Account account, Product product){
        long price = product.getPrice();
        long mileage = account.getMoney();

        if(mileage >= price){
            account.setMoney(mileage - price);
        }
        else{
            System.out.println("잔액 부족");
        }
    }
}

class Account{
    private long money;

    ...Getter Setter 생략
}

class Product{
    private String name;
    private long price;

    ...Getter Setter 생략
}

물건을 가게에서 구입할 때 물건 값을 계산하는 코드다.

주의해서 봐야 할 부분은 mileage와 price를 비교하는 조건문이다.

Shop에서 Getter를 통해 두 클래스의 멤버 변수에 해당 하는 값을 가져와 로직을 실행한다.

Account와 Product에는 각각 클래스에 필요한 데이터만 있으며 책임도 역할도 찾을 수 없다.

그렇다면, 객체에게 일을 시키게 된다면 코드가 어떻게 변할까?

public class Shop {
    public void sell(Account account, Product product){
        if(account.canAfford(product.getPrice())){
            account.setMoney(mileage - price);
        }
        else{
            System.out.println("잔액 부족");
        }
    }
}

class Account{
    private long money;
    
    public boolean canAfford(long amount){
        return money >= amount;    
    }
    
    ...Getter Setter 생략
}

class Product{
    private String name;
    private long price;
    
    public void withdraw(long amount){
        money -= amount;
    }

    ...Getter Setter 생략
}

다시 조건문을 살펴보면 Account객체에게 무언가 일을 시킨다. Getter로 물어보지 않는다.

Account 클래스를 보니 money와 amount를 비교하는 책임이 생겼고, Shop은 Account에게 너가 맡은 일을 하라고 시키고 있다.

Account 객체는 더 이상 수동적인 데이터 덩어리가 아니며, 책임을 가진 객체가 되었다.

이로써 객체들은 각자의 책임을 가지고 있고 협력하는 객체가 내부적으로 어떤 동작을 수행하는지 신경 쓸 필요가 없게 된다. 그냥 시킨 일을 잘 했는지만 판단하면 된다. 객체에게 일만 시켰는데도 캡슐화가 잘 된 것을 확인할 수 있다.

이는 Getter, Setter 사용을 줄이라는 것으로 이어진다. 첫 번째 코드는 Getter로 객체의 값을 가져와 사용했으며 두 번째 코드는 객체의 변수에 직접 접근하지 않고, 책임을 부여해 같은 로직을 구현했다.

첫 번째 코드처럼 Getter와 Setter를 무분별하게 사용하면 외부에서 모든 데이터에 접근할 수 있게 된다.

이러한 프로그래밍 방식은 스프링 개발을 할 때도 이어지는데, 바로 Util 클래스를 만들어 그 안에서 모든 일을 쉽게 처리하도록 프로그래밍 하는 것이다. 이렇게 프로그래밍을 하면 객체는 구조체와 다를게 없으며 Util 클래스만 무수히 늘어난다.

그럼 Getter, Setter는 무조건 사용하면 안될까?

shop.sell()의 조건문을 다시 확인해보면 Getter로 price 값을 가져오는 것을 알 수 있다.

객체에게 모든 일을 시킬 수는 없으며 어딘가에서는 Getter를 쓸 수 밖에 없는 상황이 나올 것이다. 이런 경우에는 사용할 수 밖에 없으며 Getter도 필요한 메서드임을 기억하자

0개의 댓글