지식조각모음
9장 코드 삭제의 미학 본문
적은 것이 더 낫다
가치는 투자 자체에서 나오는 것이 아니라 투자의 결과에서 나옵니다. (중략) 그러나 코드에 너무 집착하면 원래 문제에서 초점을 잃고 결국 문제를 수동으로 해결하는 데 걸리는 것보다 문제를 자동화하는 데 더 많은 시간을 소비하게 됩니다.
복잡성 제거를 위한 코드 삭제
시스템은 시간이 갈수록 성장한다. 즉 복잡성이 증가한다.
- 도메인 복잡성: 우리가 해결하고 있는 문제. 기본적으로 가지고 있는 복잡성
- 부수적 복잡성: 도메인에서 요구하지 않았지만 우연히 추가된 모든 복잡성
부수적 복잡성
제거를 위해 집중해야 할 부분은 다음과 같다.
- 경험 부족으로 인한 기술적 무지
- 몰라서 추가한 불필요한 결합 등
- ➡️ 의도적인 연습으로 기술을 향상시켜서 줄일 수 있다.
- 시간 압박으로 인한 기술적 낭비
- 시간 부족으로 인해 의도적으로 나쁜 결정을 하는 경우
- 테스트나 리팩터링을 건너뛰거나 프로세를 우회하는 경우
- ➡️ 건너뛸 기회를 없게 해야 한다
- 환경에 따른 기술적 부채
- 일시적으로 차선의 해결책을 선택하는 경우
- 핫픽스 구현 후 수정하는 경우
- ➡️ 문제가 해결된 후엔 삭제해야 한다.
- 성장에 따른 기술적 장애물
- 개발을 더디게 만드는 모든 것(문서, 테스트, 다른 코드들 등)
- 기능을 제거하는 것도 도움이 될 수 있다
- ➡️ 더이상 삭제할 것이 없을 때까지 가능한 한 많은 것을 삭제하자
어떤 것을 제거해야 할까?
1. 친밀도에 따른 코드 분류
익숙한 코드를 먼저 삭제하는 것이 더 안전하다
2. 레거시 시스템에서의 코드 삭제
어떻게 삭제할 것인가?
- 레거시 코드가 얼마나 사용되고 있는지 확인하자
- 거의 사용되지 않으면 바로 제거
- 적은 부분만 사용하면 해당 부분만 수정하고 나머지는 제거
- 많은 부분에서 사용하면 익숙해져서 안정적으로 만들어야 한다
- 얼마나 호출 했는지, 얼마나 많은 호출이 성공했는지도 알아야 한다
- 나머지 소프트웨어와 얼마나 밀접하게 연결되어 있는지 알아야 한다
스트랭글러 무화과나무 패턴
- 기존 코드를 얼마나 사용하고 있는지 알기 위해 사용
- 레거시 코드를 점진적으로 교체하기 위한 방법이다
- 기존 코드를 분리하여 얼마나 접근하는지 일정 시간을 들여 확인한다
코드 삭제 또는 대체하기
- 적게 호출 되는 부분부터 제거해나간다
- 가장 적게 또는 항상 실패하는 코드는 전략적으로 기능이 있는지 확인한다
- 중요한 레거시 코드는 호출 빈도가 그에 비례한지 확인한다
- 중요한 코드는 익숙해져야 한다
- 리팩터링 후 그 코드를 ‘최신 코드’로 분류한 뒤 점진적으로 수정한다
- ‘삭제 후 컴파일하기’ 패턴을 통해 불필요한 메서드를 삭제한다
3. 동결된 프로젝트에서 코드 삭제
- 동결된 프로젝트와 관련된 코드는 바로 삭제한다
- 메서드 호출 여부가 아니라 현재 사용하는 기능에 관련되어 있는지 따져봐야 한다
제거 방법
- 별도 브랜치로 옮기거나 기록해두고 6주 안에 사용하지 않으면 삭제하기로 한다
- 스파이크와 스태빌라이즈(spike & stabilize)로 낭비 줄이기
- 일반 애플리케이션과 별도로 구현하고 고품질에 노력을 기울이지 않는다
- 모니터링을 통해 많이 사용되었다면 제대로 구현하고 아니라면 삭제한다
4. 버전 관리에서 브랜치 삭제
- 핫픽스, 개인 브랜치는 main에 병합되면 삭제해야 한다
- 동결 프로젝트, 스파이크, 프로토타입의 경우
- 브랜치를 제한한다(WIP: work in progress)
5. 코드 문서 삭제
- 코드 문서: 위키 페이지, Javadoc, 설계 문서, 튜토리얼 등
- 문서의 조건
- 관련성: 올바른 질문에 답해야 한다
- 정확성: 답은 정확해야 한다
- 발견 가능성: 답을 찾을 수 있어야 한다
문서가 정확하지 않으면 오류를 유도할 수 있기 때문에 관련성과 정확성을 유지하기 위한 노력이 필요하다
문서화가 의미가 있는지 결정하기
- 문서화 대상이 자주 바뀌면 문서화해서 얻을 수 있는 것이 없다. 문서화하지 않는다.
- 드물게 사용하는 경우 문서화 한다.
- 그렇지 않고, 자동화할 수 있으면 자동화 한다.
- 그렇지 않으면, 외워라.
6. 테스트 코드 삭제
- 낙관적 테스트 삭제
- 실패할 수 없는 테스트는 가치가 없다
- 비관적 테스트 삭제
- 항상 문제가 있는 테스트는 수정해야 한다
- 불안정 테스트 수정 또는 삭제
- 결과를 예측할 수 없는 불안정 테스트
- 위에서 말한 테스트와 다를 바가 없다. 삭제 대상
- 복잡한 테스트를 제거하기 위한 코드 리팩터링
- 섬세한 설정, 많은 중복 등 코드보다 복잡한 테스트는 삭제해야 한다
- 테스트가 잘못된 것인지 코드가 잘못된 것인지 알 수 없다
- 테스트를 리팩토링해야 한다는 것은 테스트 중인 코드에 적절한 아키텍처가 없다는 신호이다
- 테스트 전문화로 속도 높이기
- 느린 테스트와 빠른 테스트를 분리
- 빠른 테스트를 자주 지속적으로 실행
- 느린 테스트의 실패 원인을 관찰하고 관련 없는 경우 제거
7. 설정 코드 삭제
설정성을 추가할 때마다 코드의 복잡성도 증가한다. 각 옵션을 모든 플래그에 대해 테스트 해야하기 때문에 테스트 양도 증가한다.
복잡성을 처리하기 위해 가능한 한 많은 설정을 임시적인 것으로 생각해야 한다.
실험을 위한 설정
출시된 후 제거될 것 또는 변경 사항이 우수한지 테스트하기 위한 설정. 베타 테스트 또는 A/B 테스트라고 한다. 후자의 경우 일부 사용자가 변경 사항을 경험할 수 있다.
실험을 위한 설정이 그대로 영구적인 설정이 되어 복잡성을 증가시킬 수 있기 때문에 실험 목적을 확실히 하고 테스트가 완료되는 즉시 제거하라는 알람을 생성해야 한다.
과도기적인 설정
레거시 시스템 변경같은 비즈니스 또는 코드베이스가 중요 변경 사항을 겪고 있는 동안 유용하다.
이런 변경 사항은 사용자에게 잘 보이지 않으므로 코드 내부에 코드의 일부로 포함시킬 수 있다. 이렇게 포함된 내용은 한 곳으로 설정을 모을 수 있다.
또 변경되고 오래된 부분은 제거할 수 있다. 스트랭글러 무화과나무 패턴을 사용해서 레거시 구성요소를 한 번에 삭제할 수 있다.
영구적인 설정
설정 플래그에 차이를 두어 다른 고객에게 동일한 소프트웨어를 대부분 재사용 할 수 있게 하거나 다양한 사용자 계층을 지원하는 경우 필요한 설정이다. 예를 들어 다크모드 지원 같은 경우 유지보수에 큰 영향을 주지 않지만 사용자 경험을 향상시킨다.
이런 설정은 사용량을 증가시키기 때문에 필요하지만 유지보수가 간단해야 한다. 또 사용량을 늘리지 않으면 삭제한다.
8. 라이브러리 제거를 위한 코드 삭제
서드파티 라이브러리는 편리하지만 종종 업데이트를 위해 코드 수정이 필요하다. 시간이 많이 걸리고 오류가 발생하기 쉬운 작업이며 업데이트가 언제 나올지, 수정에 얼마나 많은 시간이 걸릴지 예측하기 어렵다. 또는 라이브러리를 수정하거나 우회해야 하며 삭제된 기능을 대체해야 한다.
외부 라이브러리에 대한 의존성 제한
고품질의 라이브러리를 선택하고 자주 업데이트 한다. 더 자주할수록 작업량이 적어지기 때문에 비용과 위험이 감소한다.
또 다른 해결책은 종속성을 가시적으로 만드는 것이다. 각 라이브러리가 개선 용도인지 중요 용도인지 분리한다. 개선 용도의 라이브러리가 변경될 경우 대체하기 쉽다. 사용하지 않은 라이브러리나 내부에서 충분히 구현할 수 있는 코드는 불확실성을 제거하기 위해 삭제하는 편이 좋다.
9. 작동 중인 기능에서 코드 삭제
기능이 추가된다고 사용량이 증가하거나 가치가 늘어나지 않는다. 다음과 같은 점을 고려해서 삭제 또는 리팩터링을 통해 비용을 줄여야 한다.
- 충분히 사용되는가?
- 유지비가 비싼가?
- 개선할 수 있는가?
'책 > Five Lines of Code' 카테고리의 다른 글
| 7장 컴파일러와의 협업 (0) | 2023.09.04 |
|---|---|
| 8장 주석 자제하기 (0) | 2023.09.04 |
| 4장 타입 코드 처리하기 (0) | 2023.08.17 |
| 3장 긴 코드 조각내기 (0) | 2023.08.05 |
| 2장 리팩터링 깊게 들여다보기 (0) | 2023.08.01 |