객체지향의 사실과 오해 정리 - 1. 캡슐화

Kim Dong Kyun·2023년 8월 15일
post-thumbnail

개요

객체지향의 사실과 오해 라는 책을 읽으면서 이해한 것들을 내 말로 써보는 시리즈.

  • 잘못된 내용이나, 자의적인 해석이 있을 수 있습니다.

  • 이상한 부분 언제든지 피드백 주세요!


객체?

상태와 행위를 가지고, 다른 객체들과 메시지로 협력하는 녀석들

그렇다면 객체의 특징은?

  • 객체는 상태를 가지며 상태는 변경 가능하다.

  • 객체의 상태를 변경시키는 것은 객체의 행동이다.

  • 행동의 결과는 상태에 의존적이며 상태를 이용해 서술할 수 있다.

  • 행동의 순서가 실행 결과에 영향을 미친다.

  • 객체는 어떤 상태에 있더라도 유일하게 식별 가능하다.

상태?

Property : 상태를 가지는 녀석. 예를 들어 "사람" 이라는 객체의 키, 위치 등 동적인(즉, 할당가능한) 값을 가진다

Property Value : 상태를 가지는 녀석의 "현재" 상태. 값으로 표현 가능하다 (Ex 키 == 130)

행동?

객체가 스스로의 상태를 표현(조회) 하거나,(==Query) 상태를 변경시키는(==Command) 것.

예를 들어보자. 이상한 나라의 앨리스에서는 앨리스가 소인국으로 가기 위해 "음료" 를 마신다.

따라서 앨리스 객체의 행동은

  1. Command
  • 음료를 마신다
  • 문을 통과한다
  1. Query
  • 키가 몇인지 조회한다
  • 현재 위치가 어디인지 조회한다

등으로 나타낼 수 있고, 이는 객체 스스로가 외부와 소통하는 양식(행동)이다.

상태와 행동 중 어떤 걸 우선해야 할까?

행동을 우선하자. 왜냐?

1. 캡슐화가 저해된다.

  • 상태에 초점을 맞출 경우 상태가 객체 내부로 깔끔하게 캡슐화 되지 못하고 공용 인터페이스에 그대로 노출되어버릴 확률이 높아진다.

2. 객체를 고립되게 만든다. (협력자가 아닌)

  • 객체가 필요한 이유는 다른 객체와의 협력 때문이다. 상태를 먼저 고려하는 방식은 협력이라는 문맥에서 벗어난채로 객체를 설계하는 것이므로, 협력에 유리하지 못한 객체를 창조하게 된다

3. 객체의 재사용성이 저하된다

  • 재사용성은 객체가 협력에 얼마나 참여 할 수 있는가에 따라 달라진다.

코드로 써보자 한번!

아래는 객체 간의 메시지라는 측면과, 객체의 행동으로 상태를 바꾼다는 컨셉을 인지하고 의도적으로 작성한 코드이다.

1. Alice 만들기

public class Person {
    // 상태들
    private Integer height;

    private String location;

    public Person(Integer height, String location) {
        this.height = height;
        this.location = location;
    }
    
    // 행위
    public Integer getHeight() {
        return height;
    }

    public String getLocation() {
        return location;
    }

    public int drinkBeverage(Beverage beverage){
        this.height -= 20; // 임의상 20씩 작아진다고 가정
        return beverage.getQuantity() - 20; // 남은 양 알려줄게!

    }

    public void passByDoor(boolean isPassable){
        if (isPassable) {
            this.location = "새로운 어딘가";
        } else {
            System.out.println("이곳엔 들어갈 수 없다.");
        }
    }
}
  • Alice 라는 객체는 Person 이라는 청사진으로 만들어진 녀석일것이다.

  • 상태(height, Location)을 가진다.

  • 행위는, 상태를 보여주는(Query) 게터 매서드들과

  • 음료를 마시고, 마신 후의 음료 양을 음료에게 알리는 매서드

  • 문을 지나갈 수 있는지 문에게 전달받은 후, 지나가거나 / 못가는 매서드.


2. 문 만들기

public class Door {

    private Integer height;

    private boolean isOpen;

    public Door(Integer height) {
        this.height = height;
        this.isOpen = false; // 기본적으로 닫혀 있고, 키가 적절하면 열어주자
    }

    public boolean isPassable(Integer passengerHeight){
        return passengerHeight < height;
    }
}
  • 문은 기본적으로 닫혀있고, 문에게 물어봐서 "지나갈 만 하면" 열어주도록 했다.

3. 음료 만들기

public class Beverage {
    private Integer quantity;

    public Beverage(Integer quantity) {
        this.quantity = quantity;
    }

    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public void okSetQuantity(Integer drunken){
        this.quantity = drunken;
    }
}
  • 기본적으로 자신의 양(상태)를 가지고 있다.

  • 세터매서드를 통해서 상태를 변경 가능하다.(행위)

  • 예제에서는 앨리스가 말한 남은 음료의 양을 신뢰하는 것으로 하자.


테스트 코드

public static void main(String[] args) {
        // 앨리스, 도어, 음료 객체 생성
        Person alice = new Person(130, "처음 시작한 곳");
        Door door = new Door(100);
        Beverage beverage = new Beverage(200);

        // 앨리스의 키 확인
        int aliceHeight = alice.getHeight();
        System.out.println("앨리스의 키: " + aliceHeight);

        // 도어 판별
        boolean canPass = door.isPassable(aliceHeight);
        System.out.println("앨리스가 통과 가능한가? " + canPass);

        // 도어 통과 여부에 따라 처리
        alice.passByDoor(canPass);

        // 음료 마시며 키 조절
        System.out.println("음료의 처음 양: " + beverage.getQuantity());
        while (alice.getHeight() > 100) {
            int quantityOfDrunkenBeverage = alice.drinkBeverage(beverage);
            beverage.adjustQuantity(quantityOfDrunkenBeverage);
        }
        System.out.println("음료의 최종 양: " + beverage.getQuantity());
        System.out.println("앨리스의 최종 키: " + alice.getHeight());

        // 문 통과
        alice.passByDoor(door.isPassable(alice.getHeight()));

        // 결과 출력
        System.out.println("앨리스의 현재 위치: " + alice.getLocation());
    }


소감

도메인은 살찌우고, 서비스는 줄여야 한다는 말은 무엇일까 생각했다

  • 객체의 행동 을 관리해서 객체 스스로의 상태에 대해서 최대한 객체 스스로가 관리하게 하여

  • 외부 비즈니스 로직을 통해서 상태를 과도하게 비틀거나, 객체간의 결합도를 낮추라는 말이 아닐까 하는 생각을 하게 되었다.

0개의 댓글