아래 목록은 다양한 프로그램을 검토하고 리팩터링하면서 만들었다. 프로그램을 수정할 때마다 나는 "왜?"라고 자문한 다음 그 답을 기록했다. 코드를 읽으면서 나쁜 냄새를 정리하다 보니 목록이 상당히 길어졌다. 주석 부적절한 정보 다른 시스템에(소스 코드 관리 시스템, 버그 추적 시스템, 기록 관리 시스템) 저장할 정보를 주석으로 저장하는 것은 적절하지 못하다. 예를 들어 작성자, 변경 이력 같은 정보는 코드만 번잡하게 만든다. 쓸모 없는 주석 오래된 주석, 엉뚱한 주석, 잘못된 주석은 더 이상 쓸모가 없다. 쓸모 없는 주석은 아예 달지 않는 편이 가장 좋다. 쓸모 없어진 주석은 가능한 빨리 삭제하는 것이 좋다. 쓸모 없는 주석은 코드와 무관하게 혼자서 따로 놀며 코드를 그릇된 방향으로 이끈다. 중복된 주석..
첫째, 돌려보자 SerialDate 코드에서 데이비드는 엄청난 절제력과 전문가 정신을 보여준다. 의도와 목적을 고려하건대, SerialDate는 분명히 '우수한' 코드다. 그럼에도 여기서는 낱낱이 까발긴다. SerialDateTests라는 클래스는 단위 테스트 몇 개를 포함한다. 실패하는 테스트 케이스는 없지만, 테스트 케이스를 훑어보면 모든 경우를 점검하지 않는다는 사실이 드러난다. 그래서 나는 클로버를 이용해 테스트 코드를 조사했다. 클로버에 따르면 커버리지는 50% 정도였다. 클래스를 철저히 이해하고 리펙터링하려면 높은 커버리지가 필요했다. 그래서 나는 독자적으로 단위 테스트를 구현했다. SerialDate를 리팩터링하면서 나는 모든 테스트 케이스를 통과하게 코드를 손 볼 작정이다. 둘째, 고쳐보자..
JUnit JUnit의 저자는 많다. 하지만 시작은 켄트 벡과 에릭 감마 두 사람이다. 코드는 잘 분리되었고, 표현력이 적절하다. 저자들이 모듈을 아주 좋은 상태로 남겨두었지만 보이스카우트 규칙에 따라 개선해보자. 기존 코드 더보기 package junit.framework; public class ComparisonCompactor { private static final String ELLIPSIS = "..."; private static final String DELTA_END = "]"; private static final String DELTA_START = "["; private int fContextLength; private String fExpected; private String f..
1997년만 해도 TDD라는 개념을 몰랐다. 대다수가 단위 테스트란 프로그램이 '돌아간다'는 사실만 확인하는 일회성 코드에 불과했다. 직접 수동으로 테스트를 수행하고, 그로고 나서는 테스트 코드를 버렸다. 우리 분야는 지금까지 눈부신 성장을 이뤘지만 앞으로 갈 길은 여전히 멀다. 에자일과 TDD 덕택에 단위 테스트를 자동화하는 프로그래머들이 이미 많아졌으며 점점 늘어나는 추세다. 하지만 테스트를 추가하려고 급하게 서두르는 와중에 제대로된 테스트 케이스를 작성해야 한다는 사실을 놓쳐버렸다. TDD 법칙 세 가지 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다. 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다. 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 ..

시스템에 들어가는 모든 소프트웨어를 직접 개발하는 경우는 드물다. 패키지를 사고, 오픈 소스를 이용하고, 사내 다른 팀이 제공하는 컴포넌트를 사용한다. 어떤 식으로든 이 외부 코드를 우리 코드에 깔끔하게 통합해야만 한다. 외부 코드 사용하기 패키지 제공자는 적용성을 최대한 넓히려 애쓴다. 더 많은 환경에서 돌아가야 더 많은 고객이 구매하니까. 반면, 사용자는 자신의 요구에 집중하는 인터페이스를 바란다. 이런 긴장으로 인해 시스템 경계에서 문제가 생긴다. 대표적인 예로 java.util.Map을 살펴보자. Map은 다양한 인터페이스로 많은 기능을 제공한다. Map이 제공하는 기능과 유연성은 확실히 유용하지만 그만큼 위험도 크다. Map에는 clear, set, remove 함수를 제공하기 때문에 Map을 ..
자료 추상화 public class Point { public double x; public double y; } 확실히 직교좌표계를 사용한다. 개별적으로 좌표값을 읽고 설정하게 강제한다. public interface Point { double getX(); double getY(); void setCartesian(double x, double y); double getR(); double getTheta(); void setPolar(double r, double theta); } 직교좌표계를 사용하는지 극좌표계를 사용하는지 알 길이 없다. 좌표를 읽을 때 각 값을 개별적으로 읽어야 한다. 좌표를 설정할 때는 두 값을 한꺼번에 설정해야 한다. 그저 조회 함수와 설정 함수로 변수를 다룬다고 클래스가 ..
의미 있는 이름 소프트웨어에서 이름은 어디나 쓰입니다. 변수, 함수, 인수, 클래스 심지어 디렉터리, jar, war, ear 등 다양한 곳에 쓰입니다. 이렇듯 많이 사용하므로 이름을 잘 지으면 여러모로 편합니다. 의도를 분명히 밝혀라 좋은 이름을 지으려면 시간이 걸리지만 좋은 이름으로 절약하는 시간이 훨씬 더 많습니다. 그러므로 이름을 주의깊게 살펴 더 나은 이름이 떠오르면 개선해야합니다. int d; // 경과 시간 int elapsedTimeInDays; int daysSinceCreation; int daysSinceModification; int fileAgeInDays; 이름 d는 아무 의미도 없고 이를 설명하기 위한 주석이 필요합니다. 하지만 변수 명을 좀 더 자세하게 지으면 의미도 명확하고..
- Total
- Today
- Yesterday
- Kotlin
- viewmodel
- DSL
- ViewModelProvider
- 클린 코드
- Widget
- Flutter
- ViewModelStoreOwner
- commit
- rxjava
- 연산자
- DART
- ConcatAdapter.Config
- Flowable
- observable
- gradle
- CancellationException
- clean code
- TDD
- ConcatAdapter
- Coroutine
- git
- 코루틴
- null
- Exception
- 보이스카우트 규칙
- Android
- 함수
- isActive
- 클린코드
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |