티스토리 뷰
| 12. 창발성(創發性)
-
|| 창발적 설계로 깔끔한 코드를 구현하자
- 대다수는 Kent Beck이 제시한 "단순한 설계 규칙" 네 가지가 소프트웨어 설계 품질을 크게 높여준다고 믿는다..
- 다음 규칙을 따르면 설계는 '단순하다'고 말할 수 있다. - Kent Beck
1. 모든 테스트를 실행한다.
2. 중복을 없앤다.
3. 프로그래머 의도를 표현한다.
4. 클래스와 메서드 수를 최소로 줄인다.
|| 단순한 설계 규칙 1: 모든 테스트를 실행하라
- 철저한 테스트로 모든 테스트 케이스를 항상 통과하는 시스템은 '테스트가 가능한 시스템'이다.
- 테스트가 가능한 시스템을 만들려고 애쓰면 설계 품질이 더불어 높아진다.
(하나만 수행하는 클래스, SRP 준수 클래스)
- 테스트 케이스 작성이 쉬워지려면 DIP 원칙 적용, DI, 인터페이스, 추상화 등과 같은 도구를 사용해 결합도를 낮춰야 한다.
|| 단순한 설계 규칙 2~4: 리펙터링
- 리펙터링 단계에서는 소프트웨어 설계 품질을 높이는 기법을 무엇이든 적용해보자.
- 응집도 높이기
- 결합도 낮추기
- 관심사 분리하기
- 시스템 관심사를 모듈로 나누기
- 함수와 클래스 크기 줄이기
- 더 나은 이름 선택하기
..
|| 중복을 없애라
"중복은 커다란 적이다."
- 깔끔한 시스템을 만들려면 단 몇 줄이라도 중복을 제거하겠다는 의지가 필요하다 !
> Before
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public void scaleToOneDimension(float desiredDimension, float imageDimension) { if (Math.abs(desiredDimension - imageDimension) < errorThreshold) return; float scalingFactor = desiredDimension / imageDimension; scalingFactor = (float)(Math.floor(scalingFactor * 100) * 0.01f); RenderedOpnewImage = ImageUtilities.getScaledImage(image, scalingFactor, scalingFactor); image.dispose(); System.gc(); image = newImage; } public synchronized void rotate(int degrees) { RenderedOpnewImage = ImageUtilities.getRotatedImage(image, degrees); image.dispose(); System.gc(); image = newImage; } | cs |
> After
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public void scaleToOneDimension(float desiredDimension, float imageDimension) { if (Math.abs(desiredDimension - imageDimension) < errorThreshold) return; float scalingFactor = desiredDimension / imageDimension; scalingFactor = (float) Math.floor(scalingFactor * 10) * 0.01f); replaceImage(ImageUtilities.getScaledImage(image, scalingFactor, scalingFactor)); } public synchronized void rotate(int degrees) { replaceImage(ImageUtilities.getRotatedImage(image, degrees)); } private void replaceImage(RenderedOpnewImage) { image.dispose(); System.gc(); image = newImage; } | cs |
- 클래스가 SRP(단일 책임 원칙)를 위반한다면?
- 다른 클래스로 옮겨도 좋다. (가시성을 높이기 위해)
- 새 메서드를 더 추상화해 다른 맥락에서 재사용할 기회를 포착할 수 있다.
- 소규모 재사용 -> 시스템 복잡도 극적 하강!
||| TEMPLATE METHOD PATTERN
- 고차원 중복 제거
> Before
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class VacationPolicy { public void accrueUSDDivisionVacation() { // 지금까지 근무한 시간을 바탕으로 휴가 일수를 계산하는 코드 // ... // 휴가 일수가 미국 최소 법정 일수를 만족하는지 확인하는 코드 // ... // 휴가 일수를 급여 대장에 적용하는 코드 // ... } public void accrueEUDivisionVacation() { // 지금까지 근무한 시간을 바탕으로 휴가 일수를 계산하는 코드 // ... // 휴가 일수가 유럽연합 최소 법정 일수를 만족하는지 확인하는 코드 // ... // 휴가 일수를 급여 대장에 적용하는 코드 // ... } } | cs |
> After
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | abstract public class VacationPolicy { public void accrueVacation() { caculateBseVacationHours(); alterForLegalMinimums(); applyToPayroll(); } private void calculateBaseVacationHours() { /* ... */ }; abstract protected void alterForLegalMinimums(); private void applyToPayroll() { /* ... */ }; } public class USVacationPolicy extends VacationPolicy { @Override protected void alterForLegalMinimums() { // 미국 최소 법정 일수를 사용한다. } } public class EUVacationPolicy extends VacationPolicy { @Override protected void alterForLegalMinimums() { // 유럽연합 최소 법정 일수를 사용한다. } } | cs |
- 하위 클래스는 중복되지 않는 정보만 제공
|| 표현하라
-
- 코드는 개발자의의도를 분명히 표현해야 한다! (결함과 유지보수 비용을 줄이기 위해)
1. 좋은 이름을 선택
2. 함수와 클래스 크기를 가능한 줄이자
3. 표준 명칭을 사용
4. 단위 테스트 케이스를 꼼꼼히 작성
- 테스트 케이스는 소위 '예제로 보여주는 문서'
* 표현력을 높이는 가장 중요한 방법은 "노력"
출처 : 클린 코드 (Robert C. Martin)
'Books' 카테고리의 다른 글
[클린 코드: Clean Code] 14. 점진적인 개선 (0) | 2021.01.22 |
---|---|
[클린 코드: Clean Code] 13. 동시성(concurrent) (0) | 2021.01.22 |
[클린 코드: Clean Code] 11. 시스템(System) (0) | 2021.01.20 |
[클린 코드: Clean Code] 10. 클래스(Class) (0) | 2021.01.19 |
[클린 코드: Clean Code] 9. 단위 테스트 (0) | 2021.01.16 |