객체, 설계

김종준·2023년 1월 15일
0

오브젝트

목록 보기
1/4

객체, 설계

public class Theater {
    private TicketSeller ticketSeller;

    public Theater(TicketSeller ticketSeller) {
        this.ticketSeller = ticketSeller;
    }

    public void enter(Audience audience) {
        if (audience.getBag()
                .hasInvitation()) {
            Ticket ticket = ticketSeller.getTicketOffice()
                    .getTicket();
            audience.getBag()
                    .setTicket(ticket);
        } else {
            Ticket ticket = ticketSeller.getTicketOffice()
                    .getTicket();
            audience.getBag()
                    .minusAmount(ticket.getFee());
            ticketSeller.getTicketOffice()
                    .plusAmount(ticket.getFee());
            audience.getBag()
                    .setTicket(ticket);
        } 
    }
}

위의 코드의 문제점은 Audience와 TicketSeller가 Theater의 통제를 받는 수동적인 존재라는 점이다.

수동적인 존재라는 판단을 할 수 있는 코드는 다음과 같다.

  • Audience : audience.getBag().hasInvitation())
  • TicketSeller : ticketSeller.getTicketOffice().getTicket()

Theater이 Audience의 Bag를 확인하고 TickectSeller의 TicketOffice를 확인한다.

이것이 문제가 되는 이유는 Audience와 TicketSeller가 변경되면 Theater의 코드 역시 변경되기 때문이다.

이를 객체 사이에 의존성이 있다고 한다.

이 의존성은 변경에 대한 영향을 암시한다.

의존성이라는 말속에는 어떤 객체가 변경될 때 그 객체에 의존하는 다른 객체도 함께 변경될 수 있다는 사실이 내포된 것이다.

그리고 이 객체 사이의 의존성이 과한 경우를 결합도가 높다고 한다.

그렇다면 수동적인 존재가 되지 않고 능동적인 존재가 되려면 어떻게 하면 될까?

tickeOffice에 대한 접근을 오직 TicketSeller 안에만 존재하게 하는 캡슐화를 하면 된다.

그렇게 되면 TickeSeller는 ticketOffice에서 티켓을 꺼내서 판매 요금을 적립하는 일을 스스로 수행할 수밖에 없다.

public class Theater {
    private TicketSeller ticketSeller;

    public Theater(TicketSeller ticketSeller) {
        this.ticketSeller = ticketSeller;
    }

    public void enter(Audience audience) {
        ticketSeller.toSell(audience);
    }
}

이렇게 되면 Theater은 오직 자신이 가지고 있는 TicketSeller의 인터페이스에만 의존하게 된다.

TicketSeller가 내부에 TicketOffice 인스턴스를 포함하고 있다는 사실은 Theater은 모른다.

Theater가 더이상 TicketSeller가 가지고 있는 TicketOffice에 관해 알지 못해 Theater과 TicketOffice의 의존성이 사라지고 TicketSeller는 자율성을 가지게 된 것이다.

자율성이 항상 좋은 것일까?

꼭 그렇지만은 않다.

자율성이 결합도를 높이는 경우가 있다.

아래 예제를 보자.

// 경우 1
public class TicketSeller {
    public void sellTo(Audience audience) {
        ticketOffice.plusAmount(audience.buy(tickeOffice.getTicket()));
    }
}

// 경우 2
public class TicketSeller {
    public void sellTo(Audience audience) {
        ticketOffice.sellTicketTo(audience);
    }
}

public class TicketOffice {
    public void sellTicketTo(Audience audience) {
        plusAmount(audience.buy(getTicket()));
    }

    private Ticket getTicket() {
        return tickets.remove(0);
    }

    private void plusAmount(Long amount) {
        this.amount += amount;
    }
}

경우1의 경우 ticketOffice에게 자율성을 주지 않았다.

TicketSeller에서 ticketOffice.plusAmount와 같이 자율성이 빼었다.

이렇게 되면 ticketOffice의 amount에 대해 TicketSeller가 알게 되는 것이다.

하지만 경우2의 경우 ticketOffice의 amount에 대해 TicketSeller가 알 수 없다.

sellTicketTo라는 메서드를 통해 캡슐화하고 자율성을 보장하였기 때문이다.

하지만 이는 경우1에서 Audience가 TicketSeller와만 연관되었지만, 경우2에서는 Audience가 TicketSeller와 TicketOffice 두 곳과 연관되어 결합도가 증가하였다.

TicketOffice의 자율성을 보장하기 위해 Audience의 결합도가 증가한 것이다.

이러한 경우에서는 각 경우의 트래이드 오프를 생각하여 하나를 결정하면 된다.

정리

객체는 수동적이지 않고 능동적이어야 한다.

객체가 능동적이기 위해서는 캡슐화를 통해 자신이 가지고 있는 변수를 변경하는 것은 스스로 수행하도록 하는 것이다.

그렇게 되면 의존성이 사라지고 자율성이 높아진다.

하지만 이 자율성이라는 것이 항상 좋은 것만은 아니다.

만약 자율성이 결합도를 높인다면 이는 트래이드 오프를 고려하여 하나를 결정하면 된다.

0개의 댓글