공부공부

공부공부-230505

nayoon 2023. 5. 5. 21:06

어린이날

 

클래스  분리


생성자

자바 클래스 안에는 다수의 생성자를 만들 수 있다.

주 생성자 하나에 다수의 부 생성자를 가지고 있는 것이 좋다.

 

이때, 부생성자는 반드시 주생성자를 호출하는 식으로 구성해야 중복이 없다.

또한, 주생성자는 생성자 중 가장 아래 구성하는 것이 관례이다.

 

메소드

클래스 안에는 5~10개의 생성자와 2~3개의 메소드를 만드는 것이 좋은데,

많은 메소드를 가진다는 것은 단일 책임 원칙을 위반하고 여러 가지의 역할을 하고 있을 가능성이 높다.

 

생성자와 메소드

적은 수의 메소드와 상대적으로 많은 생성자가 있는 클래스는 곧 응집도가 높고 견고한 클래스라는 뜻이다.

 


private 메소드 테스트

테스트 메소드를 작성하다보면 private 메소드를 테스트해야하는 순간이 찾아온다.

 

private 메소드가 중요 로직을 구현하고 있을 경우 테스트를 해야겠다는 생각이 드는데 private이기 때문에 외부에서 호출이 불가하다.

 

이럴 경우

 

1. reflection을 이용해서 private 메소드 호출 가능

2. default로 접근 제어자 레벨을 낮춘 후 사용

(상용과 테스트 디렉토리 레벨이 같기 때문에 호출 가능)

 

그렇지만 사실 private 메소드를 테스트해야한다면 클래스가 3. 과도한 책임을 지고 있는 경우일 수 있다.

-> 클래스 분리를 하는 것도 방법이다.


Seam

코드를 직접 편집하지 않고도 프로그램의 동작을 변경할 수 있는 포인트(봉합 지점)를 말한다.

 

Seam model을 사용하면 호출하는 코드 변경 대신 호출되는 메소드만 변경하는 것이다.

 

봉합에는 전처리 봉합, 링크 봉합, 객체 봉합이 있는데 객체지향 프로그래밍에서는 객체 봉합이 적합하다고 한다.

https://namhoon.kim/2022/02/09/method-test/004/

 


DI

의존성 주입

 

스프링의 세가지 특징이라고 하면 나오는 DI, IoC, AOP 때문에 잘 알고 있는 DI

 

반드시 스프링에서만 쓰이는 것은 아니고 순수 자바 개발에서도 쓰일 수 있다.

예를 들면 아래와 같이 객체를 주입할 수 있다.

interface MovingStrategy {
    void move();
}

class MovingForwardStrategy implements MovingStrategy {
    @Override
    public void move() {
    	...
    }
}

class Car {

    ...
    
    public void move(MovingStrategy movingStrategy) {
    	movingStrategy.move();
    }
}

class Main {
    ...
    
    Car car = new Car();
    car.move(new MovingForwardStrategy());
    
}

 

DI의 장점은 무엇일까?

 

위의 경우에서 살펴보면 자동차는 이동 관련 책임과의 관계가 느슨해질 수 있다.

자동차는 자동차만의 역할이 존재할텐데 이동 관련 책임은 줄어들기 때문에 자동차 역할에 집중할 수 있다.

 

1. 의존성이 줄어든다. (주입 대상이 달라지더라도 수정사항이 없기 때문에 의존성이 줄어든다.)

2. 재사용성이 높은 코드가 된다. (위의 경우 Main 클래스에서 MovingStrategy 인터페이스를 구현하는 클래스로 바꾸면 얼마든지 재사용 가능하다.)

3. 테스트하기 좋은 코드가 된다. (Car와 MovingStrategy를 각각 테스트할 수 있고 MovingStrategy의 move를 오버라이드해서 테스트할 수도 있다.)

4. 가독성이 높아진다. (MovingStrategy의 기능이 분리되기 때문에 가독성이 높아진다.)

 

토비의 스프링에서는 아래와 같이 나와있다고 하는데

  • 클래스 모델이나 코드에는 런타임 시점의 의존관계가 드러나지 않는다. 그러기 위해서는 인터페이스만 의존하고 있어야 한다.
  • 런타임 시점의 의존관계는 컨테이너나 팩토리 같은 제3의 존재가 결정한다.
  • 의존관계는 사용할 오브젝트에 대한 레퍼런스를 외부에서 제공(주입)해줌으로써 만들어진다.

https://tecoble.techcourse.co.kr/post/2021-04-27-dependency-injection/


3개 이상의 인스턴스 변수를 가진 클래스를 구현하지 않는다.

 

인스턴스 변수 줄이는 방법

1. 중복값

2. 불필요한 값

3. 관련있는 인스턴스 변수를 새로운 클래스 객체로 분리

 


디미터 법칙

 

https://dkswnkk.tistory.com/687

 

모듈은 자신이 조작하는 객체의 속사정을 몰라야한다는 것을 의미 -> 객체의 내부 구조를 외부에 공개하지 않는다.

 

간단하게는 '.' 사용을 최대한 자제해야하고, 디미터 법칙을 준수하게 되면 캡슐화를 높여 객체의 자율성과 응집도를 높일 수 있다.

 

car.getPosition() > 100

// car의 position을 꺼내서 비교하는 것보다는
// 아래와 같이 car 객체에게 메시지를 보내는 식이 훨씬 바람직하다.
car.isOverLine(100)

 

조심할 부분

DTO와 같은 자료구조는 내부 구조를 외부에 노출하는 것이 당연하다. 따라서 디미터 법칙이 적용되지 않는다.

Java8 Stream API도 마찬가지이다. 디미터 법칙은 객체의 결합도에 관련된 이야기이기 때문에 '.'에 매몰되면 안된다.

 


Enum

 

php를 쓰다보니 잘 사용했었던 Java 문법만 조금 기억나는 상태이다..(대부분 잊었다)

https://bcp0109.tistory.com/334

 

Enum 목록을 가지고 오기 위해서는 위의 블로그에 의하면 따로 Map으로 만들어야한다고 한다.


팩토리 메소드 패턴

https://tecoble.techcourse.co.kr/post/2020-05-26-static-factory-method/

 

 

객체 생성의 역할을 하는 팩토리 메소드 패턴으로

 


Stream sum 사용

https://kapentaz.github.io/java/Java8-stream-sum-구하기/#