내 코드가 그렇게 이상한가요? - 예스24 (yes24.com)
내 코드가 그렇게 이상한가요? - 예스24
예약 판매부터 1만 부 돌파! 일본 아마존 IT 분야 베스트셀러개발자가 직접 선정한 〈IT 엔지니어 도서 대상 2023〉 기술서 부문 대상공감 100% 나쁜 코드 사례로 배우는 지속 가능한 코드 설계 입문
www.yes24.com
이 책을 읽고 공부한 것들을 올렸습니다.
응집도(cohension)란 모듈 내부에 있는 데이터와 로직 사이의 관계가 얼마나 강한지 나타내는 지표이다.
응집도가 높으면 변경하기 쉽고 응집도가 낮으면 변경시 문제가 발생이 된다. 응집도를 높이는 방법에는 인스턴스 변수와 인스턴스 변수를 사용하는 로직을 같은 클래스에 만드는 것이 있다. 정보처리기사 실기 공부 할 때 응집도는 높게 결합도는 낮게라는 구문을 외울때가 떠오른다.
예를 들어 온라인 쇼핑몰에서 신규 가입하면 무료포인트 제공할 때 기프트 포인트를 값 객체로 설계한 예를 보면
public class GiftPoint {
private static final int MIN_POINT = 0; // 객체지향에서 데이터와 로직을 별도의 클래스에 배치하게 될때
// 클래스 인스턴스를 생성하지 않고 static메서드를 활용
final int value;
GiftPoint(final int point) {
if(point < MIN_POINT) {
throw new IllegalArgumentException("포인트를 0이상 입력해야 합니다.");
}
value = point;
}
/**
* 포인트 추가하기
*
* @param other 추가 포인트
* @return 추가 후 남은 포인트
*/
GiftPoint add(final GiftPoint other) {
return new GiftPoint(value + other.value);
}
/**
* @return 남은 포인트가 소비 포인트 이상이라면 true
*/
boolean isEnough(final ConsumptionPoint point) {
return point.value <= value;
}
/**
* 포인트 소비하기
*
* @param point 소비 포인트
* @return 소비 후 남은 포인트
*/
GiftPoint consume(final ConsumptionPoint point) {
if (!isEnough(point)) {
throw new IllegalArgumentException("포인트가 부족합니다.");
}
return new GiftPoint(value - point.value);
}
}
하지만 GiftPoint 생성자를 public으로 만들면 의도하지않은 용도로 사용할 수 있어서 로직이 분산되기 때문에 유지보수하기 힘들어지고 응집도가 떨어진다. 공통의 클래스로 묶어넣고 생성자를 private를 만들어서 응집도를 높일 필요가 있다.
public class GiftPointTest {
public static void main(String[] args) {
GiftPoint standardMembershipPoint = new GiftPoint(3000); // 기본회원 회원가입 포인트
GiftPoint premiumMembershipPoint = new GiftPoint(10000); // 프리미엄 회원가입 포인트
}
}
private 생성자 + 팩토리 메서드를 사용해 목적에 따라 초기화한다.
public으로 만든 생성자를 private로 변경하면 클래스 내부에서만 목적에 따라(표준가입,프리미엄가입) 인스턴스를 새로 생성할수 있어서 응집도를 높일 수 있고 컨트롤을 할 수 있는 느낌이든다
//팩토리 메서드는 목적에 따라 만들어 두는 것이 일반적
public class GiftPoint {
private static final int MIN_POINT = 0;
private static final int STANDARD_MEMBERSHIP_POINT = 30000;
private static final int PREMIUM_MEMBERSHIP_POINT = 10000;
final int value;
private GiftPoint(final int point) {
if(point < MIN_POINT) {
throw new IllegalArgumentException("포인트는 0이상이어야 합니다.");
}
value = point;
}
/**
* @return 표준 가입 기프트 포인트
*/
static GiftPoint forStandardMembership() {
return new GiftPoint(STANDARD_MEMBERSHIP_POINT);
}
/**
* @return 프리미엄 가입 기프트 포인트
*/
static GiftPoint forPremiumMembership() {
return new GiftPoint(PREMIUM_MEMBERSHIP_POINT);
}
}
테스트 할 코드
public class GiftPointTest {
public static void main(String[] args) {
GiftPoint standardMembershipPoint = GiftPoint.forStandardMembership();
GiftPoint premiumMembershipPoint = GiftPoint.forPremiumMembership();
}
}