Home

[Develop] 훌륭한 프로그래머 되는 법 [ Part1. You.write(code); ]

훌륭한 프로그래머 되기

훌륭한 프로그래머 되는 법

날짜: 2019.08.21 ~ 2019.08.31

Part1. you.write(code)

목차

  1. 코드에 신경쓰기
  2. 정돈된 코드 유지하기
  3. 코드 적게 쓰기
  4. 코드 줄여 개선하기
  5. 코드베이스의 망령
  6. 경로 탐색하기
  7. 똥통에서 뒹굴기
  8. 오류 무시하지 않기
  9. 예상하지 못한 것을 예상하기
  10. 버그 사냥하기
  11. 테스트하기
  12. 복잡도 다루기
  13. 두 개의 시스템에 대한 이야기

코드에 신경쓰기

  • 좋은 코드를 작성하려면 코드에 신경을 써야한다. 훌륭한 프로그래머가 되려면 시간노력을 투자 해야 한다.
  • 코드에 신경쓰고 코드를 개선하려는 노력을 해야 한다.
  • 좋은 프로그래머가 되기 위해서는 다음과 같이 행동 해야 한다.

    1. 단지 작동하는 것처럼 보이는 코딩은 거부해야 한다.
    2. 프로그래머는 올바르게 동작하는 훌륭한 코드를 짜도록 노력해야 한다.
    3. 의도가 드러나는 코드를 작성해야 한다.
    4. 유지보수가 가능해야 한다.
    5. 정확하고 명확해야 한다.

정돈된 코드 유지하기

  • 좋은 프로그래머는 코드의 좋은 레이아웃에 대해 깊이 고민한다. 하지만 탭과 스페이스와 같은 사소한 논쟁은 극복한다. 어른답게 행동하자.
  • 일반적으로 잘못된 레이아웃에 집중하는 상황은 잘못된 코드 리뷰 상황을 통해 설명 할수 있다. 코드가 주어졌을때 코드의 레이아웃에서 오류를 찾으려는 경향이 있다. 진정한 코드리뷰는 레이아웃이 아닌 코드 자체에 집중해야 하는 것이다.
  • 좋은 코드는 명백하며 일광성이 있다. 좋은 코드는 레이아웃이 눈에 띄지 않는다.
  • 프로그래머가 레이아웃에 신경을 쓰지 않는다면, 품질 문제에도 신경을 쓰지 않는 것이다. 레이아웃에도 항상 주의를 하자.
  • 코드 레이아웃보다 더 중요한것은 코드의 전체 형태와 구조를 파악할수 있도록 작성해야 하는 것이다. 더 중요한것들을 보자
  • 구조 잡기

    • 글을 쓰듯 코드를 작성해야 한다. 코드를 장, 문장, 문단 단위로 자르고, 비슷한 것끼리 묶고 다른것은 나누자.
    • 가장 중요한 정보는 마지막이 아닌 맨앞에 놓는다.
    • 코드를 읽는 사람을 고려하자. 작성한 사람이 아닌 이 코드를 읽는 사람을 고려하여 작성해야 한다.
  • 일관성

    • 여러 레이아웃을 지키려 하지 말고, 딱 하나만 골라서 일광성 있게 쓰자.
    • 사용하는 언에 알맞은 스타일을 고르는 것이 좋다.
  • 명명

    • 이름은 사물의 정체성을 의미한다. 그 어떤 사물이든간에 정확하게 무엇인지 알아야만 이름을 붙일수 있다. 명확하게 설명하지 못하거나 어떻게 쓰일지 모른다면, 제대로 이름을 붙일 수 없다.
    • 문맥이 내용을 좌지우지 한다. 명명할때는 문액을 확인하자.
    • 불필요한 반복을 피하고 문맥을 이용하라.
    • 명화하게 작성하라.
    • 광용어법을 지켜라.
    • 정확하게 하라.
  • 가다듬기

    • 코드를 정리정돈해야하는 경우에는 기능 변경과 모양 변경을 동시에 진행하지 말라. 두가지가 섞여 있을 커밋을 내용을 보면 혼란스럽다.
    • 자신만의 레이아웃 스타일을 발전시키자.

