객체 지향

realBro·2024년 3월 13일

객체지향 프로그래밍

  • 오늘은 오류 없이 작동 & 내일은 쉽게 변경가능한 코드를 만들자

객체지향 패러디임; 협력, 책임, 역할

  1. 객체도 사회적 동물
    • 객체는 독립적인 존재 X
    • 객체지향 세계에서는 공동체를 만들어 서로 상호작용하며 자신의 존재 여부를 증명(=객체 간의 상호작용을 통해서 Application의 필요한 작은 단위의 기능을 제공)
  2. 객체지향 세계에서 객체는 자아를 가지는 로봇이 됨
    • 객체지향 패러다임책상, 침대 등등..... -> 이것들을 다 능독적인 존재가 되는, 이불이 사람을 덮는다 가 가능해지는 느낌
  3. 객체지향 세계에서는 독점은 없다
    • Application간 목표를 달성하기 위한 기능을 쪼개서 적절한 객체에 분배하고 객체들 간의 적절한 협력을 만들어 주는 것이 목표
  • 3번이 가장 중요
  • 객체지향 스럽게 어플리케이션을 만드는 것은 작은 작은 기능, 책임을 가지고 있는 object들을 여러개 만들어서 다양하게 조합하여 다양한 기능을 만드는 것, 그렇게 설계 해 나가야됨

협력

  • Application의 주요 기능을 구현하기 위해서 작은 단위로 쪼개진 기능을 설명하는 한 줄 요약본
  • 협력은 객체간의 상호 작용을 통해서만 이루어짐
  • 객체 간의 상호 작용은 메세지를 통해서만 가능

책임

  • 협력에 참여하기 위해서 객체가 책임지고 있는 전체 기능 정의서

역할

  • 동일한 책임을 수행하는 객체의 집합체
  • 동일한 책임을 수행하는 객체가 여러 개 있을 경우, 협력을 개별적으로 만들지 않음

의존성

의존성(Dependency)란?

  • A객체가 B객체에게 "give me the money"라는 문맥을 가지는 메시지를 보냈을 때 B객체가 A객체가 보낸 메시지를 처리할 수 있다라는 사실을 알고 있는 지식(정보)를 의존성이라고 말한다.
  • 알고 있는 지식의 수준에 따라서 높은 의존성(강한 결합도), 낮은 의존성(느슨한 결합도)라고 표현하기도 한다.
  • B객체의 변경이 A객체에게 얼마만큼의 영향을 주는가

Coupling; 강한 결합도, 낮은 결합도

  • 의존성 관계가 높을 수록 강한 결합도라고 이야기하고 낮을 수록 느슨한 결합도라고 표현한다.
  • 결합도(Coupling)란, B객체에 변경이 발생하는 경우, B객체를 의존하고 있는 다른 객체들에게 전이 되는 정도의 수준을 표현한 것이라고 보면 된다.
  • 느슨한 결합도를 유지하기 위해서 아래와 같은 목표를 가져야 한다.
    • 올바른 의존성 주입
    • 변경을 방해하는 의존성을 제거

올바른 의존관계 형성

Constructor 함수를 통한 의존 관계 형성

  • 의존하는 객체의 전체적인 행동에 대해서 지속적으로 의존 객체에게 메시지를 보내야 하는 경우에 사용하는 것이 좋음
  • 왜 의존성을 Constructor함수를 통해 하는가?
    • 어느 객체에 의존할지 런타임에 결정되기 때문
    • 생성 후, 의존성에 대한 불변성 보장 및 코드 일관성 부분에서 장점이 있음

Parameter of Method를 통한 의존 관계 형성

  • 생성자 방식과 반대로, 메서드가 실행되는 동안에만 일시적으로 의존 관계를 맺어도 무방할 때 사용하는 것이 좋다.
  • 메서드가 실행될 때마다 의존 대상이 매번 달라져야 하는 경우에도 유용하다.
  • Setter 방식과의 차이점은 특정 함수(Setter) 호출해서 의존 관계를 맺는 것이 아니라, 단순히 인자로 전달한다는 점이 다르다

Setter 함수를 통한 의존 관계 형성

  • 의존하고 있는 대상을 변경할 수 있는 가능성을 열어두고 싶을 때 사용하면 좋음
  • 의존 관계를 맺지 않은 상태에서 의존 대상에게 메시지를 요청하게 되면 NPE(Null Point Exception)이 발생하여 Application 에 치명적인 오류를 일으켜 정상 동작을 못하게 할 수도 있기 때문에 설계 시, 이 부분을 주의 해야함

변경을 방해하는 의존성 관계

  • 변경에 따른 영향이 전파되는 범위가 너무 커서 변경을 할 수 없는 상황을 이야기한다. -> 레거시

