Published on

왜 메소드는 하나의 기능만 가져야 할까

Authors
  • avatar
    Name
    ywj9811
    Twitter

우테코에서는 우리에게 메소드가 하나의 기능만 가지도록 작성하기를 요구했다.

근데, 왜 그렇게 작성해야 하는 것일까?

처음에는 그 부분에 대해서 크게 생각하지 않고 요구하니 요구 사항에 맞추기 위해서 작성을 하고 있었다.

하지만 별 이유 없이 그러한 부분을 요구하지는 않을 것이다.

그렇다면 메소드가 하나의 기능만 가지게 된다면 우리에게 무엇을 가져다 주길래 그런 습관을 들이기를 장려할까?

그저 단순히 깔끔하게 보이기 위해서?

그건 아닐 것이다.

그렇다면 왜 그런 방식을 원하는지 알아보도록 하자.

구글링을 통해서 자료를 찾아보니 하나의 메서드는 하나의 기능을 수행하자 이렇게 우테코를 경험하신 분의 글을 찾을 수 있었다.

위 글을 참고하여 작성하도록 하겠다.

객체 지향 프로그래밍에서 메소드는 객체간의 협력하는 구조를 설계하고 구현하기 위해서 반드시 필요한 객체의 행동에 해당한다고 한다.

아무 생각 없이 요구 사항에 맞게 메소드를 구현하다 보면 메소드의 길이는 몇십줄이 넘어가고 그 안에서 많은 내용을 처리하고 있다.

(적어도 이전의 나의 코드를 보면 그렇게 처리하고 있다.)

public void moveAllCarOneTime() {
    for (Car car : raceCars) {
        car.increasePositionOrNot(Util.getRandomNumber());
        if (car.checkGreaterThanMaxPos(maxPosition)) {
            ++this.maxPosition;
        }
    }
}

위의 메소드를 살펴보자.

moveAllCarOneTime() 이라는 메소드 이름을 통해서 우리는 이 메소드는 모든 자동차의 움직임을 수행하는 메소드가 아닐까? 하는 추측을 할 수 있을 것이다.

하지만 내부 코드를 살펴보면 반복문을 돌며 increasePositionOrNot() 메소드를 실행하고 있지만 checkGreaterThanMaxPos() 라는 메소드 또한 추가적으로 실행하여 Max Position을 확인하고, 그 값을 업데이트해주고 있다.

즉, 위의 moveAllCarOneTime() 메소드는 사실 두가지의 기능을 수행하고 있는 것이다.

하지만 moveAllCarOneTime() 메소드는 이 기능을 수행해야 할 책임이 없다. 오히려 더 많은 책임을 준 것이다.

왜 이렇게 작성을 하였을까?

추측 해보자면 이동을 위해서 반복문을 수행해야 하는데 Max Position을 확인하기 위해서도 마찬가지로 반복문을 수행하기 때문에 같이 넣었을 것이다.

하지만 이전에 우리가 메소드의 이름을 보고 추측하길 해당 메소드는 자동차의 움직임을 수행하는 메소드라고 생각을 했는데, 이 사실 이 메소드는 순위까지 컨트롤 하고 있었다.

이렇듯 메소드가 하나의 기능을 하지 않는다면 해당 코드를 처음 보는 사람은 기능에 대해서 오해를 할 가능성이 다분하다.

위의 예시에서 찾을 수 있는 문제점은 다음과 같다.

  1. 메소드 명이 메소드의 기능을 포괄하지 못하고 있다.
  2. 우승자 관련된 요구 사항이 변경된다면 moveAllCarOneTime() 메소드를 수정해야 한다.
  3. 반환 값이 없고 두 가지 기능을 수행하고 있기 때문에 테스트 코드를 작성하기 어렵다.

즉 유지 보수를 쉽게 하기 위해서, 의사소통을 쉽게 하기 위해서 이러한 이유로 우리는 하나의 메소드가 하나의 기능을 가지고 있도록 작성하는 방식을 지향할 필요가 있다.


어떤 장점을 가지고 있는가 정리해보도록 하자

1. 메소드의 이름을 보고 어떤 기능을 수행하는 메소드인지 알 수 있다.

이게 얼마나 큰 장점일지 아직은 확 와닿지는 않는다.

하지만 이후에 유지 보수를 하거나 큰 코드가 되게 된다면 확 와닿을 수 있지 않을까 한다.

2. 코드의 재사용이 증가하여 유지 보수가 용이해진다.

메소드를 작은 단위로 쪼갤 수록 여러 곳에서 쉽게 가져다가 쓸 수 있다.

따라서 필요한 위치에서 불러서 사용할 수 있는 것이다.

뿐만 아니라 만약 MaxPos가 아닌 MinPos를 구해야 한다면? 해당하는 메소드만 조금 수정해주면 될 것이다.

3. 단위 테스트가 수월해진다.

TDD를 할 때 도메인 객체들의 기능을 테스트 하기 위해서 단위 테스트를 작성하게 될 것이다.

그러기 위해서는 각각의 기능별로 메소드가 분리되어 있다면 훨씬 쉽고 다양한 테스트를 진행할 수 있을 것이다.


사실 이런 궁금증은 살짝 여유가 생겼을 때 생기기 마련이다.

즉, 나는 내 코드를 거의 다 작성하고 리팩토링 하던 도중 이런 궁금증이 생겨서 찾아본 것이다.

하지만 찾아보고 문제의 예시를 보다가 느껴버렸다.

나도 문제의 예시와 비슷하다는 사실을 말이다…

어떤 이유로 이런 요구 사항이 있는지 이해를 했으니 다시 한번 나의 코드로 돌아가서 신나게 리팩토링을 할 시간이다.