2025/02/28 ch.05 객체지향 설계
객체 개념을 설계에 적용하는 법
절차형 사고방식
프로시저는 프로그램이 하는 일을 중심으로 만든 개념
프로그램이 하는 일을 정리해보면 자연스레 절차적으로 표현됨
절차형 접근 방식은 일정한 단계에 따라 진행하는 프로그램에 적합하지만 최신 대규모 어플리케이션에서는 여러 이벤트가 일정한 순서 없이 발생함. 사용자는 언제든지 원하는 명령을 수행할 수 있어야 함
객체지향은 모델링하려는 현실 세계의 대상 이라는 관점에서 접근
객체지향 프로그래밍 (OOP Object - Oriented Programming)
물리적인 대상을 클래스, 컴포넌트, 속성, 동작의 관점에서 분석
클래스
어떤 대상의 유형을 정의하는 속성을 정리한 것
ex) 오렌지는 나무에서 자라고 주황색을 띄고 독특한 향과 맛을 내는 과일의 한 종류 입니다
어떤 특정한 오렌지를 가리킬 때는 구체적인 대상(객체) 를 의미함
ex) 내가 들고 있는 오렌지는 오렌지 클래스에 속한 객체임
객체는 어떤 클래스에 속하는 구체적인 예(인스턴스) 라고 볼 수 있다
같은 클래스에 속한 객체끼리도 나름 구분되는 특징이 있음
5.2.2 컴포넌트
작은 부품
OOP에서는 각체를 작은 컴포넌트로 나누는 사고방식이 굉장히 중요함
5.2.3 속성
객체는 속성으로 구분함
ex) 오렌지의 주황색, 맛 등등이 속성. 오렌지를 구성하는 속성의 종류는 같지만 그 값은 다름. 내 오렌지는 달지만 저 오렌지는 실수도 있음
속성은 객체의 특성을 표현함. 속성으로 객체끼리 구분할 수 있음
5.2.4
동작
객체가 직접 하거나 그 객체로할 수 있는 일을 표현
동작도 클래스 관점, 객체 관점으로 구분됨
클래스의 동작은 메서드로 구현한다.
5.3 클래스 세상에 살기
소프트웨어를 클래스 관점으로 개발하는 데 적용할 수 있는 접근 방식은 크게 두가지 있다
1. 클래스를 단순히 데이터와 기능을 잘 묶어주는 수단으로만 여기고 프로그램 전반에 걸쳐 사용해서 가독성과 유지 보수성을 높이는 것
2. OOP 패러다임을 완벽히 적용해서 처음부터 모든 것을 클래스로 표현하는 것
두가지를 적절히 조합
5.3.1 과도한 클래스화
OOP 시스템을 창의적으로 설계하는 것과 사소한 것까지 클래스로 만들어 팀원들을 불편하게 만드는 것은 다르다
변수는 변수일 뿐. 하나하나 전부 클래스로 정의하지 않아도 된다
정답은 없다
클래스는 어디까지나 프로그래머가 코드를 관리하는 데 도움을 주기위한 것
구체적인 이유 없이 폼난다는 이유만으로 클래스를 사용하는것은 바람직하지 않음
5.3.2 지나치게 일반화한 클래스
클래스를 유연하고 재활용하기 좋게 만들고 싶은 의도로 작성한것이 오히려 혼란만 가중시킬 수 있음
클래스가 너무 많은 기능을 포함하고 광범위한 데이터를 다루어 지나치게 일반화되면
이 클래스가 정확히 무슨 기능을 하는지 한눈에 알 수 없
5.4 클래스 관계
has-a 관계 (집계 관계, 포함 관계, 소유 관계)
A는 B를 가진다, A에 B가 있다고 표현되는 클래스 관계
동물원과 - 원숭이
두가지 유형이 있음
1. 집계 - 집계된 객체는 집계를 수행한 대상이 제거되더라도 남아있음. 동물원이 없어져도 원숭이는 남는다
2. 합성 - 여러 객체로 구성된 객체가 제거되면 포함된 객체도 함께 사라짐. 알림창이 사라지면 내부의 버튼도 함께 제거됨
is-a관계 (상속)
OOP의 핵심 개념
파생, 서브 클래싱, 확장, 상속 등으로 다향하게 표현함
클래스가 현실세계까 여러가지 속성과 동작을 가진 객체로 구성된다는 근거를 두고 모델링하는 것이고,
상속은 이러한 객체가 주로 계층 구조를 형성한다는 관점에서 모델링하는 것.
A는 일종의 B다. A는 B를 상당히 많이 닮았다
원숭이 기린 얼룩말... <- 전부 일종의 동물이라는 관계가 형성됨
공통기능을 베이스 클래스로 묶어서 다른 클래스가 확장할 수 있게 만들어야 한다.
여러 클래스의 코드가 상당 부분 겹치거나 완전히 똑같다면 그 부분을 상위 클래스로 묶어서 빼내는게 좋음
그 부분에서 변경사항이 발생하면 상위 클래스만 고쳐도 다른 하위클래스에도 똑같이 반영될것임
상속 기법
다른 클래스를 상속한 파생 클래스를 부모 클래스와 구분하는 방법들이 있다. A는 일종의 B로서..
기능 추가
파생 클래스는 기능을 더 추가해서 부모 클래스를 확장할 수 있다
기능 변경
파생 클래스는 부모 클래스가 가진 메서드를 변경하거나 무시(오버라이드)할 수 있다
베이스 클래스를 추상 클래스로 정의하면 이를 상속하는 모든 파생 클래스는 베이스 클래스에 구현되지 않은 메서드를 모두 구현해야 한다. 추상 베이스 클래스에 대한 인스턴스는 생성할 수 없다.
속성 추가
베이스 클래스를 상속한 파생 클래스는 새로운 속성을 추가할 수도 있다
속성 변경
속성도 오버라이드 할 수 있다. 베이스 클래스의 속성을 가리기 때문에 바람직하지 않을때가 많음
베이스 클래스는 특정한 이름의 속성에 어떤 값을 가지고 있는 상태에서 파생 클래스가 그 속성과 같은 이름을 정의해서 다른 값을 표현할 수 있다. - 은닉 메커니즘
다형성 (폴리모피즘)
일정한 속성과 메서드를 표준으로 정해두면 그 형식에 맞는 객체라면 어느 것이든 서로 바꿔서 적용할 수 있다는 개념
하위 클래스는 상위 클래스에 정의된 속성과 메서드를 모두 제공해야 한다
5.4.3
현실에서는 객체에 대한 has-a is-a 관계를 쉽게 구분할 수 있지만 프로그램에서는 분명하지 않을때가 많다
5.4.4 not - a 관계
두 클래스 관계중 어느 것이 적합한지 따지기 전에 먼저 그런 관계가 성립할 수 있는지부터 살핀다
불필요한 플래스 및 파생 클래스 관계를 쏟아내지 않도록 주의
억지로 관계를 형성하지 말고 기능 관점에서 관계를 표현해야 함
5.4.5 클래스 계층
파생클래스에서 여러가지 공통점이 생기면 부모 클래스로 옮기는게 좋다
파생클래스는 또 다른 클래스의 부모클래스가 될 수 있으므로 파생클래스들중 일부가 공통점을 가지고 있다면 그 클래스들을 묶는 부모클래스를 하나 더 만들어 A<-B<-C 구조의 중간 부모 클래스를 만들어주는편이 좋다
5.4.6 다중상속
다중상속이 꼭 필요할 떄가 있긴 하지만 단점이 많기 때문에 사용에 각별히 주의해야 함
- 도식화 했을때 시각적으로 표현하기 어렵다
- 구조의 명확성이 깨질 수 있다
- 구현하기 힘들다
5.4.7 믹스인 클래스
다중 상속과 같지만 의미는 전혀 다름
이 클래스가 할 수 있는 일이 ~도 있다
is-a 관계를 완전히 구현하지 않고도 기능을 추가할 때 사용. 공유 관계
사용자 인터페이스 코드에서 흔히 볼 수 있다
의미가 잘 반영된 객체관계는 이해하기도 쉽고 유지보수하기도 편하다