0

우리는 계층화 된 응용 프로그램을위한 아키텍처를 개발하고 있습니다. 우리는 모바일 브라우저와 '일반'브라우저를 모두 지원하는 ASP.NET MVC 프리젠 테이션 계층을 가질 계획입니다. 즉, 사용자가 모바일 장치에서 사이트를 탐색하는 동안 모바일 브라우저에 최적화 된보기를 제공하는 동시에 동일한 ASP.NET MVC 프레젠테이션 계층을 제공해야하며 동시에 동시에 최적화 된 '일반'보기를 제공해야합니다. 데스크톱/랩톱 컴퓨터를 사용하는 경우 데스크톱/랩톱 브라우저. 현재 모바일 앱을 지원할 계획은 없지만 앞으로 추가 할 수 있습니다. 또한 아키텍처에는 도메인 모델, 도메인 서비스, 응용 프로그램 서비스 및 EF 코드 우선 POCO와 저장소 및 작업 단위 패턴을 사용하는 데이터 계층에 대한 레이어가 있습니다. 모든 표준 도메인 모델 유형 디자인의.도메인 서비스와 응용 프로그램 서비스 비교 도메인 엔터티의 동작 (메서드)

그러나 나는 우리가 개발중인 시스템에 적용 할 때 도메인 엔터티의 도메인 서비스, 응용 프로그램 서비스 및 동작 (메서드)의 차이점을 알아 내려고 노력했습니다. 아래는 시험을위한 우리 시스템의 고급 사용 사례입니다.

보고서 및 보고서 그룹이 있습니다. 이 두 개체 사이에는 다 대다 관계가 있습니다. 도메인 개체가 같은 것을 찾고,> ReportGroups -> Jct_Reports_ReportGroups < - 보고서 < : 물론

Report class : 
    public string ReportName { get; set; } 
    ... 
    public virtual ICollection<ReportGroup> ReportGroups { get; set; } 

ReportGroup class : 
    public string GroupName { get; set; } 
    ... 
    public virtual ICollection<Report> Reports { get; set; } 

을 (보고서 그룹을 생성하지 않고) 보고서를 만들 수있는 사용자, 그리고 그들이 할 수있는 DB 테이블은 하나 이상의 보고서를 포함하는 보고서 그룹을 작성하십시오. 또한 사용자는 보고서를 삭제할 수 있습니다. 이러한 일이 발생하면 여러 가지 일이 발생합니다. 먼저 보고서가 모든 보고서 그룹에 있는지 확인합니다 (하나의 보고서가 여러 보고서 그룹에 포함될 수 있음). 보고서가 모든 보고서 그룹에서 발견되면 각 보고서 그룹을 검토하고 보고서 그룹에서 보고서를 제거합니다 (Jct_Reports_ReportGroups 테이블에서 행을 삭제하여). 그런 다음 삭제할 보고서가 포함 된 각 보고서 그룹에 대해 보고서 그룹에 남아있는 다른 보고서가 있는지 확인합니다. 보고서 그룹에 다른 보고서가 없으면 ReportGroups 테이블에서 행을 삭제하여 보고서 그룹도 삭제합니다. 보고서 그룹에 다른 보고서가 남아 있으면 보고서 그룹을 삭제하지 않습니다. 이러한 모든 작업이 성공하면 사용자가 선택한대로 삭제할 보고서를 제거합니다 (보고서 테이블의 행 삭제). 마지막으로, 사용자에게 보고서 삭제가 성공했는지 여부를 알리는 메시지가 표시됩니다.

전체적인 응용 프로그램을 약간만 이해하는 데 도움이되는 적절한 사용 사례가되기를 바랍니다.

도메인 서비스가 자연스럽게 도메인 객체 내에 들어 가지 않는 비즈니스 로직을 캡슐화하고 일반적인 CRUD 작업이 아니라는 것을 읽은 적이 있습니다. 외부 고객이 응용 프로그램 서비스를 사용하여 시스템과 대화하는 경우 - 소비자가 필요하면 CRUD 작업에 대한 액세스가 여기에 노출됩니다. 하지만, POCO 도메인 엔티티에서 어떤 메소드 (비즈니스 로직)가 사용되는지, 비즈니스 로직이 도메인 서비스로 간주되어 비즈니스 계층에 포함되는지, 어떤 비즈니스 로직이 응용 서비스 계층. 따라서, 가장 중요한 질문은 위의 유즈 케이스를 감안할 때 도메인 엔터티에서 도메인 서비스와 응용 프로그램 서비스를 구분하는 방법에 대한 권장 사항은 무엇이겠습니까?

+1

개인 플러그,하지만 내 기사를 살펴 걸릴 : 및 단체 (저장소를 참조 문제가 될 수있다) http://gorodinski.com/blog/2012/04/14/services-in-domain-driven를 -design-ddd / – eulerfx

답변

2

꽤 많은 질문입니다.

나는 나 자신을 위해 다음과 같은 비 엄격한 가이드 라인을 선호 :

응용 프로그램 서비스 : 우리는 시스템과 사용자 상호 작용을 설명하는 사용 사례의 집합을 상상해보십시오.특정 입력 및 출력에 대해및 Cash transfer 사례가 있다고 가정 해 보겠습니다. 또한 성공과 실패 시나리오를 설명합니다. 이를 위해 우리는 일반적으로 애플리케이션 서비스 사양을 가지고 있습니다. LoginResul Login(name, pass)TransferResult CashTrasnfer(from, to, amount) 메서드를 모두 공개 할 것이고, 같은 것과 벗어남, 성공/실패 동작을 함께 제공 할 수 있습니다.

사용 사례를 실현하기 위해 응용 프로그램 서비스 호출 BL (하지만 보안 및 기타 응용 프로그램 별 검사가 추가됨)이 분명합니다.

도메인 서비스 : '자연스럽게 도메인 개체에 맞지 않습니다.'

CashTrasnfer 유스 케이스를 갖는, 우리는에 있습니다 :

  • 부하 계정 '에서'

    • 부하 계정 오류가 반환 될 수 // 균형 '에서'
    • 체크 '에'
    • 계정 액세스 확인 (잠김 등) // 오류가 반환 될 수 있음
    • 'from'from 'from'from '
    • 'to '에 금액을 입력하십시오.
    • (이상적으로는 단일 '비즈니스'거래 여야 함).

    이 기능은 계정 엔터티에 맞지 않습니다. 따라서 TransferService이라는 특수 문자를 사용하는 것이 좋습니다.

    Report.Remove() { 
        foreach(group in Groups) { 
         group.RemoveReport(this); 
        } 
        repository.Remove(this); 
    } 
    Group.RemoveReport(report) { 
        reports.Remove(report); 
        if(reports.Count == 0) 
         repository.Remove(this); 
    } 
    

    또는 보고서 서비스 사이의 분할 - 특히 보고서/ReportGroup 기능에 대한


    그것은 더 비 논리적 참조가 없기 때문에 (모든 항목이 보고서에서 연결할 수 있습니다), 엔티티 범위 수

    Report.RemoveFromAllGroups() { 
        foreach(group in Groups) { 
         group.RemoveReport(this); 
         if(group.IsEmpty) 
          //add to collection to return 
        } 
    } 
    Service.Remove(report) 
    { 
        var emptyGroups = report.RemoveFromAllGroups(); 
        reportRepo.Remove(report); 
        groupRepo.Remove(emptyGroups); 
    }