[기술독서] Clean Code 1장

떵호·2022년 1월 18일
0

기술독서

목록 보기
1/8
post-thumbnail

1장 깨끗한 코드

코드가 존재하리라

이 책은 코드를 다루는 책이다.
코드를 자동으로 생성하는 시대가 다가온다고 코드는 사라지지않는다.
왜냐하면 코드는 요구사항을 상세히 표현하는 수단이기 때문에 코드의 도움 없이 요구사항을 상세하게 표현하기는 불가능하고 추상화도 불가능하다.
우리 프로그래밍 언어가 추상화 수준이 점차 높아지고 있고,
특정 응용 분야에서 적합한 프로그래밍 언어(domain-specific language[1]) 수도 점차 많아지는 것은 바람직한 현상이다.
궁극적으로 코드는 요구사항을 표현하는 언어라는 사실을 명심한다


나쁜 코드

Killer App 하나로 대박난 회사가 있었지만 얼마 못가 망했다.
그 원인은 출시에 맞추기 위해, 기능을 더 추가하기 위해 나쁜 코드를 방치했기 때문이다.
급해서 서두르느라 나쁜 코드를 방치하고 '나중에 정리해야지'라고 다짐하지만 그 나중은 결코 오지 않는다.


나쁜 코드로 치루는 대가

나쁜 코드는 개발 속도를 크게 떨어트린다.

  • 프로젝트 초반에는 번개처럼 나가다가 1~2년만에 굼뱅이처럼 기어가는 것을 볼 수 있다.
  • 시간이 지나면서 쓰레기 더미는 점점 높아지고 깊어지고 커진다.

나쁜 코드가 쌓일수록 팀 생산성은 떨어지고 마침내 0에 근접한다.

  • 관리팀은 복구를 시도하기 위해 인력을 추가한다.
  • 하지만 새 인력은 시스템 설계에 대한 이해도가 부족하다.
  • 게다가 새 인력은 팀 생산성을 높여야 한다는 압력에 시달린다.
  • 결국엔 나쁜 코드는 계속 쌓이게 된다.

원대한 재설계의 꿈

팀은 반기하기위해 재설계를 요구하고 허락을 받음
새로운 팀은 기존 시스템 기능 + 새로운 기능을 맡게 됨
기존 팀과 오래 동안 경쟁을 하지만 멤버가 하나씩 바뀌게 됨
결국 다시 재설계를 요청함

깨끗한 코드는 비용을 절감하는 방법뿐만아니라 전문가로서 살아남는 길이다.

태도

좋은 코드가 나쁜 코드로 전략했을때 요구사항의 변경, 일정이 촉박하다는 탓으로 돌린다.
하지만 잘못은 프로그래머에게 있다.
좋은 코드를 사수하는 건 프로그래머들의 책임이다.

자신이 의사라 가정하자. 어느 환자가 수술 전에 손을 씻지 말라고 요구한다. 시간이 너무 걸리니까.
확실히 환자는 상사다. 하지만 의사는 단호하게 거부한다. 왜? 질병과 감염의 위험은 환자보다 의사가 더 잘아니까.
한자 말을 그대로 따르는 행동은 전문가 답지 못하다.

나쁜 코드의 위험을 이해하지 못하는 관리자 말을 그대로 따르는 행동은 전문가답지 못하다.

원초적 난제

프로그래머는 근본적인 가치에서 난제에 봉착한다. 누구나 나쁜 코드가 업무 속도를 늦춘다는 사실을 익히안다.
기한을 맞추려면 나쁜 코드를 양산할 수 밖에 없다고 느낀다.
하지만 나쁜 코드를 양산하면 속도가 곧바로 늦어지고 결국 기한을 놓친다.
기한을 맞추는 유일한 방법은 언제나 코드를 최대한 깨끗하게 유지하는 습관이다.

깨끗한 코드라는 예술?

깨끗한 코드가 무엇인지 모르면 깨끗한 코드를 만들려고 애써봤자 소용이 없다.
깨끗한 코드란 그림을 그리는것과 비슷하다. 깨끗한 코드와 나쁜 코드를 구분할 줄 안다고 깨끗한 코드를 작성할 수 있다는 뜻은 아니다.
클린 코드를 작성하려면 '청결'이라는 힙겹게 습득한 감각을 활용해 기법들을 적용하는 절제와 규율이 필요하다. 그 열쇠는 '코드 감각'이다.
'코드 감각'이 있으면 좋은 코드와 나쁜 코드를 구분하고, 절제와 규율을 적용해 나쁜 코드를 좋은 코드로 바꾸는 전략도 파악한다.

