Object
절차지향
- 프로세스와 데이터를 별도의 모듈에 위치시키는 방식을 절차적 프로그래밍이라고 부른다.(26p)
- 모든 처리가 하나의 클래스 안에 위치하고 나머지 클래스는 단지 데이터 역할만 수행한다.(26p)
- 절차적 프로그래밍의 세상에서 데이터의 변경은로 인한 영향을 지역적으로 고립시키기 어렵다.(26p)
- 모든 처리가 하나의 클래스에 위치하기 때문에 여러 데이터 클래스 중 하나만 변경되더 라고 변경이 처리 클래스의 변경을 부른다.(26p)
- 변경하기 쉬운 설계는 한 번에 하나의 클래스만 변경할 수 있는 설계다.
객체지향 프로그래밍
- 보통 객체지향 프로그래밍을 작성할 때 가장 먼저 고려하는 것은 어떤 클래스가 필요한지 고민한다.(40p)
- 하지만 진정한 객체지향은 클래스가 아닌 객체에 초점을 맞출 때 얻을 수 있다.
- 즉 어떤 클래스가 필요한지가 아니라 어떤 객체가 필요한지 고민하라.
역할, 책임, 협력
협력
- 객체지향 시스템은 자율적인 객체들의 공동체다.
메시지 전송
은 객체 사이의 협력을 위해 사용할 수 있는 유일한 커뮤니케이션 수단이다.(49p)- 메시지를 수신한 객체는 스스로의 결정에 따라
메서드
를 실행해 요청에 응답한다. - 수신된 메시지를 처리하기 위한 자신만의 방법을
메서드
라고 부른다.
- 메시지를 수신한 객체는 스스로의 결정에 따라
- 객체를 자율적으로 만드는 가장 기본적인 방법은 내부 구현을
캡슐화
하는 것이다.- 캡슐화를 통해 변경에 대한 파급효과를 제한할 수 있다.
자율적인 객체는 자신에게 할당된 책임을 수행하는 중에 필요한 정보를 알지 못하거나 외부의 도움이 필요한 경우 적절한 객체에게 메시지를 전송해서 협력을 요청한다.
책임
- 책임이란 객체에 의해 정의되는 응집도 있는 행위의 집합이다.
- 즉 객체의 책임은
무엇을 알고 있는가
와무엇을 할 수 있는가
로 구성된다.
무엇을 알고 있는가
- 사적인 정보에 관해 아는 것
- 관련된 객체에 관해 아는 것
- 자신이 유도하거나 계산할 수 있는 것에 관해 아는 것
무엇을 할 수 있는가
- 객체를 생성하거나 계산을 수행하는 등의 스스로 하는 것
- 다른 객체의 행동을 시작시키는 것
- 다른 객체의 활동을 제어하고 조절하는 것
역할
- 객체가 어떤 특정한 협력 안에서 수행하는
책임의 집합을 역할
이라고 부른다. - 역할을 구현하는 가장 일반적인 방법은
추상 클래스
와인터페이스
를 사용하는 것이다. - 협력 관점에서 추상 클래스와 인터페이스는 구체 클래스들이 따라야하는 책임의 집합을 서술한 것이다.
응집도와 결합도
- 응집도와 결합도는 변경과 깊은 관련이 있다.
- 어떤 설계를 쉽게 변경할 수 있다다는 것은 높은 응집도와 낮은 결합도를 가지고 있다는 뜻이다.
- 높은 응집도와 낮은 결합도를 얻기 위해서는
캡슐화
가 핵심이다.- 객체는 자신이 어떤 데이터를 가지고 있는지 내부에 캡슐화하고 외부에 공개해서는 안된다.
- 속성의 가시성을
private
으로 설정했다고 해도 접근자와 수정자를 통해 속성을 외부로 공개하면 캡슐화를 위반한 것이다.
응집도
- 응집도는 변경이 발생할 때 모듈 내부에서 발생하는 변견의 정도로 측정할 수 있다.
- 하나의 변경을 수용하기 위해 모듈 전체가 변경되면 응집도가 높은 것
- 하나의 변경을 수용하기 위해 다수의 모듈이 함께 변경돼야 한다면 응집도가 낮은 것이다.
응집도의 높고 낮음
- 클래스가 하나 이상의 이유로 변경돼야 한다면 응집도가 낮은 것이다. 변경의 이유를 기준으로 클래스를 분리한다.
- 응집도가 높은 클래스는 인스턴스를 생성할 때 모든 속성을 함께 초기화 한다.
- 모든 메서드가 모든 인스턴스 변수를 사용한다면 응집도가 높다고 볼 수 있다.
- 153p
결합도
- 한 모듈이 변경되기 위해서 다른 모듈의 변경을 요구하는 정도로 측정할 수 있다.
결합도의 높고 낮음
- 한 객체가 다른 객체에 대해 알고 있는 정보(지식)의 양으로 결합도가 결정된다.
- 객체 A가 다른 객체 B의 접근자 메서드를 사용하고 있다면 결합도가 높을 수 있다.
- 객체는 자율적인 존재여야 한다.
- A 객체가 수행하고 있는 책임을 데이터를 저장하고 있는 객체 B에게 넘겨주면 결합도를 낮출 수 있다.
의존성과 결합도
- 의존성은 두 요소 사이의 관계 유무를 설명한다.
- 의존성이 존재한다 또는 의존성이 존재하지 않는다.
- 결합도는 두 요소 사이에 존재하는 의존성의 정도를 상대적으로 표현한다.
- 결합도가 강하다 또는 결합도가 느슨하다.
추상화에 의존하라
- 추상화란 세부사항, 구조를 좀 더 명확하게 이해하기 위해 특정 절차나 물체를 의도적으로 생략하거나 감춤으로써 복잡도를 극복하는 방법이다.
- 따라서 대상에 대해 알아야하는 지식의 양을 줄여 결합도를 느슨하게 유지할 수 있다.
- 목록에서 아래쪽으로 갈수록 클라이언트가 알아야하는 지식의 양이 적어진다.
- 구체 클래스 의존성
- 추상 클래스 의존성
- 인터페이스 의존성
new의 위험성
- new를 잘못 사용하면 클래스 간의 결합도가 강해진다.
- new 연산자를 사용하기 위해서는 구체 클래스의 이름을 직접 기술해야 한다.
- 이는 추상화에 의존하는 것이 아닌 구체 클래스에 의존할 수밖에 없기 때문에 결합도가 강해진다.
- new 연산자를 사용하면 어떤 인자를 이용해 클래스의 생성자를 호출해야 하는지 알아야한다.
- 즉 클라이언트가 알아야하는 지식의 양이 늘어나기 때문에 결합도가 강해진다.
- 구체 클래스를 생성하기 위해 필요한 인자로 사용되는 구체 클래스와의 의존성도 만들어 진다.
- 해결법
- 인스턴스를 생성하는 로직과 생성된 인스턴스를 사용하는 로직을 분리한다.
- 의존성 해결 방법을 이용해 외부에서 인스턴스를 전달 받아 사용하고 직접 생성하지 않는다.
- new가 항상 위험한 것은 아니다.
- 문제는 객체 생성이 아니라 부적절한 곳에서 객체를 생성한다는 것이다.
- 유연하고 재사용 가능한 설계를 원한다면 객체에 대한 생성과 사용을 분리해야 한다.
- 클래스 안에서 객체의 인스턴스를 직접 생성하는 것이 유용한 경우도 있다.
- 협력하는 기본 객체를 설정하고 싶은 경우가 이 러한 경우에 해당된다.
- 설계는 트레이드오프 활동이다.
- 결합도와 사용성을 저울질한다.
의존성
- 의존성은 두 요소 사이의 관계 유무를 설명한다.
- 의존성이 존재한다 또는 의존성이 존재하지 않는다.
- 의존성이라는 말 속에는 어떤 객체가 변경될 때 그 객체에게 의존하는 다른 객체도 함께 변경될 수 있다는 사실이 내포돼 있다.(16p)
- 그렇다고 객체 사이의 의존성을 완전히 없애라는 것이 아니다.
- 객체지향 설계는 서로 의존하면서 협력하는 객체들의 공동체를 구축하는 것이다.
- 최소한의 의존성만 유지하고 불필요한 의존성을 제거하라는 의미
결합도와의 차이
- 결합도는 두 요소 사이에 존재하는 의존성의 정도를 상대적으로 표현한다.
- 결합도가 강하다 또는 결합도가 느슨하다.
명시적인 의존성
- 의존성 대상을 생성자의 인자로 전달받는 방법
- 퍼블릭 인터페이스에 의존성을 드러낸다.
- 의존성은 명시적으로 표현해야 한다.
- 그래야 퍼블릭 인터페이스를 통해 컴파일 타임 의존성을 적절한 런타임 의존성으로 교체할 수 있다.
숨겨진 의존성
- 의존성 대상을 생성자 내부에서 직접 생성하는 방법
- 퍼블릭 인터페이스에 의존성을 감춘다.
- 의존성을 파악하기 위해 내부 구현을 직접 살펴볼 수밖에 없다.
의인화
- 비록 현실에서는 수동적인 존재라고 하더라도 일단 객체지향 세계에 들어오면 모든 것이 능동적이고 자율적인 존재로 바뀐다.(33p)
- 레베카 워프스브록은 능동적이고 자율적인 존재로 소프트웨어 객체를 설계하는 원칙을
의인화
라고 부른다.(33p)
패턴
- 객체에게 책임을 할당할 때 해당 책임을 어떤 객체에게 할당하면 좋을까?
- 이런 경우 도움이 되는 패턴들을 알아보자.
정보 전문가 패턴
- INFORMATION EXPERT 패턴이란 객체에게 책임을 할당할 때 가장 기본이 되는 책임 할당 원칙이다.
- 책임을 수행하는데 필요한 정보를 가지고 있는 객체에게 책임을 할당하는 것이 정보 전문가 패턴이다.
- 여기서 정보라는 단어를 사용했는데 이는 데이터와는 다르다.
- 책임을 수행하는 객체가 정보를 알고 있다고해서 그 정보를 저장하고 있을 필요는 없다.
- 객체는 해당 정보를 제공할 수 있는 다른 객체를 알고 있거나 필요한 정보를 계산해서 제공할 수 있다.