위 책을 보면서 정리한 글입니다.
코드의 가독성을 위해 분석해야할 영역을 일관성 있게 만드는 것이 매우 중요하다.
Client에서 호출하는 기능을 분석하기 위해 구성된 모든 비즈니스 로직과 호출되는 기능의 내부까지 다 분석해야 하는가, 섞여 있어도 상관 없지 않나?
- 기능 분석시 모든 부분을 다 분석하는 것은 시간 대비 비효율적.
- 코드의 가독성은 의미뿐만 아니라 비용에서도 아주 중요
- 한 메서드를 분석하기 위해 한 코드 영역을 분석하는 것과 여러 객체의 메서드, 내부 메서드, 비즈니스 로직 영역을 넘나들며 분석하는 것은 큰 차이가 있다.
Send 클래스의 sendResaurantEventSMS() 메서드의 기능은 다음과 같은 복잡한 비즈니스 로직으로 구성되어 있다.
sendRestaurantEventSMS() 메서드의 기능 정의
1. 호텔 고객 정보 추출(기능 호출)
2. 추출된 고객 정보 중 레스토랑 이용 고객 정보 추출(비즈니스 로직)
3. 레스토랑 이용 고객 중 문자 수신 동의 고객 추출(기능 호출)
4. 문자 수신 동의 고객별 맞춤 메시지 생성(비즈니스 로직)
5. 문자 발송(기능 호출)
public class Send {
public void sendRestaurantEventSMS() [
List<Member> members = null;
// 기능 1. 호텔 고객 정보 추출
DBManager dbManager = new DBManager();
members = dbManager.getMember();
// 기능 2. 추출된 고객 정보 중 레스토랑 이용 고객 정보 호출
List<Member> restaurantMembers = new ArrayList<Member>();
for(Member member : members) {
if(member.isRestaurantMember()) {
restaurantMembers.add(member);
}
}
// 기능 3. 레스토랑 이용 고객 중 문자 수신 동의 고객 추출
List<Member> smsMembers = getSmsMember(restaurantMembers);
// 기능 4. 문자 수신 동의 고객별 맞춤 메시지 생성
for(int i=0; i<smsMembers.size(); i++) {
if("royal".equals(smsMembers.get(i).getGrade())) {
// 메시지 생성 및 세팅 로직
// 중량
} else if("basic".equals(smsMembers.get(i).getGrade())) {
// 메시지 생성 및 세팅 로직
// 중략
} else {
// 잘못된 등급 표시 로직
// 중략
}
}
// 기능 5. 정렬된 문자 발송 로직
SMSManager smsManager = new SMSManager();
smsManager.sendSMS(smsMembers);
]
public List<Member> getSmsMember(List<Member> restaurantMembers) {
List<Member> smsMember = new ArrayList<Member>();
for(Member member : restaurantMembers) {
smsMember = divideSmsMember(smsMember, member);
}
return smsMember;
}
priivate List<Member> divideSmsMember(List<Member> smsMembers, Member member) {
if(checkSMSAgree(member)) {
smsMembers.add(member);
}
return smsMembers;
}
}
위 코드의 문제점
public class MemeberManagerTest extends TestCase {
@Tset
public void testGetMember() {
// Given
MemberManger memberManager = new MemberMangaer();
// When
List<Member> result = memberManager.getMember();
// Then
assertNotNull(result);
}
}
public class MemberManager {
public List<Member> getMember() {
DBManger dbManager = new DBManger();
List<Member> members = dbManger.getMember();
return members;
}
}
public class MemberManagerTest extends TestCase {
@Test
public void testGetMember() {
// 중략.
}
@Test
public void testGetRestaruntMembers() {
// Given
MemberManager memberManager = new MemberManager();
List<Member> members = memberManager.getMember();
// When
List<Member> result = memberManager.testGetRestaruntMembers(members);
// Then
assertNotNull(result);
}
}
public class MemberManager {
public List<Member> getMember() {
// 중략.
}
public List<Member> getRestarauntMembers(List<Member> members) {
List<Member> restaurntMembers = new ArrayList<Member>();
for(Member member : members) {
if(member.isRestaurnt()) {
restaurntMembers.add(member);
}
}
return restaurntMembers;
}
}
public class MemberManagerTest extends TestCase {
@Test
public void testGetMember() {
// 중략
}
@Test
public void testGetRestaurntMembers() {
// 중략
}
@Test
public void testGetSmsMember() {
// Given
MemberManger memberManager = new MemberManager();
List<Member> members = memberManager.getMember();
List<Member> restaruntMembers = memberManager.getRestaurantMembers(membres);
// When
List<Member> result = memberManager.getSmsMember(restaruntMembers);
// Then
assertNotNull(result);
}
}
public class MemberManager {
public List<Member> getMember() {
// 중략.
}
public List<Member> getRestarauntMembers(List<Member> members) {
// 중략.
}
public List<Member> getSmsMember(List<Member> restaurntMembers) {
List<Member> smsMember = new ArrayList<Member>();
for(Member member : restaurntMembers) {
smsMember = divideSmsMember(smsMember, member);
}
return smsMember;
}
private List<Member> divideSmsMember(List<Member> smsMembers, Member member) {
if(member.isSms()) {
smsMembers.add(member);
}
return smsMembers;
}
}
public class MemberManagerTest extends TestCase {
@Test
public void testGetMember() {
// 중략
}
@Test
public void testGetRestaurntMembers() {
// 중략
}
@Test
public void testGetSmsMember() {
// 중략
}
@Test
public void testSetCustomMessage() {
// Given
MemberManger memberManager = new MemberManager();
List<Member> members = memberManager.getMember();
List<Member> restaruntMembers = memberManager.getRestaurantMembers(membres);
List<Member> smsMembers = memeberManger.getSmsMembers(restaruntMembers);
// When
List<Member> result = memberManager.setCustomMessage(smsMembers);
// Then
assertNotNull(result);
}
}
public class MemberManager {
public List<Member> getMember() {
// 중략
}
public List<Member> getRestarauntMembers(List<Member> members) {
// 중략
}
public List<Member> getSmsMember(List<Member> restaurntMembers) {
// 중략
}
private List<Member> divideSmsMember(List<Member> smsMembers, Member member) {
// 중략
}
public List<Member> setCustomMessage(List<Member> smsMembers) {
// 기능 4. 문자 수신 동의 고객별 맞춤 메시지 생성
for(int i=0; i<smsMembers.size(); i++) {
if("royal".equals(smsMembers.get(i).getGrade())) {
// 메시지 생성 및 세팅 로직
// 중량
} else if("basic".equals(smsMembers.get(i).getGrade())) {
// 메시지 생성 및 세팅 로직
// 중략
} else {
// 잘못된 등급 표시 로직
// 중략
}
}
return smsMembers;
}
}
public class MemberManagerTest extends TestCase {
@Test
public void testGetMember() {
// 중략
}
@Test
public void testGetRestaurntMembers() {
// 중략
}
@Test
public void testGetSmsMember() {
// 중략
}
@Test
public void testSetCustomMessage() {
// 중략
}
@Test
public void testSetCustomMessage() {
// Given
MemberManger memberManager = new MemberManager();
List<Member> members = memberManager.getMember();
List<Member> restaruntMembers = memberManager.getRestaurantMembers(membres);
List<Member> smsMembers = memeberManger.getSmsMembers(restaruntMembers);
List<Member> customMembers = memberManager.setCustomMessage(smsMembers);
// When
boolean result = memberManager.sendSMS(customMembers);
// Then
assertEqauls(true, result);
}
}
public class MemberManager {
public List<Member> getMember() {
// 중략
}
public List<Member> getRestarauntMembers(List<Member> members) {
// 중략
}
public List<Member> getSmsMember(List<Member> restaurntMembers) {
// 중략
}
private List<Member> divideSmsMember(List<Member> smsMembers, Member member) {
// 중략
}
public List<Member> setCustomMessage(List<Member> smsMembers) {
// 중략
}
public boolean sendSMS(List<Member> smsMembers) {
SMSManager smsManager = new SMSManager();
boolean result = smsManager.sendSMS(smsMembers);
return result;
}
}
public class Send {
public void sendRestaurantEventSMS() [
MemberManger memberManager = new MemeberManager();
// 기능 1. 호텔 고객 정보 추출
List<Members> members = memberManager.getMember();
// 기능 2. 추출된 고객 정보 중 레스토랑 이용 고객 정보 호출
List<Member> restaurantMembers = memberManager.getRestaurntMembers(members);
// 기능 3. 문자 수신 동의 고객 추출
List<Member> smsMembers = memberManger.getSmsMember(restaruntMembers);
// 기능 4. 문자 수신 동의 고객별 맞춤 메시지 생성
List<Member> customSMSMembers = memberManger.setCustomMessage(smsMembers);
// 기능 5. 정렬된 문자 발송 로직
boolean result = memberManager.sendSMS(customSMSMembers);
}
}
메서드 이동과 추출을 이용해서 코드 분석의 영역을 일관성 있게 모아 해결