[인프런 워밍업 스터디] Readable Code - 추상과 구체
인프런 ‘Readable Code: 읽기 좋은 코드를 작성하는 사고법’을 수강한 후, 작성한 내용입니다.
코드를 잘 짠다는 것은?
개발자라면 코드를 잘 짜기 위해 노력한다. ‘코드를 잘 짠다’라는 것은 무엇일까?
코드를 잘 짠다는 것은 이해하기 쉬운 코드, 즉 ‘읽기 좋은 코드’라는 것에 동의하지 않는 사람은 없을 것이다.
내가 짠 코드를 읽는 대상은 결국 나와 동료이다. 미래의 나와 동료를 위해 매 순간 읽기 좋은 코드를 작성하려고 노력해보자.
클린 코드와 리팩토링의 가장 좋은 예시는 테스트 코드 생성 사이클로 볼 수 있다.
리팩토링 대상/범위 확인
기능 보장을 위한 테스트 코드
리팩토링 & 테스트 코드로 검증
클린 코드를 추구하는 이유
그런데 클린 코드를 추구하는 이유는 뭘까?
코드가 잘 읽힌다 ⇒ 이해가 잘 된다 ⇒ 유지보수하기 수월하다 ⇒ 시간과 자원이 절약된다!
즉, 클린 코드는 우리의 시간과 자원을 절약해준다.
클린 코드, 그리고 추상과 구체
추상은 클린 코드를 관통하는 주제이다. 그렇다면 추상이란 뭘까?
추상 : 중요한 정보는 가려내어 남기고, 덜 중요한 정보는 생략하여 버린다.
추상의 반대편은 구체라고 볼 수 있다. 하나의 예시를 들어보자.
질문
A랑 주말에 뭐 했어?
답변
답변 1 : 식당에 예약해서 갔다왔어.
답변 2 : 케치테이블을 통해 가고자 하는 식당에 들어가서 가고자하는 날짜와 시간을 선택하고 그때 식당에 들어가서 밥을 먹고왔어.
답변 1과 답변 2는 같은 의미를 나타낸다. 그런데 표현은 다르다. 답변 2는 구체적인 사실이고 답변 1은 추상화된 문장이라고 할 수 있다.
구체에서 추상으로 갈수록 정보는 함축되어 제거되고, 추상에서 구체로 갈수록 생략된 정보를 유추하고 재현한다.
이를 개발자답게 컴퓨터 과학에 적용해보자.
int는 4 byte이고, char는 1 byte이다. 같은 byte로 이루어지지만, 데이터를 어떻게 읽는지에 따라 달라진다. 즉, 데이터 개념에도 추상화가 존재하는 것이다!
잠깐 프로그램의 정의에 대해 생각해보자. 프로그램은 다음과 같이 말할 수 있다.
프로그램 = 데이터 + 코드
위의 예시를 통해 데이터 개념에 추상화가 존재함을 알 수 있었다. 당연히 코드
에도 추상화가 존재한다. 또한 데이터 + 코드
에도 추상화가 존재한다.
흔히 고수준/저수준 언어 라는 용어를 들어봤을 것이다. 고수준과 저수준이 나뉘는 이유는 추상화에 대한 수준을 나타내기 때문이다. 잊고 있을 수 있지만, 컴퓨터는 0과 1밖에 모른다!
적절한 추상화는 복잡한 데이터와 복잡한 로직을 단순화하여 이해하기 쉽게 한다!
만약 어느 도시에서 예약을 선택이라고 한다고 가정해보자. 그렇다면 답변 1은 다음과 같이 바뀔 것이다.
식당을 선택해서 갔다왔어.
이 말을 들으면 무슨 말인가 싶다. 말을 통해 유추하거나 재현하기 쉽지 않다. 단순히 말이 안된다고 생각할 수 있지만 이유에 대해 따져보자.
추상화 과정에서 중요한 정보를 남기지 않았다.
식당을 방문 날짜를 미리 정하는 예약이 아니라, 단순히 선택했다는 정보만 남김
상대적으로 덜 중요한 정보를 남기고 중요한 정보를 삭제
해석자가 동일하게 공유하는 Context가 없다.
중요한 정보의 기준이나 도메인 영역 별 추상화 기준은 다를 수 있음
해당 도시에 살았으면 이해 가능
잘못된 추상화가 야기하는 사이드 이펙트는 상당히 크다!
적절한 추상화란 해당 도메인의 문맥 안에서 정말 중요한 핵심 개념만 남겨서 표현하는 것이다.
이름 짓기
이름을 짓는다는 행위는, 추상적 사고를 기반으로 한다.
단수와 복수 구분하기
이름 줄이지 않기
은어/방언 사용하지 않기
좋은 코드를 보고 습득하기
좋은 이름을 짓기 위해 노력하자!
메서드 추상화
메서드 이름으로 구체적인 내용을 추상화할 수 있어야 한다.
서점에서 책을 샀다.
서점에 가서 책을 고른다. 책을 계산대에 가져가 직원에게 건네주고 책 가격 금액을 전달하고 책을 얻었다.
잘 쓰여진 코드라면, 한 메서드의 주제는 반드시 하나다!
그런데 내용이 다음과 같다고 해보자.
서점에서 책을 샀다.
돈을 인출하고 가는길에 아이스크림을 사먹고, 책을 구매했다.
추상화된 내용을 보고 구체적인 내용의 유추가 어렵다. 의미를 담을 수 있는 더 작은 단위로 쪼개야 한다.
현금 인출
아이스크림 사먹기
서점에서 책 구입하기
메서드 작성
메서드 선언부
반환타입
메서드명
파라미터
메서드명
추상화된 구체를 유추할 수 있는, 적절한 의미가 담긴 이름
파라미터와 연결지어 더 풍부한 의미를 전달할 수도 있다.
파라미터
파라미터의 타입, 개수, 순서를 통해 의미를 전달
파라미터는 외부 세계와 소통하는 창
어떤 재료가 필요한지 알려주는 역할이다. 외부 세계한테 필요한 재료를 요구한다.
반환타입
메서드 시그니처에 납득이 가는, 적절한 타입의 반환값 돌려주기
반환 타입이 boolean인데, 이게 이 메서드에서 무엇을 의미하는거지?
void 대신 충분히 반환할 만한 값이 있는지 고민해보기
반환값이 있다면 테스트도 용이해진다.
코드의 줄 수가 많아서 추상화하는 것이 아니다! 같은 라인 수를 가지더라도 추상화할 수 있다.
추상화 레벨
메서드를 추출한다 ⇒ 외부 세계와 내부 세계를 나누고, 추상화 레벨이 나뉜다.
하나의 세계 안에서는, 추상화 레벨이 동등해야 한다!
게임 시작 멘트 출력
게임 초기화
게임 보드 보여주기
게임 상태가 1이면
게임 종료 메시지 출력
1, 2, 3, 4를 쭉 읽다보면 4에서 멈칫하게 된다. 게임 상태 = 1이라는 것의 의미에 대해서 의문이 생기게 된다. 즉, 읽는 사람이 해석을 하게 만든다. 따라서 동등한 추상화 레벨을 맞춰야 한다.
게임 시작 멘트 출력
게임 초기화
게임 보드 보여주기
게임을 이겼다면,
게임 종료 메시지 출력
전보다 훨씬 읽기 수월하다.
메서드로 추출한다는 것은 로직이 복잡하거나 의미를 부여할 수 있어서도 맞지만, 추상화 레벨을 동등하게 맞춤으로써 읽는 사람으로 하여금 자연스럽게 이해할 수 있게 한다.
매직 넘버, 매직 스트링
의미를 갖고 있으나, 상수로 추출되지 않은 숫자, 문자열 등
상수 추출로 이름을 짓고 의미를 부여함으로써 가독성, 유지보수성 증가
댓글을 작성해보세요.