public class Member {
// 다른 데이터
private Date expiryDate;
private boolean male;
public Date getExpiryDate() {
return expiryDate;
}
public boolean isMale() {
return male;
}
}
// 만료 여부를 확인하는 코드 (여러 곳에서 사용됨)
if (member.getExpiryDate() != null && member.getExpiryDate().getTime() < System.currentTimeMillis()) {
// 만료되었을 때의 처리
}
// 정책 변경 후 (여성 회원은 만료 후 30일 추가 제공)
long day30 = 1000L * 60 * 60 * 24 * 30; // 30일을 밀리초로 변환
if ((!member.isMale() && member.getExpiryDate() != null &&
member.getExpiryDate().getTime() < System.currentTimeMillis() - day30) ||
(member.isMale() && member.getExpiryDate() != null &&
member.getExpiryDate().getTime() < System.currentTimeMillis())) {
// 만료되었을 때의 처리
}
public class Member {
private Date expiryDate;
private boolean male;
public boolean isExpired() {
return expiryDate != null && expiryDate.getTime() < System.currentTimeMillis();
}
// 정책 변경 후
public boolean isExpired() {
if (male) {
return expiryDate != null && expiryDate.getTime() < System.currentTimeMillis();
} else {
long day30 = 1000L * 60 * 60 * 24 * 30; // 30일을 밀리초로 변환
return expiryDate != null && expiryDate.getTime() < System.currentTimeMillis() - day30;
}
}
}
---
// 사용 코드
if (member.isExpired()) {
// 만료되었을 때의 처리
}
첫번째..
ASK
라고 합니다.// 잘못된 예: 데이터를 가져와서 직접 처리
if (member.getExpiryDate() != null && member.getExpiryDate().getTime() < System.currentTimeMillis()) {
// 만료 처리
}
Tell
이라고 합니다.// 올바른 예: 객체에게 작업 수행을 요청
if (member.isExpired()) {
// 만료 처리
}
Member
클래스에 캡슐화 되며Member
클래스만 수정하면 됩니다.최소 지식 원칙
이라고 불리는 데, 객체가 다른 객체의 내부 구조에 대해 가능한 적게 알아야 함.// 데미테르의 법칙을 위반하는 코드
public class Order {
public Customer getCustomer() {
return customer;
}
}
public class Customer {
public Address getAddress() {
return address;
}
}
public class Address {
public String getStreet() {
return street;
}
}
// 사용 코드 (법칙 위반)
String street = order.getCustomer().getAddress().getStreet();
// 데미테르의 법칙을 준수하는 코드
public class Order {
public String getCustomerStreet() {
return customer.getStreet();
}
}
public class Customer {
public String getStreet() {
return address.getStreet();
}
}
// 사용 코드 (법칙 준수)
String street = order.getCustomerStreet();
신물 배달부와 지갑
이라는 사례인데요// 고객
public class Customer {
private Wallet wallet;
public Wallet getWallet() {
return wallet;
}
}
// 지갑
public class Wallet {
private int money;
public int getTotalMoney() {
return money;
}
public void subtractMoney(int debit) {
money -= debit;
}
}
---
사용자 클래스 - 신문 배달부 클래스
// Paperboy 클래스의 코드
int payment = 10000;
Wallet wallet = customer.getWallet();
if (wallet.getTotalMoney() >= payment) {
wallet.subtractMoney(payment);
} else {
// 다음에 요금 받으러 오는 처리
}
해당 코드에는 문제점이 있는데요
이를 수정하여 데미테르의 법칙을 준수하는 경우
public class Customer {
private Wallet wallet;
public int getPayment(int payment) {
if (wallet == null) {
throw new NotEnoughMoneyException();
}
if (wallet.getTotalMoney() >= payment) {
wallet.subtractMoney(payment);
return payment;
}
throw new NotEnoughMoneyException();
}
}
---
사용부 -
// Paperboy 클래스
int payment = 10000;
try {
int paidAmount = customer.getPayment(payment);
} catch (NotEnoughMoneyException ex) {
// 다음에 요금 받으러 오는 처리
}
신문배달부는 본인이 고객 지갑을 뺏어서 상태를 변화시키기 보다
또한 데미테르의 법칙을 위반 증상으로는
연속된 get 메서드를 호출한 경우
value = someObject.getA().getB().getValue();
임시 변수의 get 호출이 과다하게 많은 경우
```jsx
A a = someObject.getA();
B b = a.getB();
value = b.getValue();
```
가 있습니다.
데미테르의 법칙 준수하는 경우 이점으로는
캡슐화를 강화하고
유지보수성 증대 등이 있습니다
이는 캡슐화의 장점과 유사합니다.