📕 캡슐화
- 데이터와 함수를 쉽고 효과적으로 캡슐화하는 방법을 객체지향 언어가 제공한다.
- 데이터와 함수가 응집력 있게 구성된 집단을 서로 구분 짓는 선을 그을 수 있다.
- 구분선 바깥에서 데이터는 은닉되고, 일부 함수만이 외부에 노출된다. (private 멤버, public 멤버)
OO 프로그래밍은 프로그래머가 충분히 올바르게 행동함으로써 캡슐화된 데이터를 우회해서 사용하지 않을 것이라는 믿음을 기반으로 한다. 실제로 많은 OO 언어가 캡슐화를 강제하지 않는다.
📗 상속
- 어떤 변수와 함수를 하나의 유효 범위로 묶어서 재정의하는 일이다.
- OO 고안 이전에도 사용했지만 다중 상속 구현에는 어려움이 있었다.
- OO 언어가 완전히 새로운 개념을 만들지는 못했지만, 편의성을 높였다.
📙 다형성
- OO 언어 이전에도 다형성은 표현 가능했다.
- 함수를 가리키는 포인터를 응용
- ex) C언어에서 포인터가 가리키는 함수 호출 하는 방식
- OO 언어는 다형성을 새롭게 만들어 제공하진 않지만, 다형성을 좀 더 안전하고 더욱 편리하게 사용할 수 있게 해준다.
- 포인터를 안전하게 사용하려면 관례를 따라야 하는데 객체지향 언어는 이러한 관례를 없애줌으로써, 실수할 위험이 없다.
- OO 언어는 제어흐름을 간접적으로 전환하는 규칙을 부과한다.
📍 다형성이 가진 힘
앞서 봤던 복사 프로그램에서 새로운 입출력 장치가 생기더라도 수정할 필요가 없어진다.
복사 프로그램의 소스 코드는 입출력 드라이버의 소스코드에 의존하지 않기 때문이다.
입출력 드라이버가 복사 프로그램의 플러그인*이 되었기 때문이다.
* 플러그인 아키텍처는 독립성을 지원, OO의 등장으로 어디서든 플러그인 아키텍처 적용 가능
📍 의존성 역전
다형성을 적용하는 방법이 등장하기 전 소프트웨어 코드의 의존성 방향은 아래 그림처럼 제어흐름(flow of control)을 따랐다.
여기에 다형성을 추가하게 되면 아래 그림처럼 변하게 된다.
HL1 모듈은 ML1 모듈의 F() 함수를 호출한다. 소스 코드에서는 HL1 모듈은 인터페이스를 통해 F()함수를 호출한다.
하지만 ML1과 I 인터페이스 사이의 소스 코드 의존성(상속 관계)이 제어흐름과는 반대인 점을 주목하자. 이를 의존성 역전(dependency inversion)이라고 한다.
이러한 접근법을 사용한다면, 객체지향 언어로 개발된 시스템을 다루는 소프트웨어 아키텍트는 시스템의 소스 코드 의존성 전부에 대해 방향을 결정할 수 있는 절대적인 권한을 갖는다.
의존성 역전을 통해 위의 그림처럼 UI와 데이터베이스가 업무 규칙의 플러그인이 되게끔 할 수 있다.
- 배포 독립성 : 업무 규칙을 UI와 데이터베이스와는 독립적으로 배포할 수 있다.
- 개발 독립성 : 시스템의 모듈을 독립적으로 배포할 수 있게 되면, 서로 다른 팀에서 각 모듈을 독립적으로 개발할 수 있다.
📘 결론
OO란?
- 다형성을 이용하여 전체 시스템의 모든 소스 코드 의존성에 대한 절대적인 제어 권한을 획득할 수 있는 능력
- 아키텍트는 플러그인 아키텍처를 구성할 수 있다.
- 고수준의 정책을 포함하는 모듈은 저수준의 세부사항을 포함하는 모듈에 대해 독립성을 보장할 수 있다.
- 저수준의 세부사항은 중요도가 낮은 플러그인 모듈로 만들 수 있고, 고수준의 정책을 포함하는 모듈과는 독립적으로 개발하고 배포할 수 있다.
📚 Reference
- Clean Architecture : 소프트웨어 구조와 설계의 원칙