본문 바로가기
독서

[책리뷰] 읽기 좋은 코드가 좋은 코드다

by 도쿄정대리! 2022. 8. 18.

이전 직장에서 서브 리더에게 추천받은 책 '읽기 좋은 코드가 좋은 코드다'를 읽었습니다. 모든 전공서적들이 대게 잘 읽히지 않게 되는데요. 다른 전공서적에 비해서는 쉽게 읽히는 책이며 공감을 하게 되는 책입니다. 간단한 책 내용과 평가를 정리해 보도록 하겠습니다.

 

읽기 좋은 코드가 좋은 코드다 책 표지
간단하면서 공감되는 핵심을 이야기하는 책

 

책 내용 요약

한사람이 컴퓨터로 작업한뒤 2주뒤에 본인이 작성한 것을 알아보지 못하고 있는것을 그린 만화
한번쯤 공감이 될만하다

책 내용은 제목의 내용과 동일합니다. 잘 읽고 이해하기 쉬운 코드가 좋은 코드라는 내용을 반복해서 전달하고 있으며, 이을 위해서 작은 수준에서는 변수명과 함수명 그리고 코드의 줄과 열 정리에 대해서 이야기하고 있으며, 크게는 코드를 재작성하는(리팩토링) 방법에 이르기까지 설명하고 있습니다. 단순하게 이론적으로만 이야기하는 것이 아닌, 실제 코드 예시를 들어서 설명하고 있기 때문에 이해하기에 더욱 쉽고 읽기도 편합니다.

 

코드 예제는 대부분 쉬운 예제를 사용하여 파이썬, c++, java, javascript 등 언어로 적혀 있으나, 해당 언어를 잘 모르더라도 이해에 별 무리가 없도록 만들어져 있습니다.

 

책의 목차는 총 14장으로 이루어져 있으며 그 내용은 아래와 같습니다.

1장 코드는 이해하기 쉬워야 한다

2장 이름에 정보 담기

3장 오해할 수 없는 이름들

4장 미학

5장 주석에 담아야 하는 대상

6장 명확하고 간결한 주석 달기

7장 읽기 쉽게 흐름 제어 만들기

8장 거대한 표현을 잘게 쪼개기

9장 변수와 가독성

10장 상관없는 하위 문제 추출하기

11장 한 번에 하나씩

12장 생각을 코드로 만들기

13장 코드 분량 줄이기

14장 테스트와 가독성

15장 분/시간 카운터를 설계하고 구현하기

추천 도서목록

 

복습 겸 각각의 목차를 간단히 정리를 해보면 아래와 같이 정리됩니다.

1장 코드는 이해하기 쉬워야 한다

다른 프로그래머가 보기에 코드가 쉽게 이해되어야 한다는 내용입니다. 여기에서 다른 프로그래머는 6개월 뒤의 자기 자신도 포함됩니다. 코드를 만들 당시에는 전반적인 모든 정보들을 알고 있기 때문에 여러 내용을 한 번에 처리하여 작성할 수 있지만 나중에 그 코드를 다시 보게 되면 이해하는데 시간이 꽤나 걸리는 경우가 많습니다. 제 개인적으로도 있었던 일이어서 더욱 많은 공감이 되었습니다.

 

사내에서 쓰던 기존의  업무 자동화 프로그램에 기능을 조금 더 추가하여 수정을 하였는데요. 당시에는 나름의 설명까지 잘 붙여서 만들었다고 생각했지만, 정확히 5개월 뒤에 동료가 사용법이 이게 맞는지 물어봤을 때 저도 전혀 기억이 나지 않아 코드를 다시 분석해 보는 헛수고를 했던 경험입니다. 이처럼 사용자가 이해하기 쉽게 코드를 만드는 것이 중요하다는 내용이 나와있습니다.

 

예를 들면 람다식을 써서 2줄로 만든 코드보다 조건, 반목 문을 사용한 8줄짜리 코드가 훨씬 더 가독성이 좋고 이해하기 편하다는 내용입니다. 짧은 코드가 더 좋은 코드가 아닌 읽는 순간 바로 이해되는 코드좋은 코드라는 이야기입니다.

 

