GYUD-TECH

[스터디: 객체지향의 사실과 오해] 역할 중심 설계와 캡슐화 본문

스터디

[스터디: 객체지향의 사실과 오해] 역할 중심 설계와 캡슐화

GYUD 2024. 1. 23. 00:49

 

이전에 한번 읽은 책이지만, 스터디를 시작하면서 스터디원들과 다시 읽어보았다.

자바와 스프링을 공부한 후에 다시 읽어보니, 책의 내용이 SOLID원칙이나 캡슐화와 연결된다는 느낌을 받을 수 있었다.

또한 스터디원들과 관련된 자료도 공유하면서 더 많은 내용을 학습할 수 있었다.

앞으로 매주 스터디 이후에, 스스로 공부한 내용과 스터디에서 공유한 내용들을 공부하고 정리할 계획이다.

 

https://strong-lace-c81.notion.site/14d230239a6a4e7d8ae7e0ee3ea781a6

 

객사오 북 스터디 | Notion

✅ 스터디 일지 (2024/01/15 ~ )

strong-lace-c81.notion.site

 


1. 협력하는 객체들의 공동체

1장에서는 객체의 협력, 역할, 책임을 생각하여 설계해야하는 것을 강조한다.

커피 주문이라는 과정을 실세계에 비교하여 아래의 객체지향적 특징을 소개한다.

1. 기능을 수행하기 위해서 여러 역할이 협력한다.
  - 커피 구매를 위해서 손님, 캐시어, 바리스타의 역할이 협력한다.

2. 객체들은 협력관계 내에서 특정 역할을 수행한다.
  - A 객체는 손님, B 객체는 캐시어, C 객체는 바리스타의 역할을 수행했다.

3. 역할을 수행하는 객체는 바뀔 수 있다.
  - 바리스타 역할을 수행하던 C가 퇴근시간이 되면, D로 바뀔 수 있다.

4. 객체들은 역할에 맞는 책임을 수행한다.
  - C와 D는 바리스타 역할에 맞게 커피를 제조하는 책임을 수행한다.

5. 객체는 자신의 역할에 맞는 책임을 수행하기만 하면 되고 상대 객체가 누구인지 알 필요가 없다.
  - 바리스타역할을 하는 객체가 C이건, D이건 간에, B는 똑같이 커피 제조를 지시하는 캐시어의 역할만 수행하면 된다.

6. 책임을 수행하기만 하면 수행 방식은 상관없다.
  - C와 D가 커피를 만드는 방식이 다를테지만 커피 제조라는 책임을 수행하는데는 문제가 없다.

프로젝트에 대입

책에서는 이해를 위해서 실세계에 빗대어 표현해 주었지만 나는 반대로 수행했던 프로젝트를 대입하여 생각해 보았다.

해피에이징 프로젝트 에서는 스프링 서버를 구축하고 mariaDB에 데이터를 저장했다.

1. 데이터 저장이라는 기능을 수행하기 위해서는 데이터를 전달하는 역할과, 데이터를 저장하는 역할이 협력한다.

2. spring 서버는 서버의 역할을, mariaDB는 저장소의 역할을 수행한다.

3. 데이터를 메모리에 저장하고 싶다면 저장소의 역할을 메모리 객체로 바꿀 수 있다.

4. spring 서버는 저장소에 데이터를 전달하는 책임을 수행한다.
    mariDB는 데이터를 저장하는 책임을 수행한다.

5. 스프링 서버는 저장소가 mariaDB 객체인지, memory 객체인지 알 필요가 없다.

6. 저장소 역할을 수행하는 객체는 데이터를 저장하는 책임을 수행하기만 하면 memory에 저장하는지, 데이터베이스에 저장하는지는 상관없다.

 

이렇게 프로그램을 만들면 변경에 용이하고 재사용성이 좋은 프로그램을 만들 수 있다.

 

이때 6번과 7번 내용은 SOLID 원칙의 DIP 의존관계역전원칙과 내용이 비슷하다는 것을 느낄 수 있었다.
그래서 자바의 인터페이스를 활용해서 위의 내용을 어떻게 구현할 수 있을지 고민하였다.

자바로 구현

데이터 저장을 위해서는 서버 역할저장소 역할이 협력한다.

저장소 역할을 수행하기 위해 repository라는 인터페이스를 생성한다.

