-
제외 )여러 메서드로 쪼개기
원래 매개변수 목록의 부분집합을 받는 메서드로 분할한다
직교성(orthogonality)을 높여 메서드 수를 줄이는 효과가 가능
직교성?
서로 직각(90도)을 이루며 교차한다는 수학적 개념이다.
SW 상에서는 기능들이 서로 독립적이라는 의미로 사용된다.
java.util.List 인터페이스상에서는
- subList 메서드
- 부분리스트로 반환
- indexOf 메서드
- 주어진 원소의 인덱스를 반환
- 두 메서드 조합으로 복잡한 기능 구현이 가능함.
2 가지 메서드는 서로 관련이 없다.
해당 메서드같은 경우 같이 개발 메서드로 각각의 기능을 독립적으로 제공하는 것이, 직교성이 매우 높은 설계라고 볼 수 있다.
도우미 클래스의 활용
public void createCard(int rank, String suit) {
// 카드 생성 로직
}
사용시
createCard(1, "hearts");
createCard(12, "spades");
createCard(14, "triangle")
Card
라는 도우미 클래스를 만들면public class Card {
private final int rank;
private final String suit;
public Card(int rank, String suit) {
this.rank = rank;
this.suit = suit;
}
// getters 등
}
public void createCard(Card card) {
// 카드 생성 로직
}
메서드를 위와 같이 변경하면
createCard(new Card(1, "hearts"));
createCard(new Card(12, "spades"));
이런식으로 Card
객체를 통해 데이터의 의미가 명확해지고
유효성 검사를 할때 Card 클래스내에서 모두 제어가 가능해진다.
또한 Card
객체를 다른 메서드에서도 사용할 수 있게 된다.
정적 멤버 클래스로 구현한다면
public class CardGame {
public static class Card {
private final int rank;
private final String suit;
public Card(int rank, String suit) {
this.rank = rank;
this.suit = suit;
}
}
public void createCard(Card card) {
// 카드 생성 로직
}
}
Card
를 CardGame
의 컨텍스트 내에서만 사용하도록 제한이 가능하다.빌더 패턴 사용
public class SearchService {
public List<Result> search(String keyword, int maxResults, boolean caseSensitive,
String category, Date fromDate, Date toDate) {
// 검색 로직
}
}
public class SearchService {
public List<Result> search(SearchCriteria criteria) {
// 검색 로직
}
public static class SearchCriteria {
private String keyword;
private int maxResults = 10; // 기본값 설정
private boolean caseSensitive = false; // 기본값 설정
private String category;
private Date fromDate;
private Date toDate;
public SearchCriteria setKeyword(String keyword) {
this.keyword = keyword;
return this;
}
public SearchCriteria setMaxResults(int maxResults) {
this.maxResults = maxResults;
return this;
}
// 다른 setter 메서드들...
public List<Result> execute(SearchService service) {
// 유효성 검사
if (keyword == null || keyword.isEmpty()) {
throw new IllegalStateException("Keyword must be set");
}
return service.search(this);
}
}
}
SearchService service = new SearchService();
List<Result> results = new SearchService.SearchCriteria()
.setKeyword("Java")
.setMaxResults(20)
.setCategory("Programming")
.setFromDate(new Date())
.execute(service);
@Builder
public SearchCriteria(String keyword, int maxResults, boolean caseSensitive,
String category, Date fromDate, Date toDate) {
// 유효성 검증
if (keyword == null || keyword.isEmpty()) {
throw new IllegalArgumentException("Keyword must not be empty");
}
if (maxResults <= 0) {
throw new IllegalArgumentException("Max results must be positive");
}
if (fromDate != null && toDate != null && fromDate.after(toDate)) {
throw new IllegalArgumentException("From date must be before to date");
}
this.keyword = keyword;
this.maxResults = maxResults;
this.caseSensitive = caseSensitive;
this.category = category;
this.fromDate = fromDate;
this.toDate = toDate;
}
왜?
예시
Map
인터페이스를 사용HashMap
클래스 사용장점
public enum TemperatureScale {
FAHRENHEIT, CELSIUS
}
Thermometer.newInstance(TemperatureScale.CELSIUS)
Thermometer.newInstance(true)
true false 로 구분하는건 멍청한 짓임
새로운 옵션이 추가되는 경우 대비하기가 힘들다.