2장 이름에 정보 담기

변수, 함수명을 제대로 작성하는 것에 대한 내용입니다. 일본에서 일하고 있으면 정말 말도 안 되는 변수 이름들을 만나게 되는데요. 역시나 엄청나게 공감되는 내용이었습니다. 내용을 정리하면 아래와 같습니다.

 

・특정한 단어를 사용하여 변수명을 만들기(Get 대신 Download를 사용하는 등)

・보편적으로 사용되는 변수명(tmp, i 등)을 피하고 구체적으로 만들기

・단위를 포함하는 값은 단위 명도 같이 표기하기

・이름 길이에 관한 조언(짧은 범위에서 잠깐 쓰이며 짧은 변수명, 사용범위가 넓으면 긴 변수명, 약어 사용하지 않기 등)

・포맷팅으로 의미를 전달하기(상수는 대문자, 클래스명은 카멜 케이스로 작성, 멤버 변수 뒤에는 밑줄을 붙일 것 등 팀에서 논의된 대로 작성할 것)

 

3장 오해할 수 없는 이름들

내가 만든 이름(변수, 함수명 등)이 '다른 사람들이 다른 의미로 해석할 여지가 있는가?' 이게 바로 3장의 핵심입니다. 이를 위한 내용은 아래와 같습니다.

 

・경계를 포함하는 범위 - 변수명으로 first와 last를 사용

・경계를 포함/배제하는 범위 - 변수명으로 begin와 end를 사용

・불리언 변수 - is, has, can, should 등을 덧붙여서 사용, 부정 단어 사용 피하기(disable 등)

・get 함수명 남발하지 않기

・여러 개의 이름을 후보로 놓고 고민하기

 

변수 및 메서드 명을 지을 때 '다른 사람들이 이 변수를 보고 혼동하지 않고 바로 이해할 수 있는가?'를 한 번쯤 더 생각해 보면 더 좋은 변수명을 만들 수 있다는 내용입니다.

 

4장 미학

한글 및 워드에서 문서 작업을 하더라도 한눈에 보기 쉽게 쓰인 글은 잘 읽힙니다. 4장에서 이야기하는 것도 이와 마찬가지입니다. 눈을 편하게 하는 코드가 핵심 내용입니다. 일관된 레이아웃, 비슷한 코드를 묶는 등의 작업으로 코드를 보는 사람이 좀 더 한눈에 코드를 담고 이해하기 쉽게 만드는 것이 목적입니다. 이를 위한 내용은 아래와 같습니다.

 

・좌우로 길게 늘어진 코드를 줄 바꿈하고 다른 코드들도 똑같이 맞추기

・헬퍼 메서드를 이용하여 지저분한 코드를 깔끔하게 하기

・코드의 위아래 열을 맞추어 읽기 쉽게 하기

・코드의 순서를 '가장 중요한 것'에서 '가장 덜 중요한 것'까지 순서대로 나열하기

・코드를 문단으로 만들기(ex: 3줄 연속으로는 핸들러 메서드, 한 행을 띄운 뒤는 DB 관련 메서드 등 글을 쓸 때 문단으로 만드는 것과 동일)

・개인의 코드 스타일과 vs 전체 코드의 일관성 - 일관성이 '올바른' 스타일보다 더 중요하다

 

5장 주석에 담아야 하는 대상

코드의 변수, 함수명과 마찬가지로 주석은 코드를 읽는 사람이 작성자만큼 잘 이해하도록 있는 데 있습니다. 이러한 주석을 다는데 필요한 것들을 바로 알아보겠습니다.

 

・불필요한 설명을 피하라 - 코드를 보는 순간 직관적으로 알 수 있는 것들을 일일이 설명하지 마라

・나쁜 이름에 대한 변명 - 변수명, 메서드명이 이해하기 힘들다면 주석으로 설명할게 아니라 직접 이름을 바꿔라(좋은 코드 > 나쁜 코드 + 주석)

