Skip to main content

김주엽

1. 📌 핵심 개념 정리

✅ 요약하기

어째서 수많은 프로그래머가 getter/setter를 당연하게 public으로 설정해 변수를 외부에 노출할까?

  1. 자료 추상화
    변수를 private으로 선언하더라도 각 변수마다 getter/setter를 제공한다면 구현을 외부로 노출하는 셈이다.
    추상 인터페이스를 제공해 사용자가 구현을 모른 채 자료를 조작할 수 있어야 한다.

    • 개선 전

      public class Point {
        private double x;
        private double y;
      
        public double getX(){ return x; }
        public double getY(){ return y; }
        public void setX(double x){ this.x = x; }
        public void setY(double y){ this.y = y; }
      }
      

      모든 멤버 변수에 대해 getter/setter를 제공해 외부로 노출하고 있다.

    • 개선 후

      public class Point {
        private double x;
        private double y;
      
        public double getTheta(){
           Math.atan2(y, x);
        }
      }
      

      필요한 메서드만 public으로 설정해 멤버 변수를 외부로부터 보호하도록 개선했다.


  1. 자료/객체 비대칭
    객체는 추상화 뒤로 내부는 숨긴 채 자료를 다루는 메서드만 공개한다.

    • 절차 지향적인 구조의 클래스

       public class Square {
       	public Point topLeft;
       	public double side;
       }
      
       public class Rectangle {
       	public Point topLeft;
       	public double height;
       	public double width;
       }
      
       public class Circle {
       	public Point center;
       	public double radius;
       	public double width;
       }
      
       public class Geometry {
       	public final double PI = 3.141592653585793;
      
       	public double area(Object shape) throws NoSuchShapeException {
       		if(shape instanceOf Square) {
       			Square s = (Square)shape;
       			return s.side * s.side;
       		}
       	else if(shape instanceOf Rectangle) {
       			Rectangle r = (Rectangle)shape;
       			return r.height * r.width;
       		}
       	else if(shape instanceOf Circle) {
       			Circle c = (Circle)shape;
       			return PI * c.radius * c.radius
       		}
       	}
       }
      

      Geometry클래스는 세 가지 도형을 모두 다룬다.
      도형이 동작하는 방식은 Geometry클래스에서 구현하고 메서드를 추가로 구현해도 도형 클래스는 영향을 받지 않는다. 그러나 도형을 추가하고 싶다면 Geometry클래스의 메서드를 모두 고쳐야 할 수도 있다.

    • 객체 지향적인 구조의 클래스

       public class Square implements Shape {
       	public Point topLeft;
       	public double side;
      
       	public double area() {
       		return side*side;
       	}
       }
      
       public class Rectangle implements Shape {
       	public Point topLeft;
       	public double height;
       	public double width;
      
       	public double area() {
       		return height*width;
       	}
       }
      
       public class Circle implements Shape {
       	public Point center;
       	public double radius;
       	public double width;
      
       	public double area() {
       		return PI*radius*radius;
       	}
       }
      

      객체 지향적인 구조의 클래스에서는 area메서드를 도형마다 구현해 새 도형을 추가해도 기존 함수에 아무런 영향을 미치지 않는다. 그러나 새 함수를 추가하고 싶다면 모든 도형 클래스를 고쳐야 한다.

    • 절차 지향적인 코드 vs 객체 지향적인 코드

      • 절차 지향적인 코드
        • 기존 자료 구조를 변경하지 않고 새 메서드를 추가하기 쉽다.
        • 새로운 자료 구조를 추가하기가 어렵다.
        • 새로운 자료 타입이 아닌 메서드가 필요한 경우에 유리하다.
      • 객체 지향적인 코드
        • 기존 메서드를 변경하지 않고 새 클래스를 추가하기 쉽다.
        • 새로운 클래스를 추가하기가 어렵다.
        • 새로운 함수가 아닌 타입이 필요한 경우에 유리하다.

  1. 디미터 법칙
    모듈은 자신이 조작하는 객체의 속사정을 몰라야 한다는 법칙이다.

    클래스 C의 메서드 f는 다음과 같은 객체의 메서드만 호출해야 한다.

    • 클래스 C: f는 자기 자신(this)의 메서드를 호출할 수 있다.
    • f가 생성한 객체: 메서드 f가 만든 객체의 메서드는 호출해도 된다
    • f 인수로 넘어온 객체: f가 인수로 받은 객체의 메서드는 호출할 수 있다.
    • C 인스턴스 변수에 저장된 객체: 멤버 변수로 저장된 객체는 사용 가능하다.
    • 기차 충돌(train wreck)

      • 여러 객체가 한 줄로 이어진 기차처럼 보이는 코드
      Car car = new Car();
      car.getEngine().getBattery().checkBattery(); // 기차 충돌 발생 (Car → Engine → Battery)
      car.getEngine().start(); // Car 내부 구조를 너무 깊이 탐색함
      
      • 기차 충돌 코드는 다음과 같이 나누는 편이 좋다.
       class Battery {
           public void checkBattery() {
               System.out.println("배터리 상태 확인: 정상");
           }
       }
      
       class Engine {
           private Battery battery = new Battery();
      
           public void start() {
               System.out.println("엔진 시동 걸림!");
           }
      
           public void checkBatteryStatus() {  // 배터리 체크는 엔진이 처리
               battery.checkBattery();
           }
       }
      
       class Car {
           private Engine engine = new Engine();
      
           public void startEngine() {  // 엔진을 직접 노출하지 않음
               engine.start();
           }
      
           public void checkBattery() {  // 배터리 체크도 Car가 담당
               engine.checkBatteryStatus();
           }
       }
      
       class Driver {
           public static void main(String[] args) {
               Car car = new Car();
               car.checkBattery();  // Driver는 Car에게만 요청
               car.startEngine();   // Engine을 직접 알 필요 없음
           }
       }
      
      

  1. 자료 전달 객체
    • Data Transfer Object, DTO라고 부르며 데이터베이스, 소켓에서 받은 메시지를 소통하거나 분석할 때 유용하다.
    • public 변수만 있고 메서드가 없는 클래스의 형태를 띄고 있다.
       class User {
           public String account;
           public String password;
           public String email;
           public String address;
       }
      
    • Bean: private 변수를 getter/setter로 조작하는 형태
       @Getter
       class User {
           public String account;
           public String password;
           public String email;
           public String address;
       }
      
    • 활성 레코드: public 변수가 있거나 private 변수에 getter/setter가 있는 자료 구조이며 save, find와 같은 탐색 함수도 제공한다.
      @Getter
      @Setter
      class User {
          public String account;
          public String password;
          public String email;
          public String address;
      
          // 데이터 저장 (DB에 저장한다고 가정)
          public void save() {
              System.out.println(account + " 유저 정보를 DB에 저장합니다.");
          }
      
          // 데이터 조회 (DB에서 검색한다고 가정)
          public static User find(String account) {
              System.out.println(account + " 유저 정보를 DB에서 찾습니다.");
              User user = new User();
              user.account = account;
              user.password = "hashed_password"; // 실제 DB에서 불러오는 가정
              user.email = account + "@example.com";
              user.address = "Seoul, Korea";
              return user;
          }
      }
      
      그러나 위와 같은 방식은 잡종 구조로 비즈니스 규칙을 담는 객체를 따로 생성하는 것을 권장한다.

2. 🤔 이해가 어려운 부분

🔍 질문하기

책을 읽으며 이해하기 어려웠던 개념이나 명확하지 않았던 내용을 정리합니다.

  1. 디미터 법칙
    • 어려웠던 부분
      책에 나와있는 예제를 이해하기에는 코드에 대한 정보가 조금 부족해서 이해하는데 어려웠다.
    • 궁금한 점
      대다수의 개발자들이 기차 충돌이 발생하는 코드를 많이 작성하는데 이를 방지할 수 있는 방법이 있을까?

3. 📚 참고 사항

📢 논의하기

  1. 관련 자료 공유