ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Setter, 맥락 이해가 되지 않아요!
    Java & Kotlin 2023. 4. 3. 01:34
    반응형

    1) 서론

    혹시 새로운 업무를 맡았을 때 이전의 업무 맥락을 파악하기 어려웠던 적이 있으신가요?
     
    아마도 이유는 다양할 것 같습니다. 새로 맡은 업무가 너무 생소할 수도 있고요. 혹은 너무 많은 업무들이 한 번에 들이닥쳐서 무언가 정리할 시간이 없었을 수도 있습니다.
     
    하지만 제가 경험했을 때 가장 힘들었던것은 어떤 문제 해결에 있어서 과정없이, 결론만 남아있을 때인데요. 예를 들어 A라는 문제가 발생한 슬랙 스레드가 존재하고, 댓글에는 단순히 "해결됐습니다~" 라는 것만 존재할 때 가장 당황스럽습니다. 무엇을, 어떻게, 왜 해결했는지에 대한 과정 없이 그저 한 문장으로 모든 것을 생략했기 때문입니다.
     
    "정말로 해결한것은 맞을까", "도대체 뭘 어떻게 해결했다는 것인가", "같은 문제가 발생했을 때 어떻게 할 것인가" 등등 많은 생각이 들 수 밖에 없습니다.
     
    사실 개발 할 때도 마찬가지인것 같습니다. 어떠한 흐름에 의한 코드들이 단순히 나열되어 있다면 어떠한 의미로 작성했는지 파악하기 어렵습니다. 코드는 당시의 현실 상황을 대신 말해주지는 않으니까요.
     
    위와 같이 파악하기 힘든 업무 도메인 코드들에 대해서 조금 더 나아질 수 있는 방법을 고민했고, 이를 공유드리겠습니다.
     


    2) 햄버거 주문서 도메인이 존재해요

    햄버거 가게에 들어와서, 주문을 위한 주문서를 직접 작성한다고 가정하겠습니다.

    • 햄버거 주문서 작성
    • 패티, 치즈, 소스, 피클 등 갯수 지정

     
    위와 같이 햄버거를 주문할 수 있는 도메인 모델이 존재합니다. 그리고 아래와 같은 도메인 로직이 존재하는데요.

    • 햄버거 주문 위해 주문서를 작성한다
    • 요리 완료 전 치즈 갯수를 추가할 수 있다
      • 치즈 갯수가 늘어나면 소스도 추가되어야 한다

     
    만약 치즈를 추가하려면 어떻게 해야 할까요? 그리고 치즈가 추가될 때 소스도 함께 추가되어야 합니다. 그렇지 않으면 치즈맛만 너무 강할테니까요.


    3) setter를 이용해서 치즈를 추가해 볼게요!

    • 현재 치즈, 소스 양 조회하여 1 추가

     
    치즈를 추가하는 기능은 완벽히 구현되었습니다. 최초 도메인 로직으로 정의된 것을 제대로 구현한 것 같은데요. 하지만 이러한 setter를 이용한 도메인 로직을 작성하는 데는 약간의 문제가 존재합니다.

    3. 1) 도메인 로직이 보이지 않아요

    위와 같이 setter를 이용한 변경을 했을 때는 도메인 로직이 뚜렷이 보이지 않습니다.
     
    DDD나 객체지향의 이야기를 하려고 하는 것은 아닙니다.
     
    코드로서 개발하는 것은 현실 세계를 바탕으로 문제를 해결하고 이야기하는 것이라고 생각하는데요. 즉 현실에서 우리가 말로써 도메인을 나타내는 것을 코드로서 표현할 수 있어야 한다고 생각합니다.
     
    현실 세계의 고객이 이렇게 말합니다. "치즈 한 장 더 추가해 주세요"
     
    하지만 이러한 현실 세계의 말을 코드로서 표현한 것은 이렇습니다. "현재 치즈 개수 가지고 온다. + 1 한다. set 한다." 치즈뿐만 아니라 소스도 마찬가지입니다.
     
    만약 시간이 흐른 뒤 다른 개발자가 해당 코드를 본다면 어떨까요? "왜 갑자기 치즈 카운트가 늘어나고, 소스 횟수가 늘어나지?"라고 생각할 수 있을 것 같습니다.
     
    개발자뿐만 아니라, 다른 직군의 사람이 치즈 추가 기능에 질문을 한다면 "그냥 치즈 하나가 늘어나요"라고 말을 할 수밖에 없을것입니다. 치즈 갯수를 하나 더 늘리는 기능에 소스가 추가되는것을 표현하지 못 하고 있습니다. 그리고 함께 변경되어야 하는것이 많아진다면 커뮤니케이션 비용이 증가할 수 밖에 없습니다.

    3. 2) 객체의 응집도가 떨어져요

    이번에는 객체지향 이야기를 조금 해야 할 것 같은데요. setter 사용 시 도메인 모델 객체의 응집도가 떨어지게 됩니다.
     
    객체지향은 각각의 객체들이 역할과 책임을 가지고 서로 대화하는 것이라고 생각하는데요. 여기서 응집도는 객체의 요소들이 얼마나 서로 연관되어 함께 존재하는지의 정도를 나타내줍니다. 즉 각각의 객체들이 얼마나 각자의 역할과 책임을 응집도 있게 가지고 있으면서, 서로 대화할 수 있는지가 중요한데요.
     
    단순히 setXX, setXX라는 것들은 어디서든지 사용될 수 있습니다. 그리고 이러한 기능들이 햄버거 주문이라는 도메인 객체에 응집도 있게 함께 존재한다는 느낌을 주기는 어려워 보입니다.
     
    그리고 각 필드들에 대해서 set이 공개적으로 열려있다면 더더욱 해당 도메인 객체의 응집도는 떨어지고, 전혀 관계없는 도메인 로직에서 변경될 위험도 존재합니다.
     
    심지어 lombok 라이브러리를 사용한다면 습관적으로 setter를 추가하게 되고, 더더욱 자유롭게 사용하는 환경이 됩니다.


    4) 도메인 로직을 표현해 볼게요

     

    • 요리 완료 전 치즈 추가 기능에 대한 함수. 해당 도메인 객체에 요리 완료 여부를 표현하는 필드가 존재하고, 사전에 이를 검증하는 로직이 있다면 더 좋을 것 같습니다.
    • 치즈 한 장 추가
    • 치즈가 추가되면서 소스도 추가

     
    즉 햄버거 주문 도메인 객체를 만들고, 해당 객체를 바탕으로 치즈 추가 도메인 로직까지 표현했습니다.
     
    이렇게 했을 때는 위에서 언급한 단점들이 개선됩니다.

    • 개발자가 로직을 봤을 때 도메인을 이해할 수 있게 됩니다
    • 다른 직군의 사람과 이야기할 때 현실 도메인에 대해서 이야기 나눌 수 있게 됩니다

     
    만약 기획자가 "치즈 하나 더 추가하는 기능에 대해서 이야기하고 싶은데요"라고 한다면, 당연히 소스도 추가될 것이라고 이해하고 있을 것입니다. 그리고 개발자도 당연히 기획자가 말로 표현하는 도메인에 대해서 동일한 이해를 가지게 됩니다.


    5) 결론

    도메인 모델 객체를 정의하고, 도메인 로직을 응집도 있게 구성하는 것에 대해서 배웠습니다.
     
    사실 이전에는 꼭 setter 뿐만 아니라 단순히 로직을 흐름대로 나열하기만 했었습니다. 즉 도메인 로직이 눈에 들어오지 않고, 단순히 기능별로 쪼개었습니다. 이렇게 코드를 작성했을 때 기획자분들과 대화할 때 어려웠었는데요. 머릿속에 하나의 기능이 존재하지 않고, 흐름대로 로직의 변화를 설명할 수밖에 없었고 기획자분들도 답답할 수 밖에 없었습니다.
     
    setter의 문제뿐만 아니라 도메인 모델 객체 정의와 응집도 있는 로직을 구성했을 때는 한결 더 대화하기 편한 것을 느꼈습니다. 앞으로도 조금 더 도메인 이해에 대해서 노력하고 이를 코드로서 정의하려고 해 보겠습니다.
     

    반응형

    댓글

Designed by Tistory.