2008-09-19 2 views
12

괴물을 계승했습니다.리팩토링 용 리팩터링 아이디어가 필요합니다

.NET 1.1 응용 프로그램이 Healthcare Claim Payment (ANSI 835) 표준을 따르는 텍스트 파일을 처리하지만 가장 괴괴 망측 한 것으로 가장합니다. 처리되는 정보는 건강 관리 청구, EOB 및 환급과 관련됩니다. 이 파일은 처음 몇 위치에 식별자가 있고 해당 레코드 유형에 대한 스펙에 따라 형식화 된 데이터 필드로 구성됩니다. 일부 레코드 ID는 특정 유형의 트랜잭션과 관련된 레코드 그룹을 구분하는 제어 세그먼트 ID입니다.

파일을 처리하려면 작은 괴물이 첫 번째 레코드를 읽고 수행하려고하는 트랜잭션의 종류를 결정한 다음 현재 처리중인 트랜잭션의 종류에 따라 다른 레코드를 처리하기 시작합니다. 이렇게하려면 중첩 된 if를 사용합니다. 많은 레코드 유형이 있기 때문에, 몇 가지 결정을 내려야합니다. 각 결정에는 이전 결정에 근거하여 수행해야하는 몇 가지 처리 및 기타 2-3 가지 결정이 포함됩니다. 즉, 중첩 된 if에는 많은 중첩이 있음을 의미합니다. 그것은 내 문제가있는 곳입니다.

길이가 715 인 경우 중첩됩니다. 네, 맞습니다. 7 백 - 십오 - 하이틴 라인. 나는 코드 분석 전문가가 아니기 때문에 몇 가지 프리웨어 분석 도구를 다운로드하고 49의 McCabe Cyclomatic Complexity 등급을 제안했습니다. 그들은 꽤 높은 숫자라고 말해줍니다. 애틀란타 지역의 꽃가루 수가 100 대를 기준으로 높고 뉴스에서 "오늘의 꽃가루 수는 1,523"이라고합니다. 이것은 제가 본 Arrow의 반 패턴의 가장 훌륭한 예 중 하나입니다. 가장 높은 곳에, 들여 쓰기는 15 개의 탭을 깊게합니다.

제 질문은 리팩터링하거나 구조 조정할 때 어떤 방법을 제안하겠습니까?

아이디어를 검색하는 데 시간을 할애했지만 나에게 좋은 발판이되었습니다. 예를 들어, 레벨에 대한 보호 조건을 대체하는 것이 한 가지 방법입니다. 나는 그 중 하나만 가지고있다. 하나는 둥지를 틀고, 14 개는 가야합니다.

아마도 도움이 될 수있는 디자인 패턴이있을 것입니다. 명령 사슬이이 문제에 접근 할 수있는 방법일까요? .NET 1.1에 있어야한다는 것을 명심하십시오.

모든 아이디어에 감사드립니다.

답변

2

state machine은 논리적으로 시작하고 WF를 사용하면 스윙 할 수있는 것처럼 보일 수 있습니다.

아직 WF없이 구현할 수 있습니다. 직접해야합니다. 그러나 처음부터 상태 머신처럼 생각하면 아마 모든 행동에 대해 내부 상태를 확인하는 절차 몬스터를 만드는 것이 더 나은 구현 방법이 될 것입니다.

상태를 전환하면 전환이 발생합니다. 레코드를 처리하기위한 실제 코드는 팩터 아웃되어야하며, 상태가 실행될 때 (특정 상태가 필요하면) 호출되어야합니다.

그래서 State1의 실행은 "레코드 읽기"를 호출 한 다음 해당 레코드를 기반으로 다른 상태로 전환합니다.

다음 상태는 여러 레코드 및 호출 레코드 처리 명령어를 읽고 State1로 다시 전환 할 수 있습니다.

1

설명으로 판단하면 상태 시스템이이를 처리하는 가장 좋은 방법 일 수 있습니다. 현재 상태를 저장하기위한 enum 변수가 있고, 현재 상태 및 입력 데이터를 기반으로 수행 할 작업을 선택하는 switch 또는 if 문을 사용하여 레코드에 대한 루프로 처리를 구현하십시오.너무 커지면 함수 포인터를 사용하여 상태를 기반으로 함수를 분리하여 작업을 쉽게 파견 할 수도 있습니다.

