2 분 소요

💡 객체 지향 프로그래밍 입문 시리즈

인프런의 객채 지향 프로그래밍 입문을 기반으로 작성한 게시물 입니다.
(본 시리즈의 모든 예시는 JavaScript(TypeScript)로 변환하여 작성하였습니다.)
객체 지향 프로그래밍 입문_1
객체 지향 프로그래밍 입문_2
객체 지향 프로그래밍 입문_3
객체 지향 프로그래밍 입문_4
객체 지향 프로그래밍 입문_5
객체 지향 프로그래밍 입문_6
객체 지향 프로그래밍 입문_7


“캡슐화 = 데이터 + 관련 기능 묶기 “

캡슐화란?

단순하게 말하자면 데이터와 데이터가 관련되어 있는 기능들을 묶는 것이다.

이렇게 캡슐화를 하는 목적은 객체가 기능을 어떻게 구현했는지 (예를들어 데이터의 타입, 파라미터 등등) 외부에 감추는 것이다. 이를 통해 외부의 영향 없이 객체 내부 구현 변경이 가능하게 된다.

캡슐화가 되지 않은 코드 예제

// acc = account 일반 사용자(regular)면서 만료되지 않은 사용자인 경우
if (acc.getMembership() === REGULAR && acc.getExpDate().isAfter(now())) {
    ... 정회원 가능
}

// -> 이벤트 형식으로 5년 이상 사용자에게 일부 기능 정회원 혜택 1개월 무상 제공

if (
    acc.getMembership() === REGULAR && 
    (
        (acc.getMembership().isAfter(fiveYearAgo) && acc.getExpDate().isAfter(now())) ||
        (acc.getMembership().isBefore(fiveYearAgo) && addMonth(acc.getExpDate()).isAfter(now()))
    );
) {
    ... 정회원 기능
};

위의 코드에 미루어 보아 캡슐화가 되지 않은 코드는 요구사항의 변화가 많은 코드의 수정을 야기하게 된다는 것을 알 수 있다.

위의 코드를 캡슐화 한 예제

if(acc.hasRegularPermission()) {
    ... 정회원 기능
}

public class Account {
    private _membership: Membership;
    private _expDate: Date;

    public hasRegularPermission(): boolean {
        return (membership === REGULAR) && (expDate.isAfter(now()));
    }
}

->

public class Account {
    private _membership: Membership;
    private _expDate: Date;

    public hasRegularPermission(): boolean {
        return (membership === REGULAR) &&
                (expDate.isAfter(now()) ||
                    (
                        serviceDate.isBefore(fivYearAgo()) && 
                        addMonth(expDate).isAfter(now())
                    )
                );
    };
};

캡슐화의 장점

위 코드에서 살펴보았듯 캡슐화가 잘 되있는 경우에는 캡슐화된 기능을 사용하는 코드의 영향을 최소화 할 수 있다는 장점이 있다.

뿐만 아니라 캡슐화를 시도함으로써 기능(기획 의도)에 대한 이해를 높일 수 있다. 이러한 지속적인 고민들은 더욱 좋은 코드 작성으로 이루어 질 수 있다.

캡슐화를 위한 규칙

1. Tell, Don’t Ask

데이터를 달라고 하지 말고 해달라고 해라

// 잘못된 예
// account가 멤버쉽을 달라고 하는 코드
if(acc.getMembership() === REFULAR) {
    ...
}
    
// 올바른 예
// account가 정회원 기능을 부여해 달라고 한다.
if(acc.hasRegularPermission()) {
    ...
}

2. Demeter’s Law(데미테르 or 디미터 법칙)

Demeter’s Law
- 메서드에서 생성한 객체의 메서드만 호출
- 파라미터로 받는객체의 메서드만 호출
- 필드로 참조하는 객체의 메서드만 호출

즉, 파라미터나 리턴값의 메소드를 연속 호출하지 말라는 뜻이다.

이러한 법칙이 생겨난 이유는 객체는 다른 객체가 어떠한 자료를 갖고 있는지 속사정을 몰라야 하기 때문이다.

예를 들어

acc.getExpDate().isAfter(now())

위와 같이 코드를 작성하면, Account 객체가 Date 객체를 가지고 있고 Date 객체는 시간 비교 기능을 가지고 있다는 것을 유추할 수 있게 된다.

이를 기능별로 구분하여

acc.isExpired()
acc.isValide(now())

와 같이 single dot 규칙(dont use multiple dots)을 지켜야 한다.

댓글남기기