엄범


객체 지향

객체지향 패러다임을 사용할 때, 개발 대상을 물리적 또는 추상적 대상에 비유하는 것이 도움이 된다.

유즈케이스 다이어그램을 그린다거나, 시나리오를 분석하여 클래스를 추출하는 작업을 진행하는 등.


객체 지향의 장점

  • 캡슐화, Encapsulation
    • 크게 2가지로 나눠볼 수 있음. 로직+데이터 묶음 / 정보 은닉
    • 정보 은닉이란, public으로 공개할 API들만 공개하고, 실제 로직은 비공개로 처리하여 구현과 API를 깔끔히 분리.
    • 서로의 내부 구현에 연연하지 않기 때문에 의존성이 내려간다.
  • 추상화, Abstraction
    • layer 개념을 통해서 체계적으로 구조화 할 수 있음. (절차지향도 추상화가 가능은 한데... 캡슐화/상속과 맞물려서 추상화가 더 용이하지 객체지향에서는....)
  • 상속, Inheritance
    • 실세계의 계층 관계 표현, 코드 재사용성, 유지보수성, 코드를 DRY하게.
  • 다형성, Polymorphism
    • 한 마디로 "상위 타입 변수에 하위 타입을 담을 수 있는 것"을 의미. 
    • 동물원에넣다(사자 x),  동물원에넣다(고양이 x)처럼 써야 했던 것을 동물원에넣다(동물 x)와 같이 쓸 수 있게 되니 일단 코드가 DRY해지고, 인터페이스를 이용해 결합도를 낮추거나 하는게 가능해진다.

객체 지향 5대 원칙

SOLID
  • SRP 단일 책임의 원칙
  • OCP 개방 폐쇄의 원칙
  • LSP 리스코프 치환의 원칙
    • 다형성을 나타내는 말인데, 상속해서 하위 타입이면 상위 타입 변수로 치환될 수 있다. 뭐 이런 의미라고 보면 된다.
  • ISP 인터페이스 분리 원칙
  • DIP 의존성 역전 원칙
*** 근데 이런 학문적인 정의보단... 직접 체감하는게 중요할 것 같다.


응집도 ( 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

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``)


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

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


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


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

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


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