코드 적게 쓰기

  • 소프트웨어를 개선하는 최고의 방법 가운데 하나는 바로 코드를 제거 하는 것이다.
  • 돼지들이나 자신의 오물안에서 산다. 코드를 작성한 후에는 스스로 정리하고 불필요한 코드를 제거한다.
  • 코드가 길면 좋지 않은 이유에 대해서 알아보자.

    1. 코드를 길게 쓸수로 유지보수 비용은 증가한다.
    2. 긴 코드는 이해해야 할 내용이 많음을 의미하고, 이는 곧 프로그램을 파악하기 더 어렵게 만든다.
    3. 코드가 많을수록 수정해야 할 부분도 많아지고 수정하기도 어려워진다.
    4. 코드가 많을수록 버그가 많아진다.
  • 그렇다면 코드를 줄이기 위해서는 어떠한 방법을 사용할 수 있는지 알아보자.

    • 조건문의 중복적인 논리구조 남발을 꼽을 수 있다.
    if (expressions) {
    return true;
    } else {
    return false
    }
    
    // 위 코드는 다음 코드로 줄일 수 있다.
    return expressions;
    // 훨씬 간단하고 이해하기도 쉽다.
    if (a || (!a  b)) {
    // Code
    }
    
    // 위 코드는 다음 코드로 줄일수 있다.
    if ( a || b) {
    // Code
    }
  • 중복 제거

    • 게으른 프로그래머는 반복되는 코드를 공통 함수에 넣기를 고려하는 대신, 에디터를 통해 한 곳에서 다른 곳으로 물리적으로 복사하여 옮긴다. 붙여넣기를 한 코드에 약간의 변경이 더해질 때 죄악을 가증한다.
    • 약간 다르지만 비슷한 코드가 있다면, 다른 부분을 파악하여 하나의 함수에서 매개 변수로 분기 처리하자.
    • 공통 함수에 넣을 경우 긴밀한 결합도(coupling)을 가지게 되는데, 수정된 내용은 연관된 코드에 모두 적용되고 올바르게 작동해야 한다.
  • 죽은 코드 제거

    • 죽은 코드란 실행되거나 호출되지 않는 생명력 없는 코드를 말한다. 이러한 코드를 삭제하면 전체 코드량을 줄일 수 있다.
  • 주석 제거

    • 좋은 코드는 작동법을 설명하는 대량의 주석을 필요로 하지 않는다. 변수, 함수, 클래스 이름의 적적한 선택과 올바른 구조는 코드를 더욱 명확하게 만든다.
    • 주석을 달아야 할 만큼 복잡한 알고리즘은 거의 존재하지 않는다.
    • 애초에 주석을 달만한 코드를 작성하지 말라.
  • 장황한 내용

    • 많은 코드가 쓸데없이 수다스러운 경우가 있다. 코드를 줄일 수 있는지 다시 생각해보자
    • 삼항연산자를 두려워 하지 말자. 이는 코드를 줄이는데 도움이 된다.
    • 변수의 선언 부분과 정의 부분을 같은 위치에 쓰라. 코드 이해에 필요한 노력을 최소화하고 초기화 되지 않는 변수로 인한 잠재적 에러를 줄일수 있다.
  • 나쁜 설계

    • 사용되지 않는 많은 코드와 원래의 의도와 다른게 변화한 코드를 갈아엎는 것을 두려워 하지 말라.
    • 오래된 코드를 필요한 것만 남기고 간결한 컴포넌트로 바꿔라
  • 공백

    • 적절한 공백은 코드 구조에 도움이 된다. 다만 과한 사용은 좋지 않다.

