자바지기 박재성님 TDD 강의를 보던 도중 .. `compose 메소드 패턴`이란 것이 나왔습니다.
TDD를 진행할 때, 실패하는 테스트 작성 -> 기능 구현 및 테스트 통과 -> 코드 리팩토링을 진행하는데, `코드 리팩토링` 부분에서 compose method 패턴을 적용해야한다고 설명해주셨습니다. 여기서 나온 compose method 패턴이 무엇인지 궁금하여 한번 정리를 해보았습니다.
참고로, 박재성님은 코드 리펙토링할 때 아래와 같은 것들을 지키면 좋다고 하셨습니다.
- 한 메서드에 오직 한 단계의 들여쓰기(indent)만 한다. -> 2 이상의 indent는 메소드로 작성
- else 예약어를 쓰지 않는다. -> else을 사용하지 말고 if~ retrun으로 작성하기
- 메소드가 한 가지 일만 하도록 구현하기
- 로컬 변수가 필요한지 생각해보기
- compose method 패턴 적용
compose 메소드 패턴이란,
객체지향 설계에서 메소드의 동작을 분리된 여러 작은 단위로 나누고, 이를 조합하여 더 큰 동작을 구성하는 방식입니다. 이 패턴은 특히 `단일 책임 원칙(Single Responseibility Principle)` 과 `재사용성`을 강조하는 상황에서 유용합니다.
단일 책임 원칙(Single Responseibility Principle)이란 ?
객체지향 설계의 핵심 원칙 중 하나로, 클래스는 단 하나의 책임만 가져야 한다는 개념입니다.
즉, 클래스는 하나의 명확한 목적을 가지고 그 목적을 이루는 데 필요한 작업만 수행해야 합니다.
특징
- 재사용성 : 작은 단위의 메소드를 다양한 컨텍스트에서 재사용 가능
- 확장성 : 새로운 기능 추가 시 기존 코드를 수정하지 않고 새로운 메소드를 추가하여 조합 가능
- 가독성 : 각 메소드가 하나의 명확한 작업을 수행하므로 코드가 더 읽기 쉽고 유지보수하기 쉬움
문자열 처리 예제를 보면서 compose 메소드의 특징을 자세히 알아봅시다.
public class StringProcessor {
// 개별 메소드 정의(compose 메소드 x)
private String trim(String input) {
return input.trim();
}
private String toUpperCase(String input) {
return input.toUpperCase();
}
private String replaceSpaces(String input) {
return input.replace(" ", "_");
}
// Compose 메소드
public String process(String input) {
return replaceSpaces(toUpperCase(trim(input)));
}
public static void main(String[] args) {
StringProcessor processor = new StringProcessor();
String result = processor.process(" hello world ");
System.out.println(result); // 결과: HELLO_WORLD
}
}
위 코드에서 process 메소드는 trim, toUpperCase, replaceSpaces 메소드를 조합하여 전체 작업을 처리합니다. 개별 메소드는 작고 재사용 가능하며, 조합을 통해 더 큰 동작을 수행합니다.
해당 클래스에서 Compose 메소드 특징을 볼 수 있습니다.
1. 재사용성
Compose 메소드는 여러 작은 메소드를 조합하며, 이 작은 메소드들은 재사용이 가능하도록 설계됩니다.
각 메소드 `trim, toUpperCase, replaceSpaces`는 작고 독립적인 작업을 수행합니다.
만약 다른 클래스나 메소드에서 동일한 작업(ex. 공백제거, 대문자 변환 등)이 필요하다면, 이 메소드를 그대로 호출해서 재사용할 수 있습니다. 따라서 중복 코드 작성을 줄일 수 있습니다.
StringProcessor processor = new StringProcessor();
String onlyTrimmed = processor.trim(" example "); // "example"
String upperCaseOnly = processor.toUpperCase("hello"); // "HELLO"
2. 확장성
`확장성`은 새로운 요구사항이 생겼을 때 기존 코드를 크게 수정하지 않고 기능을 추가하거나 변경할 수 있는 능력을 의미합니다.
이 코드에서 확장성의 핵심은 작업 단위가 메소드로 분리되어 있어, 추가 작업이 필요할 때 쉽게 확장할 수 있다는 점입니다.
private String appendSuffix(String input, String suffix) {
return input + suffix;
}
// Compose 메소드 확장
public String processWithSuffix(String input, String suffix) {
return appendSuffix(replaceSpaces(toUpperCase(trim(input))), suffix);
}
예를 들어, 문자열 끝에 특정 접미사를 추가하는 기능을 넣고 싶다면, 새로운 메소드를 만들어 process에 조합하면 됩니다.
3. 가독성
가독성의 핵심은 코드가 직관적이고 명확하게 읽히는가 입니다.
메소드 분리 덕분에 각각의 동작이 명확히 표현되며, process 메소드에서 각 작업이 어떤 순서로 수행되는지 쉽게 이해할 수 있습니다.
public String process(String input) {
return replaceSpaces(toUpperCase(trim(input)));
}
작업 단계를 직관적으로 이해할 수 있기 때문에 한눈에 논리 흐름을 파악할 수 있습니다.
compose 패턴은 코드 간소화, 확장성, 가독성 등 다양한 장점을 제공하지만 무분별하게 사용할 경우 코드 복잡성이 증가하고 메소드 호출이 많아지면 약간의 성능 저하 가능성이 있을 수 있습니다. 따라서 활용시 적절한 균형을 유지하는 것이 중요하다고 생각합니다.
'WEB' 카테고리의 다른 글
[Spring] 스프링 MVC에 Microsoft OAuth 연동하기 (2) | 2025.01.22 |
---|---|
[Spring Boot] 스프링 시큐리티에 Microsoft OAuth 연동하기 (1) | 2025.01.15 |
[Spring boot] Spring Security에 구글 로그인 연동하기 (2) | 2024.11.13 |
[Spring Security] Session 기반 인증 방식 VS Token 기반 인증 방식 (1) | 2024.11.08 |
[WEB] HttpServletRequest / ServletRequest (0) | 2024.10.28 |