객체지향적 코딩에 대해서 생각해보았다
코딩을 하면서 처음으로 생각해 본 듯?

이전에는 Scanner를 CommerceSystem 안에서 직접 생성할지,
아니면 Main에서 만들어서 넘길지 고민했다.
예를 들면 이런 두 방식이 있다.
public class CommerceSystem {
private Scanner scanner = new Scanner(System.in);
}
public class CommerceSystem {
private Scanner scanner;
public CommerceSystem(Scanner scanner) {
this.scanner = scanner;
}
}
이 두 방식 중에서 객체지향적으로 더 깔끔한 방법은
생성자 주입 방식이다.
생성자 주입은
클래스가 필요한 객체를 스스로 만들지 않고, 밖에서 전달받는 방식이다.
예를 들면:
Scanner scanner = new Scanner(System.in);
CommerceSystem commerceSystem = new CommerceSystem(scanner);
이 구조는 이런 흐름이다.
Main이 필요한 객체를 생성한다.CommerceSystem은 생성자를 통해 그 객체를 전달받는다.즉, CommerceSystem이 Scanner를 직접 만들지 않고
이미 준비된 Scanner를 받는 구조다.
Main은 프로그램 시작점이고,
필요한 객체를 준비하는 역할을 맡는다.
CommerceSystem은
준비된 객체를 받아서 실제 기능을 수행하는 역할을 맡는다.
즉 역할이 이렇게 나뉜다.
Main : 준비 담당CommerceSystem : 실행 담당이 구조가 더 자연스럽다.
만약 CommerceSystem 안에서 Scanner를 직접 만든다면,
CommerceSystem은 기능 수행뿐 아니라
객체 생성까지 같이 하게 된다.
그러면 역할이 조금 섞인다.
이미 CommerceSystem은 products도 밖에서 받고 있다.
public CommerceSystem(List<Product> products, Scanner scanner) {
this.products = products;
this.scanner = scanner;
}
즉 products는 밖에서 받고, scanner만 내부에서 직접 만들면
설계가 통일되지 않는다.
반면 둘 다 밖에서 전달받으면 흐름이 깔끔하다.
Main이 준비한다.CommerceSystem은 전달받은 것만 사용한다.이런 구조가 더 읽기 쉽고 설계 의도가 분명하다.
처음에는 Scanner(System.in)을 쓸 수 있다.
그런데 나중에는 입력 방식이 달라질 수도 있다.
예를 들어:
만약 CommerceSystem 안에서 직접 new Scanner(System.in)을 써버리면,
입력 방식을 바꾸려면 CommerceSystem 코드를 직접 수정해야 한다.
하지만 생성자 주입 구조라면
CommerceSystem은 그대로 두고,
Main에서 어떤 Scanner를 넘길지만 바꾸면 된다.
즉 변경에 더 유연하다.
지금 단계에서는 테스트 코드까지 깊게 안 가도 되지만,
구조적으로는 이것도 큰 장점이다.
직접 생성하는 방식은:
private Scanner scanner = new Scanner(System.in);
이렇게 고정돼 있어서 테스트할 때 다루기 불편하다.
반면 생성자 주입은:
public CommerceSystem(Scanner scanner) {
this.scanner = scanner;
}
이렇게 되어 있으니,
테스트할 때 원하는 입력 객체를 넣어볼 수 있다.
즉 외부에서 조립 가능하다는 점이 장점이다.
public class CommerceSystem {
private Scanner scanner = new Scanner(System.in);
}
이 방식의 특징:
public class CommerceSystem {
private Scanner scanner;
public CommerceSystem(Scanner scanner) {
this.scanner = scanner;
}
}
이 방식의 특징:
Scanner scanner = new Scanner(System.in);
CommerceSystem commerceSystem = new CommerceSystem(products, scanner);
commerceSystem.start();
scanner.close();
private List<Product> products;
private Scanner scanner;
public CommerceSystem(List<Product> products, Scanner scanner) {
this.products = products;
this.scanner = scanner;
}
이 구조의 장점은 명확하다.
Main이 필요한 객체를 준비한다.CommerceSystem은 전달받은 객체를 사용한다.이걸 아주 쉽게 생각하면:
CommerceSystem이 말한다.
“상품도 내가 받고, Scanner는 내가 직접 만들게.”
Main이 말한다.
“필요한 재료는 내가 다 준비해줄게.
너는 그걸 받아서 일만 하면 돼.”
두 번째가 더 깔끔하지 않나?
즉 생성자 주입은
필요한 재료를 밖에서 넣어주는 방식이라고 생각하면 된다.
생성자 주입이 좋은 이유는 다음과 같다.
Main에 모인다이번 과제를 하면서 느낀 점은,
단순히 “동작만 하면 된다”가 아니라
누가 만들고, 누가 받고, 누가 사용하는지를 나누는 것이 중요하다는 점이었다.
특히 Scanner처럼 작은 객체 하나도
어디서 생성하는지가 설계 차이를 만든다는 걸 알게 됐다.
처음에는 CommerceSystem 안에서 직접 new Scanner(System.in)을 해도 된다고 생각했지만,
생성자 주입 방식으로 바꾸고 나니
코드의 역할이 더 분명해지고 구조도 더 자연스러워졌다.
생성자 주입은 클래스가 필요한 객체를 직접 만들지 않고, 밖에서 전달받아 사용하는 방식이며, 역할 분리와 유지보수 측면에서 더 좋은 설계이다.