[클린코드] Ch 14-16

Ericamoyed·2021년 2월 27일
0

클린코드

목록 보기
7/8

Chapter 14

점진적인 개선: 명령행 인수 구문분석기 코드 개선

  • 깨끗한 코드를 짜려면 먼저 지저분한 코드를 짠 뒤에 정리해야한다.
  • 인수 유형은 다양하지만 모두가 유사한 메서드를 제공할 경우 클래스 하나가 적합
  • TDD: 언제 어느 때라도 시스템이 돌아가야 한다.
  • 각 인수 유형을 처리하는 코드를 모두 한 클래스에 넣고 나서, 이후 파생 클래스들을 만들어 코드를 분리한다.
    • 프로그램 구조를 조금씩 변경하는 동안에도 시스템의 정상 동작을 유지하기 쉽기 때문: 이후 파생 클래스를 만들어 기능을 분산
  • protected 변수인 상위클래스 변수를 하위 클래스로 내려 private 변수로 선언하기도 함
  • 한 함수에서 if문으로 유형을 일일이 확인하는 대신 파생 클래스로 내려서 if문을 제거한다.

Chapter 15

JUnit 들여다보기: JUnit 라이브러리 리팩토링

  • 한 함수에서 몇 줄은 변수를 반환하고, 몇 줄은 반환값이 없는 형태로 사용방식이 일관적이지 못할 경우 반환값을 임의로 줌으로써 코드 가독성을 높이기도 한다.
  • findCommonSuffix가 findCommonPrefix의 특정 연산에 의존할 경우: 함수간의 시간결합이 있는 상황이 있을 수 있다.
    • 뒤에서 부르는 함수에서 첫 함수의 반환값을 이용하게끔 구성함으로써 호출 순서를 보장할 수 있다.
    • 하지만 꼭 인수에 prefixIndex를 넣어야했던 이유를.. 의미론적으로 설명하기 어려움
    • 따라서 모듈화를 없애고 한 메소드로 결합하는 형태로 시간결합을 해결
    • 항상 모듈화가 좋은 것은 아니고, 추후에 코드를 읽는 사람이 개별적으로 특정 메소드만 호출했을 때 문제가 생기지 않도록까지 고려를 한 다음, 다시 메소드를 합치는 경우도 있다.

Chapter 16

