2017-10-03 4 views
0

클래스 모델링 방법에 대한 제안이 필요합니다.올바른 사용을 보장하는 클래스 설계

클래스의 메소드는 A, BC입니다. 메서드는이 특정 순서로 실행해야하지만 모든 메서드가 필요하지는 않습니다. 원하는 경우 C 번으로 전화하지 않고도 AB으로 전화 할 수 있습니다. 여기

는 가능한 해결책 : 문제는 내가 BC

워크 플로는 다음이된다 실행하기 전에 B의 결과를 실행하기 전에 A의 결과를 처리 할 필요가 있다는 점이다

public void RunA() 
{ 
    A(); 
} 

public void RunAB() 
{ 
    A(); 
    B(); 
} 

public void RunABC() 
{ 
    A(); 
    B(); 
    C(); 
} 

이 :

  • 실행 A

제가 상기 용액 설계 방법의 결과 B

  • 실행 C
  • 거래의 결과 A
  • 실행 B
  • 거래의 결과
  • 거래,이 흐름은 불가능합니다. A, BC을 개별적으로 실행하도록 허용 할 수 있지만 작동 순서는 더 이상 보장되지 않습니다.

    이 워크 플로우를 설계하는 더 좋은 방법이 있습니까?

    편집

    내가 물었다 봤는데 :

    은 "왜이 방법은 특정 순서로 호출해야합니까?"

    질문에 대답하려면 설치 프로그램을 설명해야합니다.

    • A : : DTO들에 변환 도메인 모델링의 결과에
    • 거래 : A, BC는 느슨하게 다음 단계로 변환 저장 변환 중에 발생한 예외
    • B : DTO에 대한 통계 및 결과 계산
    • B의 결과 : 할인 일 전자 통계
    • C :

    A 체인에서 첫 번째 것은 분명하다 제출 저장 상태 :이 API를 통해 C의 결과에

  • 거래를 DTO들을 보냅니다. BC은 서로 바꿔야 할 수도 있지만, 질문을 위해서 이 실행되기 전에 C이 적합하지 않다고 가정 해 봅니다.

    A, BC은 이론적으로 결과 자체를 처리 할 수 ​​있습니다. 대부분 결과에 대한 정보를 저장하는 것으로 귀결됩니다. 그러나 내가 성취하고자하는 것은 결과가 어디로 향하는 지 전혀 알지 못하는 것입니다.

  • +1

    호출을 추적하고 순서가 잘못된 호출을 던지십시오. 그런 다음 메소드를 문서화하여 사람들이이 메소드를 사용하는 것이 확실하도록하십시오. 그런 다음 재 설계하십시오. – Will

    +3

    그 방법에는 여러 가지가 있습니다. 확실히이 디자인을 사용하지 마십시오. 하나의 대안 (다른 많은 것 중 하나)은'A()'의 결과를'B()'에 전달한 다음 그 결과를'C()'에 전달하는 것입니다. 'A() '등의 결과가 없으면'B()'를 호출 할 수 없다. – xxbbcc

    +0

    또 다른 옵션은 단순히'A()'가 호출되기 전에'B() '. 클러치를 누르지 않으면 (A) 수동 변속기 (B)를 시동 할 수없는 것과 유사합니다. –

    답변

    0

    정말 스스로에게 물어보아야 할 것은 "왜이 방법들이 특정 순서로 호출되어야합니까?"라고 생각합니다. 나는 B가 A가 요구 되었다면, 그것은 "문제의 원리"때문이 아니라고 생각한다. 그것은 A가 B가 요구하는 일을하기 때문입니다. 그런 경우에는 다음 단순히 이상적으로

    public void B() 
    { 
        if (!CanProcessB()) { 
         throw new Exception("B is not ready, Call A first"); 
        } 
    
        // Do your work here 
    } 
    

    같은 것을 가지고, A는 B의 방법 다음

    public void A() { /* Do Work */ } 
    

    를 호출 할 수있는 것은 "CanProcessB"개인 방법은 더 많은 것보다는 A가 호출되었는지 확인하십시오. 실제로 B가 호출되기 위해 조건이 내부적으로 올바른지 확인합니다. 아마도 A()는 B가 호출되도록 내부적으로 어떤 것을 설정할 것입니다. 그 것을 확인하고 준비가되지 않았다면 예외를 던지십시오.

    최소한이 방법을 사용합니다.

    편집 :

    근본 문제는 클래스가 너무 많이하고있는 것입니다처럼 정말로 보인다. 여기에 세 가지 "일"이있는 것처럼 보입니다. DTO 변환

    도메인

    DTO 통계 Caluclation

    API 발신자

    솔직히,이 세 가지 책임 같은 것, 당신은 SOLID 설계 방법을 구현하기 위해 찾고 있다면, 내가 주장하는 것 그들은 3 개의 분리 된 수업이어야한다.

    DomainToDTOConverter 
    DTOStatisticsCalculator 
    ApiInterface 
    

    DomainToDTOConverter는 분명히 도메인 개체를 가져 와서 DTO를 반환합니다. DTOStatisticsCalculator는 생성 된 DTO를 받아 들여 (그래서 A가 호출되어야 할 필요가 있습니다), 그것에 관한 통계를 반환합니다. ApiInterface는 API를 통해 DTO를 전송합니다.

    이들은 독립적으로 서로의 사용할 수있는 세 가지 별도의 클래스, 그리고 또한 단위 테스트 훨씬 쉽게 만드는 것

    편집 2 :

    아, 그래서 당신은 사용자가 통계를 얻을 수 있도록하려는 경우 DTO에 관해서는 DTO Creation 프로세스의 일부로이를 반환 할 수 있습니다. 따라서 DomainToDTON 변환기는 DTOStaisticsCalculator를 사용하고 DTO에 대한 통계와 DTO에 대한 통계를 모두 반환합니다. 그렇게하면 사용자가받은 것을 알 수 있습니다.

    물론 통계를 의미있는 방식으로 사용하는지 확인할 수는 없습니다.

    +1

    실제로 질문에 대답하기 위해 제 질문을 편집했습니다. 특정 순서 ". 어쩌면 내가 왜이 특정한 모델링을 쫓고 있는지 분명히 할 수있을 것이다. – Treeline

    +0

    귀하의 제안이 현재 가지고있는 것에 매우 가깝습니다. 하지만 제 질문은 여전히 ​​같은 문제로 귀결됩니다 : 당신이 제안한 세 가지 클래스를 제공한다면,'ApiInterface'를 사용하기 전에 다른 프로그래머가'DTOStatisticsCalculator'를 사용하지 않고 건너 뛰지 않도록 어떻게 보장해야할까요? 당신이 말했듯이, 수업은 서로 독립적으로 사용될 수 있습니다. 하지만 그건 허용되지 않습니다. – Treeline

    +1

    알겠습니다. 내 대답을 다시 업데이트했습니다. –

    0

    이 문제를 해결하는 방법 중 하나는 전략 패턴을 이용하는 것입니다.

    공통 인터페이스 만들기 :

    public interface IMethod 
    { 
        int MethodSequence { get; } 
        void RunMethod(); 
    } 
    

    그런 다음 당신은 당신의 개인 방법을 가질 수 있습니다

    public class RunMethods 
    { 
        public void Execute(IEnumerable<IMethod> methods) 
        { 
         methods.OrderBy(method => method.MethodSequence) 
          .ToList() 
          .ForEach(method => method.RunMethod()); 
        } 
    } 
    
    :

    public class MethodA : IMethod 
    { 
        public int MethodSequence => 1; 
        public void RunMethod() 
        { 
         Console.WriteLine("Ran Method A"); 
        } 
    } 
    
    public class MethodB : IMethod 
    { 
        public int MethodSequence => 2; 
    
        public void RunMethod() 
        { 
         Console.WriteLine("Ran Method B"); 
        } 
    } 
    
    public class MethodC : IMethod 
    { 
        public int MethodSequence => 3; 
        public void RunMethod() 
        { 
         Console.WriteLine("Ran Method C"); 
        } 
    } 
    

    지금 자신의 시퀀스의 순서대로 방법을 컨텍스트를 생성하고 실행을

    귀하의 전화 코드는 다음 방법의 조합이됩니다 :

    var runMethods = new RunMethods(); 
    
    runMethods.Execute(new List<IMethod> 
    { 
        new MethodA(), 
        new MethodB() 
    });