코드 줄여 개선하기

  • YAGNI -> “You Aren’t Gonna Need It”(불필요한 코드를 작성하지 말자)
  • 당장 필요하지 않은 코드라면 작성하지 말고 정말로 필요할때 작성하라.
  • 새로운 코드를 추가하여 시스템을 개선 할 수 있다. 반대로 코드를 제거하여 시스템을 개선 할 수도 있다.
  • 제멋대로인 코드가 작성하지 않으려면 다음 사항을 유의 해야 한다.

    • 의미가 있을 때만 코드를 작성한다.
    • 당장 필요하지 않다면 지금 작성하지 않는다.
    • 여분의 작은 코드 덩어리는 시간이 지날수록 유지보수가 필요한 큰 덩어리로 변한다.
    • 프로그래머가 시스템의 요구사항을 결정하지 말자. 그것은 사용자의 몫이다.
  • 반대로 불가피한 상황으로 인해 죽은 코드가 발생하는 경우가 있다. 괴사 코드는 보통 다음과 같다.

    • 백엔드 지원 코드에 남아 있는 경우
    • 더는 사용되지 않는 자료형 또는 클래스가 프로젝트에 남아 있는 경우
    • 기존 제품의 기능들이 거의 제거되지 않는 경우
    • 코드에 대한 오랜 기간의 유지 보수로 인해 함수 일부가 실행되지 않는 경우
    • 잘 사용되지 않는 이벤트 핸들러가 있는 경우
    • 전혀 사용되지 않는 함수 반환 값이 있는 경우
    • 디버그 코드가 괴사하는 경우
  • 괴사 코드는 다음과 같은 문제를 야기한다. 그렇기 때문에 죽은코드는 정기적으로 적출 해야 한다.

    • 불필요한 코드 역시 다른 필요한 코드와 마찬가지로 유지 보수가 되어야 한다.
    • 추가적인 이해와 검토를 필요로 한다.
    • 사용 여부와 상관없이 쓸데없이 긴 코드는 주의깊게 프로그래밍할 수 없으며 엉성하게 작성할 수 밖에 없다.
    • 코드가 좀비로 가득차면 리팩토링이나 간소화, 최적화는 더 어려워진다.
  • 죽은 코드를 찾아내는 방법

    • 코드 작업을 할 때 주의를 기울인다.
    • 작업 후에는 쓸모 없는 코드를 확실하게 정리한다.
    • 정기적인 코드 리뷰는 죽은 코드를 찾는데 도움이 된다.
    • IDE를 활용한다.
  • 죽은 코드를 제거하는 일은 해롭지 않다. 이전 기능이 다시 필요할 때는 버전 관리 시스템으로 다시 살릴수 있다.
  • 죽은 코드를 제거하는 작업과 기능 축가 작업을 병행하지 말라. 항상 다른 개발작업과 대청소 기능을 분리한다.

코드베이스의 망령

  • 오래된 코드는 시간에 지남에 따라서 문제가 생길 수 있다.
  • 오래된 코드를 다시 살펴 보는 것은 코딩 기술 등을 향상시키는 데 도움을 준다.
  • 오래된 코드를 다시 보면 다음과 같은 이유로 끔찍한 기분에 휩싸일수 있다.

    • 외관
    • 코드를 작성했을시에 코딩 스타일과 지금의 코딩 스타일을 달라 보일수 있다.
    • 최신 기술
    • 라이브러리, 언어가 발전함에 따라서 이전에 작성한 코드가 구식처럼 보일 수 있다.
    • 관례
    • 처음 코드를 작성하였을때 관례적으로 사용한 코드가 시간이 지남에 따라서 다양한 모습으로 변경될 수 있다.
    • 설계 결정 사항
    • 이전 설계에서 결정한 내용들이 끔찍해 보일 수 있다
    • 버그
    • 오래된 코드를 보게 만드는 가장 큰 이유일 것이다. 오래된 코드를 다시 보았을때 이전에는 놓친 문제를 발견 할 수도 있다.
  • 오래된 코드는 고쳐야 할까?. -> 고장 나지 않았다면 고치지 말자. 코드 주변이 변하지 않는 이상 코드는 썩지 않는다.

경로 탐색하기

  • 거대한 코드베이스 적응하기란 어려운 일이다. 적응을 위해서는 다음과 같은 작업을 재빠르게 해내야 한다.

    • 코드의 어느 부분부터 보아야 하는지 파악하기
    • 코드의 부분별 기능을 알아내고, 그 기능을 어떻게 수행하는지 살펴보기
    • 코드의 품질을 가늠하기
    • 시스템 내부를 어떻게 탐색할 것인지 계획하기
    • 코딩 관례를 이해하고, 본인의 수정 사항이 그것과 어울리도록 만들기
    • 특정 기능이 있을 법한 위치를 파악하고, 그 기능에 의해 발생하는 버그 찾아보기
    • 코드와 함께 그것의 중요한 부속 부분들인 테스트 코드 및 문서등의 관계를 이해하기
  • 코드를 파악하는 가장 좋은 방법은 이미 코드를 파악하고 있는 사람의 도움을 얻는 것이다. 도움 요청을 주저하지 말자.
  • 합리적이고 적절한 질문을 하자. “제 숙제를 대신 해주실 수 있을까요”와 같은 질문을 통해서는 좋은 대답을 들을 수 없다.
  • 도와주는 사람이 없다면 코드속에서 단서를 찾아야 한다. 좋은 단서는 다음과 같다.

    • 소스 획득의 용이성
    • 코드 빌드의 용이성
    • 테스트
    • 파일 구조
    • 문서
    • 정적 분석
    • 요구사항
    • 프로젝트의 의존성
    • 코드 품질
    • 구조

똥통에서 뒹굴기

  • 훌륭한 코드는 순수 예술이나 한 편의 시와 같다. 아름다움이 있다.
  • 하지만 악취가 나는 똥통과 같은 코드가 있다. 이런 코드에서 일을 할 경우를 준비하자.
  • 나쁜 코드를 만났을 때 느껴지는 혐오감을 참으라. 대신 그걸 나아지게 할 방법을 찾으라.
  • 나쁜 코드를 고쳐야 할까? -> 시간을 지혜롭게 쓰라. 별다른 수정 없이도 몇 년 동안 적절히 작동했다면, 지금 수정하는 것은 적절하지 않을 수 있다.
  • 다만 지금 당장 코드를 수정하는게 적절하지 않다 판단했다고 해서, 오물 위에 둥둥 떠다녀도 된다는 것은 아니다. 간단한 수정부터 하자. 코드 외관을 수정하고, 변수명을 바꾸고, 복잡한 분기를 수정하자. 조금씩 나아지게 만들면 좋은 결과를 만들수 있다.
  • 나쁜 코드 수정하기

    • 코드 수정은 천천히 주의 깊게 하자. 한번에 하나씩이다.
    • 기능 변경을 하면서 코드의 레이아웃을 바꾸지 말라. 레이아웃을 바꾸고 커밋한뒤 기능변경을 해라.
    • 수정으로 인해 기존 기능에 문제가 생기지 않음을 보장할 수 있는 모든 수단을 사용하라.
    • 이 목표에 효과적으로 도달하려면 적절한 단위 테스트들로 코드를 충분히 둘러싸야 한다.
    • 코드를 감싼 API를 수정하되 내부 로직을 직접 수정하지 말라.
  • 코드에 비난을 퍼붓는건 도움이 되지 않는다. 일부러 잘못된 코드를 작성하려는 사람은 없다.

오류 무시하지 않기

  • 오류를 무시하는 것은 견고한 코드를 만들기 위한 좋은 전략이라고 할 수 없다. 항상 유심히 확인하고 검토해야 한다.
  • 코드에서 오류를 확인 하는 방법
  • 코드 응답

    • 함수(순수 함수)일 경우 일정한 값을 넣으면 항상 일정한 값을 돌려줄 것이다. 이를 확인하자.
  • 부수적 작용

    • 다중 쓰레드 사용 환경
  • 예외

    • 예외는 언어 자체에서 기원하는, 보다 구조적으로 오류를 전달하고 다루는 방법이다.
    try {
    // 어떤 것들
    } catch (e) {
    /// 오류 무시
    }
    • 이러한 코드는 사용하면 안된다. 이 코드는 도덕적으로 미심쩍은 행위를 하고 있다는 것을 나타낸다.
    • 예외는 완벽하지 않다. 예외를 사용할 경우에는 규칙에 맞게 잘 사용해야 한다.
  • 오류를 적절히 처리하지 않는다면 다음과 같은 일이 발생 한다.

    • 불안정한 코드
    • 불완전한 코드
    • 나쁜 구조
  • 코드에서 모든 잠재적인 오류를 확인해야 하는 것처럼, 사용자 인터페이스에서도 모든 잠재적인 잘못된 상황을 노출시켜야 한다. 그것들을 숨기지 말라. 정상적으로 작동하는 것처럼 보이게 하면 안된다.
  • 우리는 다음과 같은 이유로 오류를 확인하고 처리하지 않는다.

    • 오류 처리로 인하여 코드가 더 복잡해지는 경우
    • 마감시간의 압박
    • 해당 코드에서 절대 오류가 동작하지 않는 다는 사실
    • 정말 간단한 프로그램이라서
    • 언어가 익숙치 않아서
  • 위와 같은 이유는 무시해야 한다. 오류는 무시하면 안되다.

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

  • 코드 작성시 벌어질 것으로 예상되는 상황에 대한 대비만으로는 부족하다. 모든 단계에서, 조금이라도 발생할 가능성이 있는 특이 사항들은 모두 고려 해야 한다.
  • 오류

    • 항상 오류를 고려하여 작성하여 그로부터 복구 할 수 있도록 해야 한다. 복구하지 못한 오류 역시 고혀 해야 한다. 오류를 무시해서는 안된다.
  • 쓰레딩

    • 기본적인 동시 실행의 원리와 함께, 쓰레드간의 결합도를 완화하여 위험하게 상호 작용하지 않도록 하는 방법을 이해해야한다.
    • 경합 조건을 발생시키거나 불필요하게 쓰레드를 막지 않은 채, 스레드 간에 안정적이고도 신속하게 메세지를 전달하는 메커니즘에 대해서도 숙지해야 한다.
  • 셧다운

    • 리소소의 누출이나 데드락, 충돌없이 우아하게 중단시킬 수 있는지 고민해보자.
  • 위 모든것들은 개발 초기에 고려 해야 한다. 이 괴물들은 코드가 커진뒤에는 제거하기 어렵다.