2

이러한 경우 내가 한 일은 'Composed Method'패턴을 사용하는 것입니다. 이 주제의 Jeremy Miller's Blog Post을 참조하십시오. 기본 아이디어는 IDE에서 리팩토링 도구를 사용하여 의미있는 작은 메서드를 추출하는 것입니다. 일단 그렇게하면보다 의미있는 수업을 리팩터링하고 추출 할 수 있습니다.

1

때로는 상태 패턴을 스택과 결합합니다.

이것은 계층 구조에 적합합니다. 부모 요소는 자식 요소를 처리하기 위해 어떤 상태를 스택으로 밀어 넣을 지 알고 있지만, 자식은 부모 요소에 대해 아무 것도 알 필요가 없습니다. 다른 말로하면, 아이는 다음 상태가 무엇인지 알지 못합니다. 단순히 "완전"하다는 신호를 보내 스택에서 튀어 나옵니다. 이것은 종속성을 단방향으로 유지하여 각 주를 서로 분리시키는 데 도움이됩니다.

SAX 파서로 XML을 처리하는 데 효과적입니다. 콘텐츠 핸들러는 요소를 입력하고 종료 할 때의 동작을 변경하기 위해 상태를 푸시하고 팝합니다. EDI는이 접근법에도 도움이되어야합니다.

+0

흥미로운 아이디어. 이 코드에서 어떻게 보이는지 설명하는 데 문제가 있습니다. –

20

저는 이번 주에 직장에서 여러분이 묘사 한 것과 비슷한 (비록 무섭지는 않지만) 비슷한 코드를 가지고있었습니다.

이 문제를 해결할 수있는 방법은 없습니다. state machine은 코드의 최종 형식 일 수도 있지만 이 아니라이 도움이 될 것입니다. 이미 해결해야 할 혼란을 해결하기 전에 이러한 솔루션을 결정해야합니다.

첫 번째 단계는 기존 코드에 대한 테스트를 작성하는 것입니다. 이 테스트는 코드가 정확하다는 것을 나타내는 것이 아니라 리팩토링을 시작할 때 무언가를 깨뜨리지 않았는지 확인하는 것입니다. 처리 할 큰 데이터를 가져 와서 괴물에게주고 출력을 얻으십시오. 리트머스 검사 야. 코드 적용 도구로이 작업을 수행 할 수 있다면 테스트하지 않은 것을 볼 수 있습니다. 가능한 경우이 코드를 연습 할 반복 기록을 만들고 반복하십시오. 이 작업으로 수행 할 수있는 작업을 수행했다면 출력 데이터가 테스트의 예상 결과가됩니다.

리팩토링은 코드의 동작을 변경해서는 안됩니다. 기억. 따라서 입력 데이터와 알려진 출력 데이터 세트가 사용자의 작업을 중단시키지 않을 것이라는 것을 확인한 것입니다. 이것은 귀하의 안전망입니다.

지금 리팩터링하십시오! 내가 발견 한

몇 가지 유용한 :

반전 if 내가 해당 else 문을 찾을 수 없습니다 때 단지 코드를 읽고 있던 한 큰 문제는, 내가 눈치

블록의 많은이 if 반전으로이

if (someCondition) 
{ 
    100+ lines of code 
    { 
    ... 
    } 
} 
else 
{ 
    simple statement here 
} 

처럼 보였다 것을 나는 간단한 경우를 참조하고 일에 움직일 수 다른 하나가 이미 한 것을 아는 더 복잡한 블록. 거대한 변화가 아니라 이해에 도움이되었습니다.

추출

방법 그것을 grok 수 있으며 자신의 방법을 따로 밀어, 이것을 lot.Take 일부 복잡한 멀티 라인 블록을 사용했다. 이로 인해 코드 중복이있는 곳을 더 쉽게 볼 수있었습니다.

