Book & Lesson

[책] 더 나은 프로그래머 되는법 Part1. you.write(code);

카프리썬_ 2024. 5. 12. 16:00
728x90
728x90

 

 

아래 글은 <더 나은 프로그래머 되는법>을 읽고 요약한 내용이며 개인적인 생각이 담겨있습니다.



    Ch1. 코드에 신경쓰기

    좋은 코드를 작성하려면 코드에 신경써야한다. 
    평범한 프로그래머와 훌륭한 프로그래머의 차이는 태도에 있다.
    최고의 코드를 작성하려는 태도부터 훌륭한 프로그래밍이 태어난다. 

     

    Ch2. 정돈된 코드 유지하기

    좋은 프로그래머는 코드의 좋은 레이아웃에 대해 깊이 고민한다. 
    좋은 레이아웃이란 보기 예쁜것이 아니다. 보기 좋은 코드는 의도를 드러낸다.

    두명의 관객을 위해 코딩을 해라. 우선 컴파일러를 위해, 그 다음은 동료를 위해. 
    다른사람을 위해 코딩하는것을 잊지말자.

    코드를 훑어보는것만으로도 전체 형태와 구조를 파악할수 있어야한다. 


    글쓰듯 코드를 작성하라.
    - 전체적인구조 - 연관성과 순서, 코드를 장,문잔,문단 단위로.
    - 일관성 - 팀전체의 IDE와 소스코드 편집기 같은 환경으로 
    - 명명 - 이름은 사물의 정체성.정확하게 무엇인지 알아야만 이름을 붙일수 있다.
    - 불필요한 단어 반복을 피하라 
    - 간결함보다 명확함이 우선이다. 문맥이 전체내용을 좌우한다. 
    - 언어에서 쓰이는 대문자화 규약 따르기
    - 명명을 정확하게 하라. 

    코드를 정돈할 경우 기능변경과 모양변경을 동시에 진행하지 마라.

     

    기능변경과 모양변경을 다른 커밋으로 두어야겠다. 
    지금까지 커밋의 기준을 그냥 내가 작업한 내용. 그 이상으로 의미부여하지 않았다. 
    그러다보니 기능추가 뿐만 아니라 구조가 변경되서 헷갈리는 부분이 종종 있었다. 

     

    Ch3. 코드 적게 쓰기

    불필요한 코드는 사악하다. 
    개선하는 가장 좋은 방법은 코드를 제거하는것이다. 
    코드를 명백하고 간결하게 써라. 불필요하게 구구절절 늘어놓는 행동은 피하라.

    짧고 명확한 글을 좋아한다. 주저리 긴 글이 아니라 수식어를 전부 제외하고도 담백하게 핵심 내용이 전부 전달이 되는 글 말이다.
    그런데 글과 코드가 유사한걸 알면서도 글은 이렇게 잘 평가하고, 잘 읽고, 잘 쓰면서 왜 코드는 돌아보지 않았을까.


    리팩토링이란 결과의 변경없이 기존코드의 구조를 재조정하는것. 

    프로그램의 작동방식을 바꾸는것은 개선. 
    코드가독성을 높이고, 내부구조를 향상하며, 유지보수 원활 목적. 기능향상에 대한 대비이다. 

    리팩토링과 개선은 나의 주된업무이다.
    그럼에도 두 단어의 명확한 차이를 잘 몰랐다.
    몰랐으니까 그냥 커밋도 섞어서 했던거 같기도;
    이제 알았다. 


    불필요한 코드중복은 사악하다. 
    코드복사는 존재하는 버그까지 모두 복사한다. 리팩토링은 중복된 코드를 하나의 함수로 만드는 일이다. 
    DRY(Don't Repeat Yourself) 자신을 반복하지 말라 원리

    죽은코드를 지워라. 
    실행되거나 호출되지 않은 생명력 없는 코드. 한번도 호출되지 않은 함수, 선언되었지만 할당되지 않은 변수 등 

    끔찍한 주석이 많다. 주석이 코드에 가치를 더하지는 않는다. 
    코드자체만으로도 이유가 명확하게 드러나지 않을때만 주석을 달아야한다. 

    굳이 주석이 필요하다면 잘 명명된 새로운 함수로 로직을 재구성하는 편이 더나을수도있다.

    코드에 주석을 책 쓰듯, 문서 쓰듯 길게 작성하는 스타일이신 분이 떠올랐다.
    처음에는 되게 배려있고 꼼꼼하신가보다 싶었다.
    그런데 코드는 계속 바뀐다. 결국 주석도 유지보수해야한다. 일이 더 늘어나는것이다.
    주석 없이 코드만으로도 설명이 전부 되는게 가장 바람직하다는것을 알게 되었다. 

     

    코드를 작성한 후에는 스스로 정리하고 불필요한 코드는 즉시 제거해라. 

    미루기 대장, 귀차니즘 대마왕으로써 반성.
    어제 작성한 코드에서도 죽은 코드, 안쓰는 코드를 발견했었다;;.

     

     Ch4. 코드 줄여 개선하기 

    죽은 코드는 불가피하다. 가능하면 죽은코드를 제거하라. 남겨둔다면 방해가 되고 작업을 지체시킨다. 
    미래에 필요할지 모르는 기능이라도 하더라도 코드를 제거하는것이 안전하다. 
    다만 코드 정리와 기능변화는 별도의 커밋으로 이루어져야한다

    프로젝트가 클수록 더 많은 불필요한 코드가 존재한다. 실패의 징조가 아니다.
    죽은코드를 발견했음에도 아무런 조치를 취하지 않은것이 실패의 징조이다. 

    큰일이다. 실패의 징조가 도대체 몇개냐;; 

     

    Ch5. 코드 베이스의 망령 

    다른 사람의 잘못된 코드에 대해 불평하는것은 재밌어하면서, 자신의 코드가 얼마나 잘못되었는지는 쉽게 잊어버린다. 
    오래된 코드를 다시 살펴보는것은 코딩기술을 향상시키는게 도움을준다. 

    새로운 시각으로 재검토 해보면 이전에 놓친 명백한 문제를 발견할수 있다. 

     

    Ch6. 경로 탐색하기 

    코드를 파악하는 가장 좋은 방법은 이미 코드를 파악하고 있는 사람의 도움을 얻는것이다. 
    도움 요청을 주저하지마라.

    그리고 도움을 받았다면 그에 대한 답례로 언제든 다른이를 도울 준비를 해라. 
    쉽게 검색으로 알아낼수 있는 바보같은 질문을 하지 않는것이 최소한의 예의이다. 

    도움을 요청해주는 사람이 없다면 코드속에서 방향을 가늠해줄 단서를 찾아라. 
    테스트, 파일구조, 문서, 정적분석, 요구사항, 코드품질
    시스템 구조는 코드를 심도있게 확인하기전에 알수있는 최상위개념. 

    코드를 배우는 가장 좋은 방법은 수정해보는것이다.
    코드를 작성하는것이 읽는것보다 쉽다.

     

    코드를 읽는게 생각보다 어려운 일이라는걸 알게 되었다. 그래서 코드를 리뷰해주시는 시니어 분들에게 다시한번 감사함을 느꼈다.
    나는 반대로 읽는것보다 작성하는게 더 어려울것이라고 생각했다. 정말 난 부족하다. 
    생각해보니 내 코드를 읽고 봐주신다는것 자체만으로도 쉽지 않을것 같다..(또 반성)

     

    Ch7. 똥통에서 뒹굴기

    나쁜코드를 언제든 만날 수 있다는 마음의 준비를해라. 나쁜코드를 다룰때 강력한 도구를 미리 준비해두어라. 
    나쁜 코드를 만났을때 혐오감을 참고, 더 나아지게 할 방법을 찾아라. 

    어떤 코드를 건드리든 이전보다 나아지도록 하라. 
    코드수정은 천천히 신중하게 하라. 한번에 하나씩 수정해라. 

     

    워딩이 생각보다 직설적이여서 재밌었다.  어떻게 건드리더라도 이전보다 조금이라도 나아지면 된것이다

     

    Ch8. 오류 무시하지 않기 

    코드에서 발생할 수 있는 모든 오류를 무시하지 마라. 더늦기전에 오류처리를 미루지 마라.
    규칙에 맞춰서 예외를 잘 사용하자. 

    오류를 적절히 처리하지 않으면 다음과 같은 일이 발생한다.
    - 불안정한 코드 
    - 불안전한 코드 
    - 나쁜구조 


    잘못된상황을 노출시키는걸 숨기지마라. 정상적으로 동작하는것처럼 보이게 만들지마라.

     

    Ch9. 예상하지 못한것을 예상하기 

    예상하지 못한것은 결고 이상한것이 아니며 버그의 구성요소이다. 
    코드를 작성할때 고려해야한다.다만 개발초기에 해야한다. 나중에는 처리하기 더어렵다. 

     

    Ch10. 버그 사냥하기

    버그를 피하지말라. 어차피 많은 디버깅을 하게 될것이다. 점차 익숙해질것이고 잘 해낼 것이다. 
    버그가 생긴뒤에 고치기 보다는 처음부터 버그가 생기지 않도록 적극적으로 예방하라. 
    assert와 하찮은 로그도 강력한 디버깅 도구이다. 디버거를 잘 사용해라.

     

    Ch11. 테스트하기 

    TDD(Test Driven Development)는 소프트웨어를 만들기 위한 중요한 기법 중 하나이다.
    좋은 테스트란 피드백절차를 간소화하는것. 빠른 피드백으로 문제파악에 소모되는 시간을 줄여라. 

     

    가장 이상적인 방법은 최대한 많은 개발자 테스트를 자동화 하는것이다. 

     

    테스트 코드를 작성하는 시간이 낭비(?)라고 생각이 들어서 지금까지 안해왔다. 
    하지만 이번 프로젝트를 진행하면서 <서둘러야하는 상황일수록 오히려 천천히 가라> 라는 말대로 테스트코드를 작성해봤다.
    훨씬 더 요구사항을 꼼꼼하게 확인할수 있어서 좋았다. 

    다만 테스트로 인해 속도가 더뎌진다는것 조차 공감이 됐다.
    요구사항이 워낙 까다로워서 하나하나 확인하는게 일이였기 때문이다. 
    하지만 본문의 내용처럼 이게 테스트를 하지 말아야하는 이유가 되는것은 아니다. 


    테스트 유형
     - 단위테스트 : 가장 작은 단위의 기능에 대한 테스트를 단독으로 수행. 하나의 함수나 클래스 동작 확인
     - 통합테스트 : 각각의 단위모듈을 큰 결합체로 통합해서 작동
     - 시스템테스트 : 전체시스템에 대한 요구사항 명세 확인

    레드-그린-리팩토링
    - 레드 : 구현해야하는 기능을 결정하고, 해당기능에 대한 테스트 작성. 이때 테스트 실패
    - 그린 : 기능구현. 테스트통과하면 기능구현성공. 기능추가하면서 테스트추가. 
    - 리펙토링 : 코드정리,더 나은 내부구조로 만들기. 


    코드를 작성하면서 테스트를 같이 작성하라. 테스트작성을 미루면 그만큼 효과가 줄어들것이다.

    나는 테스트코드를 작성해 본적이 없어서 심지어 언제 어떤시점에 작성해야할지 조차 몰랐다
    그래서 개발이 어느정도 다 됐다고 생각하던 시점에 갑자기 테스트코드를 작성했다.
    갑자기가 포인트이다. 심지어 고작 테스트 케이스 짜겠다고 밤샌날도 있었다. 

    다음에 테스트코드를 작성하게 될 상황이 생긴다면 <레드-그린-리팩토링> 기법으로 진행해야겠다.
    가장 먼저 요구사항과 기능부터 먼저 정리해서 테스트 케이스를 짜두고,
    그다음에 이거바탕으로 구현을 해나가는것이다. 
    나는 반대로 구현하고 요구사항을 다시 확인하려고 하니 일을 두번하는 기분이 들었다. 


    테스트를 빠르게 자주 수행하라. 빌드 과정에 테스트를 통합하라.
    출시전 사람에 의한 QA검수 과정은 필요하다. 

     

    테스트가 쓸모없을까 걱정하여 무력해져서는 안된다.

    정말 공감. 또 공감. 공감!
    테스트코드를 작성하면서 가장 큰 현타가 왔던 순간이다.
    어차피 이거 빌드할때도 포함안하고, 그냥 테스트해보면 되는데 굳이 테스트 코드를 써야돼? 라는 생각이 문득문득 자주 들었다.
    이런 무력함이 들었던 이유는 내가 잘못된 방법으로, 잘못된 시점에 시작해서 그랬던것 같다. 

    다음부터는 코드를 작성하면서 테스트코드를 작성하는 올바른 시점에
    좋은 테스트 코드를 통해 이런 걱정과 무력함을 타파해버리겠다.

     

    좋은테스트의 특징 
    - 짧고 명확한 이름, 실패했을때 무엇이 문제인지 쉽게 알수 있다.
    - 유지보수가능, 읽고 수정이 쉬움.
    - 오랜시간이 걸리지 않는다.
    - 특별한 머신 설정이 필요없다. 


    테스트 구조 : 배치-실행-확인 패턴
    - 배치 : 입력을 준비한다
    - 실행 : 동작을 실행한다
    - 확인 : 결과를 확인한다. 이때 일반적으로 한가지만 확인. 

    테스트네이밍은 명세사항으로 읽힌다고 가정하고 작성하라. 즉 하나의 정의에 대한 설명이다. '

    테스트를 통해 좋은 코드를 작성할수 있는 코드품질을 유지할수 있다. 
    코드설계를 개선할수 있고, 기능문서화 가능하다.

    테스트로 모든 문제를 해결할 수 없다. 버그의 존재는 확인할수 있지만, 버그가 없음을 확신할 순 없다.
    확신을 얻기 위해 얼마나 많은 노력을 테스트 작성에 투자할것인지의 문제다. 
    구현코드만큼이나 테스트코드를 주의깊게 살펴봐야한다.

    Ch12. 복잡도 다루기

    복잡한 무언가를 작성하는 일은 너무나 쉽다. 

    복잡도의 원인1. 블롭 (blob)
    블롭의 크기와 수가 복잡도를 결정한다. 큰 프로젝트일수록 큰 블롭이 필요하다. 필연적인 복잡도.
    크기가 문제가 아니라 문제는 이 코드를 어떻게 구성하는가이다. 크기를 어떻게 배분할지가 문제다. 

    더 좋은 구조, 이해하기 쉽고 유지보수 하기 쉬운 구조로 만들기 위해서는 모듈로 만들어야한다.
    각 블롭이 정확한 역할과 책임을 확실히 가져야 쪼갤수도 있다.

    복잡도의 원인2. 라인 
    복잡도는 각 블롭안에서 커진게 아니라 블롭을 연결하는 과정에서 커진것이다. 
    라인이 적을수록 디자인은 간결해진다. 

    연결을 배치할때 객체간 순환연결로 복잡도가 증가하기도 한다. 
    객체를 바꾸려면 다른것도 변경해야한다. 

    복잡도의 원인3. 사람 
    책임은 코드를 작성하는 사람에게 있다. 사람은 복잡성을 불러일으키기도 하면서, 간결한 형태로도 바꿀수 있다. 

     

    복잡도를 줄이는 방법은 개발에 책임감을 가지고,

    업무압박으로인해 적절하지 않은 구조로 코드를 밀어넣는 상황을 피하고자 노력하는 것이다.

    728x90
    반응형