왜 OOP?

이번 주에 개발을 하면서 느낀 OOP의 중요성에 대해 느낀 점을 일기를 빌려 쓰고자한다.

Spring + MyBatis 조합이라면 매퍼에 returnType으로 Map을 사용하면 컬럼이 추가/변경되더라도 편리하게 DB 데이터를 Map 타입으로 받을 수 있다.
그럼 굳이 컬럼과 매핑되는 필드를 가진 클래스를 만들필요가 있을까?
더 나아가 Map에다 데이터를 넣고 빼고 계산하고 잘하면 되지 굳이 역할을 나눠서 객체를 만들고하는 OOP가 필요할까?

예를 들어 유저기능이 있는 비지니스 로직이 있다고 쳐보자.
유저의 정보를 Map에 담는다면 아래와 같이 데이터를 넣을 것이다.

1
2
3
4
Map<String, Object> userMap = new HashMap<>();
userMap.put("userId", "Chris");
userMap.put("age", "29");
userMap.put("gender", "Man");

여기서 유저가 성인인지를 확인해야하는 로직이 있다고 하면

1
2
3
if (userMap.get("age") < 19) {
throw new IllegalStateException("미성년자 입니다.");
}

이런 식으로 코드가 나올 것이다.
여기서 userMap.get("age") < 19 라는 코드가
모든 앞뒤 문맥을 제외하고 이 라인 하나만 봤을 때 무엇을 위한 코드인지 이해가 가능한가?
19의 의미는? 왜 19를 비교하는 건지?

객체에서 값을 빼와 다른 값과 비교하는 절차지향적인 방식이 아닌 회원 객체에 성인인지를 물어보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class User {}
private static final int ADULT_AGE = 19;

private String userId;
private int age;
private String gender;

// 성인인지를 User 객체에 묻는다.
public boolean isAdult() {
return ADULT_AGE <= this.age;
}
}

// -------------------

if (!user.isAdult()) {
throw new IllegalStateException("미성년자 입니다.");
}

앞서 본 Map을 사용한 방식과 큰 차이는 없다.
오히려 Class를 추가해서 디렉토리가 더 복잡해질 수도 있다.
그런데 왜 객체에 물어야 할까?

  1. 중복코드를 줄여준다.
    성인인지를 확인하는 로직이 한 기능에만 있다고 할 경우 userMap.get("age") < 19 이런 식으로 쓸 수도 있다.
    하지만 성인인지를 확인하는 로직이 다른 기능에도 필요하다면?
    저 코드가 2,3 개 있으면 그나마 괜찮지만 10, 20개 있다고 하면?
    잘 모르는 누군가가 기능 변경을 하면서 해당 기능을 고쳐야하는데 몇개를 찾지 못했다면?
    테스트 코드가 있지 않다면 버그의 가능성이 매우 높다.
    객체에게 성인인지를 묻는 로직에 변경이 있다면 isAdult 메서드의 로직만 변경하면 된다.
  1. 코드의 가독성이 증가하고 비지니스 로직을 파악하기 쉽다.
    userMap.get("age") < 19 이 코드를 보면 아 얘가 성인인지를 확인하는구나 라고 생각되기 보다는

Map에서 age의 값을 빼와서 19 미만인지를 보는구나라고 생각이 든다.
하지만 user.isAdult() 메서드의 경우 내부 코드를 들여다보지 않아도 메서드명을 보고 성인인지를 확인한다는 것이 바로 파악이된다.
코드에 네이밍을 할 수 있는 것 이것이 정말 크다고 생각된다.
변수도 그렇지만 메서드도 적절한 네이밍을 통해 코드의 가독성을 높여줄 수 있다.


중복된 로직으로 인해서 길게 늘여뜨린 Service 클래스를 볼 때마다 적절한 클래스 몇개만 만들어줘도 보다 간결하고 짧게 코드가 나올텐데라고 생각을 많이 한다.
SOLID를 전부 이해하지 못해도 적절한 객체를 통해 로직을 수행한다면 유지보수가 좀 더 즐거워질 것 같다.

Share