・생각을 기록하라 - 본인이 만들면서 생각한 통찰 등을 주석에 기록해야 한다(ex 이 클래스는 엉망이 되어가고 있다. xxx의 하위 클래스를 만들어서 새로 정리를 해야 할지도 모르겠다)

・결함을 설명하라 - 미쳐 아직 다 처리하지 못한 기능 혹은 일어날 수 있는 결함 등에 대해서 주석으로 설명을 달아라

・상수의 의미를 설명하라

・쉽게 일어날 수 있는 함정을 경고하라 - 다른 프로그래머가 실수를 일으킬 수 있는 부분을 예상해 보고 그곳에 주석을 달아라(ex 외부 이메일 서비스를 호출한다(1분 이후 타임 아웃된다), 실행시간이 0(number_tag * average_tag_depth) 이므로 중첩 입력을 사용할 때 주의할 것)

・2중 3중 반복문과 조건문이 잔뜩 달린 긴 함수는 무엇을 위한 것인지 함수 시작 위에 요약 주석을 단다(ex:for문 바로 위에 고객이 본인을 위해 구입한 상품을 모두 찾는다)

・주석을 다는 것에 대한 두려움을 버려라 - 우선은 머릿속에 떠오른 대로 주석을 쓰고 뒤에 정리하라(ex: 이런 xx, 리스트 안에 중복된 항목이 있으면 겁나 복잡했는데 -> 주의 : 이 코드는 리스트 안에 있는 중복된 항목을 다루지 않는다. 그렇게 구현하는 게 어렵기 때문이다.)

 

6장 명확하고 간결한 주석 달기

주석을 신문 사설처럼 길게 쓰지 말고 핵심만 뽑아서 간결하게 쓰라는 내용입니다. 내용을 설명하면 아래와 같습니다.

 

・주석을 간결하게 하라 - 각각의 변수명을 길게 설명하지 말고 의미가 전달되게 짧게 줄여라

・대명사는 피하라 - 그것, 이것, 여기, 저기등의 대명사의 사용은 최대한 줄여라(혼동을 피하라)

・문장을 다듬어라 - 더  잘 설명될 수 있는지 보고 편집하라

