[객체지향] 객체지향과 객체

Hyebin Lee·2022년 2월 25일
0

JAVA

목록 보기
1/6
post-thumbnail

객체 지향의 필요성과 소프트웨어의 가치

💡 메뉴 버튼을 클릭하면 해당 메뉴를 선택했을 때 필요한 기능을 수행하고 Button이라고 쓰여진 버튼 클릭 시 해당 버튼의 이름과 선택된 메뉴를 함께 출력하는 기능을 구현한다고 가정해봅시다.

메뉴 클릭 처리 코드는 메뉴 관련 기능을 수행하는데 반해, 버튼 클릭 처리 코드는 화면에 해당 내용을 출력하는 기능을 수행한다. 두 종류의 버튼 처리 코드는 목적이 다르며 서로 다른 이유로 변경이 된다.

이렇게 서로 다른 기능을 하는 코드가 한 메서드에 섞여있으면 향후에 유지보수를 하기 어려워진다.

👍 객체 지향 기법을 적용하면 소프트웨어를 더 쉽게 변경할 수 있는 유연함을 얻게 된다.

다시 말해서, 요구 사항의 변화를 더 빠르게 수용할 수 있다는 것을 뜻한다.

소프트웨어의 가치는 사용자가 요구하는 기능을 올바르게 제공 하는 데 있다. 그러나 요구 사항은 언제나 변한다. 따라서 소프트웨어는 변화할 수 있어야한다. 그리고 이렇게 변화 가능한 유연한 구조를 만들어주는 핵심 기법 중의 하나가 바로 객체 지향이다.


절차 지향과 객체 지향

  • 절차 지향: 데이터를 조작하는 코드를 별도로 분리해서 함수나 프로시저와 같은 형태로 만들고 각 프로시저들이 데이터를 조작하는 방식으로 코드를 작성하는 방식 😧한 데이터를 사용하는 프로시저가 많아질수록 그 데이터의 타입을 변경하기 어려워진다.
    프로그램의 규모가 커질수록 같은 데이터를 서로 다른 의미로 사용하는 경우가 발생할 가능성이 높다. 여기서의 문제는 여러 프로시저가 하나의 데이터에 접근한다는 점이다.
  • 객체 지향: 객체는 프로시저를 실행하는데 필요한 만큼의 데이터를 갖는다. 따라서 객체는 **자신만의 데이터와 프로시저**를 갖는다. 이 때, 프로시저는 자신이 속한 객체의 데이터에만 접근할 수 있으며 다른 객체에 속한 데이터에는 접근할 수 없다. 😎 객체 지향적으로 만든 코드에서는 객체의 데이터를 변경하더라도 해당 객체로만 변화가 집중되고 다른 객체에는 영향을 주지 않기 때문에 요구사항의 변화가 발생했을 때 절차 지향 방식보다 프로그램을 더 쉽게 변경할 수 있는 장점이 있다.

객체

⭐객체의 핵심은 기능을 제공하는 것

객체를 정의할 때 사용되는 것은 객체가 제공할 기능이며 객체가 내부적으로 어떤 데이터를 갖고 있는 지로 정의되지 않는다.

  • 오퍼레이션: 객체가 제공하는 기능 오퍼레이션은 크게 기능 식별 이름, 파라미터 및 파라미터 타입, 기능 실행 결과 값으로 구성된다.
    오퍼레이션 이름파라미터결과
    increaseVolume()없음없음
    decreaseVolume()없음없음
    getVolumeRate()없음0~1사이의 실수값
  • 인터페이스(interface): 객체가 제공하는 모든 오퍼레이션의 집합.
  • 타입(type): 다른 인터페이스를 구분할 때 사용되는 명칭

인터페이스는 객체가 제공하는 기능에 대한 명세서일 뿐, 실제 객체가 기능을 어떻게 구현하는지에 대한 내용은 포함하고 있지 않다.

  • 클래스: 실제 객체의 구현을 정의하는 것. 오퍼레이션을 구현하는데 필요한 데이터 및 오퍼레이션의 구현
  • 인스턴스: 메모리에 생성된 객체

