창발적 설계로 깔끔한 코드를 구현하자
- 켄트 백이 제시한 단순한 설계 규칙 네 가지가 소프트웨어 품질을 크게 높여준다고 믿는다.
1. 모든 테스트를 실행한다.
2. 중복을 없앤다.
3. 프로그래머 의도를 표현한다.
4. 클래스와 메서드 수를 최소로 줄인다. - 이로 인해 코드 구조와 설계를 파악하기 쉬워져
단일 책임 원칙, 의존 관계 역전 원칙을 적용하기 쉬워지고 우수한 설계의 창발성을 촉진하게 된다.
단순한 설계 규칙 1: 모든 테스트를 실행하라
- 설계는 의도한 대로 돌아가는 시스템을 내놓아야 한다.
- 테스트를 철저히 거쳐 모든 테스트 케이스를 항상 통과하는 시스템은 '테스트가 가능한 시스템'이다.
테스트가 불가능한 시스템은 검증도 불가능하다. - 테스트가 가능한 시스템을 만들려고 애쓰면 설계 품질이 더불어 높아진다.
- 테스트 케이스를 많이 작성할수록 개발자는 의존 관계 역전 원칙과 같은 원칙을 적용하고
의존성 주입, 인터페이스, 추상화 등과 같은 도구를 사용해 결합도를 낮춘다. 따라서 설계 품질은 더욱 높아진다. - 테스트 케이스를 만들고 계속 돌리는 단순한 규칙을 따르면
시스템은 낮은 결합도와 높은 응집력이라는 객체 지향 방법론이 지향하는 목표를 저절로 달성한다.
단순한 설계 규칙 2~4: 리팩터링
- 테스트 케이스를 모두 작성했다면 코드와 클래스를 점진적으로 리팩터링 해나간다.
- 테스트 케이스가 있으므로 코드를 정리하면서 시스템이 깨질까 걱정할 필요가 없으므로
깔끔히 코드를 정리한 후 테스트 케이스를 돌려 기존 기능을 깨뜨리지 않았다는 사실을 확인한다. - 리팩터링 단계에서는 소프트웨어 설계 품질을 높이기 위해서라면 응집도를 높이고, 결합도를 낮추고, 관심사를 분리하고,
시스템 관심사를 모듈로 나누고, 함수와 클래스 크기를 줄이고, 더 나은 이름을 선택하는 등 다양한 기법을 동원한다.
중복을 없애라
- 중복은 추가 작업, 추가 위험, 불필요한 복잡도를 뜻하므로 우수한 설계에서 커다란 적이다.
- 비슷한 코드는 더 비슷하게 고쳐주면 리팩터링이 쉬워진다.
// bad
// 코드 각각 구현
int size() {}
boolean isEmpty() {}
// good
// size 메서드를 이용하여 isEmpty 메서드 구현
int size() {}
boolean isEmpty() {
return 0 == size();
}
- 깔끔한 시스템을 만들려면 단 몇 줄이라도 중복을 제거하겠다는 의지가 필요하다.
- 공통적인 코드를 새 메서드로 뽑게 될 경우 클래스가 단일 책임 원칙을 위반하게 되므로
뽑혀진 메서드를 다른 클래스로 옮기게 되면 가시성이 높아지고
다른 팀원이 새 메서드를 좀 더 추상화해 다른 맥락에서 재사용할 기회를 포착할지도 모른다. - 소규모 재사용은 시스템 복잡도를 극적으로 줄여주며 소규모 재사용을 제대로 익혀야 대규모 재사용이 가능하다.
- TEMPLATE METHOD 패턴은 고차원 중복을 제거할 목적으로 자주 사용하는 기법으로
중복을 모아 상위 클래스에 작성해 제거하고 하위 클래스는 중복되지 않는 정보만 제공해 알고리즘에서 빠진 구멍을 메운다.
표현하라
- 자신이 이해하는 코드를 짜기는 쉽지만
나중에 코드를 유지보수할 사람이 코드를 짜는 사람만큼이나 문제를 깊이 이해할 가능성이 희박하다. - 그러므로 코드는 개발자의 의도를 분명히 표현해야 한다.
개발자가 코드를 명백히 짤수록 다른 사람이 그 코드를 이해하기 쉬워진다. 그래야 결함이 줄어들고 유지보수 비용이 적게 든다. - 1. 좋은 이름을 선택한다.
이름과 기능이 완전히 딴판인 클래스나 함수로 유지보수 담당자를 놀라게 해서는 안 된다. - 2. 함수와 클래스 크기를 가능한 줄인다.
작은 클래스와 작은 함수는 이름 짓기도 쉽고, 구현하기도 쉽고, 이해하기도 쉽다. - 3. 표준 명칭을 사용한다.
디자인 패턴은 의사소통과 표현력 강화가 주목적이므로 표준 패턴을 사용해 구현된다면 클래스 이름에 패턴 이름을 넣어준다.
그러면 다른 개발자가 클래스 설계 의도를 이해하기 쉬워진다. - 4. 단위 테스트 케이스를 꼼꼼히 작성한다.
잘 만든 테스트 케이스를 읽어보면 클래스 기능이 한눈에 들어온다. - 하지만 표현력을 높이는 가장 중요한 방법은 노력이다.
자신의 작품에 조금만 더 주의를 기울이자. 주의는 대단한 재능이다.
클래스와 메서드 수를 최소로 줄여라
- 중복을 제거하고, 의도를 표현하고, 단일 책임 원칙을 준수한다는 기본적인 개념도 극단으로 치달으면 득보다 실이 많아진다.
- 클래스와 메서드 크기를 줄이자고 조그만 클래스와 메서드를 수없이 만들지 말고 함수와 클래스 수를 가능한 줄이자.
- 목표는 함수와 클래스 크기를 작게 유지하면서 동시에 시스템 크기도 작게 유지하는 데 있다.
- 하지만 이 규칙은 간단한 설계 규칙 중 우선순위가 가장 낮으므로
클래스와 함수 수를 줄이는 작업도 중요하지만, 테스트 케이스를 만들고 중복을 제거하고 의도를 표현하는 작업이 더 중요하다.
'Java-Spring > 클린 코드' 카테고리의 다른 글
[클린 코드] 14장. 점진적인 개선 (0) | 2023.03.12 |
---|---|
[클린 코드] 13장. 동시성 (0) | 2023.03.11 |
[클린 코드] 11장. 시스템 (0) | 2023.03.07 |
[클린 코드] 10장. 클래스 (0) | 2023.03.02 |
[클린 코드] 9장. 단위 테스트 (0) | 2023.03.01 |
창발적 설계로 깔끔한 코드를 구현하자
- 켄트 백이 제시한 단순한 설계 규칙 네 가지가 소프트웨어 품질을 크게 높여준다고 믿는다.
1. 모든 테스트를 실행한다.
2. 중복을 없앤다.
3. 프로그래머 의도를 표현한다.
4. 클래스와 메서드 수를 최소로 줄인다. - 이로 인해 코드 구조와 설계를 파악하기 쉬워져
단일 책임 원칙, 의존 관계 역전 원칙을 적용하기 쉬워지고 우수한 설계의 창발성을 촉진하게 된다.
단순한 설계 규칙 1: 모든 테스트를 실행하라
- 설계는 의도한 대로 돌아가는 시스템을 내놓아야 한다.
- 테스트를 철저히 거쳐 모든 테스트 케이스를 항상 통과하는 시스템은 '테스트가 가능한 시스템'이다.
테스트가 불가능한 시스템은 검증도 불가능하다. - 테스트가 가능한 시스템을 만들려고 애쓰면 설계 품질이 더불어 높아진다.
- 테스트 케이스를 많이 작성할수록 개발자는 의존 관계 역전 원칙과 같은 원칙을 적용하고
의존성 주입, 인터페이스, 추상화 등과 같은 도구를 사용해 결합도를 낮춘다. 따라서 설계 품질은 더욱 높아진다. - 테스트 케이스를 만들고 계속 돌리는 단순한 규칙을 따르면
시스템은 낮은 결합도와 높은 응집력이라는 객체 지향 방법론이 지향하는 목표를 저절로 달성한다.
단순한 설계 규칙 2~4: 리팩터링
- 테스트 케이스를 모두 작성했다면 코드와 클래스를 점진적으로 리팩터링 해나간다.
- 테스트 케이스가 있으므로 코드를 정리하면서 시스템이 깨질까 걱정할 필요가 없으므로
깔끔히 코드를 정리한 후 테스트 케이스를 돌려 기존 기능을 깨뜨리지 않았다는 사실을 확인한다. - 리팩터링 단계에서는 소프트웨어 설계 품질을 높이기 위해서라면 응집도를 높이고, 결합도를 낮추고, 관심사를 분리하고,
시스템 관심사를 모듈로 나누고, 함수와 클래스 크기를 줄이고, 더 나은 이름을 선택하는 등 다양한 기법을 동원한다.
중복을 없애라
- 중복은 추가 작업, 추가 위험, 불필요한 복잡도를 뜻하므로 우수한 설계에서 커다란 적이다.
- 비슷한 코드는 더 비슷하게 고쳐주면 리팩터링이 쉬워진다.
// bad
// 코드 각각 구현
int size() {}
boolean isEmpty() {}
// good
// size 메서드를 이용하여 isEmpty 메서드 구현
int size() {}
boolean isEmpty() {
return 0 == size();
}
- 깔끔한 시스템을 만들려면 단 몇 줄이라도 중복을 제거하겠다는 의지가 필요하다.
- 공통적인 코드를 새 메서드로 뽑게 될 경우 클래스가 단일 책임 원칙을 위반하게 되므로
뽑혀진 메서드를 다른 클래스로 옮기게 되면 가시성이 높아지고
다른 팀원이 새 메서드를 좀 더 추상화해 다른 맥락에서 재사용할 기회를 포착할지도 모른다. - 소규모 재사용은 시스템 복잡도를 극적으로 줄여주며 소규모 재사용을 제대로 익혀야 대규모 재사용이 가능하다.
- TEMPLATE METHOD 패턴은 고차원 중복을 제거할 목적으로 자주 사용하는 기법으로
중복을 모아 상위 클래스에 작성해 제거하고 하위 클래스는 중복되지 않는 정보만 제공해 알고리즘에서 빠진 구멍을 메운다.
표현하라
- 자신이 이해하는 코드를 짜기는 쉽지만
나중에 코드를 유지보수할 사람이 코드를 짜는 사람만큼이나 문제를 깊이 이해할 가능성이 희박하다. - 그러므로 코드는 개발자의 의도를 분명히 표현해야 한다.
개발자가 코드를 명백히 짤수록 다른 사람이 그 코드를 이해하기 쉬워진다. 그래야 결함이 줄어들고 유지보수 비용이 적게 든다. - 1. 좋은 이름을 선택한다.
이름과 기능이 완전히 딴판인 클래스나 함수로 유지보수 담당자를 놀라게 해서는 안 된다. - 2. 함수와 클래스 크기를 가능한 줄인다.
작은 클래스와 작은 함수는 이름 짓기도 쉽고, 구현하기도 쉽고, 이해하기도 쉽다. - 3. 표준 명칭을 사용한다.
디자인 패턴은 의사소통과 표현력 강화가 주목적이므로 표준 패턴을 사용해 구현된다면 클래스 이름에 패턴 이름을 넣어준다.
그러면 다른 개발자가 클래스 설계 의도를 이해하기 쉬워진다. - 4. 단위 테스트 케이스를 꼼꼼히 작성한다.
잘 만든 테스트 케이스를 읽어보면 클래스 기능이 한눈에 들어온다. - 하지만 표현력을 높이는 가장 중요한 방법은 노력이다.
자신의 작품에 조금만 더 주의를 기울이자. 주의는 대단한 재능이다.
클래스와 메서드 수를 최소로 줄여라
- 중복을 제거하고, 의도를 표현하고, 단일 책임 원칙을 준수한다는 기본적인 개념도 극단으로 치달으면 득보다 실이 많아진다.
- 클래스와 메서드 크기를 줄이자고 조그만 클래스와 메서드를 수없이 만들지 말고 함수와 클래스 수를 가능한 줄이자.
- 목표는 함수와 클래스 크기를 작게 유지하면서 동시에 시스템 크기도 작게 유지하는 데 있다.
- 하지만 이 규칙은 간단한 설계 규칙 중 우선순위가 가장 낮으므로
클래스와 함수 수를 줄이는 작업도 중요하지만, 테스트 케이스를 만들고 중복을 제거하고 의도를 표현하는 작업이 더 중요하다.
'Java-Spring > 클린 코드' 카테고리의 다른 글
[클린 코드] 14장. 점진적인 개선 (0) | 2023.03.12 |
---|---|
[클린 코드] 13장. 동시성 (0) | 2023.03.11 |
[클린 코드] 11장. 시스템 (0) | 2023.03.07 |
[클린 코드] 10장. 클래스 (0) | 2023.03.02 |
[클린 코드] 9장. 단위 테스트 (0) | 2023.03.01 |