mariaDB와 memory 클래스는 repository를 상속받아서 데이터베이스에 데이터를 저장하는 역할을 수행한다.

데이터를 메모리에 저장하고 싶다면 repository의 구현체를 바꾸어 주기만 하면 된다.

서버 역할의 레포지토리 server는 repository만을 의존하고 그 구현체는 의존하지 않는다.

 

이렇게 정적인 객체(클래스)를 중심의 설계가 아닌 동적인 역할(인터페이스) 중심의 설계를 통해서 보다 프로그램을 유연하게 만들 수 있다.

 


2. 이상한 나라의 객체

캡슐화

2장은 객체의 캡슐화를 알기 쉽게 설명해주고 있었다.

그 중 객체의 상태는 행동에 의해서 변경될 수 있으며, 외부에서 객체의 상태를 직접 바꿀 수 없다는 것이 가장 인상깊었다.

이 내용을 읽으면서 우아한테크코스 프리코스에서 setter의 사용을 지양하라 했던 것이 생각났다.

setter는 외부에서 객체의 상태를 직접 바꾸는 것이기 때문에 캡슐화의 원칙에 어긋나고 두 객체간 의존도를 높이는 문제가 있다.

setter의 지양도 결국 객체를 객체답게 사용하기 위한 방법 중 하나라고 느꼈다.


동일성 vs 동등성

객체의 구성요소로 식별자에 대해서 소개하는데, 이 내용을 보고 스터디에서 동일성과 동등성애 대한 이야기를 나누었다.

동일성은 두 객체가 완전히 같은지 비교하는 것이고, 동등성은 두 객체의 상태가 같은지 비교하는 것이다.

 

equals

객체는 primitive type이 아닌 reference type이기 때문에 동등 비교를 위해서 equals 메서드를 사용해야 한다.

 

하지만 이때 모든 객체의 조상인 Object 클래스의 equals 메서드를 살펴보면 동일 비교를 수행하는 것을 알 수 있다.

따라서 동등 비교를 위해서는 equals 메서드를 재정의하여 원하는 상태값으로 비교를 수행하도록 해주어야 한다.

 

 

hashCode

Collection에서의 동등성 비교를 위해서 equals() 와 같이 재정의해줘야 하는 메서드 이다.

 

Hash Table을 이용하는자료구조에서는 값을 중복된 값을 저장하지 않기 위해서 아래 과정으로 동등성 비교를 수행한다.

hashCode() 메서드를 실행하여 리턴되는 값이 같은지 판단한다.
hashCode의 값이 같다면 equals로 동등성 비교를 수행한다.

 

따라서 완전히 동등한 비교를 위해서는 equals 뿐 만 아니라 hashCode() 메서드도 재정의해야만 컬렉션 프레임워크에서 같은 값으로 인식할 수 있다.

@Override
public int hashCode(){
	return Object.hash(value1, value2); // 해시코드를 생성할 값을 넣어준다.
}

이렇게 함으로써 객체의 동등 비교를 개발자의 목적에 맞게 사용할 수 있다.

 


마무리

이전에 읽은 책이였지만 다시 읽으니 최근에 공부했던 내용과 연관지어 책을 읽을 수 있어서 더 잘 읽혔다. 
또 스터디를 통해서 같은 내용이지만 다른 분들이 느꼈던 점과 공부했던것을 공유하면서 더 많은 내용을 학습할 수 있는 것 같다. 
앞으로 매주 2번씩 스터디에 참여하여 많은 책을 읽고, 좋은 내용을 함께 공유하고 싶다.

 

참고자료

https://creampuffy.tistory.com/140

 

동일성(Identity) vs 동등성(Equality) - feat. equals() hashCode()

우아한테크코스 1주차 과정 중, 객체의 동일성과 동등성이라는 키워드를 접하게 되어 관련하여 학습한 뒤 포스팅하게 되었습니다. 📱📱 동일성과 동등성 자바에서 객체를 비교할 땐, 동일성

creampuffy.tistory.com

https://jiwondev.tistory.com/113

 

.equals와 .hashCode()는 항상 함께 오버라이딩해야한다.

Object 메서드에 있는 .hashCode() 메서드는 해당 객체의 주소값을 이용하여 만든 객체만의 고유한 정수 값을 가진다. equals()를 오버라이딩 할 때에는 반드시 hashCode()도 동일한 결과를 내도록 함께 오

jiwondev.tistory.com