(화)2024.10.01 자 끄적끄적....
팀 프로젝트에서 내 담당은 Battle기능을 구현하는 것이다. Text RPG에서의 Battle 구현은 선택지를 사용자가 입력하면, 그것에 해당하는 액션을 취하고 화면에 출력해주는 것의 반복이다.
Battle에서 Player와 Monster객체들을 사용해야 하다보니, 어느새 의존성이 매우 높아졌다. 처음 작성할 때는, 얽히고 설킨 코드들에 아무생각 없이 그냥 선택하고 넘어가는 Scene별로 메서드를 만들어 작성했으니, 완전 객체 잘 만들었잖아? 라는 생각을 하였었다.
하지만, 얼마전에 튜터님이 도움이 된다고 올려주신 한 블로그를 보고 깨달음을 얻었는데, 이 글을 읽고 나서 내 코드를 떠올리니 완전 의존성이 난무한, 객체라고도 부를 수 없는 스파게티 코드임을 깨달아 버렸다.(스파게티 맛있겠다)
아무튼, 이 블로그에는 getter를 쓰지말라고만 하는 선배들 때문에 힘들었던 주인공이, 왜 getter를 사용하지 말라고 했는지에 대한 이유를 혼자서 공부하여 작성한 내용이다.
뭐 이렇게만 보면 그래서 무슨 내용인데? 그런 물음이 나오겠지만, 다 보고나면 객체지향이 무엇인지 좀 구체적으로 알 수 있게 되는 아주아주 정말정말 매우매우 좋은 내용이라, 소개해 본다.
아주아주 유익하고 재미난 블로그:
getter 쓰지 말라고만 하고 가버리면 어떡해요 (╯‵□′)╯︵┻━┻
그리고, 긴 글을 읽기 불편한 분들을 위해, 나의 깨달음을 정말 간단하게 정리해 보았다. (근데 정말 재밌고, 유익한 글임. 재미도 있다는 게 중요하지 음음)
정리하면, 객체의 내부 데이터를 가지고 하는 행동을 객체 외부에서 구현하지 않고, 객체 내부에서 구현을 마쳐서 외부에선 그 메서드(나 프로퍼티의 get
set
)를 사용해서 객체끼리의 의존성을 낮춰야 한다.
객체 내부의 데이터를 은닉해서, 객체를 캡슐화하고, 객체끼리의 의존성을 낮춰서(없애서) 객체지향을 실현해야 한다.
프로퍼티의 get
set
을 사용하는 이유? 데이터를 가져오거나 설정할 때, 설정해줘야 하는 조건이 있을 수도 있다.
예를 들면, 출석부 객체의 필드에 List<string> name
으로 사람이름을 관리한다고 해보자. 여기에 사람 이름을 추가할 때, 한글이나 영어가 아닌 다른 문자(이름이 될 수 없는 문자)들이 들어오면 안되니 조건을 설정해야 할 것이다.
//ex 제약사항
if(빈문자열인가(name) || 한글또는영어가아닌가(name)) { /*에러*/ }
그런데 이것을 만약 출석부 객체 외부에서(객체에게 이름을 넘겨주는 다른 객체들에서) 조건을 설정해주게 된다면, 출석부 객체가 관리하는 출석부 List의 타입을 바꾸게 되었을 때, 출석부 객체와 소통하는 다른 모든 객체들의 조건을 바꿔줘야 된다.
(만약 List
가 아닌, Map
이라는 Dictionary
타입의 변수들을 관리하는 타입으로 바뀌었을 때, 관련된 모든 객체의 Type 조건을 수정해야 할 것이다.)
(객체에게 이름을 넘겨주는 객체가 100개만 넘어도 개발자 100명에게 각각 수정해달라고 요청해야 된다...ㄷㄷ..)
그런데 이것을 객체 내부에서 조건을 다뤄주게 되면, List
에서 Map
으로 바뀌었을 때, 객체의 내부에서 작성한 조건만 변경해주면 된다. (와......내 프로퍼티만 변경해주면 된다고?)
아무튼, 객체끼리의 의존성을 낮추는 설계를 하고, 꼭 객체의 내부의 값을 직접적으로 볼 필요가 있을 때(참조형 데이터를 가져올 때만/값형은 상관x) 읽기 전용 인터페이스를 이용해 읽거나(ex: IEnumerator<T>
), 불변타입으로 바꿔서 가져오거나(ex: ImmutableList
), 깊은 복사를 이용해 참조를 가져오지 말고 값을 가져오는 방식을 이용해 객체끼리의 의존성을 단절시키는 방법을 사용하는 게 좋다.
그러니까 get, set을 이용해서,
그 객체의 내부 데이터를 사용하는 행동을 밖에서 만들어서 의존성을 높이지 말고,
객체가 사용하는 행동을 객체의 내부에서 만들어서 밖에서 호출해서 쓰기만 해라.
그리고 오늘은 튜터님께 코드의 피드백을 받고 질문도 한 가지 해보았다.
코드에 대한 G튜터님의 피드백
1. 코드 컨벤션을 잘 지켜라
_을 써도 좋지만, 따로 내규가 정해진 게 없다면, 코드컨벤션을 지키는 게 좋다.
2. 주석을 최대한 지우고, 함수를 보면 역할을 알 수 있게 만들어라.
오류에 대한 질문에 L튜터님의 피드백
1. 자동완성에 익숙해지고 자주 써라.
오브젝트. 을 누르면 나오는 자동완성들을 잘 파악하고 쓸 수 있는 것도 능력이다.
->이걸 사용하면 코드를 잘못 입력하는 것도 줄일 수 있다.