클린코드 핵심 정리 (6장 객체와 자료구조)
자료구조 vs 객체
예시 Vehicle
자료구조
// 자료 구조
public interface Vehicle {
double getFuelTankCapacityInGallons(); // 연료탱크 용량(갤런 단위)
double getGallonsOfGasoline(); // 가솔린 (갤런 단위)
}
public class Car implements Vehicle {
double fuelTankCapacitInGallons;
double gallonsOfGasoline;
public double getFuelTankCapacityInGallons() {
return this.fuelTankCapacitInGallons;
}
public double getFuelTankCapacityInGallons() {
return this.gallonsOfGasoline;
}
}
비지니스 로직 없이 순수 데이터를 저장하는 자료구조의 역할이다.
객체
// 객체
public interface Vehicle {
double getPercentFuelRemain();
}
public class Car implements Vehicle {
private double fuelTankCapacitInGallons;
private double gallonsOfGasoline;
public Car(double fuelTankCapacitInGallons, double gallonsOfGasoline) {
if (fuelTankCapcitInGallons <= 0) {
throw new IllegalArgumentException("fuelTankCapacitInGallons must be greater than zero");
}
this.fuelTankCapacitInGallons = fuelTankCapacitInGallons;
this.gallonsOfGasoline = gallonsOfGasoline;
}
public double getPercentFuelRemain() {
return this.gallonsOfGasoline / this.fuelTankCapacitInGallons * 100;
}
}
위의 코드는 생성자에 비즈니스 로직과 관련된 코드가 들어가 있고, 필드를 private 으로 하여 자료를 숨겼다.
예시 Shape
자료구조
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 class Geometry {
public final double PI = 3.141592653589793;
public double area(Object shape) throws NoSuchShapeException {
if (shape instanceof Square) {
Shape 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;
}
throw new NoSuchShapeException();
}
}
만약 Triangle 이라는 새로운 클래스(자료구조가) 추가된다면? area() 함수 안에 if-else 문을 수정해야 한다.
- 절차적인 코드는 새로운 자료구조를 추가하기 어렵다.
- 함수를 고쳐야 한다.
객체
public class Square implements Shape {
private Point topLeft;
private double side;
public double area() {
return side * side;
}
}
public class Rectangle implements Shape {
private Point topLeft;
private double height;
private double width;
public double area() {
return height * width;
}
}
public class Circle implements Shape {
private Point center;
private double radius;
public final double PI = 3.141592653589793;
public double area() {
return PI * radius * radius;
}
}
만약 Triangle 이라는 클래스를 추가한다면?
Triangle 클래스를 생성 후 Shape 인터페이스를 상속 받은 후area() 함수를 오버라이딩 하면된다.
즉 객체지향 코드는 새로운 클래스를 추가하기가 쉽다. 하지만 함수를 추가해야 한다.
상황에 맞는 선택을 하면 된다.
자료구조
- 자료구조를 사용하는 절차적 코드는 기본 자료구조를 변경하지 않으면서 새 함수를 추가하기가 쉽다.
- 절차적인 코드는 새로운 자료 구조를 추가하기 어렵다. 그러려면 모든 함수를 고쳐야 한다.
객체
- 객체지향 코드는 기존 함수를 변경하지 않으면서 새 클래스를 추가하기 쉽다.
- 객체 지향 코드는 새로운 함수를 추가하기 어렵다. 그러려면 모든 클래스를 고쳐야 한다.
객체 - 디미터 법칙
클래스 C의 메서드 f는 다음과 같은 객체의 메서드만 호출해야 한다.
- 클래스 C
- 자신이 생성한 객체
- 자신의 인수로 넘어온 객체
- C 인스턴스 변수에 저장된 객체
A a = new A(); B b = a.getB() (O) C c = a.getB().getC(); (X)
디미터의 법칙에 어긋나는 상황
// 객체 - 기차 충돌. 디미터의 법칙 위배
final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
// 자료구조 - OK
final String outputDir = ctxt.options.scratchDir.absolutePath;
// 객체에 대한 해결책이 아니다. getter를 통했을 뿐, 값을 가져오는 것은 자료구조이다.
ctxt.getAbsolutePathOfScratchDirectoryOption();
ctxt.getScratchDirectoryOption().getAbsolutePath();
// 왜 절대 경로를 가져올까.. 근본 원인을 생각해보자!
// 객체는 자료를 숨기고 자료를 다루는 함수만 공개한다.
BufferedOutputStream bos = ctxt.createScratchFileStream(classFileName);
DTO
다른 계층 간 데이터를 교환할 때 사용
-
로직 없이 필드만 갖는다.
-
일반적으로 클래스명이 Dto(or DTO)로 끝난다.
-
getter/setter 를 갖기도 한다.
- Beans
-
Java Beans: 데이터 표현이 목적인 자바 객체
-
멤버 변수는 private 속성이다.
-
getter와 setter를 가진다.
public class AddressDto {
private String street;
private String zip;
}
public AddressDto(String street, String zip) {
this.street = street;
this.zip = zip;
}
public String getStreet() {
return street;
}
public String setStreet(String street) {
this.street = street;
}
public String getZip() {
return zip;
}
public String setZip(String zip) {
this.zip = zip;
}
Active Record
Database row를 객체에 맵핑하는 패턴
- 비즈니스 로직 메서드를 추가해 객체로 취급하는 건 바람직하지 않다.
- 비즈니스 로직을 담으면서 내부 자료를 숨기는 객체는 따로 생성한다.
- 하지만.. 객체가 많아지면 복잡하고, 가까운 곳에 관련 로직이 있는 것이 좋으므로 현업에서는 Entity에 간단한 메서드를 추가해 사용한다.
public class Employee enxtends ActiveRecord {
private String name;
private String address;
...
}
// ----
Employee bob = Employee.findByName("Bob Martin");
bob.setName("Robert C. Martin");
bob.save();
참고
해당 포스팅은 제로 베이스 클린코드 한달한권을 수강 후 정리한 내용입니다.
Author And Source
이 문제에 관하여(클린코드 핵심 정리 (6장 객체와 자료구조)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@coconenne/클린코드-핵심-정리-5장-객체와-자료구조
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
로직 없이 필드만 갖는다.
일반적으로 클래스명이 Dto(or DTO)로 끝난다.
getter/setter 를 갖기도 한다.
- Beans
Java Beans: 데이터 표현이 목적인 자바 객체
멤버 변수는 private 속성이다.
getter와 setter를 가진다.
public class AddressDto {
private String street;
private String zip;
}
public AddressDto(String street, String zip) {
this.street = street;
this.zip = zip;
}
public String getStreet() {
return street;
}
public String setStreet(String street) {
this.street = street;
}
public String getZip() {
return zip;
}
public String setZip(String zip) {
this.zip = zip;
}
Database row를 객체에 맵핑하는 패턴
- 비즈니스 로직 메서드를 추가해 객체로 취급하는 건 바람직하지 않다.
- 비즈니스 로직을 담으면서 내부 자료를 숨기는 객체는 따로 생성한다.
- 하지만.. 객체가 많아지면 복잡하고, 가까운 곳에 관련 로직이 있는 것이 좋으므로 현업에서는 Entity에 간단한 메서드를 추가해 사용한다.
public class Employee enxtends ActiveRecord {
private String name;
private String address;
...
}
// ----
Employee bob = Employee.findByName("Bob Martin");
bob.setName("Robert C. Martin");
bob.save();
참고
해당 포스팅은 제로 베이스 클린코드 한달한권을 수강 후 정리한 내용입니다.
Author And Source
이 문제에 관하여(클린코드 핵심 정리 (6장 객체와 자료구조)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@coconenne/클린코드-핵심-정리-5장-객체와-자료구조
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
해당 포스팅은 제로 베이스 클린코드 한달한권을 수강 후 정리한 내용입니다.
Author And Source
이 문제에 관하여(클린코드 핵심 정리 (6장 객체와 자료구조)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@coconenne/클린코드-핵심-정리-5장-객체와-자료구조저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)