• [CleanCode] 16장 SerialDate 리팩터링

    첫째, 돌려보자 둘째, 고쳐보자 🔹 추상 팩토리 패턴상세화된 서브클래스를 정의하지 않고도 서로 관련성이 있거나 독립적인 여러 객체의 군을 생성하기 위한 인터페이스를 제공하는 패턴 위 클래스에서 createInstance 메서드를 makeDate라고 좀 더 서술적으로 변경했다. MINIMUM_YEAR_SUPPORTED와 MAXIMUM_YEAR_SUPPORTED 변수를 적절한 위치인 SpreadsheetDate로 옮긴다. 결론 따라서 리팩터링을 통해 테스트 커버리지가 증가시키고, 버그 고치고, 코드 크기를 줄이고 코드를 명확하게 할 수 있다. 참고 링크

  • [CleanCode] 15장 JUnit 들여다보기

    JUnit 프레임워크 우리가 살펴볼 모듈은 문자열 비교 오류를 파악할 때 유용한 코드다. ComparisonCompactor라는 모듈로, 영리하게 짜인 코드다. ComparisonCompactor는 두 문자열을 받아 차이를 반환한다. 위 테스트 케이스로 ComparisonCompactor 모듈에 대한 코드 커버지리 분석을 수행했을 때 100%가 나왔다. 테스트 케이스가 모든 행, 모든 if문, 모든 for문을 실행한다는 뜻이다. 비록 저자들이 모듈을 아주 좋은 상태로 남겨두었지만 보이스카우트 규칙에 따르면 우리는 처음 왔을 때보다 더 깨끗하게 해놓고 떠나야 한다. 접두어 if를 제거하자 compact 함수 시작 부에 캡슐화되지 않은 조건문이 보인다. 이름은 명확하게 붙이자fExpect, fActual 부정문이 긍정문보다 이해하기 약간 어렵다. 부정문을 긍정문으로 표현하자.첫 문장 if를 긍정으로 만들어 조건문을 반전한다. 함수의 이름으로 효과를 명확하게 설명하자 문자열을 압축하는 함수지만 canBeCompacted가 false면 압축하지 않는다. 게다가 함수는 단순히 압축된…

  • [CleanCode] 14장 점진적인 개선

    Intro 확장성이 부족했던 모듈을 소개하고, 모듈을 개선하고 정리하는 단계를 살펴볼 것. 14-1 간단한 Args 사용법 Args는 사용법이 간단하다. Args 생성자에 (입력으로 들어온) 인수 문자열과 형식 문자열을 넘겨 Args 인스턴스를 생성한 후 Args 인스턴스에다 인수 값을 질의한다.매개변수 두 개로 Args 클래스의 클래스의 인스턴스를 만든다. 첫째 매개변수는 형식 또는 스키마를 지정한다. “l,p#,d*”은 명령행 인수 세 개를 정의한다. 첫 번째 -l은 부울 인수다. 두 번째 -p는 정수 인수다. 세 번째 -d는 문자열 인수다. 두 번째 매개변수는 main으로 넘어온 명령행 인수 배열 자체다.ArgsException이 발생하지 않는다면 명령행 인수의 구문을 성공적으로 분석했으며 Args 인스턴스에 질의를 던져도 좋다는 말이다.형식 문자열이나 명령행 인수 자체에 문제가 있으면 ArgsException이 발생한다.구체적인 오류를 알아내려면 예외가 제공하는 errorMessage 메서드를 사용한다. Args 구현 목록…

  • [CleanCode] 13장 동시성

    🔹 요약 ◽ 동시성과 깔끔한 코드는 양립하게 어렵다. ◽ 스레드를 하나만 실행하는 코드는 짜기가 쉽다. 겉으로 보기에는 멀쩡하나 깊숙한 곳에 문제가 있는 다중 스레드 코드도 짜기 쉽다. 이런 코드는 시스템이 부하를 받기 전까지 멀쩡하게 돌아간다.  🔹이 장에서 다룰 내용 ◽ 여러 스레드를 동시에 돌리는 이유 ◽ 여러 스레드를 동시에 돌리는 어려움◽ 동시성을 테스트하는 방법과 문제점 동시성이 필요한 이유? 구조적 개선만을 위해 동시성을 채택하는 건 아니다. 💡 예시1) 매일 수많은 웹 사이트에서 정보를 가져와 요약하는 정보 수집기  💡 예시 2) 한 번에 한 사용자를 처리하는 시스템: 한 사용자를 처리하는 시간은 1초 💡 예시 3) 정보를 대량으로 분석하는 시스템 미신과 오해 난관 동시성을 구현하기 어려운 이유 두 스레드가 같은 변수를 동시에 참조하면 세 번째와 같은 놀라운 결과가 발생한다! 두…

  • [CleanCode] 12장 창발성(創發性)

    🔹 켄트 백이 제시한 단순한 설계 규칙 네 가지    ◽ 모든 테스트를 실행한다.    ◽ 중복을 없앤다.    ◽ 프로그래머 의도를 표현하라.    ◽ 클래스와 메서드 수를 최소로 줄여라 . 단순한 설계 규칙 1: 모든 테스트를 실행하라 단순한 설계 규칙 2~4: 리팩터링 단순한 설계 규칙 2. 중복을 없애라 각 메서드를 따로 구현하는 방법도 있지만, isEmpty 메서드는 부울 값을 반환하며 size 메서드는 개수를 반환한다. 하지만 isEmpty 메서드에서 size 메서드를 이용하면 코드를 중복해 구현할 필요가 없어진다. 깔끔한 시스템을 만들려면 단 몇 줄이라도 중복을 제거하겠다는 의지가 필요하다. scaleTOOneDimension 메서드와 rotate 메서드를 살펴보면 일부 코드가 동일하다. 다음과 같이 코드를 정리해 중복을 제거한다. 아주 적은 양이지만 공통적인 코드를 새 메서드로 뽑고 보니 클래스가 SRP를 위반한다. 그러므로 새로…

  • [CleanCode] 11장 시스템

    도시를 세운다면? 시스템 제작과 시스템 사용을 분리하라 🔹 소프트웨어 시스템은 (애플리케이션 객체를 제작하고 의존성을 서로 ‘연결’하는) 준비 과정과 (준비 과정 이후에 이어지는)런타임 로직을 분리해야 한다. 관심사(concern) 분리 (장점) (단점) 체계적이고 탄탄한 시스템을 만들고 싶다면 설정 논리는 일반 실행 논리와 분리해야 모듈성이 높아진다. 또한 주요 의존성을 해소하기 위한 방식, 즉 전반적이며 일관적인 방식도 필요하다. Main 분리 팩토리 의존성 주입 확장 횡단(cross-cutting) 관심사 자바에서 사용하는 Aspect or Aspect와 유사한 메커니즘 3가지 테스트 주도 시스템 아키텍처 구축 의사 결정을 최적화하라 명백한 가치가 있을 때 표준을 현명하게 사용하라 시스템은 도메인 특화 언어가 필요하다 결론 참고 링크

  • [CleanCode] 10장 클래스

    클래스 체계 🔹 클래스를 정의하는 표준 자바 관례 (순서)◽ 변수 목록    – 정적 공개 상수 (public static final)    – 정적 비공개 (private static final)    – 비공개 인스턴스 변수 공개 변수 (공개 변수가 필요한 경우는 거의 없다)◽ 공개 함수    – 비공개 함수는 자신을 호출하는 공개 함수 직후에 넣는다.    – 추상화 단계가 순차적으로 내려간다. </aside> 클래스를 만들 때 가장 중요한 규칙은 크기다. 또한, 클래스 설명은 만일(if), 그리고(and), 하며(or), 하지만(but)을 사용하지 않고 25단어 내외로 가능해야 한다. 응집도Cohesion 일반적으로 응집도가 높은 클래스는 가능하지도 바람직하지도 않다. 그러나 우리는 응집도 높은 클래스 (클래스에 속한 메서드와 변수가 서로 의존하며 논리적인 단위로 묶인다)를 선호한다. 응집도를 유지하면 작은 클래스 여럿이 나온다 이를 수정하지 않으려면 어떻게 해야 할까? 이렇게 수정한다면…

  • [CleanCode] 9장 단위 테스트

    🔹 기존에는 단위 테스트란 자기 프로그램이 ‘돌아간다’는 사실만 확인하는 일회성 코드에 불과했다. 클래스와 메서드를 공들여 구현한 후 임시 코드를 급조해 테스트를 수행했는데 대개는 간단한 드라이버 프로그램을 구현해 자신이 짠 프로그램을 수동으로 실행했다.     💻 TDD(Test Driven Development)     ◽ 테스트 주도 개발 (실제 코드를 짜기 전에 단위 테스트부터 짜라)    ◽ 애자일과 TDD 덕택에 단위 테스트를 자동화하는 프로그래머들이 이미 많아졌으며 점점 늘어나는 추세이다.       그러나 많은 프로그래머들이 제대로 된 테스트 케이스를 작성해야 한다는 좀 더 중요한 사실을 놓쳐버렸다.  TDD 법칙 세 가지 깨끗한 테스트 코드 유지하기 🔹 테스트 코드를 ‘지저분 해도 빨리’하기 위해 변수 이름을 신경쓰지 않고, 테스트 함수를 간결하거나 서술적이지 않고 테스트 코드를 잘 설계하거나 주의해서…

  • [CleanCode] 8장 경계

    🔹 시스템에 들어가는 모든 소프트웨어를 직접 개발하는 경우는 드물다.오픈소스를 이용하거나, 사내 다른 팀이 제공하는 컴포넌트를 이용하거나, 어떤 식으로든 이 외부 코드를 우리 코드에 깔끔하게 통합해야 한다. 이 장에서는 소프트웨어 경계를 깔끔하게 처리하는 기법과 기교를 살펴본다. 외부 코드 사용하기 💻 java.util.Map 위와 같은 경우 Map이 반환하는 Object를 올바른 유형으로 변환할 책임은 Map을 사용하는 클라이언트에게 있다. 이 방식 보다는 아래와 같이 제네릭을 사용하는 것이 좋다. 그렇지만 이 방법도 사용자에게 필요하지 않은 기능까지 제공한다는 문제를 해결하지는 못한다. 조금 더 깔끔하게 아래와 같이 제네릭스의 사용 여부를 Sensors 안에서 결정하면 어떨까? 경계 인터페이스인 Map을 Sensors 클래스 안으로 숨긴다. 따라서 Map 인터페이스가 변하더라도 나머지 프로그램에는 영향을 미치지 않는다. 제네릭스를 사용하든 하지 않든 더이상 문제가 안 된다.…

  • [CleanCode] 7장 오류 처리

    오류 코드와 깨끗한 코드오류 처리는 중요하다.하지만 오류 처리 코드로 인해 프로그램 논리를 이해하기 어려워진다면 깨끗한 코드라 부르기 어렵다. 이 장에서는 고상하게 오류를 처리하는 기법과 고려사항 몇 가지를 소개한다. 오류 코드보다 예외를 사용하라 Try-Catch-Finally 문부터 작성하라 다음은 파일이 없으면 예외를 던지는지 알아보는 단위 테스트다.단위 테스트에 맞춰 다음 코드를 구현했다.그런데 코드가 예외를 던지지 않으므로 단위 테스트는 실패한다. 잘못된 파일 접근을 시도하게 구현을 변경하자. 아래 코드는 예외를 던진다.코드가 예외를 던지므로 이제는 테스트가 성공한다. 이 시점에서 리팩터링이 가능하다. catch 블록에서 예외 유형을 좁혀 실제로 FileInputStream 생성자가 던지는FileNotFoundException을 잡아낸다. 미확인 unchecked 예외를 사용하라 자바에서 처음으로 Checked Exception을 지원한 당시는 확인된 예외를 멋진 아이디어라 생각했다. 실제로도 확인된 예외는 몇가지 장점을 제공한다. 하지만 지금은 안정적인 소프트웨어를 제작하는…