자 이제 코드를 깨지 않았으므로 (테스트가 올바르게 진행됩니다.) 절차 코드를 더 잘 읽고 더 잘 이해할 수 있습니다. 이미 개선 된 걸보세요! 하지만 이전에 작성한 테스트는 실제로 좋지는 않습니다 ... 단지 원래 코드의 기능 (버그 및 모든 것)을 복제하고 있음을 알리고 그 범위 만 커버했을뿐입니다. 방법을 알아낼 수 없거나 적중을 할 수없는 코드 블록을 발견 할 것입니다 (필자의 연구에서 두 가지를 모두 보았습니다).

이제 큰 이름 패턴이 모두 적용되는 큰 변화는 올바른 OO 방식으로 리팩토링 할 수있는 방법을 살펴 보는 것입니다. 이 고양이를 껍질을 벗기는 방법은 여러 가지가 있으며 여러 패턴이 포함됩니다. 파싱하는 파일의 형식에 대한 세부 정보를 알지 못하는 경우 최상의 솔루션 일 수 있거나없는 유용한 제안을 던질 수 있습니다.

Refactoring to Patterns은 이러한 상황에서 도움이되는 패턴을 설명하는 데 도움이되는 훌륭한 책입니다.

당신은 코끼리를 먹으려 고하고 있습니다. 다른 방법은 없지만 한 번에 하나씩 물으십시오. 행운을 빕니다.

+1

코끼리 유추를 위해 Upvoted. 이것이 리팩토링의 본질입니다. 조금씩입니다. – troelskn

+0

리팩토링에 대한 훌륭한 지침이지만 몇 가지 사항이 있습니다. 상태 테이블을 정의하고 코드를 다시 구현하고 재 구현하는 데 도움이되는 평가판 데이터로 기존 코드를 연습 할 것을 제안합니다. 나는 조건문을 잘못 작성하는 것이 가능하기 때문에 if 문을 뒤집지 않는 것이 좋습니다. – Huperniketes

2

나는 Extract Method를 사용하기 시작했습니다. 현재 Visual Studio IDE에이 기능이 없으면 타사 추가 기능을 사용하거나 최신 VS로 프로젝트를로드 할 수 있습니다. (프로젝트를 업그레이드하려고 시도하지만 변경 사항을 확인하는 대신 해당 변경 사항을 신중하게 무시합니다.)

코드를 15 단계 들여 쓰기했습니다. 1/2-way out 및 추출 방법 시작. 당신이 좋은 이름을 가지고 올 수 있다면 그것을 사용하십시오. 그러나 할 수 없다면, 어쨌든 추출하십시오. 다시 반으로 나눠 라. 당신은 이상적인 구조를 여기에 가지 않을 것입니다. 당신은 당신의 두뇌에 맞는 조각으로 코드를 분해하려고합니다. 내 머리가 그리 크지 않기 때문에 더 이상 다치게하지 않을 때까지 계속 깨지 려합니다. &.

이동하면서 나머지 부분과는 다른 새로운 긴 방법을 찾아보십시오. 이것을 새로운 수업에 들여 라. 지금은 단 하나의 메소드 만있는 간단한 클래스를 사용하십시오. 지옥, 정적 메서드를 만드는 것은 좋습니다. 당신은 그들이 좋은 수업이라고 생각하기 때문에가 아니라, 당신이 어떤 조직에 절망적이기 때문에.

체크 아웃하면 작업을 체크하고 나중에 기록을 이해할 수 있으며 병합 할 필요없이 "실제 작업"을 수행 할 준비가되어 팀원들이 어려운 병합을 수행하는 번거 로움을 줄일 수 있습니다.

결국 당신은 당신이있는 경우 등

, 돌아가서 메소드 이름은 당신이 메이크업 감각을 만든 방법의 세트, 새로운 클래스를 청소하는 것이 좋은 있는지 확인해야합니다 매우 신뢰할 수있는 Extract Method 도구를 사용하면 자동화 된 테스트없이 도망 갈 수 있습니다. (예를 들어, VS를 신뢰합니다.) 그렇지 않으면, 당신이 일을 깨뜨리지 않고 있는지 확인하십시오. 그렇지 않으면 전혀 작동하지 않는 프로그램에서 시작한 것보다 더 나빠질 것입니다.

여기서 페어링 파트너가 도움이 될 것입니다.

관련 문제