오브젝트 1.객체, 설계

조현창·2022년 12월 10일
0

오브젝트

목록 보기
1/5

원본 링크: https://github.com/vcho1958/TIL/blob/master/%EC%B1%85/%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8/202210111732%201.%EA%B0%9D%EC%B2%B4%2C%20%EC%84%A4%EA%B3%84.md

모든 프로그램은
1. 실행중에 제대로 동작하는 것
2. 생명주기동안 간단한 작업으로 변경이 가능해야함
- 만약 변경이 불가능하다면 1번을 만족하더라도 개선
3. 개발자가 독해하기 편한 코드여야함

public class Theater {  
    private TicketSeller ticketSeller;  
  
    public Theater(TicketSeller ticketSeller) {  
        this.ticketSeller = ticketSeller;  
    }  
  
    public void enter(Audience audience){  
        Ticket ticket = ticketSeller.getTicketOffice().getTicket();  
        if(audience.getBag().hasInvitation()){  
            audience.getBag().setTicket(ticket);  
            return;        }  
        audience.getBag().minusAmount(ticket.getFee());  
        ticketSeller.getTicketOffice().plusAmount(ticket.getFee());  
        audience.getBag().setTicket(ticket);  
    }  
}

위 코드에서 문제점은 Theater 클래스가 합성관계인 클래스들의 기능을 노출시키고 있다는 점이다.
그렇게 되면서 Theater는 자신의 필드가 아닌 인스턴스가 어떤 동작을하는지 알고 있어야하며 이는 해당 인스턴스의 동작이 바뀌면 Theater의 구현도 바뀌어야하는 것을 뜻한다. 이를 의존성이라고하며 의존성이 생길수록 특정 클래스를 변경할 때 사이드 이펙트를 고려해야하는 상황이 많이 발생하게된다.

우리는 사람이 달리는 과정을 다음처럼 묘사할 수 있다.
사람이 무릎을 빠르게 접었다가 편다.

무릎을 접었다가 펴는 것은 다음처럼 구체화할 수 있다.
무릎의 관절을 40도 접고 60도 다시 편다.

이 과정을 역순으로 하는 것이 추상화이며 사람이 달린다는 것으로 속에 있는 관절의 각도 등의 구체적인 정보에 대한 접근을 제한하여 캡슐화를 지킬 수 있다.

자기자신의 값을 참조할 수 있는 과정을 그룹화해서 책임으로 만들고 각 클래스에 메소드에 분리시킨 뒤 해당 메소드만 공개하여 사용하도록 하는 것이다.

	//Audience 클래스
   public Long buy(Ticket ticket){
       if(bag.hasInvitation()){
           bag.setTicket(ticket);
           return 0L;
       }
       bag.minusAmount(ticket.getFee());
       bag.setTicket(ticket);
       return ticket.getFee();
   }

Theater에 있던 audience의 기능을 참조하는 부분을 그룹화해서 Audience에 가져왔다.
이렇게해서 Theater는 audience의 공개된 buy메소드만 알고 있으면 되며 audience 클래스 역시 Theater에서 사용하기 위해 공개했던 베소드들의 접근 제한자를 private로 변경해 사용시 좀 더 추상화된 메소드명만 공개하는 과정을 통해 개발효율을 높일 수 있다.

	//Bag 클래스
    public Long hold(Ticket ticket){
        if(hasInvitation()){
            setTicket(ticket);
            return 0L;
        }
        minusAmount(ticket.getFee());
        setTicket(ticket);
        return ticket.getFee();
    }

이후 해당 메소드에서 bag의 메소드를 참조하는 과정도 묶어서 Bag 클래스에 할당함으로써
이렇게 리팩토링 함으로써 외부 클래스에서 어떤 클래스를 사용할 때 공개된 메소드에 해당하는 역할만 알고있으면 쉽게 사용할 수 있는 상황이 형성된다.

만약 절차지향이었다면 해당 과정을 함수화하더라도 주체가되는 인스턴스(구조체가 될 것이다)를 인자로 넘겨야하는 상황이 되지만 각 책임을 클래스에 분리하면 인자로 넘겨야하는 개수가 줄고 메소드 내부에서 어떤 클래스의 값만을 사용하는지 예측할 수 있다.
그렇게해서 해당 메소드가 어떤 값을 실제적으로 사용하는지 예상할 수 있으며 이것이 책에서 처음 Theater에서 짠 코드가 예측한대로 동작하지 않는다고 한 이유라고 생각된다.
왜냐면 함수의 인자로 audience의 인스턴스만 넘어가는데 내부에서는 티켓도 조작하고 가방도 조작하니 말이다.

profile
공부중

1개의 댓글

comment-user-thumbnail
2022년 12월 10일

잘 읽었습니다

답글 달기