객체의 책임(역할)의 크기는 작을 수록 좋다

객체마다 제공하는 기능을 객체의 책임이라고 하는데, 객체가 갖는 책임은 어떻게 결정될까? 이 결정을 하는 것이 바로 객체 지향 설계의 출발점이다. 이를 위해서는 프로그램을 만들기 위해 필요한 기능 목록 정리가 필요하다.

객체가 갖는 책임의 크기는 작아질수록 객체 지향의 장점인 변경의 유연함을 얻을 수 있다.

  • 단일 책임 원칙: 객체는 단 한 개의 책임만을 가져야 한다는 원칙

순환 의존이 되지 않도록 주의하기

한 객체가 다른 객체를 생성하거나 다른 객체의 메서드를 호출할 때, 이를 그 객체에 의존한다고 한다.
객체를 생성하거나 메서드를 호출하는 것뿐만 아니라 파라미터로 전달받는 경우에도 의존한다고 볼 수 있다.
의존이 순환해서 발생할 경우 순환 의존 변경의 여파가 나 자신에게 다시 영향을 줄 수 있기때문에 의존 역전 원칙을 따라야 한다.

캡슐화 💊

객체 지향의 장점은 한 곳의 구현 변경이 다른 곳에 변경을 가하지 않도록 해준다는 것에 있다.
즉 , 수정을 원활하게 해준다.

캡슐화는 객체가 내부적으로 기능을 어떻게 구현하는지를 감추는 것이다. 이를 통해 내부의 기능 구현이 변경되더라도 그 기능을 사용하는 코드는 영향을 받지 않도록 만들어준다.

😧 데이터를 직접적으로 사용하는 코드는 데이터의 변화에 직접적인 영향을 받기 때문에 요구 사항의 변화로 인해 데이터의 구조나 쓰임새가 변경되면 이로 인해 데이터를 사용하는 코드들도 연쇄적으로 수정해 주어야 한다.

캡슐화를 위한 두 개의 규칙

  • Tell, Don’t Ask : 데이터를 물어보지 않고 기능을 실행해 달라고 말하라는 규칙.
    데이터 대신에 기능을 실행해달라고 명령을 내리려면 직접 get 방식으로 데이터를 가져오는게 아니라 해당 데이터를 갖고 있는 객체에서 해당 데이터를 처리해야 하는 기능을 수행하도록 명령해야 한다.
  • 데미테르의 법칙: 특정 객체의 메서드가 연달아 두 번 이상 호출되지 않도록 한다.
    member.getDate().getTime() <- 데미테르 법칙 위반 
    • 메서드에서 생성한 객체의 메서드만 호출

    • 파라미터로 받은 객체의 메서드만 호출

    • 필드로 참조하는 객체의 메서드만 호출

      😧 데미테르의 법칙을 지키지 않는 전형적인 증상 두 가지가 있는데, 연속된 get 메서드를 호출하거나 임시 변수의 get 호출이 많은 것이다.

흐름 제어 기능 주의하기

💡 원본 파일의 데이터를 읽어 와서 암호화 한 뒤에 새로운 파일에 결과를 저장하는 기능의 소프트웨어를 구현한다고 가정해봅시다.

제공해야 할 기능은 크게 [데이터 읽기, 암호화, 데이터 쓰기] 세 가지이다.

그런데 각 기능의 흐름을 잘 파악해보면 결국 암호화 기능에서는 데이터를 읽어서 암호화하고 데이터를 쓰는 흐름 제어 역할까지 하고 있게 된다.

이러한 흐름 제어 기능이 한 클래스에 다른 책임과 섞여있으면 객체 지향적인 설계가 아니므로 이 경우 흐름 제어 객체를 꼭 따로 빼서 관리해야 한다.

그렇게 되면 흐름 제어 객체가 각 파일 읽기, 암호화, 파일 쓰기 객체의 흐름을 관리하는 기능을 단독으로 하게 된다.

0개의 댓글