SerialDate 리팩터링: SerialDate 라이브러리 리팩토링

  • 코드 커버리지 분석도구: 클로버!
  • static final 상수 모음에 불과한 클래스들 -> 옛날 자바 프로그래머들이 많이 쓰던 기교 -> enum으로 정의하자!
  • 부모 클래스는 파생 클래스를 몰라야 바람직: abstract factory 패턴을 적용하자!
    • 약간 부모 클래스와 파생 클래스 사이의 어떤 완충제같은 느낌.. 파생 클래스만 넣기는 모두에게 필요할 것 같은데 부모 클래스에 넣기는 구현적인 내용을 많이 포함하고 있을 때..
  • 추상 메서드로 위임하는 정적 메서드 (abstract class에 들어가는 static method들): singleton, decorator, abstract factory 패턴 조합을 이용
    • singleton
      • abstract class 내부에 static DayDateFactory factory;를 활용하여 static 변수를 하나 선언 (해당 abstract class 를 파생한 구체 클래스로 초기화 필요)
      • 물론 setInstance를 구성하여 상기 factory 객체를 수정할 수 있도록 구성
      • static 변수이므로, class 하나당 하나만 생성됨 (객체별로 존재 X: 싱글톤 보장 가능)
      • 클래스 내부의 모든 static 메소드에서 static 변수인 해당 factory에 대해 abstract method를 수행하도록 되어있어, 이를 파생한 클래스의 객체 또는 클래스 자체에서 메소드 호출을 통해 어디서든 해당 factory 사용 가능 -> 싱글톤!
      • 스태틱 변수에 대해 반드시 초기화를 해야하나? 안해도 된다! 기본적으로 그 객체의 초기값이 들어가겠지. 일반적으로 null, Integer 면 0, ...
    • decorator
      • 객체의 결합을 통해 기능을 동적으로 유연하게 확장할 수 있도록 하는 패턴
      • 도로 표시에 대한 다양한 방식을 적용하는 상황에서, 추상 클래스인 Display를 만들고, 이를 확장한 기본 도로를 의미하는 RoadDisplay를 하나 만든다.
      • 그리고 추상 클래스인 Display를 확장해서 다양한 추가 기능에 대한 상위 클래스인 DisplayDecorator를 만든다
      • 그리고 이 상위 클래스를 확장하여 다양한 추가기능에 대한 concrete class들을 만든다.
        • 이들의 생성자에서는 super() 즉, DisplayDecorator의 생성자를 수행하도록 하고, 이들의 draw에서는 super.draw()와 본인 특유의 추가기능 draw에 대한 구현을 추가한다.
        • 이부분이 핵심!!
        • super.draw()를 하기 때문에, 내가 parameter로 제시한 특유한 친구에 대한 draw도 수행하고, 나만의 draw도 수행하게 되기 때문에 유연한 확장이 가능한 것!
        • parameter로 정의하게 되면, 그 순간 contructor가 작동하고, 상위 클래스에서는 그 contructor로 인해 정의된 decoratedDisplay에 대한 draw를 수행하게 되는 것!
      • 따라서 실제로 수행할 때에는 하기와 같이 유연하게 확장할 수 있다는 것!
        Display roadWithCrossingLaneAndTraffic =
          new LaneDecorator(
            new TrafficDecorator(
              new CrossingDecorator(
                new RoadDisplay()
              )
            )
          );
    • abstract factory
    • 디자인패턴에 대한 부분은 모두 https://gmlwjd9405.github.io/2018/07/06/singleton-pattern.html 해당 블로그를 참조하였음
  • 부모 클래스와 자식 클래스를 나누는 상황에서 변수가 특정 클래스에서만 사용되더라도 특정 구현에 의존하지 않는 이상 하위 클래스로 위치를 변경하지 않는다.
    • 단지 변수가 사용되는 위치에 가깝게 위치만 변경할 뿐
  • 한 메서드가 다른 메서드를 호출하며 출력 형식을 선택하는 플래그를 넘김 (축약 여부에 대해서 true/false로 넘기면 그에 따라 출력에 축약을 할건지/말건지를 담아서 return)
    • 모듈화를 없애서 이러한 형태를 제거하는 것이 바람직
  • addDays vs. plusDays
    • 전자는 sample.addDays(5)를 하면 sample의 값이 변경되는지, 아니면 단순히 sample 값에 5를 더한 값을 return 하는지 판단이 모호
    • 후자와 같이 sample.plusDays(5)를 하면 sample의 값이 변경된다기보다 sample 값에 5를 더한 값을 return 한다고 좀더 쉽게 예측이 가능
  • 클래스로 만들어지는 인스턴스를 인수로 받아 클래스 메서드를 호출하는 인스턴스 메소드
    • 진짜 인스턴스 메소드로 변경하고 인수로 들어가는 인스턴스 제거
  • 모든 enum 클래스는 toString을 사용하면 이름이 반환된다.
    • ex) weekInMonth.toString (weekInMonth: enum 객체)
  • enum 내부에 abstract method를 선언해두고, 각 enum 값에 대해 명시할 때 해당 메소드를 구현함으로써 구성할 수 있다.
    • if문의 분기를 줄일 수 있는 좋은 방법
      public enum sample {
        OPEN {
          public boolean is In() {
            return true;
          }
        },
        CLOSED {
          public boolean is In() {
            return false;
          }
        }      
        public abstract boolean is In() {}
      }
profile
꿈많은 개발자, 일상 기록을 곁들인

0개의 댓글