깨끗한 코드란?

비야네 스트롭스트룹Bjarne Stroustrup, C++ 창시자이자 The C++ Programming Language 저자

나는 우아하고 효율적인 코드를 좋아한다. 논리가 간단해야 버그가 숨어들지 못한다. 의존성을 최대한 줄여야 유지보수가 쉬워진다.
오류는 명백한 전략에 의거해 철저히 처리한다. 성능을 최적으로 유지해야 사람들이 원칙 없는 최적화로 코드를 망치려는 유혹에 빠지지 않는다. 깨끗한 코드는 한 가지를 제대로 한다.

  • 깨끗한 코드는 보는 사람에게 즐거움을 선사해야 한다.
  • 효율적인 코드여야 한다. 효율은 단순히 속도뿐만 아니라 CPU 자원을 낭비하지 않아야 한다.
  • 나쁜 코드는 나쁜 코드를 유혹한다. (깨진 유리창 이론)[2]
  • 오류 처리는 세세한 사항까지 꼼꼼하게 신경써야 한다.
    • 메모리 누수, 경쟁 상태, 일관성 없는 명명법에 주의깊게 사용해야 한다.
  • 클린 코드는 한 가지를 잘 한다.
    • 나쁜 코드는 너무 많은 일을 하려다가 목적이 흐려진다.
    • 클린 코드는 한 가지에 '집중'한다.

그래디 부치Grady Booch, Object Oriented Analysis and Design with Application 저자

클린 코드는 단순하고 직접적이다. 클린 코드는 잘 쓴 문장처럼 읽힌다. 클린 코드는 결코 설계자의 의도를 숨기지 않는다. 오히려 명쾌한 추상화와 단순한 제어문으로 가득하다.

  • 클린 코드는 잘 쓴 문장 처럼 읽혀야 한다.
  • 명쾌한 추상화란 코드는 추측이 아니라 사실에 기반, 반드시 필요한 내용만 담아야 한다.

'큰' 데이브 토마스 Dave Thomas, OTI 창립자이자 이클립스 전략의 대부

클린 코드는 작정자가 아닌 사람도 읽기 쉽고 고치기 쉽다. 단위 테스트 케이스와 인수 테스트 케이스가 존재한다. 클린 코드에는 의미 있는 이름이 붙는다.
특정 목적을 달성하는 방법은(여러 가지가 아니라) 하나만 제공한다. 의존성은 최소이며 각 의존성을 명확히 정의한다. API는 명확하며 최소로 줄였다.
언어에 따라 필요한 모든 정보를 코드만으로 명확히 표현할 수 없기에 코드는 문학적으로 표현해야 마땅하다.

  • 다른 사람이 고치기 쉬워야 한다. 읽기 쉬운 코드와 고치기 쉬운 코드는 다르다
  • 테스트 케이스가 있어야 한다.
  • '문학적'이어야 한다. 인간이 읽기 좋은 코드를 작성해라

마이클 페더스Michael Feathers, Working Effectively with Legacy Code 저자

클린 코드의 특징은 많지만 그 중에서도 모두를 아우르는 특징이 하나 있다. 클린 코드는 언제나 누군가 주의 깊게 짰다는 느낌을 준다.
고치려고 살펴봐도 딱히 손 댈 곳이 없다. 작성자가 이미 모든 사항을 고려했으므로.
고칠 궁리를 하다보면 언제나 제자리로 돌아온다. 그리고는 누군가 남겨준 코드, 누군가 주의 깊게 짜놓은 작품에 감사를 느낀다.

  • 코드를 주의 깊에 짜라. 세세한 사항까지 꼼꼼하게 신경써서

론 제프리스Ron Jeffries,Extrem Programming Installed와 Extreme Programming Adventure in C# 저자

최근 들어 나는 켄트 벡이 제안한 단순한 코드 규칙으로 구현을 시작한다. (그리고 같은 규칙으로 구현을 거의 끝낸다.) 중요한 순으로 나열하자면 간단한 코드는

  • 모든 테스트를 통과한다.
  • 중복이 없다.
  • 시스템 내 모든 설계 아이디어를 표현한다.
  • 클래스, 메서드, 함수 등을 최대한 줄인다.

