객체 지향

객체지향 패러다임을 사용할 때, 객체를 만드는 1순위 원칙은 책임이다.

객체를 물리적 또는 추상적 대상에 비유하는 것이 도움이 된다. (Domain Model에 한해서)

 

  • Alan Kay : OOP to me means only
    • messaging,
    • local retention and protection and hiding of state-process,  (상태 변경 프로세스의 로컬 바운더리 유지, 보호, 숨김. 더 많은 영역에서 상태를 변경 할 수록, 어디서 변경했나 추적하기 어렵고, 이는 예상과 다른 변수값을 유발하며, 버그를 생산한다.)
    • and extreme late-binding of all things.
  • https://velog.io/@eddy_song/alan-kay-OOP  
  • http://wiki.c2.com/?AlanKayOnMessaging  
    • The key in making great and growable systems is much more to design how its modules communicate rather than what their internal properties and behaviors should be.
    • 객체의 내부 구현 보다는 주고 받는 메시지(그 객체가 외부에 공개하는 API)가 중요하다. 정도로 이해할 수 있을 듯.
      • 내부 기능은 캡슐화로 숨기게 되니까, 거시적인 관점에서 신경쓸 내용은 아니다.
      • Domain Model 설계 시 [책임 > 객체 > 메시지 > 메서드 > 상태] 순으로 설계하라는 얘기도, 메시지를 먼저 생각하고 이 것이 메서드와 상태로 이어지는 설계이므로 통하는 얘기라고 생각한다.

 

객체 지향의 장점

  • 캡슐화, Encapsulation
    • 크게 2가지로 나눠볼 수 있음. 로직+데이터 묶음 / 정보 은닉
    • 정보 은닉이란,
      • 1. 외부에 공개할 API들만 public으로 공개하고, 몰라도 되는 API는 private(또는 다른 접근지정자) 사용하여 비공개처리 하는 것을 의미
      • 2. Data Encapsulation의 의미 (Getter, Setter)
    • 객체 내부에서 로직을 method 단위로 쪼개어 구조화 할 수 있으면서, 의도하지 않은 API가 외부에 공개되어 오남용 되는 것을 막아준다.
  • 추상화, Abstraction
    • 실제 구현이 아니라 추상화된 인터페이스를 참조하여 의존성 감소. (구현이 어떻게 되어 있는지는 사용하는 쪽의 관심사가 아니다)
  • 상속, Inheritance
    • 실세계의 계층 관계 표현, 코드 재사용성, 유지보수성, 코드를 DRY하게.
  • 다형성, Polymorphism
    • 한 마디로 "상위 타입 변수에 하위 타입을 담을 수 있는 것"을 의미. 
    • 동물원에넣다(사자 x),  동물원에넣다(고양이 x)처럼 써야 했던 것을 동물원에넣다(동물 x)와 같이 쓸 수 있게 되니 일단 코드가 DRY해지고, 인터페이스를 이용해 결합도를 낮추는 것이 가능함.
 

객체 지향 5대 원칙 : SOLID

객체 지향 5대 원칙 : SOLID

 

응집도 ( Cohension ) 와 결합도 ( Coupling )

  • 응집도 (Cohension)
    • 하나의 모듈(클래스) 내의 구성 요소들 사이의 기능적 관련성
    • 즉 한 모듈이 쓸데없는 기능 없이 목표하는 기능만 가지고 있는지.
    • 높을 수록 좋다.
  • 결합도 (Coupling) = 의존성 (dependency)
    • 어떤 모듈과 다른 모듈 간의 의존성 (dependency)을 의미
    • 낮을 수록 좋다. 디커플링 해야 한다고 자주 얘기 나오지.
    • 모듈을 독립적으로 짜야 수정할 때 영향이 적다. 독립적으로 짠다는건, 다른 모듈과의 의존성을 최대한 없앤다는걸 의미한다.
 
