DesignPatternSmalltalkCompanion:2.1
2.1 장면 1: 혼란에 빠지다
이 이야기는 피로한 기색이 역력한 돈이 조용히 앉아 키보드를 치고 있는 제인의 칸막이 사무실로 다가가는 장면부터 시작된다.
돈⊗ 저기, 제인, 혹시 이 문제 좀 도와줄 수 있을까? 몇 일간 이 요구문서(requirements document)를 보고 있는데 도저히 이해할 수가 없어서 말이야.
제인⊗ 그래, 그러지 뭐. 뭐가 문제야?
돈⊗ 이게 바로 내가 요청 받은 보험청구처리 작업흐름 시스템인데 말이야. 객체들이 어떻게 작동할지 알 수가 없어. 시스템에서 기본 객체는 찾았다고 생각되는데 객체의 행위를 어떻게 이해를 할지 모르겠어.
제인⊗ 여태까지 한 작업을 보여줄래?
돈⊗ 여기, 요구문서1 중에 문제가 되는 부분을 보여줄게.
- 데이터 입력. 다양한 시스템으로 구성되어 있으며, 다양한 소스로부터 건강보험청구가 수신된다. 이는 모두 유일한 식별자를 할당함으로써 로그된다. 보험청구 문서와 지원문서가 스캔된다. 스캔된 보험청구 문서와 팩스는 OCR(광학식 문자 인식)로 처리되어 각 양식 필드(form field)와 관련된 데이터를 읽어낸다.
- 유효성 검사. 스캔되어 입력된 양식은 일관성 있고 완벽하게 기입되었는지 보장하기 위해 유효성 검사를 거친다. 불완전하거나 부적절하게 기입된 양식은 시스템에 의해 거부되어 청구자에게 재접수 요청이 전송된다.
- 제공자/보험의 일치. 자동화된 처리에 의해 보험청구에 기입된 보험 (현재 지급하려는 보험청구의 계약) 및 의료보험 제공자(예: 의사)와 전체적인 보험청구처리기관과 계약한 제공자들 중 일치하는 결과를 찾기 시작한다. 정확하게 일치하는 결과가 없을 경우, 프로그램은 사운덱스 기술을 (Soundex technology; 유사한 발음의 단어를 찾아내는 알고리즘) 바탕으로 가장 비슷한 결과를 확인한다. 시스템이 가능성 있는 결과를 일치성이 높은 순으로 정리하여 정보 취급자에게 보여주면 그는 정확한 제공자를 식별한다.
- 자동 판정. 시스템은 보험청구금액을 지급할 수 있는지와, 보험청구와 관련된 주요 데이터 항목 간에 비일관성이 발견되지 않는다는 조건에 한해 얼만큼 지급하는지를 결정한다. 비일관성이 발견될 경우 시스템은 적절한 보험청구 심사에 의한 처리를 받을 수 있도록 보험청구를 “보류(pend)”한다.
- 보류된 보험청구의 심사. 심사관은 보험청구 이력 또는 청구서 원본의 제출을 확인하기 위해 시스템에 접근할 수 있다. 심사관은 지급액에 대한 보험청구를 허락하여 적절한 지급액을 명시하거나 보험청구를 거부하는 답변서(correspondence)를 생성시킨다.
나머지 시스템이 중심으로 다루는 “Claim”이 있는 걸 확인했거든. 근데 방해가 되는 요소는 바로 Claim이 사람마다 다르단 점이야! Claim에 작업할 때 내가 대화하는 상대마다 다르게 나타나는 것 같아. 매번 책임성을 확인했다고 생각할 때마다 또 새로운 것이 나타나. 뿐만 아니라 “재량껏 수정하세요”나 “아끼세요”와 같이 Claim에 대한 단순한 책임성은 작업흐름의 어디에 위치하는지에 따라 여러 의미를 가질 수 있는 것 같아.
제인⊗ 으음. 나도 이런 걸 읽은 적이 있는데. 한 번 찾아볼게. [그녀는 그녀의 책상에 놓인 서류를 바스락거린다] 어, 찾았다. Object Magazine 이번 호에 주문 관리 시스템에서 State 패턴을 이용하는 데 관한 기사가 하나 있어.
돈⊗ 내 말을 뭘로 들은 거야? 이건 주문 관리 시스템이 아니라 보험청구 처리 시스템이야.
제인⊗ 알고 있어, 그치만 저자가 State 패턴을 작업흐름 문제에 적용시킨 방법이 재밌어. [잡지를 뒤적인다] 그래, 여기 기사야. [기사를 훑어본다] 흐음…그렇지…Claim이 위치할 수 있는 상태 전이 다이어그램(state transition diagram)을 그려봤어?
돈⊗ [놀란다] 상태 전이 다이어그램? 아니, 그건 생각을 못해봤어. 그걸 왜 그려야 하지?
제인⊗ 이렇게 되는 거야. 작업흐름 실행은 State 간에 전이가 발생하는 거야. 각 Claim은 마지막에 발생한 일에 따라 그것이 위치할 수 있는 상태의 집합을 가져. 예를 들어서 네 작업흐름에서 첫 항목이 뭐지?
돈⊗ 데이터 엔트리.
제인⊗ 그 다음은?
돈⊗ 유효성 검사.
제인⊗ 그럼 모든 Claim이 유효성 검사로 통과하는 거야?
돈⊗ 아니. 일부는 유효성 검사단계에서 거부 돼. 통과하는 경우에만 보험과 보험 제공자에 일치하는 결과를 찾지.
제인⊗ 그럼 다이어그램을 이렇게 그려보겠어? [제인이 펜과 종이를 들어 다음의 다이어그램을 그린다.]
돈⊗ [조심스럽게] 응, 해볼 순 있지. 이걸로 뭘 하는거지?
제인⊗ 그냥 시키는대로 따라해 봐. 작업흐름에서 다음 단계는 뭐야?
[두 사람은 작업흐름의 모든 단계를 그려 마침내 다음과 같은 다이어그램이 완성되었다.]
돈⊗ 좋아. 상태 전이 다이어그램이 완성됐어. 그런데 이 그림이 어떻게 Claim 작업을 이해하는데 도움이 된단 말이지?
제인⊗ 글쎄, 기사에선 State 디자인 패턴을 작업흐름 객체 설계에 적용할 수 있다고 나와 있어. 이전 다이어그램에 있는 각 State가 클래스가 될거야. Claim은 State 클래스 중 하나의 인스턴스로 변경 돼. 네 설계는 이런 모양이겠지: [제인은 새 용지로 넘겨 다음 페이지에 그려진 OMT 다이어그램을 그린다]
돈⊗ 다시 묻지만 이게 어떻게 도움이 된단 말이지?
제인⊗ [소리 없이 활짝 웃으며] 거의 다 돼가! 자, 네가 겪는 문제 중 하나는, 작업흐름 내에 보험청구의 위치에 따라 “수정”의 의미가 변한다는 거였지?
돈⊗ [대화의 중심이 본인 문제로 돌아갔다는 사실에 기뻐하며] 맞아. 예를 들어 데이터를 입력하는 사람은 이런 UI(사용자 인터페이스)를 보게 돼 [인터페이스 그림 하나를 보여준다]. 반대로 시스템이 보험과 제공자에 일치하는 결과를 찾지 못하면 이런 화면이 나타나 [두 번째 그림을 보여준다]. 그리고 보험청구를 조정해야 하는 심사관은 이런 화면을 보게 돼 [세 번째 그림을 보여준다]. 이 중 어떤 화면을 보여줘야 하는지가 문제야.
제인⊗ 음, 그렇다면 “수정”을 위한 코드를 Claim이 속하는 아래쪽 특정 State로 위임하는 것이 네 일이야. 여길 예로 들어보자 [클래스 다이어그램에서 Entered 상태를 가리킨다]. Claim이 이 상태에 있다면 네가 방금 나에게 보여준 첫 번째 화면으로 돌아가는 거야. Claim이 MatchPended 상태에 있으면 두 번째 화면으로, 그리고 AdjudicationPending 상태에 있으면 마지막 화면으로 돌아가는 거야. Claim은 어떤 화면을 표시해야 할 지 알아내기 위해 해당 State에서 화면을 요청한 후 그 UI에게 화면을 열도록 시키는 거지.
돈⊗ [부드럽게] 내가 생각했던 것보다 훨씬 간단하네. 난 어떤 사람이 Claim을 마지막으로 실행했는지 확인한 후에 그 결과를 바탕으로 화면을 표시하는 조건 코드가 훨씬 많을 거라고 예상했거든. 이 방법이 훨씬 간단하구나.
제인⊗ 이것이 바로 디자인 패턴의 힘이라고 할 수 있지.
돈⊗ 조금 전에도 그 말을 언급했지? 대체 무슨 뜻이야?
제인⊗ 디자인 패턴은 계속해서 발견되는 디자인 문제에 대해 반복해 사용하는 해법 접근법이야. 디자인 패턴이라는 책도 있지. 이 책은 23개의 패턴을 구축하고 있는데, 각 패턴은 특정 클래스의 문제에 객체 기반의 해법을 제시하고 있어.
돈⊗ [믿지 못하겠다는 듯] 그럼 이 책에 내 문제에 대한 답이 모두 있단 뜻이야?
제인⊗ 그런 건 아냐. 가장 많이 발생하는 문제와 해법을 몇 가지씩 소개하고 있어. 방금 우리가 이야기한 해법은 State 패턴이라고 불러. 각 패턴은 패턴이 만들어진 의도를 설명하는 문장으로 시작해. State 패턴은, “객체의 내부 상태에 따라 객체가 행위를 변경할 수 있게 한다”는 의도를 가지고 있어. 네 Claim에 필요한 패턴이라고 생각하지 않니? 돈⊗ 듣고 보니 그러네. 하지만 네가 이런 말을 하기 전엔 생각도 못했을 거야. 내게 이 패턴이 필요할지는 어떻게 알지?
제인⊗ 기사를 읽었던 것이 행운이었어. 하지만 디자인 패턴에 소개된 패턴들에 좀 더 익숙해지고 나니 어떻게 새로운 문제에 더 쉽게 적용시킬 수 있을지가 눈에 보여. 빌려줄까?
돈⊗ 아니, 지금은 됐어. 이 새로운 설계를 쓰기 시작했거든. 나중에 빌려 갈게. 도와줘서 고마워!