버그 사냥하기

  • 버그는 피할수 없다.
  • 버그가 생긴 뒤에 고치기보다는 처음부터 버그가 생기지 않도록 적극적으로 에방 하는 편이 낫다.
  • 디버깅이 코드 작성보다 두 배는 힘들다. 그러니 코드를 작성할때 복잡한 코드를 작성하지 말고 이해할 수 있는 코드를 작성하자.
  • 버그가 고치기 얼마나 어려운지를 나타내는 두 가지 요소는 다음과 같다.

    • 재현가능성이 얼마나 되는가?
    • 버그가 포함된 코드와 이를 발견한 시점 사이의 간격이 얼마나 되는가?
    • 위 두가지가 높으면 높을수록 버그는 고치기 힘들어진다.
  • 버그를 잡기위한 좋은 방법
  • 함정 파기

    • 시스템 내의 불변 요소들을 검증하기 위해 테스트 코드(assert, console.log)를 삽입한다.
  • 이진 탐색 배우기

    • 코드를 한 줄씩 단순히 따라가기 보다는 일련의 시작과 끝을 확인하라. 그럼 다음 문제 공간을 두 개로 나누고, 가운데 시점에서 코드가 괜찮은지 확인한다.
    • 이렇게 한다면 문제 영역을 반으로 줄일 수 있다.
  • 소프트웨어 고고학

    • 과거 이력을 바탕으로 버전 관리 시스템을 뒤져보는 방법이다.
    • 어떤 코드 변경 모음으로 버그가 발생했는지 확인한다. 해당 방법으로 먼저 시도해보고 이진 탐색 전략을 사용한다.
  • 테스트

    • 단위 테스트를 작성하는데 시간을 투자하라.
    • 간단하고 재현 가능한 단위 테스트 케이스는 완전히 가동되는 프로그램보다 디버깅하기 훨씬 수월한 발판 역할을 한다.
    • 버그의 원인을 최종 수정하였다면, 문제를 명백히 재현해내는 간단한 코드를 작성하고 테스트 코드에 추가하라.
  • 좋은 도구 사용하기

    • 버그를 탐지할 수 있는 좋은 도구들을 사용하고 몸에 익히자.
  • 코드를 제거 하라

    • 코드 탐색시 연관되지 말아야 할 주제들은 서로 엮이지 않도록 한다.
    • 서로 관련싱이 없어 보이는 코드의 세부 항목들도 삭제 한다.
  • 청경은 감역을 막는다.

    • 버그가 소프트웨어에 필요 이상으로 오래 머물지 않도록 해야 한다.
    • 최대한 빨리 버그를 고쳐라. 코드 오물통에 빠질때까지 쌓이게 놓아두서는 안된다.
  • 간접적 전략

    • 때로는 몇 시간동안 씨름하지만 아무것도 얻지 못하는 경우도 발생한다. 이럴때는 간접적 접근 적략을 시도한다.
    • 쉬어가기 (휴식하기)
    • 다른 사람에게 설명하기
  • 재현할 수 없는 버그

    • 재현 방법을 찾을 수 없는 버그를 발견 하기도한다. 버그가 논리과 추론을 거부하는 것이다.
    • 실패를 유발하는 요소들을 기록하라. 이를 반복하다 보면 어떤 패턴을 발견 하는데 도움이 될것이다.
    • 더 많은 테스트와 실제 사용시 정보를 로그로 남긴다.
    • 보통 다음과 같을 때 재현할 수 없는 버그가 발생한다.

      1. 쓰레드를 이용하는 코드
      2. 네트워크 상호 작용
      3. 저장 장치의 다양한 속도
      4. 메모리 손상
      5. 전역 변수/싱글톤