```
기능적 응집 / 순차적 응집 / 교환적 응집 / 절차적 응집 / 시간적 응집 / 논리적 응집 / 우연적 응집
```
앞쪽으로 갈 수록 응집도가 크다. 

 

 

Relationship

두 클래스 사이에 다양한 Relationship이 동시에 존재 할 수 있음.

 

 

Extends : A is B

우리가 다 아는 상속. 화살표 머리가 부모 방향. Impl도 마찬가지.
 

 

Aggregation : A has B (약한 연관)

  • 전체와 부분의 연관 관계를 맺지만, 동일한 생명 주기를 갖지는 않는다.
    • Person과 House. Person이 사라진다고 건물을 부실 필요는 없으니까
    • A가 B를 소유하기는 하지만, B 자체로 독립적으로 존재할 수 있음
  • 예제?
    • Person과 Address
    • Professor와 Student
  • 소유 주체에 마름모
UML aggregation
 
DDD에서는 소유 주체를 Aggregate Root, 속하는 대상을 Aggregates 라고 명칭.
An aggregate is a group of entities that is guaranteed to be consistent between atomic changes to it.
Each aggregate has exactly one aggregate root, which is one of the entities of the aggregate. The aggregate gets manipulated only through methods on that aggregate root. These are the atomic changes mentioned earlier.

 

Composition : A has B (강한 연관)

  • 전체와 부분이 강한 연관 관계를 맺으며, 같은 생명 주기를 가진다.
    • 즉 A가 삭제되면 B도 삭제 되는 경우
    • 보통 B가 A 내부가 아닌 다른 곳에서는 어떤 의미도 갖지 못하는 경우
  • 예제?
    • Car와 Engine
  • 소유 주체에 마름모
 

UML composition

 

 

Dependency

  • 의존성이란건 그냥 A에서 B를 사용하면 의존성이 존재하는 것
  • A에서 B를 사용하기 때문에 B에 변경이 발생하면 A를 수정해야 할 수도 있음.
  • A가 B에 대한 의존성을 가지고 있다. 라는 의미에서 화살표 방향은 `` A --> B``
  • IntelliJ 에서는 대체로 이 arrow로 처리하며, 아래 텍스트를 덧붙여서 구분하면 좋음.

메서드 내 변수로 생성하거나`` <<create>>``

메서드 파라미터로 받거나`` <<param>>``

그냥 `` <<use>>``로 처리하는 경우도 있음.

 

Association

subscribe, observe 등 기타 다양한 형태의 연관을 이걸로 처리 (화살표는 상황에 따라 양쪽 다 없는걸로 써도 됨)
밑에 텍스트 설명을 덧붙이는 식으로 쓰면 깔끔함. (ex, `` subscribe``)

 

동적 디스패치 / 정적 디스패치

  • 동적 디스패치
    • 객체의 동적 타입에 따라 적절한 메소드를 호출해 주는 방식
    • 즉, 실제로 할당된 객체에 연결된 메소드를 호출해준다.
  • 정적 디스패치
    • 컴파일 시점에 어떤 메소드가 호출될지를 결정
    • 즉, 컴파일 타임에 결정된 객체의 타입에 연결된 메소드를 호출해준다.

 

  • 자바에서는 구현클래스를 참조하게 되면 정적 디스패치한다. (바이트코드에 어떤 클래스의 어떤 메서드를 호출하겠다. 라는 것이 드러난다.)
  • 반면 인터페이스를 참조하게 되면 동적 디스패치한다. 런타임에 어느 메서드를 부를지 결정한다는 것.

 

대부분의 객체지향 언어에서 같은 클래스에 속한 객체는 같은 메소드 테이블을 공유한다.

그래서 메소드 테이블은 클래스마다 하나씩만 만들어 두고, 각 객체는 자신의 클래스에 대한 참조를 통해 그 메소드 테이블을 참조하는 방식을 많이 사용한다.

 

그러나 동적 디스패치를 처리할 때는 대체로 객체별로 자신의 메소드에 대한 테이블을 저장하는 방법을 사용한다.