상태와 프로퍼티

객체 :

            프로퍼티

                         (

                               속성[객체를 구성하는 단순한 값],링크[객체와 객체사이의 의미있는 연결]

                          )

                        [객체의 상태를 구성하는 모든 특징]+행동


객체는 자신의 상태를 책임져야 한다. 간접적으로 객체의 상태를 변경하거나 조회하려면 행동(메서드)이 필요하다.

 

상태와 행동

객체가 취하는 행동은 객체 자신의 상태를 변경시킨다.

객체의 행동은 상태에 영향을 받는다

객체의 행동은 상태를 변경시킨다.

협력과 행동

객체의 행동은 객체가 협력에 참여할 수 있는 유일한 방법이다.

객체는 다른 객체와 메시지를 통해서만 의사소통을 할 수 있다.

객체가 어떤 행동을 하게 만드는것은 객체가 외부로부터 수신한 메시지다.

객체는 수신된 메시지에 따라 행동하면서 협력에 참여하고 그 결과로 자신의 상태를 변경한다.

객체의 행동은 부수효과를 명확하게 서술해야 한다.

  • 객체자신의 상태 변경
  • 행동 내에서 협력하는 다른 객체에 대한 메시지 전송

행동 : 외부의 요청 또는 수신된 메시지에 응답하기 위해 동작하고 반응하는 활동

행동의 결과로 객체는 자신의 상태를 변경하거나 다른 객체에게 메시지를 전달 할 수 있다.

객체는 행동을 통해 다른 객체와의 협력에 참여하므로 행동은 외부에 가시적이어야 한다

상태 캡슐화

모든 객체는 자신의 상태를 스스로 관리하는 자율적인 존재다.

객체가 외부에 노출하는것은 행동뿐이며, 외부에서 객체에 접근할 수 있는 방법 또한 행동뿐이다.

객체의 행동을 유발하는 것은 외부의 메시지지만, 객체의 상태를 변경할지 여부는 객체 스스로 결정한다.

캡슐화는 객체의 자율성을 높인다.

상태를 잘 정의된 행동 집합 뒤로 캡슐화하는것은 객체의 자율성을 높이고 협력을 단순하고 유연하게 만든다.

 

→ 컴퓨터 본체의 전원은 전원 스위치라는 캡슐화된 메서드로 동작한다. 내부의 어떤회로가 어떻게 전류를 타는지 사용자는 알 필요없이 스위치만 누르면 된다. 컴퓨터 본체를 바꾼다고 해도, 스위치만 누르면 전원을 킬 수 있다.

우리가 가지는 컴퓨터 본체에 대한 고정관념은 어쩌면 객체지향 세상의 인터페이스와 같은 것같다.

크기는 직사각형, 전원버튼은 상단부, 후면에는 연결포트들. 우리는 이런 본체에 대한 고정관념이 있기 때문에 쉽게 다른 본체를 접하더라도 어렵지 않게 작동시킬수 있다.

 

인터페이스는 캡슐화를 구현하기 위한 도구이다.

식별자

식별자 : 식별 가능한 경계를 가진 모든 사물

식별자 : 객체가 식별 가능하다 - 구별 할 수 있는 프로퍼티가 객체 안에 존재한다.

모든 객체는 식별자를 가진다 ↔ 값은 식별자가 없다.

값은 불변 상태를 가진다. 두개의 값이 같은 값이라면 동일한 것으로 간주한다.

객체는 시간에 따라 변경되는 상태를 포함하며, 행동을 통해 상태를 변경한다. 객체는 가변상태를 가진다. - 타입이 같은 두 객체의 상태가 동일하더라도, 두 객체는 구별되는 존재다.

동등성 : 상태를 이용해 두 값이 같은지 판단할 수 있는 성질

동일성 : 식별자를 기반으로 객체가 같은지를 판단할 수있는 성질

엔티티 : 식별자를 지닌 전통적인 의미의 객체

값 객체 : 식별자를 가지지 않는 값을 가리킴

기계로서의 객체

쿼리 : 객체의 상태를 조회하는 작업

명령 : 객체의 상태를 변경하는 작업

쿼리와 명령은 객체가 외부에 제공하는 행동이다.

명령과 쿼리 외에는 객체를 조작할 수 없다.

→ 즉 객체에 접근할 수있는 방법은 객체가 제공하는 행동뿐이다.

 

행동이 상태를 결정한다.

초보자 → 객체에 필요한 상태를 결정하고, 상태에 필요한 행동을 결정한다.

상태를 먼저 결정하고 행동을 나중에 결정하는 방법의 단점

  1. 캡슐화가 저해된다.
  2. 객체를 협력자가 아닌 고립된 섬으로 만든다. (객체가 필요한 이유는 애플리케이션의 문맥 내에서 다른 객체와 협력하기 위함이다)
  3. 객체의 재사용성이 저하된다.

상태가 아니라 행동에 초점을 맞춰라

객체의 적합성을 결정하는것은 상태가 아니라 객체의 행동이다

 

은유와 객체