・메서드의 동작을 명확히 설명하라(ex 파일에 담긴 줄 수를 반환한다 -> 파일 안에 새 줄을 나타내는 바이트('\')가 몇 개 있는지 센다.) 

・간단한 입출력 예시를 사용하라(ex 이 코드는 스트링을 가져와서 접두사와 접미사를 제거한다 -> Strip("abba/a/ba", "ab")는 "a"를 반환한다)

・코드의 수행 동작이 아니라 코드의 의도를 적어라(ex 리스트를 역순으로 반복한다 -> 각 가격을 높은 값에서 낮은 값 순으로 나타낸다)

・파라미터에도 주석을 넣는다(ex: InputUserInfo(/*user_age =*/ 10,/* use_phone = */ false))

・축약된 단어를 사용하라(ex : 주소 값에서 불필요한 빈칸을 제거하고 [..중략...] 동일한 방식으로 정리된 값을 [..중략..] 서로 비교해서 확인할 수 있다. -> 주소 값을 표준화한다(빈칸을 제거, "Avenue" -> "Ave")등의 정리 작업을 수행한다))

 

7장 읽기 쉽게 흐름 제어 만들기

조건, 루프 그리고 기타 다른 요소들을 최대한 '자연스럽게' 만들도록 노력하는 것, 코드를 읽다가 다시 되돌아가서 코드를 읽지 않아도 되게 만드는 것 이 중요하다고 말하고 있습니다. 내용은 아래와 같습니다.

 

・조건문에서 유동적인 값은 왼쪽 상대적으로 고정적인 값은 오른쪽에 쓰라

・if/else 블록 순서 - 긍정을 다루어라, 간단한 것을 먼저 처리하라, 흥미롭고 확실한 것을 먼저 다루어라

・삼항 연산자 사용은 아주 간단하게 쓸 수 있는 상황이 아니라면 피하라

・do/while 사용을 피하라 - 자주 에러와 혼동의 원인이 된다

・함수를 중간에서 반환하라 - 중첩을 피하고 코드를 더 깔끔하게 작성할 수 있다

・중첩을 피하라 - 이중 if 문 등은 나누어서 중간에 반환하라

 

8장 거대한 표현을 잘게 쪼개기

큰 표현을 잘게 분해하여 설명하는 것입니다. 내용은 아래와 같습니다.

 

・설명변수를 사용하라 - 작은 하위 표현을 담을 추가 변수를 만들어라

(ex : if line.split(':')[0].strip() == "root"; -> username =line.split(':')[0].strip())

・요약 변수를 사용하라 - 메서드 내에서 반복되는 조건식의 중요 비교 값을 상수로 만들기 등

・드모르간의 법칙 사용하라

・쇼트서킷 사용을 오용하지 마라 - 영리하게 작성된 코드에 유의할 것 그런 코드가 혼란을 초래한다

・복잡한 논리를 간단하게 표현하기

・거대한 구문 나누기 - 자바스크립트 등에서 반복되는 항목은 변수로 만들어서 처리한다 

 

9장 변수와 가독성

불필요한 변수를 없애는 것, 최대한 변수의 범위를 줄여서 사용하여 다른 사람이 코드를 쉽게 알아보게 하는 게 이 장의 목적입니다. 내용은 아래와 같습니다.

 

・불필요한 임시 변수를 없애라 - 불필요한 임시 변수, 중간 결과 저장 변수, 흐름 변수(boolean) 제거하기

・변수의 범위를 좁혀라 - 많은 메소들을 정적 static으로 만들어서 클래스 멤버 접근을 제한하라, 커다란 클래스를 작은 클래스로 나누어라

・전역 변수 사용을 피하라 - 일일이 변수를 기억해야 하고, 해당 변수가 뭔지 알아보기 위해 다시 위로 가서 변수를 읽는 일이 생긴다

・값을 한 번만 할당하는 변수를 선호하라

 

10장 상관없는 하위 문제 추출하기

하위 문제를 추출하는 것은 코드의 직접적인 상위 목적(예: 좌표에서 가장 가까운 지하철역을 찾기)과는 관련은 있지만 상위 목적 자체와는 직접적으로 상관없는 하위 문제를 해결하는 코드를 끄집어내는 것입니다. 쉽게 말하면 '일반적인 목적의 코드(문자열 빈칸 제거, url 형식, 주소 형식 등을 이쁘게 다듬는 메서드)를 프로젝트의 특정 코드에서 분리하라'입니다. 내용은 아래와 같습니다.

 

・지하철역을 찾는 메서드에서 복잡한 계산식은 따로 끄집어내어 메서드로 만드는 것

・일반적인 목적의 코드 - 서버에 ajax를 호출을 하고 응답하는 상위수준 목적이 있다면 딕셔너리에 담긴 내용을 이쁘게 출력하는 인은 다른 메서드에서 해결하라

・일반적인 목적(ex:ReadFileToString()과 같은)을 가진 코드를 많이 만들어라 - 다른 프로젝트 등에서도 많이 사용될 가능성이 높다.

・자신의 필요에 맞춰서 인터페이스를 바꾸기

・과유불급 - 지나치게 나누고 메서드를 추출하면 오히려 가독성을 해친다

 

11장 한 번에 하나씩

작성한 코드를 읽기 어렵다면, 일단 수행하는 작업을 모두 나열하여 보는 것을 추천합니다. 그리고 나면 나열된 작업 중 일부가 쉽사리 별도의 함수 혹은 클래스로 분리할 수 있을 것이라는 것이라고 합니다. 이 장은 예제 코드를 가지고 설명하고 있는데요. 간단히 요약하면 파편처럼 나뉘어서 각각의 일을 수행하는 코드들을 정리하여 묶어서 다시 리팩토링을 하는 것을 이야기하고 있습니다.

 

12장 생각을 코드로 만들기

이 장의 핵심은 구현하고자 하는 프로그램을 평범하게 설명하고, 그 설명에 부합하는 자연스러운 코드만드는 것입니다. 이 테크닉은 믿을 수 없을 정도로 간단하지만 매우 강력하다고 합니다. 내용은 아래와 같습니다.

 

・논리를 명확하게 설명하기

・언어에서 제공하는 라이브러리를 많이 보고 사용하라

・해결책을 말로 묘사하기

 

13장 코드 분량 줄이기

'가장 읽기 쉬운 코드는 아무것도 없는 코드다'가 내용의 핵심입니다. 내용은 아래와 같습니다.

 

・필요가 없는 기능을 구현하려고 애쓰지 마라

・코드 베이스를 작게 유지하라

・요구사항에 질문을 던져 질문을 잘게 나누어 분석하라

・표준 라이브러리와 친해져라 - 매일 15분씩 표준 라이브러리에 있는 함수/모듈/형들의 이름을 읽어라

 

14장 테스트와 가독성

읽거나 유지 보수하기에 쉽게 테스트를 만들어라는 내용입니다. '다른 프로그래머가 수정 혹은 새로운 테스트를 더하는 걸 쉽게 느낄 수 있게 테스트 코드는 읽기 쉬어야 한다'라고 강조하고 있습니다. 내용은 아래와 같습니다.

 

・긴 테스트 내용은 따로 메서드로 만들어라

・읽기 편한 에러 메시지 출력 폼을 만들어라

・좋은 테스트 입력값의 선택 - 입력값 단순화하라, 작은 테스트를 여러 개 사용하라

・테스트 함수에 이름 붙이기(ex : Test1() -> Test_SortAndFilterDocs())

・테스트에 친숙한 개발 - 테스트 주도 개발을 이야기하는 것이 아니라 지금 작성하는 코드의 테스트 코드를 나중에 작성할 거라는 사실을 염두에 두라

・지나친 테스트 - 테스트가 숭배되어 테스트에만 매달리는 일은 지양해야 한다

 

15장 분/시간 카운터를 설계하고 구현하기

좋은 코드의 실제 예시로 1분과 1시간 동안 얼마나 많은 바이트를 전송했는지 추적하는 코드를 보여줍니다. 처음에 만든 메서드를 점점 더 고치고 수정해 가면서 1~14장에서 배운 개념들을 적용하는 장입니다. 이장에서 나온 내용들은 아래와 같습니다.

 

・이름을 개선하기

・주석을 개선하기

・가독성을 위한 리팩토링

・성능 문제 해결을 위한 컨베이어 벨트 설계

・시간 바구니 설계 - 각각의 시간을 하나의 버킷(바구니)으로 만들어 정수의 올림 반올림 등의 에러를 개선한 설계

・구현하려는 시스템 전체를 여러 개의 하위 문제로 나누어서 문제를 해결하기

 

추천 도서목록

이 장에서는 프로그래머가 읽으면 좋은 책들을 추천하고 있습니다. 코드의 완성 등 프로그래머가 읽으면 좋은 많은 좋은 책들을 추천하고 있습니다.

 

책 평가 및 감상

프로그래머라면 꼭 한번 읽어 보기를 권하는 좋은 책입니다. 코딩을 거의 하지 않았던 저의 경우에 비추어 보아도 잘 읽혔습니다. 물론 책 중반을 넘어가면서 점점 읽는 속도가 느려지고 책과 예제 코드가 읽기 싫어지는 과정을 겪기는 하였지만, 완독을 하고 난 뒤에는 '정말 읽어서 다행이다.'라는 안도감이 드는 책이었습니다. 

 

책에서 읽은 내용을 실제 코드에 적용할 생각을 하면 조금 머리가 아픈 것은 사실입니다. 하지만 읽는 중간중간에는 이전에 제가 만들었던 코드들의 변수명과 주석 내용 그리고 엉망이었던 메서드 안의 구성들이 생각나서 얼굴이 화끈거렸던 것을 차치하고, 그 과정에서 조금 더 나은 결과물이 나올 수 있다는 생각에 한편으로 조금의 희망을 받기도 하였습니다. 프로그래머라면, 프로그래머를 지향하고 있다면 꼭 한번 읽어보시기를 추천합니다.

반응형

댓글