물론 나는 중복에 집중한다. 같은 작업을 여러 차례 반복한다면 코드가 아이디어를 제대로 표현하지 못한다는 증거다. 나는 문제의 아이디어를 찾아내 좀 더 명확하게 표현하려 애쓴다.
내게 있어 표현력은 의미 있는 이름을 포함한다. 보통 나는 확정하기 전에 이름을 여러 차례 바꾼다. 이클립스와 같은 최신 개발 도구는 이름을 바꾸기가 상당히 쉽다. 그래서 별 고층 없이 이름을 바꾼다.
하지만 표현력은 이름에만 국한되지 않는다. 나는 여러 기능을 수행하는 객체나 메서드도 찾는다. 객체가 여러 기능을 수행한다면 여러 객체로 나눈다.
메서드가 여러 기능을 수행한다면 메서드 추출Extract Method 리팩터링 기법을 적용해 기능을 명확히 기술하는 메서드 하나와 기능을 실제로 수행하는 메서드 여러개로 나눈다.
중복과 표현력만 신경써도 (내가 생각하는) 클린 코드라는 목표에 성큼 다가선다. 지저분한 코드를 손볼 때 이 두 가지만 고려해도 코드가 크게 나아진다.
하지만 나는 한가리르 더 고려한다. 이는 설명하기 조금 까다롭다.
오랜 경험 끝에 나는 모든 프로그램이 아주 유사한 요소로 이뤄진다는 사실을 깨달았다. 한 가지 예가 '집합에서 항목 찾기'다. 직원 정보가 저장된 데이터베이스든, 키/값 쌍이 저장된 해시 맵이든, 여러 값을 모아놓은 배열이든,
프로그램을 짜다 보면 어떤 집합에서 특정 항목을 찾아낼 필요가 자주 생긴다. 이런 상황이 발생하면 나는 추상 메서드나 추상 클래스를 만들어 실제 구현을 감싼다. 그러면 여러가지 장점이 생긴다.
이제 실제 기능을 아주 간단한 방식으로, 예를 들어 해시 맵으로, 구현해도 괜찮다. 다른 코드는 추상클래스나 추상 메서드가 제공하는 기능을 사용하므로 실제 구현은 언제든지 바꿔도 괜찮다.
지금은 간단하게 재빨리 구현했다가 나중에 필요할 때 바꾸면 된다.
게다가 집합을 추상화하면 '진짜' 문제에 신경 쓸 여유가 생긴다. 간단한 찾기 기능이 필요한데 온갖 집합 기능을 구현하느라 시간과 노력을 낭비할 필요가 없어진다.
중복 줄이기, 표현력 높이기, 초반부터 간단한 추상화 고려하기. 내게는 이 세 가지가 클린 코드를 만드는 비결이다.

  • 중복을 피하라.
  • 한 기능만 수행하라.
  • 제대로 표현하라.
  • 작게 추상화하라.

워드 커닝햄 Ward Cunningham, 위키wiki 창시자, 피트fit 창시자, 익스트림 프로그래밍eXtreme Programming 공동 창시자, 디자인 패턴을 뒤에서 움직이는 전문가, 스몰토크Smalltalk와 객체 지향OO의 정신적 지도자, 코드를 사랑하는 프로그래머들의 대부

코드를 읽으면서 짐작했던 기능을 각 루틴이 그대로 수행한다면 클린 코드라 불러도 되겠다. 코드가 그 문제를 풀기 위한 언어처럼 보인다면 아름다운 코드라 불러도 되겠다.

  • 코드를 읽고 끄덕일 수 있게 작성해야 한다.
  • 언어를 탓하지 마라.
  • 코드를 아름답게 만드는 것은 프로그래머다.

우리들 생각

이 책은 깨끗한 변수 이름, 깨끗한 함수, 깨끗한 클래스를 만드는 방법을 소개한다.
우리가 가르치는 기법을 따른다면 깨끗하고 수준 높은 코드를 작성하리라 장담한다. 하지만 우리가 절대적으로 '옳다'라는 단정은 금물이다.
이 책에서 주장하는 기법 다수는 논쟁의 여지가 있다. 여러분도 모든 기법에 동의하지 않고, 어떤 기법은 격렬히 반대할 수 있다. 그래도 괜찮다.
하지만 다른 한편으로 우리가 오랫동안 고민하고 숙교한 교훈과 기법을 권고한다. 수십 년에 걸친 경험과 반복적인 시행착오로 습득한 교훈과 기법이다.
동의하든 동의하지 않든 우리 시각을 이해하고 존중해주길 바란다.

우리는 저자다