현실세계의 객체와 프로그래밍 세계의 객체는 같아보이지만 큰 차이점이 있다.

내가 현실에서 책의 페이지를 넘긴다면, '내'가 '책'의 페이지를 넘기는것이지만,

프로그래밍에서는 '내'가 책을 넘기는 행동을하면, '책'이 스스로 페이지를 넘기는 것이다.

하지만 은유를 통해 대상을 추상화 한다는 공통점도 있다.

 

 

 

객체란 상태(필드)와 행위(메서드)를 하나의 단위로 묶는 자율적인 존재라고 한다.

객체의 자율성은 객체가 다른 객체들과 명확히 구분되는것(캡슐화)으로부터 시작되고,

객체 지향의 핵심은 ‘클래스(설계도)’가 아닌 ‘객체(Object)’라고 한다. 또한 중요한것은 메시지를 주고받는 객체들의 동적인 관계 라고 한다. 그러므로 저자는 클래스의 구조와 메서드가 아니라, 역할, 책임, 협력에 집중하라고 한다.

 

또한, 객체는 두가지 덕목을 지녀야 한다고 한다.

  1. 객체는 ‘협력적’ 이어야 한다.
  2. 객체는 ‘자율적’ 이어야 한다.

 

  • ‘객체는 협력적이어야 한다’ 는 말은 어느정도 희미하게나마 이해가 되는것 같았다. 객체지향 설계원칙에서는 모든 객체는 하나의 책임만을 져야 하기 때문에(단일 책임 원칙), 하나의 책임을 가지고 다른 객체들과 협력하여 하나의 결과물을 만든다.

 

  • 하지만 ‘객체는 자율적이어야 한다’는 말은 이해가 잘 가지 않았다.

    "자율적이라고? 객체가 스스로 행동하고 결정해야한다는 말이야? 이게 무슨 말이지? 프로그래밍의 객체는 사람도, 하물며 인공지능도 아닌데, 어떻게 스스로 행동한다는거야? "

    ‘자율적’ 이라는 단어를 스스로의 행동을 결정(메서드)하고, 책임을 진다(단일 책임 원칙)는 의미에서 본다면, 객체는 메서드를 통해 스스로 동작하고 책임을 지는 존재, 즉 자율적인 존재여야 한다는 의미로 보여진다.

 

 

 

 

 

 

 


 

이를 기반으로 했을때, 현재 작업중인 Member 클래스의 필드를 보면 단일 책임원칙을 어기고 있다.

회원의 개인정보, 구독, 체육관 정보 등을 한번에 담고 있기 때문이다.

 @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String email;
    private String password;
    private String name;
    @Lob
    private String profileImage;
    private LocalDate birthdate;
    private String phoneNumber;
    private String address;
    @Enumerated(EnumType.STRING)
    private Gender gender;
    private Long height;
    private Long weight;
    //
    private String occupation;
    private String note;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "gym_id")
    private Gym gym;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "schedule_id")
    private Schedule schedule;
    private Role role = Role.MEMBER;
    //체육관 등록일
    private LocalDate gymJoinDate;
    //결제일
    private LocalDate subscribeDate;
    //만료일
    private LocalDate endSubscribeDate;
    //결제여부
    private boolean isSubscribed;

 

읽은 내용을 토대로 다시 재구성한다면 이런식으로 재구성할 수 있다.

 

  @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    @Embedded
    private PersonalInformation personalInformation;
    @Embedded
    private BodyProfile bodyProfile;
    @Embedded
    private GymInformation gymInformation;
    @Embedded
    private SubscribeInformation subscribeInformation;
    private String note;
    private Role role = Role.MEMBER;

그런데 의문이 생겼다. 객체란, 행동과 상태를 하나의 단위로 묶는것이라고 했는데, gymInformation 과 subcribeInformation은 각각 메서드(행위)와 필드(상태)를 가지고 있기 때문에 객체라고 부를 수 있다고 볼 수 있다.

 

그렇다면 필드와 생성자만을 가지고 있는 personalInformation, bodyProfile 은 객체인가? 객체가 아닌가?

-> '생성자 메서드'도 '메서드' 이기 때문에 객체이다.

 

이전까지는 참 많은 필드들을 그냥 한 클레스에 담아 넣었다.

잘 모르기도 했던것도 있고, 구현하기에 급급했던것도 있다. 이제와서 클레스들을  객체지향적으로 수정하자니, 프로젝트를 구현조차 제대로 되지 않은 상황에서  더 시간을 쓰는것은 아닌가 고민된다.

 

현재 내가 가진 고민은 다음과 같다.

  1. 객체지향적으로 엔티티를 수정하면서 생기는 시간비용을 감수하면서까지 진행하는게 맞을까,
    아니면 구현이 우선일까?
  2. 객체를 생성할때마다 메모리를 사용한다고 알고있는데, 그렇다면 어떻게 메모리를 효율적으로 사용할수있을까?

 

'하루 한장 > 객체지향의 사실과 오해' 카테고리의 다른 글

02 이상한 나라의 객체  (0) 2023.06.28

+ Recent posts