변경을 방해하는 의존성 주입 방식

  • Constructor 함수에서 new 키워드를 사용하여 구현체를 직접 할당하는 방식은 올바르지 않다. (파라미터로 받는게 아닌)
  • 구현부에 숨겨저 있어 독자 입장에서 찾기 힘들 수도 있고, 구현체에 직접적으로 의존하는 것은 병경을 방해하는 시작점 이기 때문
  • 무조건 나쁜것? -> 100% 나쁜것은 없지만 표준 클래스 또는 Default로 할당이 필요한 경우는 생성자 체이닝을 이용해서 직접 할당하는 방식을 가끔 채택하는 것 또한 나쁘지 않다

응집도와 결합도

응집도란?

  • 클래스에 포함된 내부 요소(상태와 행동)가 하나의 책임(목적)과 연관된 정도와 책임을 수행하기 위해서 필요한 기능들이 하나의 연관 클래스에 잘 정의가 되어 있는지를 알려주는 척도이다.

응집도와 결합도는 비례 or 반비례 관계?

  • 응집도가 낮아지거나 높아진다고 하더라도 결합도에는 영향을 줄 수 없는 구조
  • 하나의 책임이 여러 개의 클래스들로 분산 되어 있고 분산된 클래스를 의존하는 객체들이 분산된 클래스의 내부 구현까지 알고 있다면 낮은 응집도와 높은 결합도를 가지는 구조가 될 것이다.
  • 하지만, 캡슐화를 통한 내부 구현을 숨기는 형태를 가진다면 아무리 많은 클래스가 해당 클래스를 의존한다고 하더라도 높은 응집도와 낮은 결합도를 가지고 있는 클래스라고 이야기할 수 있지 않을까?

상속

상속이란?

  • 부모 클래스(Super or 기반 클래스)가 가지고 있는 상태와 행동을 자식 클래스(Sub or 기반 클래스)가 물려 받아서 코드를 재사용할 수 있게 해주는 기법을 말한다.

상속을 사용하는 이유

  • 변경에서 가장 큰 악 중 하나인 "코드의 중복"을 제거하기 위함

상속; 재사용의 함정

  1. 캡슐화 규칙 위반
    • 상속은 단순히 부모 클래스의 행독만 상속 받는 것이 아니라, 상태까지 상속 받기 때문에 상속을 제대로 활용하기 위해서는 내부 구현을 알아야함
    • Public Interface에 의존하는 것이 아니라 코드에 의존하는 설계 구조 탄생
  2. 부모 클래스와 자식 클래스 간 강한 결합이 생김
    • 자식 클래스에서 호출하는 부모 클래스의 함수가 수정되거나 부모 클래스의 내부 구현이 변경되면 자식 클래스 또한 변경의 영향을 받아 자식클래스 또한 변경을 적용해야 하는 문제가 있다.
    • 자식 클래스가 메서드 오버라이딩 시, 부모 클래스의 인터페이스를 사용할 때 의도하지 않는 동작을 수반하여 예상치 못한 오류를 만날수도 있다.
      (ex. HashSet을 상속한 CustomeHashSet)
    • 객체지향 이론과 SOLID 규칙을 지키면서 코딩을 하는 이유는 "변경이 유연한 설계"를 하기 위함인데 상속은 이것을 무력하게 만드는 기법이다
  3. 변겨의 유연함과 규칙이 깨진다
    • 상속 관계는 컴파일 타임에 결정된다, 그런데 객체지향이 추구하는 방향성은 작은 기능들을 조합해 유연하게 문맥을 완성 시키는 것인데, 상속 관계의 경우는 컴파일 시점에 결정되기 때문에 런타임 시점에 문맥의 변경이 어렵다(OCP 위반)
    • 의도 하지 않은 기능을 부모 클래스에게 상속 받아 자식 클래스의 기능 설계(or 규칙)와 다르게 동작할 가능성이 생긴다(불필요한 기능 상속)

상속을 사용 해도 될때

  • 개념적으로 명확한 is -a 관계에 있는 경우, 상위 클래스가 확장할 목적으로 설계되었고 상속에 대한 설계도가 문서화 및 최신화 되어 있다면 괜찮음

합성

상속과 다른 점은?

상속
  • 기반이 되는 클래스(Car)를 중심으로 변경이 필요한 부분들만 코드를 재사용(오버라이딩)하여 파생 클래스(Diesel Car, Gasoline Car)를 만들어 내는 구조
  • 상속 관계는 컴파일 시점에 결정된다.
합성
  • 기반 클래스에 필요한 기능을 제공하는 외부 객체를 런타임 시점에 적절하게 선택하여 주입하는 구조를 가진다.
  • 합성 관계는 런타임 시점에 결정된다. 그래서 합성은 작은 기능들을 조합해서 다양한 기능을 만들어낼 수 있다.(OCP, DIP)

참고

https://i-am-your-father.notion.site/java-OOP-477254766b5440059732a48d0fba2780

0개의 댓글