테스트하기

  • 좋은 소프트를 제대로 만들기 위해서는 피드백을 받아야 한다. 가능하면 자주, 그리고 빨리 피드백을 받는 것이 좋다. 좋은 테스트 전략이란 피드백 절차를 간소화하는 것으로, 이를 통해 더 효율적으로 일할 수 있다.
  • 피드백 과정이 짧을수록 설계 변경을 더 빠르게 반복할 수 있고 코드에 대해 더 강하게 확신할 수 있다.
  • 문제를 빨리 알수록 수정은 쉬워지고 비용은 낮아진다.
  • 자동화된 테스트를 통해 피드백 과정을 줄이면, 코드에 개발 과정에 도움이 될 뿐만 아니라 재활용도 가능하다는 이점이 있다.
  • 개발자란 더 열심히 일하기 보다는 더 영리하게 일해야 한다.
  • 코드에 대한 확신은 곧 테스트 코드의 품질에 따라 결정된다.
  • 테스트 코드는 코드를 작성한 사람 자신이 테스트 코드를 작성해야 한다는 것이다.
  • 테스트의 종류

    • 유닛 테스트(Unit Tests)
    • 가장 작은 단위의 기능 테스트를 단독으로 수행한것으로, 각각의 함수가 정확히 작동하는지 확인하기 위한 것이다.
    • 단독이라는 말은 어떤 외부에 대한 접속도 하지 않는다는 뜻이다. 데이터 베이스, 네트워크, 파일 시스템없이 실행된다는 것이다.
    • 통합 테스트(Intergration Tests)
    • 통합 테스트를 통해 각각의 단위 모듈을 더 큰 결합체로 통합하여 작동시키는 복합 기능을 검증할 수 있다.
    • 많은 사람들이 말하는 ‘유닛 테스트’는 실제로는 통합 테스트의 수준의 테스트로서, 테스트 대상이 하나 이상의 객체들인 테스트를 의미한다.
    • 시스템 테스트(System Tests)
    • ‘종단 간 테스트’라고도 알려진 이 테스트를 통해 전체 시스템에 대한 요구사항 명세를 확인 할 수 있다.
  • 테스트 코드는 미루면 미룰수록 덜 효과적이다. 가장 좋은 방법은 코드를 작성하면 테스트를 같이 작성하는 것이다. 아니면 버그를 수정할 때이다. 코드 수정을 무작정 하기 보다는 우선 버그의 원일을 설명하는 실패 유닛 테스트를 작성하라.
  • 테스트 코드는 지속적으로 추가 되야 하며 모든 테스트는 빌드서버에서 실행되야 한다. 테스트는 수작업으로 실행 시키면 안된다. 자동으로 실행되야 한다.
  • 테스트 코드를 완벽하게 넣었다 하더라도 사람에 의한 QA는 필요 하다.
  • 좋은 테스트란.?

    • 짧고 명확한 이름을 가지고 있어 실패 했을때 무엇이 문제인지 쉽게 알수 있다.
    • 유지보수가 가능하다. 작성은 물론 읽고 수정하기도 쉽다.
    • 수행에 오랜 시간이 걸리지 않는다.
    • 최신 구현코드에 맞춰져 있다.
    • 특별한 머신 설정이 필요 없다.
    • 다른 테스트에 대한 의존성이 없어서 특정 테스트 전후에 실행할 필요가 없다. 외부 상태나 코드상의 어떤 공유 변수에 대한 의존성이 없다.
    • 실제 구현 코드를 테스트한다.
  • 나쁜 테스트란.?

    • 때로는 성공하고 때로는 실패하는 테스트
    • 이상해 보이고, 읽거나 수정하기 힘든 테스트
    • 하나의 테스트 케이스에서 둘 이상을 수행하는 테스트
    • 클래스 API에 대해 개별 행태를 확인하는 것이 아닌 함수마다 공격을 하는 테스트
    • 직접 장성하지 않은 서드파티 코드에 대한 테스트
    • 클래스의 주요 기능이나 행태에 대해 실제로 테스트를 하지 않는데다 별다른 필요없는 테스트들로 상황을 숨기는 테스트
    • 지나치게 상세하여 중구난방인 테스트
    • SUT의 내부 구현에 대한 지식을 바탕으로 한 화이트박스식 테스트
    • 단 하나의 머신에서만 수행가능한 테스트
  • 테스트가 코드의 중요 기능을 모두 다룬다는 점을 보장하라. ‘정상적인’입력 값들은 물론, 일반적인 실패 케이스를 비롯해 빈 값이나 0과 같은 경곗값에서 발생 할 수 있는 모든 경우의 수를 고려 해야 한다.
  • 테스트는 중복해서 수행하지 않으며 각 테스트 케이스는 하나의 정의만을 검증해야 한다.
  • 개발자가 테스트에 들이는 노력은 물물교환과 같다. 즉 확신을 억기 위해 얼마나 많은 노력을 테스트 작성에 투자할 것인지의 문제다.
  • 작성해야 할 만큼 중요한 코드라면 테스트해야 할 만큼 중요한것이다. 그러므로 구현한 코드에 대해 개발자 테스트 코드를 작성하라.

