독서록
[Clean Architecture] 4부: 컴포넌트 원칙 - 14장 컴포넌트 결합
ADP: 의존성 비순환 원칙 컴포넌트 의존성 그래프에 순환(cycle)이 있어서는 안 된다. 순환이 생기면 컴포넌트를 분리하기가 상당히 어려워진다. 단위 테스트를 하고 릴리스를 하는 일도 굉장히 어려워지며 에러도 쉽게 발생한다. 게다가 모듈의 개수가 많아짐에 따라 빌드 관련 이슈는 기하급수적으로 증가한다. 뿐만 아니라 의존성 그래프에 순환이 생기면 어떤 순서로 빌드해야 올바를지 파악하기가 상당히 힘들어진다. 사실 순환이 생기면 올바른 순서라는 것 자체가 없을 수 있다. 순환을 끊는 방법 의존성 역전 원칙(DIP)을 적용한다. 인터페이스를 통해 의존성을 역전시키는 방법이다. 모두가 의존하는 새로운 컴포넌트를 만든다. 그리고 의존하는 클래스들을 새로운 컴포넌트로 이동시킨다. 하향식(top-down) 설계 컴..
[Clean Architecture] 4부: 컴포넌트 원칙 - 13장 컴포넌트 응집도
REP: 재사용/릴리스 등가 원칙(Reuse/Release Equivalence Principle) 재사용 단위는 릴리스 단위와 같다. 소프트웨어 컴포넌트가 릴리스 절차를 통해 추적 관리되지 않거나 릴리스 번호가 부여되지 않는다면 해당 컴포넌트를 재사용하고 싶어도 할 수도 없고, 하지도 않을 것이다. 릴리스 번호가 없다면 재사용 컴포넌트들이 서로 호환되는지 보증할 방법이 전혀 없다. 또한 릴리스 번호를 통해 새로운 버전이 언제 출시되고 무엇이 변했는지를 소프트웨어 개발자들이 알아야 한다. 이 원칙을 소프트웨어 설계와 아키텍처 관점에서 보면 단일 컴포넌트는 응집성 높은 클래스와 모듈들로 구성되어야 함을 뜻한다. 컴포넌트를 구성하는 모든 모듈은 서로 공유하는 중요한 테마나 목적이 있어야 한다. 하나의 컴포넌..
[Clean Code] 10장 클래스
클래스 체계 클래스를 정의하는 표준 자바 관례에 따르면, 가장 먼저 변수 목록이 나온다. 정적(static) 공개(public) 상수가 있다면 맨 처음에 나온다. 다음으로 정적 비공개(private) 변수가 나오며, 이어서 비공개 인스턴스 변수가 나온다. 공개 변수가 필요한 경우는 거의 없다. 변수 목록 다음에는 공개 함수가 나온다. 비공개 함수는 자신을 호출하는 공개 함수 직후에 넣는다. 즉, 추상화 단계가 순차적으로 내려간다. 캡슐화 때로는 변수나 유틸리티 함수를 protected로 선언해 테스트 코드에 접근을 허용하기도 한다. 같은 패키지 내에서 테스트 코드가 함수를 호출하거나 변수를 사용해야 한다면 그 함수나 변수를 protected로 선언하거나 패키지 전체로 공개한다. 클래스는 작아야 한다 함수..
[Clean Code] 9장 단위 테스트
TDD 법칙 세 가지 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다. 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다. 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다. 위 세 가지 규칙을 따르면 개발과 테스트가 대략 30초 주기로 묶인다. 테스트 코드와 실제 코드가 함께 나올뿐더러 테스트 코드가 실제 코드보다 불과 몇 초 전에 나온다. 깨끗한 테스트 코드 유지하기 테스트는 유연성, 유지보수성, 재사용성을 제공한다. 테스트 케이스가 있으면 변경이 쉬워지기 때문이다. 따라서 테스트 코드가 지저분하면 코드를 변경하는 능력이 떨어지며 코드 구조를 개선하는 능력도 떨어진다. 테스트 코드가 지저분할수록 실제 코드도 지저분해진다. 깨끗한 테스트 코드를 만들..
[Clean Code] 8장 경계
학습 테스트 외부 코드(오픈소스, 라이브러리)를 익히기는 어렵다. 외부 코드를 통합하기도 어렵다. 해결 방법으로 우리 쪽 코드를 작성해 외부 코드를 호출하는 대신 먼저 간단한 테스트 케이스를 작성해 외부 코드를 익히는 방법이 있다. 이 방법을 학습 테스트라 부른다. 학습 테스트는 패키지가 예상대로 도는지 검증한다. 일단 통합한 이후라고 하더라도 패키지가 우리 코드와 호환되리라는 보장은 없다. 패키지 새 버전이 나올 때마다 새로운 위험이 생긴다. 새 버전이 우리 코드와 호환되지 않으면 학습 테스트가 이 사실을 곧바로 밝혀낸다. 학습 테스트를 이용한 학습이 필요하든 그렇지 않든, 실제 코드와 동일한 방식으로 인터페이스를 사용하는 테스트 케이스가 필요하다. 이런 경계 테스트가 있다면 패키지의 새 버전으로 이전..
[Clean Code] 7장 오류 처리
Try-Catch-Finally 문부터 작성하라 try 블록에서 무슨 일이 생기든지 catch 블록은 프로그램 상태를 일관성 있게 유지해야 한다. 그러므로 예외가 발생할 코드를 짤 때는 try-catch-finally 문으로 시작하는 편이 낫다. 그러면 try 블록에서 무슨 일이 생기든지 호출자가 기대하는 상태를 정의하기 쉬워진다. 먼저 강제로 예외를 일으키는 테스트 케이스를 작성한 후 테스트를 통과하게 코드를 작성하는 방법을 권장한다. 그러면 자연스럽게 try 블록의 트랜잭션 범위부터 구현하게 되므로 범위 내에서 트랜잭션 본질을 유지하기 쉬워진다. 예외에 의미를 제공하라 예외를 던질 때는 전후 상황을 충분히 덧붙인다. 그러면 오류가 발생한 원인과 위치를 찾기가 쉬워진다. 오류 메시지에 정보를 담아 예외..
[Clean Code] 6장 객체와 자료 구조
자료 추상화 자료를 세세하게 공개하기보다는 추상적인 개념으로 표현하는 편이 좋다. 인터페이스나 조회/설정 함수만으로는 추상화가 이뤄지지 않는다. 개발자는 객체가 포함하는 자료를 표현할 수 있는 가장 좋은 방법을 심각하게 고민해야 한다. (자료 구조를 사용하는) 절차적인 코드는 기존 자료 구조를 변경하지 않으면서 새 함수를 추가하기 쉽다. 반면, 객체 지향 코드는 기존 함수를 변경하지 않으면서 새 클래스를 추가하기 쉽다. 다시 말해, 객체 지향 코드에서 어려운 변경은 절차적인 코드에서 쉬우며, 절차적인 코드에서 어려운 변경은 객체 지향 코드에서 쉽다. 디미터 법칙 객체는 조회 함수로 내부 구조를 함부로 공개하면 안 된다는 법칙. 디미터 법칙은 "클래스 C의 메서드 f는 다음과 같은 객체의 메서드만 호출해야..
[Clean Code] 5장 형식 맞추기
형식을 맞추는 목적 오랜 시간이 지나 원래 코드의 흔적을 더 이상 찾아보기 어려울 정도로 코드가 바뀌어도 맨 처음 잡아놓은 구현 스타일과 가독성 수준은 유지보수 용이성과 확장성에 계속 영향을 미친다. 원래 코드는 사라질지라도 개발자의 스타일과 규율은 사라지지 않는다. 적절한 행 길이를 유지하라 일반적으로 큰 파일보다 작은 파일이 이해하기 쉽다. 이름은 간단하면서도 설명이 가능하게 짓는다. 이름만 보고도 올바른 모듈을 살펴보고 있는지 아닌지를 판단할 정도로 신경 써서 짓는다. 소스 파일 첫 부분은 고차원 개념과 알고리즘을 설명한다. 아래로 내려갈수록 의도를 세세하게 묘사한다. 마지막에는 가장 저차원 함수와 세부 내역이 나온다. 서로 밀접한, 연관성 있는 개념은 세로로 가까이 둬야 한다. 물론 두 개념이 서..