일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 프로그래머스
- piplining
- 크롤링
- 쿠키
- langgraph
- 구현
- BFS
- jwt 표준
- 셀러리
- AWS
- 아키텍쳐 개선
- gRPC
- 추천 검색 기능
- 완전탐색
- docker
- 몽고 인덱스
- 백준
- 결제서비스
- 누적합
- JPA
- ipo 매매자동화
- 트랜잭샨
- 레디스 동시성
- 검색어 추천
- ai agent
- 카카오
- next-stock
- spring event
- 이분탐색
- 디버깅
- Today
- Total
코딩관계론
[Clean code] 자료추상화 본문
자료추상화
구현을 감출려면 추상화가 필요하고 그보는 추상인터페이스를 제공해 사용자가 구현을 모른 채 자료의 핵심을 조작할 수 있어야 한다(오른쪽 코드)
자료를 세세하게 공개하기보다는 추상적인 개념으로 표현해야 한다.
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 |