6장 객체와 자료 구조
1. 📌 핵심 개념 정리
✅ 요약하기
1. 자료 추상화
추상 인터페이스를 제공해 사용자가 구현을 모른 채 자료의 핵심을 조작할 수 있어야 진정한 의미의 클래스다. 단순히 인터페이스나 조회/설정 함수만 제공한다고 해서 추상화가 이루어지는 것이 아니다.
변수 사이에 함수라는 계층을 넣는다고 구현이 감춰지지는 않는다. 구현을 감추려면추상화가 필요하다.단순한 조회 함수와 설정 함수로 변수를 다루는 것이 아니라,추상적인 개념으로 표현하는 것이 좋다.개발자는 객체가 포함하는 자료를 표현할 가장 좋은 방법을 고민해야 한다.무작정 조회/설정 함수를 추가하는 것은 가장 나쁜 방법이다.
2. 자료/객체 비대칭
객체와 자료 구조는 본질적으로 서로 반대되는 개념이다.
객체(Object): 자료를 숨기고 동작(메서드)을 공개한다.기존 객체에새로운 타입을 추가하기 쉽다.반면, 기존 객체에새로운 동작을 추가하는 것은 어렵다.
자료 구조(Data Structure): 별다른 동작 없이 자료를 노출한다.기존 자료 구조에새로운 동작을 추가하기 쉽다.반면, 기존 동작에새로운 자료 구조를 추가하는 것은 어렵다.
📌 예제 코드
절차적 코드 (자료 구조 중심)
public class Square {
public Point topLeft;
public double side;
}
public class Geometry {
public final double PI = 3.141592653589793;
public double area(Object shape) throws NoSuchShapeException {
if (shape instanceof Square) {
Square s = (Square) shape;
return s.side * s.side;
}
throw new NoSuchShapeException();
}
}
새로운 도형을 추가하면Geometry클래스를 수정해야 한다.하지만area()같은 기존 함수에 새로운 동작을 추가하는 것은 쉽다.
객체 지향 코드 (객체 중심)
public class Square implements Shape {
private Point topLeft;
private double side;
public double area() {
return side * side;
}
}
새로운 도형을 추가해도 기존 클래스는 변경할 필요가 없다.하지만perimeter()같은 새로운 동작을 추가하려면 모든 도형 클래스를 수정해야 한다.
정리
새로운함수가 필요한 경우 →절차 지향적인 코드(자료 구조 중심)새로운자료 타입이 필요한 경우 →객체 지향적인 코드(객체 중심)
3. 디미터 법칙
객체는 자신이 조작하는 객체의 내부를 몰라야 한다.
📌 기차 충돌 (Train Wreck)
final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
여러 객체가 한 줄로 이어진기차처럼보이는 코드.내부 자료 구조가 외부로 노출됨.
📌 디미터 법칙을 위반한 예제 코드
class Engine {
public void start() {
System.out.println("Engine started");
}
}
class Car {
private Engine engine = new Engine();
public Engine getEngine() { // 내부 객체를 직접 반환
return engine;
}
}
class Driver {
public void drive(Car car) {
car.getEngine().start(); // 🚨 디미터 법칙 위반
}
}
📌 디미터 법칙을 준수한 코드
class Car {
private Engine engine = new Engine();
public void startEngine() { // 중간 계층을 제공
engine.start();
}
}
class Driver {
public void drive(Car car) {
car.startEngine(); // ✅ 디미터 법칙 준수
}
}
내부 자료를 감추고 필요한 동작만 제공해야 한다.
4. 자료 전달 객체 (DTO, Data Transfer Object)
DTO는 데이터베이스에서 가져온 가공되지 않은 정보를 애플리케이션 코드에서 사용할 객체로 변환하는 데 사용된다.
📌 DTO 예제 코드
public class Address {
private String street;
private String city;
private String state;
private String zip;
public Address(String street, String city, String state, String zip) {
this.street = street;
this.city = city;
this.state = state;
this.zip = zip;
}
}
활성 레코드 (Active Record)
DTO의 특수한 형태로데이터 + 데이터베이스 관련 기능을 포함.save(),find()같은 탐색 함수 제공.하지만비즈니스 로직을 포함하면 안 된다→ 잡종 구조가 되기 때문.
🚨 해결책: 활성 레코드는 자료 구조로 취급하고, 비즈니스 규칙을 담을 별도의 객체를 만든다.
2. 🤔 이해가 어려운 부분
🔍 질문하기
디미터 법칙을 위반하는 코드와 이를 개선한 코드의 차이는 무엇인가?위에서 설명한getEngine().start();같은 직접적인 내부 구조 노출이 문제다.개선 코드에서는car.startEngine();처럼객체가 직접 행동을 수행하도록 변경했다.
3. 📚 참고 사항
📢 논의하기
객체 지향 vs 절차 지향
책에서는 객체 지향이 항상 최선이 아니며, 절차 지향이 적합한 경우도 있다고 말한다. 그렇다면 언제 절차 지향이 더 적합할까?
📌 절차 지향이 적합한 경우
단순한 데이터 처리→ 객체 간의 복잡한 상호작용이 필요하지 않은 경우.일회성 스크립트→ 데이터를 가져와 가공하고 저장하는 간단한 작업.성능이 중요한 경우→ 불필요한 객체 생성을 줄이고, 순차적인 처리가 유리한 경우.기능 중심의 코드→ 데이터보다는 로직이 중심이 되는 경우.
📌 결론: 모든 상황에서 객체 지향이 정답은 아니다. 변화의 방향에 따라 절차 지향이 더 적합할 수도 있다!