복잡도 다루기

  • 복잡한 무언가를 작성하는 일은 너무나 쉽게 이루어진다. 집중하지 안고 충분히 계획을 세우지 않으면 일어날 수 있다.
  • 소프트웨어의 복잡도는 크게 세가지 원인에서 기인하며, 그중 두가지는 블럽(blob)라인(line), 그리고 사람이다
  • 블럽(blob)

    • 블런은 컴포넌트를 말한다.
    • 블럽의 크기와 수가 복잡도를 결정한다.
    • 크기 자체는 문제가 되지 않는다. 이 코드를 어떻게 구성하는가 하는 점이 문제가 되는 것이다. 즉 크기를 어떻게 배분할 지에 대한 문제이다.
    • 실제로 간결해지도록 설계하려면, 각 블럽이 정확한 역할과 책임을 갖도록 해야 한다.
    • 하나의 역할을 시스템 전반에 흩어 놓기 보다는 하나의 부분에 배치해야 한다.
  • 라인(line)

    • 블럽을 서로 연결하는 과정에서 생성되는 것이 라인이다.
    • 라인이 적을수록 소프트웨어 디자인은 간결해진다.
    • 블럽 사이의 연결이 많아질수록 설계는 경직되며, 시스템상에서 작업 시 이해해야 할 (그리고 싸워야 할) 연동이 더 많아진다.
    • 연결들을 배치할 때 객체들 간의 순환 열결 관계로 인해 복잡도가 증가 하기도 한다.
  • 사람

    • 책읨은 코드를 작성하는 사람에게 있다.
    • 복잡도를 줄일 수 있는 유일한 방법은 소프트웨어에 책임감을 가지고, 업무 압박으로 인해 적절하지 않은 구조로 코드를 밀어넣는 상활을 피하고자 노력 하는 것이다.

두 개의 시스템에 대한 이야기

  • 잘 된 소프트웨어와 그렇지 못한 소프트웨어 두개를 비교하고 잘된 이유, 안된 이유를 나열 하였다.
  • 지저분한 대도시

    • 이해 불가
    • 응집도의 부족
    • 불필요한 결합
    • 코드 문제
    • 코드 외부 문제
  • 디자인 타운

    • 기능 위치 선정
    • 일관성
    • 구조 확장
    • 품질 유지
    • 기술 부채 관리
    • 테스트
    • 설계를 가지고 작업하기
Loading script...