코딩관계론

[Clean code] 자료추상화 본문

Clean code

[Clean code] 자료추상화

개발자_티모 2023. 1. 6. 01:46
반응형

자료추상화

구현을 감출려면 추상화가 필요하고 그보는 추상인터페이스를 제공해 사용자가 구현을 모른 채 자료의 핵심을 조작할 수 있어야 한다(오른쪽 코드)

자료를 세세하게 공개하기보다는 추상적인 개념으로 표현해야 한다.

public class Point {
  private double x;
  private double y;
}

변수를 private로 선언했다 하더라도 무분별한 get, set함수를 제공한다면 구현을 외부로 노출하는 샘이다.

public interface Point {
  double getX();
  double getY();
  void setCatesian(double x, double y);
  double getR();
  double getTheta();
  void setPolar(double r, double theta);
}
public interface Vehicle {
  double getFuelTankCapacityInGallons();
  double getGallonsOfGasoline();
}

단순히 두 함수가 변수의 값을 읽어서 사용자에게 알려줌

public interface Vehicle {
  double getPercentFuelRemaining();
}

위의 함수는 정보 어디서 오는지 전혀 드러나지 않는다

자료/객체 비대칭성

객체는 추상화 뒤로 자료를 숨긴 채로 자료를 다루는 함수만 제공한다 Ex.interface Vehicle

자료 구조는 자료를 그대로 공개하며 별다른 함수를 제공하지 않는다 Ex.interface Vehicle

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
		}
	}
}
  • square, rectangle, geometry는 모두 자료구조다
    • 변수를 그대로 외부에 노출하며 별다른 함수를 제공하지 않기 때문이다.
  • Geometry에 새로운 기능을 추가한다면 위의 세 개의 클래스는 영향을 받지 않는다.
  • 반대로 새 도형을 추가한다면 Geometry에 속한 함수들은 모두 수정이 필요하다.

자료 구조를 사용하는 코드는 기존 자료 구조를 변경하지 않으면서 새 함수를 추가하기 쉽다.

절차적인 코드는 새로운 자료 구조를 추가하기 어렵다. 그러려면 모든 함수를 고쳐야 한다.

→ Geometry 클래스에 새로운 자료 구조 클래스를 추가한다면 area에도 수정이 들어가고 모든 함수에 수정 필요

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;
	}
}
  • 객체 지향적인 클래스다
    • 새 도형을 추가해도 기존 클래스에 영향을 미치지 않는다.
  • 새 함수를 추가하고 싶으면 모든 클래스를 고쳐야 한다.

객체 지향 코드는 기존 함수를 변경하지 않으면서 새 클래스를 추가하기 쉽다. → 그냥 클래스를 추가하면 되기 때문이다.

객체 지향 코드는 새로운 함수를 추가하기 어렵다. 모든 클래스를 고쳐야 하기 때문이다.

→ 각 클래스마다 추가해야 하기 때문이다.

새로운 함수가 아니라 새로운 자료 타입이 필요하다 → 객체 지향 코드

새로운 자료가 아니라 새로운 함수가 필요하다. → 절차적인 코드로

모든 것이 객체라는 생각은 미신임. 적절하게 선택 필요

디미터의 법칙

디미터의 법칙은 메소드가 반환하는 객체의 메소드를 사용하면 안 된다. 즉 자신이 조작하는 객체의 속사정을 몰라야 한다.

객체는 자료를 숨기고 함수를 외부로 노출한다. 즉 조회 함수로 내부를 공개해선 안된다는 의미이다.

String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();

디미터 법칙의 예는 클래스 c의 메서드 f는 다음과 같은 객체의 메서드만 호출해야 한다

  • 클래스 C
  • f가 생성한 객체
  • f 인수로 넘어온 객체
  • c 인스턴스 변수에 저장된 객체

하지만 위 객체에서 허용된 메서드가 반환하는 객체의 메서드는 호출하면 안됨
Ex) String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();

ctxt.getOptions()이 반환하는 객체의 함수를 호출하기 때문이다

Options opts = ctxt.getOptions();
File scratchDir = opts.getScratchDir();
String outputDir = scratchDir.getAbsolutePath();

ctxt, opts, scratchDir 객체라면 디미터 법칙 위반 → getOptions()은 option을 외부로 노출하는 꼴이다

ctxt, opts, scratchDir 자료 구조라면 내부 구조를 노출하므로 디미터 법칙이 적용되지 않음.

결론: 자료구조는 무조건 함수 없이 공개 변수만 포함하고, 객체는 비공개 변수와 공개 함수를 포함한다면 된다.

Options opts = ctxt.getOptions();
File scratchDir = opts.getScratchDir();
String outputDir = scratchDir.getAbsolutePath();

이 코드가 객체를 반환한다면 어떻게 고쳐야 하는가?

 

자료 전달 객체(DTO)

자료 전달 객체 = 자료 구 객ㅔ의 전형적인 형태(공개 변수만 있고 함수는 없음)

일반적인 형태는 bean 구조다(사이비 캡슐화 모든 변수에 get, set 존재).

활성 레코드 = DTO + 탐색 함수

결론: 절차적 코드와 객체 코드의 장점과 단점을 생각하면서 프로그래밍 하자.

  • 객체: 새로운 자료 타입 추가 용이
  • 자료 구조: 새로운 메소드 추가 용이

반응형

'Clean code' 카테고리의 다른 글

파이썬 데코레이터(Decorator)  (0) 2023.02.26
[Clean code] 클래스  (0) 2023.01.11
[Clean code] 형식 맞추기  (0) 2023.01.09
[Clean code] 함수  (0) 2023.01.04
[Clean Code] 코드에는 의미가 있어야 한다.  (0) 2023.01.03