Args 구현 출발은 좋았으나 확장성이 부족했던 모듈을 점진적으로 개선하고 정리해보자. 프로그램을 짜다 보면 종종 명령행 인수의 구문을 분석할 필요가 생긴다. 이때 편리한 유틸리티가 없다면 main 함수로 넘어오는 문자열 배열을 직접 분석하게 된다. 또는 여러 가지 훌륭한 유틸리티가 있지만 내 사정에 딱 맞는 유틸리티가 없다면 직접 짜겠다고 결심한다. 이제 새로 짤 유틸리티를 Arg라 부르겠다. Args를 사용하기 위해서는 Args 생성자에 인수 문자열과 형식 문자열을 넘겨 Args 인스턴스를 생성한 후 Args 인스턴스에다 인수 값을 질의하게 되고 생성자에 ArgsException이 발생하지 않는다면 명령행 인수의 구문을 성공적으로 분석했으므로 Args 인스턴스에 질의를 던져도 좋게 된다. 만약 형식 ..
동시성이 필요한 이유? 동시성은 결합을 없애는 전략으로 무엇과 언제를 분리하는 전략이다. 스레드가 하나인 프로그램은 무엇과 언제가 서로 밀접하다. 무엇과 언제를 분리하면 애플리케이션 구조와 효율이 극적으로 나아진다. 마치 프로그램이 작은 협력 프로그램 여럿으로 보인다. 동시성을 정확히 구현하기 위해서는 각별한 주의와 노력을 기울여야 하지만 그럼에도 이것이 제공하는 구조적 이점은 아주 크다. 또한 응답 시간과 작업 처리량 개선이라는 요구사항으로 인해 직접적인 동시성 구현이 불가피한 상황이 발생하기도 한다. 이렇듯 반드시 동시성이 필요한 상황이 존재한다. 동시성은 항상 성능을 높여주는 것이 아니라 대기 시간이 아주 길어 여러 스레드가 프로세서를 공유할 수 있거나, 여러 프로세서가 동시에 처리할 독립적인 계산..
창발적 설계로 깔끔한 코드를 구현하자 켄트 백이 제시한 단순한 설계 규칙 네 가지가 소프트웨어 품질을 크게 높여준다고 믿는다. 1. 모든 테스트를 실행한다. 2. 중복을 없앤다. 3. 프로그래머 의도를 표현한다. 4. 클래스와 메서드 수를 최소로 줄인다. 이로 인해 코드 구조와 설계를 파악하기 쉬워져 단일 책임 원칙, 의존 관계 역전 원칙을 적용하기 쉬워지고 우수한 설계의 창발성을 촉진하게 된다. 단순한 설계 규칙 1: 모든 테스트를 실행하라 설계는 의도한 대로 돌아가는 시스템을 내놓아야 한다. 테스트를 철저히 거쳐 모든 테스트 케이스를 항상 통과하는 시스템은 '테스트가 가능한 시스템'이다. 테스트가 불가능한 시스템은 검증도 불가능하다. 테스트가 가능한 시스템을 만들려고 애쓰면 설계 품질이 더불어 높아진..
도시를 세운다면? 도시는 수도 관리 팀, 전력 관리 팀, 교통 관리 팀, 건축물 관리 팀 등 각 분야를 관리하는 팀이 있기 때문에 잘 돌아간다. 또한 적절한 추상화와 모듈화로 인해 큰 그림을 이해하지 못해도 개인과 개인이 관리하는 '구성요소'는 효율적으로 돌아간다. 깨끗한 코드를 구현하면 낮은 추상화 수준에서 관심사를 분리하기 쉬워진다. 그러므로 높은 추상화 수준인 시스템 수준에서도 깨끗함을 유지하는 방법을 살펴보자. 시스템 제작과 시스템 사용을 분리하라 제작은 사용과 아주 다르다. 소프트웨어 시스템은 애플리케이션 객체를 제작하고 의존성을 서로 연결하는 준비 과정과 준비 과정 이후에 이어지는 런타임 로직을 분리해야 한다. 시작 단계는 모든 애플리케이션이 풀어야 할 관심사이지만 대다수 애플리케이션은 시작 ..
클래스 체계 가장 먼저 변수 목록이 나온다. 정적 공개 상수가 있다면 맨 처음에 나온다. 다음으로 정적 비공개 변수가 나오며, 이어서 비공개 인스턴스가 나온다. 공개 변수가 필요한 경우는 거의 없다. 변수 목록 다음에는 공개 함수가 나온다. 비공개 함수는 자신을 호출하는 공개 함수 직후에 넣는다. 즉, 추상화 단계가 순차적으로 내려간다. 변수와 유틸리티 함수는 가능한 공개하지 않는 편이 낫지만 반드시 숨겨야 한다는 법칙도 없다. 테스트는 아주 중요하므로 같은 패키지 안에서 테스트 코드가 함수를 호출하거나 변수를 사용해야 한다면 protected로 선언하거나 패키지 정체로 공개해야 한다. 하지만 그 전에 비공개 상태를 유지할 온갖 방법을 강구한다. 클래스는 작아야 한다! 클래스를 설계할 때도, 함수와 마찬..
TDD 법칙 세 가지 첫째 법칙 : 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다. 둘째 법칙 : 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다. 셋째 법칙 : 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다. 세 가지 규칙을 따르면 테스트 코드와 실제 코드가 함께 나올뿐더러 테스트 코드가 실제 코드보다 불과 몇 초 전에 나온다. 이렇게 일하면 실제 코드를 사실상 전부 테스트하는 테스트 케이스가 나온다. 하지만 실제 코드와 맞먹을 정도로 방대한 테스트 코드는 심각한 관리 문제를 유발하기도 한다. 깨끗한 테스트 코드 유지하기 실제 코드가 진화하면 테스트 코드도 변해야 한다. 그런데 테스트 코드가 지저분할수록 변경하기 어려워진다. 테스트 코드가 복..
외부 코드 사용하기 인터페이스 제공자(패키지 제공자, 프레임워크 제공자)는 더 많은 환경에서 돌아가야 더 많은 고객이 구매하므로 적용성을 최대한 넓히려 애쓴다. 반면, 사용자는 자신의 요구에 집중하는 인터페이스를 바란다. 이런 긴장으로 인해 시스템 경계에서 문제가 발생할 소지가 많다. Map은 다양한 인터페이스로 수많은 기능을 제공한다. Map이 제공하는 기능성과 유연성은 확실히 유용하지만 그만큼 위험도 크다. 프로그램에서 Map을 만들어 여기저기 넘길 경우, Map 사용자라면 누구나 Map 내용을 지울 권한이 있으므로 Map 내용이 삭제될 수도 있으며 Map은 객체 유형을 제한하지 않으므로 마음만 먹으면 사용자는 어떤 객체 유형도 추가할 수 있다. 즉, Map이 반환하는 Object를 올바른 유형으로 ..