백엔드 웹개발 (Java/Spring) 초격차 - 3

김재현·2022년 9월 28일
0

FastCampus

목록 보기
3/9
  • 조금 더 리팩토링 해보자.

  • 인터페이스를 생성해준다.
    supports 메서드로 operator 를 받아 boolean값을 반환하고
    calculate 메서드로 operand 를 받아 int값을 반환한다.

  • NewArithmeticOperator를 상속받은 클래스가 나머지를 구현한다.
    operator가 "+" 와 같다면
    두 operand를 +해서 반환한다는 의미.
  • SubtractionOperator MultiplicationOperator DivisionOperator도 구현해주자.

  • 각각의 구현체들을 상위 인터페이스인 NewArithmeticOperator을 통해 받는다.
  • enum대신
    .filter 오퍼레이터에 해당하는 실제 구현체를 필터링.
    .map 선택받은 오퍼레이터를 calculate할 때 operand 둘을 전달.
    .findFirst
    .orElseThrow 아니면 예외 반환
  • 인터페이스를 하나 주고 인터페이스를 구현한 네개의 구현체를 받음.
    들어온 오퍼레이터에 맞는 구현체를 찾고,
    구현체에게 calculate 작업 위임. 인자로 들어온 opernad 1, 2, 전달.
    해당하는 값이 int니까 int로 받기 위한 map.
    .findFirst로 첫 값을 받지만
    연산자에 해당하는 구현체가 없다면 .orElseThrow로 예외 반환.
  • 0으로 나누는 경우 예외를 발생시키는지 테스트 코드를 작성하자.
    테스트는 실패할텐데, DivisionOperator클래스에 해당 상황에 대한 부분이 없기 때문이다. 작성해주자.

  • DivisionOperator 클래스에 operand2 가 0인 상황에 대한 코드를 작성한다.
    IllegalArgumentException으로 예외를 발생시킨다.
  • 테스트 코드도 그에 맞춰 수정해 줄 수 있다.
  • 그렇다면 operand가 양수라는 조건은 어디서 만들어줘야할까?
    만약 각 클래스나 인터페이스에서 operand가 양수라는 조건이 만족하는지 테스트해주어야 한다면, operand가 있는 곳마다 validation을 체크해주어야 한다. 굉장히 비효율적
  • 따라서 value 오브젝트를 만드는 편이 더 좋다.

  • if(isNegativeNumber(value)) value가 음수라면,
    throw new IllegalArgumentException argumnet 예외를 반환하도록 한다.
  • 해당 값을 전달했을 때 value가 음수면 예외가 발생하고
    양수면 객체가 만들어진다.

  • 다음과 같이 리팩토링 작업을 해주어야한다.

  • 양수 테스트

객체지향

  • 에러가 발생했을 때, 혹은 어떠한 기능을 추가하고 싶을 때 응집도가 높다면, 해당 기능이 구현되어 있는 곳에 가서 문제를 해결할 수 있을 것이다. 응집도가 낮다면 어디에서 문제가 발생했는지를 찾는 데에만도 꽤나 시간이 필요할 것.
  • 결합도를 낮추기 위해 외부 클래스를 작성해서 확장하는 방법을 사용하는 것이 더 좋다.
  • 메소드를 호출한다 = 메시지를 주고 받는다.

학점 계산기 만들기

  1. 도메인을 구성하는 객체에는 어떤 것들이 있는지 고민해보자.
    • 학점계산기 도메인 : 이수한 과목, 학점 계산기
    • 이 단계에서 모든 객체를 다 도출할 수는 없다.
      생각나는 데까지만 하자.
  2. 객체들 간의 관계 고민
    • 학점 계산기는 이수한 과목을 갖고 학점을 계산하지 않을까?
      학점 계산기가 이수한 과목을 인스턴스 변수로 갖으면서 평균학점을 계산할 수 있어야겠다.
  3. 동적인 객체를 정적인 타입으로 추상화, 도메인 모델링 하기
    • 이수한 과목 예시를 상상해보자.
      객체지향 프로그래밍, 자료구조, 중국어 회화 등..
      객체는 세가지이다.
    • 동적인 세가지 객체를 정적인 타입으로 추상화.
      과목(코스) 클래스로 표현할 수 있다.
  4. 협력 설계
    • 작은 객체부터 만들어본다.
    • 학점 계산기를 만들기 위해서는 이수한 과목이 있어야 한다.

  • 이수한 과목 테스트 생성

  • 정보를 받을 수 있게 클래스를 생성해준다.
  • 다음은 이수한 과목 정보를 이용할 수 있는 평균학점 계산기 테스트를 작성해준다.

  • 다음은 calculateGrade 구현부 작성
    학점수X교과목 평점 을 해주어야하니 for문을 사용한다.

  • (학점수 * 교과목 평점)의 합계multipliedCreditAndCourseGrade 변수를 선언, for 문 안에 넣어준다.
  • course의 credit값과 문자(A+, A, ..)인 grade를 숫자로 변환한 값인 gradeToNumber을 곱해준다.

  • getCreditgetGradeToNumber구현해준다.

  • 수강신청 총학점 수인 totalCompletedCredit를 구현해주고,
    둘을 나누어주면 학점 계산기를 만들 수 있다.
  • 테스트 코드도 잘 작동된다.
  • 이제 리팩토링을 통한 개선을 해보자.
  • 문제점을 생각해본다.
    • course가 직접 자신의 학점과 성적을 갖고 있지만, 학점X성적 정보를 해당 값을 가진 course가 계산하는 것이 아닌, 이들의 정보를 getter를 통해 가져와 gradeCalculator가 계산하고 있다.
    • 만약 학점 계산, 예를 들어 학점X교과목 평점의 합계 부분이 여러 군데에서 사용하게 된다면, 한 곳에서 수정할 때 모든 곳에서 수정해주어야한다는 문제가 있다.
      → 응집도가 낮다.
    • 하지만 이것을 course에서 수행해준다면,
      게터를 이용하는 것이 아닌, 메서드를 호출해서 해당 객체에게 작업을 위임해준다면 수정 소요가 발생했을 때 해당 부분만 수정해주면 된다.
      → 응집도가 높기 때문에 변화가 발생했을 때 한 군데만 수정해주면 된다.

  • 게터를 통해 정보를 갖고와서 처리하는 것이 아닌, 해당 데이터를 가진 객체에게 메시지를 던져 작업을 처리해주게 된다면 변화에 유연한 코드를 작성할 수 있을 것이다.

일급 콜렉션 사용

  • GradeCalculator에 있던 정보를 모두 CoursesmultiplyCreditAndCourseGrade로 이동시켰다.

  • 마찬가지로 calculateTotalCompletedCredit를 만들어 이동시켰다.

  • 리팩토링 된 GradeCalculator
  • 1급 콜렉션이란
    리스트 형태로 된 Course 정보만 인스턴스 변수로 갖는 클래스.
    변수는 오직 하나여야한다.

  • 여러개의 Course 정보를 갖는 클래스
  • Course를 갖고 처리할 수 있는 책임들이 해당 1급 컬렉션 밑으로 이동하게 된다. 어떠한 수정이 발생했을 때 해당 메서드만 수정하면 되겠다. 하는 판단이 서게 됨.
  • 객체들끼리 메시지의 전달을 통해, 자신이 모두 처리하는 것이 아닌 해당 값을 가진 객체에게 메시지를 통해 작업을 위임 결과값을 가져오고 이를 통해 최종적인 결과를 얻어내는 객체지향적인 프로그램을 설계하자.

음식 주문

0개의 댓글