책 자체에 좋은 내용이 많지만 기본적으로 같은 내용을 반복해서 길게 말한다는 느낌을 받았다.
그러다보니 조금 지루해지기 시작했고 내 스타일의 도서가 아니란 것을 알게되었다.
또한 오래된 도서였기 때문에 현재의 유행(?)과는 조금 다른 부분도 충분히 존재하는 것 같았다.
이것과 관련해서 동료와 얘기를 했었는데, 동의하지 못하는 부분들도 있었다.
(정답은 없기때문이지..)
여태 읽은 내용은 머리에 잘 세겨두도록하고 다른 도서로 갈아타야겠다.
05. 형식 맞추기
코드 형식을 맞추기 위한 간단한 규칙을 정하고 착실히 따라야 한다.
팀으로 일한다면 팀이 합의하여 규칙을 정한다.
필요하면 규칙을 자동으로 적용하는 도구를 활용한다.
형식을 맞추는 목적?
코드 형식은 의사소통의 일환이다.
늘 구현한 기능이 다음 버전에서 바뀔 수도 있다. 그런데 구현한 코드의 가독성에 따라 바뀔 코드의 품질에 영향을 미칠 것이다. 오랜 시간이 지나 원래 흔적을 찾아보기 어려워져도 맨 처음 잡아둔 구현 스타일과 가독성의 수준은 유지보수 용이성과 확장성에 계속 영향을 미칠 것이다. (개발자의 스타일과 규율)
적절한 행 길이를 유지하라
신문 기사처럼 작성하라
위에서 아래로 기사를 읽는 것처럼 아래로 내려갈 수록 의도를 세세하게 묘사하라.
이름은 간단하면서 설명이 가능하게 짓는다. 이름만 보도고 모듈을 살펴보고 판단할 수 있도록 신경써서 짓는다.
(소스 파일 처음은 고차원 개념과 알고리즘, 끝 부분은 저차원함수와 세부내역이 나오게 작업한다?)
개념은 빈행으로 분리하라
패키지 선언부, import문, 각 함수 사이에 빈행이 들어간다.
너무도 간단한 규칙이지만 코드의 세로 레이아웃에 심오한 영향을 미칠수 있다.
빈 행은 새로운 개념을 시작한다는 시각적 단서이다.
세로 밀집도
줄 바꿈이 개념을 분리한다면 세로 밀집도는 연관성을 의미한다.
서로 밀접한 코드 행은 세로로 가까이 놓아야한다.
수직 거리
서로 밀접한 개념은 세로로 가까이 둬야한다. (변수 선언, 인스턴스 변수, 종속 함수, 개념적 유사성)
세로 순서
가로 형식 맞추기
예전에는 오른쪽으로 스크롤할 필요가 없도록 코드를 구현했다. 하지만 요즘은 모니터 크기도 커졌고 글꼴 크기도 작게 작업하는 사람들이 많이 생겼다. 하지만 이렇다고해서 200자까지 한 화면에 들어가게는 하지마라.
행 길이를 제한하라.
가로 공백과 밀집도
가로로는 공백을 사용해 밀접한 개념과 느슨한 개념을 표현한다.
가로 정렬
들여쓰기
프로그래머는 들여쓰기 체계에 크게 의존한다. 코드를 맞춰 코드가 속한 범위를 시각적으로 표현한다.
가짜 범위
팀 규칙
팀은 한가지 규칙에 합의해야한다.
그리고 합의된 규칙을 따라야한다.
그래야 소프트웨어가 일관적이다.
밥 아저씨의 형식 규칙
06. 객체와 자료 구조
이번 장은 어려워서 이해가 잘 안간 부분이 많다.
자료 추상화
변수를 비공개로 정의 -> 의존성을 낮추기 위해
그런데 왜 조회(get)와 설정(set) 함수는 공개하여 비공개 변수를 외부에 노출 시킬까?
변수 사이에 함수라는 계층을 넣는다고 구현이 저절로 감춰지지는 않는다. (= 비공개 되지는 않는다?)
-> 구현을 감추려면 추상화가 필요하다? -> 즉, 추상 인터페이스를 제공해 사용가자 구현을 모른 채 자료의 핵심을 조작할 수 있어야 진정한 의미의 클래스다?
자료/객체 비대칭
객체는 추상화 뒤로 자료를 숨긴 채 자료를 다루는 함수만 공개(내부 구조를 숨긴다)
자료구조는 자료를 그대로 공개하며 별다른 함수는 제공하지 않는다. (내부 구조 노출)
-> 객체 지향 코드에서 어려운 변경은 절차적인 코드에서 쉽다. 절차적인 코드에서 어려운 변경은 객체 지향 코드에서 쉽다.
디미터 법칙
모듈은 자신이 조작하는 객체의 속 사정을 몰라야한다.
잡종 구조
절반은 객체, 절반은 자료구조이다. 새로운 함수, 자료 구조를 추가하기 어려우므로 되도록 피하는 것이 좋다.
자료 전달 객체
자료 구조체의 전형적인 형태는 공개 변수만 있고 함수가 없는 클래스이다.
활성 레코드
DTO의 특수한 형태, 활성 레코드에 비즈니스 규칙 메서드를 추가해(=자료구조가 됨???) 객체로 취급하는 것은 바람직하지 않다. (-> 자료 구조도 객체도 아니게 되는 잡종 구조)
결론
개발자는 하나에 편견을 가지지 말고 사실을 이해하고 최적인 선택을 해야한다.
객체는 동작을 공개하고 자료를 숨김. -> 시스템 구현 시 새로운 자료 타입 추가할 경우 적합
자료 구조는 별다른 동작 없이 자료를 노출. -> 새로운 동작을 추가할 경우 자료구조/절차적인 코드가 적합
07. 오류 처리
오류처리는 프로그램에 반드시 필요한 요소 중 하나이다.
무언가 잘못될 가능성은 늘 존재하며 바로 잡을 책임은 프로그래머에게 있다.
그리고 오류 처리 코드로 인해 프로그램 논리를 이해하기 어려워진다면 깨끗한 코드라 부르기 어렵다.
오류 코드보다 예외를 사용하라
호출자 코드에서 분기문으로 오류를 처리할 경우 호출자 코드가 복잡해지기 때문에 예외를 사용한다.
-> 알고리즘과 오류 처리 알고리즘을 분리
Try-Catch-Finally문을 유용하게 사용하라
미확인(unchecked) 예외를 사용하라
예외에 의미를 제공하라
오류 메세지에 정보를 담아 예외와 함께 던진다.
호출자를 고려해 예외 클래스를 정의하라
-> 외부 API 사용 시 감싸기 기법이 최선일 것이다.
정상 흐름을 정의하라
특수 사례 패턴 -> 클래스를 만들거나 객체를 조작해 특수 사례를 처리하는 방식
null을 반환하지 마라, 전달하지 마라
호출자에게 문제를 떠넘기는 코드이므로 예외를 던지거나 특수 사례 객체를 반환하라
결론
깨끗한 코드는 읽기도 좋아야하지만 안정적이어야한다.
오류 처리를 프로그램 논리와 분리해 독자적인 사안으로 고려하게된다면 튼튼하고 깨끗한 코드를 작성할 수 있을 것이다. 또한 독립적인 추론이 가능해지고 코드 유지보수성도 높아진다.
08. 경계
시스템에 들어가는 모든 소프트웨어를 직접 개발하는 경우는 드물다. 때로는 패키지를 사기도하고 오픈소스나 컴포넌트를 사용한다.
외부 코드를 우리 코드에 깔끔하게 통합하여 경계를 깔끔하게 처리하는 기법과 기교를 살펴보는 장이다.
-> 제공자는 많은 환경에서 돌아가야 하기 때문에 적용성을 최대한 넓히여 애를 쓰고 사용자는 자신의 요구에 집중하는 인터페이스만을 바란다. 이 두 경계에서 문제가 생길 가능성을 고려해야한다.
외부 코드 사용하기
경계 인터페이스를 이용할 때는 이를 이용하는 클래스나 클래스 계열 밖으로 노출되지않도록 주의한다.
경계 살피고 익히기
우리쪽 코드를 먼저 작성해 외부 코드를 호출하는 대신 먼저 간단한 케이스를 작성해 외부 코드를 익힌다.
log4j 익히기
학습 테스트는 공짜 이상이다
학습 테스트를 이용한 학습이 필요하든, 그렇지 않든, 실제 코드와 동일한 방식으로 인터페이스를 사용하는 테스트 케이스가 필요하다.
아직 존재하지 않는 코드를 사용하기
아는 코드와 모르는 코드를 분리하는 경계
깨끗한 경계
변경 비용이 커지지 않도록 주의해야한다.
09. 단위 테스트
과거에는 TDD 개념을 몰랐다. 대다수의 테스트라고 하면 `돌아간다`는 사실만 확인하는 일회성 코드에 불과했다.
지금은 프로그램만 도는 것이 아닌 코드가 제대로 도는 지 확인하는 테스트 코드를 작성한다.
테스트 케이스를 구현하고 이 코드를 사용하는 사람들에게도 공개한다.
(테스트 코드와 내 코드를 같은 소스 패키지로 묶어 배포)
TDD 법칙
TDD가 실제 코드를 짜기 전에 단위테스트부터 짜는 것을 요구한다.
방대한 테스트 코드가 나오면 관리 문제가 발생한다.
깨끗한 테스트 코드 유지하기
테스트 케이스가 늘어나는 부담, 그리고 이에 따른 유지 보수 비용 증가
즉, 테스트 코드를 막 짜도 좋다고 허용하게 된다면 테스트 코드가 늘어가는 것이 부담되고 이에따라 유지 보수 비용이 증가한다. 결국 이렇게되면 개발자는 테스트 케이스와 코드의 정리 및 수정을 포기하게 된다.
그렇기 때문에 테스트 코드도 실제 코드 못지 않게 중요하게 작성해야한다.
테스트는 유연성, 유지보수성, 재사용성을 제공한다.
테스트 코드를 깨끗한게 유지하지 않으면 결국은 잃게된다.
깨끗한 테스트 코드
가독성이 가장 중요하다. 최소한의 표현으로 많은 것을 나타내야하며 테스트는 명확히 나누어야한다.
도메인에 특화된 테스트 언어
이중 표준
테스트 당 asset 하나(=테스트 당 개념 하나)
assert문이 하나일 경우 결론이 하나이기 때문에 코드를 이해하기 쉽고 빠르다.
독자적인 개념 세개를 테스트할 경우 테스트를 세개로 나눈다.
결론
테스트 코드는 실제 코드만큼이나 프로젝트 건강에 중요하다. 테스트 코드는 실제 코드의 유연성, 유지보수성, 재사용성을 보존하고 강화하며 테스트 코드가 방치되어 망가지면 실제 코드에도 영향이 있다.
그러므로 테스트 코드는 지속적으로 깨끗하게 관리해야하며 표현력을 높이고 간결하게 정리한다.
10. 클래스
클래스 체계
변수 목록 다음에는 공개 함수가 나온다, 비공개 함수는 자신을 호출하는 공개 함수 직후에 넣는다.
즉, 추상화 단계가 순차적으로 내려간다.
캡슐화
공개하지 않는 편이 낫지만 반드시 숨겨야 한다는 법칙은 없다.
하지만 그 전에 비공개 상태를 유지할 온갖 방법을 강구한다.
캡슐화를 풀어주면 결정은 언제나 최후의 수단이다.
클래스는 작아야한다.
클래스를 만들때 가장 기본적인 규칙은 크기이다. 그렇다면 얼마나 작아야할까?
-> 물리적인 행 수로 크기를 측정하는 것이 아닌 클래스가 맡은 책임의 갯수이다.
단일 책임 원칙
클래스나 모듈을 변경할 이유가 하나여야한다.