Javadoc에서 @author 필드는 저자를 소개한다. 우리는 저자다. 저자에겐 독자가 있고 저자에겐 독자와 잘 소통할 책임도 있다.
다음에 코드를 짤 때는 자신이 저자라는 사실을, 당신의 노력을 보고 판단을 내릴 독자가 있다는 사실을 기억하기 바란다.

밥이 모듈을 입력한다.
변경할 함수로 스크롤해 내려간다.
잠시 멈추고 생각한다.
이런! 모듈 상단으로 스크롤해 변수 초기화를 확인한다.
다시 내려와 입력하기 시작한다.
이런, 입력을 지운다!
다시 입력한다.
다시 지운다!
뭔가를 절반쯤 입력하다가 또 지운다!
지금 빠구려는 함수를 호출하는 함수로 스크롤한 후 함수가 호출되는 방식을 살펴본다.
다시 돌아와 방금 지운 코드를 입력한다.
잠시 멈춘다.
코드를 다시 지운다!
다른 윈도를 열어 하위 클래스를 살핀다. 함수가 재정의 되었는가?
...

위 예를 보면 코드를 읽는 시간대 코드를 짜는 시간 비율이 10:1을 훌쩍 넘는다. 새 코드를 짜면서 우리는 끊임없이 기존 코드를 읽는다.
기존 코드를 읽어야 새 코드를 짜므로 읽게 쉽게 만들면 짜기도 쉬워진다.
그러므로 급하다면, 서둘러 끝내려면, 쉽게 짜려면, 읽게 쉽게 작성하면 된다.

보이스카우트 규칙

잘 짠 코드가 전부는 아니다. 시간이 지나도 언제나 깨끗하게 유지해야 한다.
미국 보이스카우트가 따르는 규칙은 우리에게도 유용하다.

캠프장은 처음 왔을 때보다 더 깨끗하게 해놓고 떠나라
체크아웃할 때보다 좀 더 깨끗한 코드를 체크인한다면 코드는 절대 나빠지지 않는다.
한꺼번에 많은 시간과 노력을 투자해 코드를 정리할 필요가 없다. 변수 이름 하나를 개선하고, 조금 긴 함수 하나를 분할하고, 약간의 중복을 제거하고, 복잡한 if문 하나를 정리하면 충분하다.

프리퀄과 원칙

많은 면에서 이 책은 내가 2002년에 출판한 Agile Software Development: Principles, Patterns, and PracticesPPP의 프리퀄prequel이다.
SRP, OCP, LSP, DIP, ISP등 다양한 설계 원칙을 소개하는 PPP[3]도 읽어 보는 것을 추천한다.

결론

이 책을 읽는다고 뛰어난 프로그래머가 된다는 보장과 '코드 감각'을 확실히 얻는다는 보장은 없다. 단지 뛰어난 프로그래머가 사고 방식과 그들이 사용하는 기술과 기교와 도구를 소개할 뿐이다.
이 책은 좋은 코드, 나쁜 코드 모두 소개하고, 나쁜 코드를 좋은 코드로 바꾸는 방법도 소개한다. 다앙한 경험적 교훈과 체계와 절차와 기법도 열거한다. 예제도 무수히 많이 보여준다. 나머지는 독자에게 달렸다.

공연장으로 가다가 길을 잃은 연주회의 바이올리니스트에 대한 우스개 소리를 기억하는가? 그는 길거리에서 한 노인에게 카네기 홀로 가는 방법을 물었다. 노인은 연주자와 그가 든 바이올린을 보고 이렇게 말했다.
'연습해, 연습!'

참조

1 domain-specific language

https://ko.wikipedia.org/wiki/도메인_특화_언어

2 깨진 유리창 이론

https://ko.wikipedia.org/wiki/깨진_유리창_이론

3 PPP에서 얘기하는 원칙은 다음과 같다
  • SRP(The Single Responsiblility Principle): 클래스에는 한 가지, 단 한 가지 변경 이유만 존재해야 한다.
  • OCP(The Open Closed Principle): 클래스는 확장에 열려 있어야 하며 변경에 닫혀 있어야 한다.
  • LSP(The Liskov Substitution Principle): 상속받은 클래스는 기초 클래스를 대체할 수 있어야 한다.
  • DIP(The Dependency Inversion Principle): 추상화에 의존해야 하며, 구체화에 의존하면 안된다.
  • ISP(The Interface Segregatino Principle): 클라이언트에 밀접하게 작게 쪼개진 인터페이스를 유지한다.
profile
꾸준히 해보자❗️

0개의 댓글