1

내 asp.net 핵심 웹 API와 함께 탄성 검색을 사용하고 있습니다. 저장소 책임에 관해서는 어디에서 그려지는 지 알 수 없습니다. 여기저장소 패턴은 실제로 어떻게 이루어 집니까?

내가 내 구현을 정의하는 방법이다 : 내 컨트롤러에서

public SearchRespository: ISearchRespository<Product> 
{ 
    private ElasticClient _client 

    public async Task<ISearchResponse<Product>> SearchAsync(ISearchRequest request) 
    { 
     var response = _client.SearchAsync<Product>(request); 
     return await products; 
    }   

    . . . // others 
}   

:

public SearchController : Controller 
{ 
    private ISearchRespository _repo; 

    public SearchController(ISearchRespository repo) 
    { 
     _repo = repo; 
    } 

    public async Task<IActionResult> Search() 
    { 
     // build my search request from Request.Query 

     var response = await _client.SearchAsync(request); 
     var model = new SearchModel 
     { 
      Products = response.Documents; 
      Aggregations = response.Aggregations; 
     } 

     return Ok(model) 
} 

이 그대로 REPO가 탄성 응답을 통과 의미한다. 제 질문은 제가 제 노선을 그려 놓은 것입니까? _client을 제 컨트롤러로 옮기거나 건물 요청을 이동하여 model_repo으로 만들면 어떻게 될까요? 당신들은 어떻게 당신의 창고를 제대로 얻었습니까?

+0

이 질문은 codereview.stackexchange.com –

+0

에 물어볼 것을 제안합니다. 저장소의 목적은 지속성을 추상화하는 것입니다. ISearchResponse와 ISearchRequest는 탄성 검색 인터페이스라고 가정합니다. ISearchRespository에 정의되어서는 안됩니다. 왜냐하면 지속성이 비즈니스/도메인 계층으로 누출되기 때문입니다. 여기서 당신은 당신 자신의 클래스를 사용하거나 검색 요청이 충분히 단순하다면, 그것의 메소드 매개 변수를 사용하십시오. 지속성 유형이 도메인에 누출 될 때 DRY – Tseng

+0

을 제외하고는 저장소가 거의 사용되지 않습니다. 검색 요청이 상당히 복잡하므로이를 구축하기 위해 도우미 클래스를 정의했습니다. 그래서 제 '레포 (repo)'가 내 '수색 모델 (SearcModel)'을 돌려주고 그 도우미가 제 레포 (repo)를 도와 줄 것을 제안하고 있습니까? –

답변

4

Elastic Search를 사용한다는 사실은 특히 컨트롤러가 알지 못하는 구현 세부 사항이어야하므로 컨트롤러에서이를 추상화하는 것이 옳습니다. 나는 종종 올바른 방향으로 나아가고 있는지 아닌지에 대한 이해를 얻으려고 솔리드 원칙을 생각합니다. Dependency Inversion Principle을 보면 Ports and Adapters이라고도하는 스타일로 안내한다는 것을 알 수 있습니다. 이는 기본적으로 외부 도구의 사용이 추상화 된 상태 (포트)이고 응용 프로그램의 경계에 있음을 의미합니다 해당 타사에 연결하는 Adapter을 구현합니다.

그래서 종속성 반전 원칙의 의미에서 올바른 길을 걷고 있습니다.

그러나 무엇이 Martin Fowler's Repository Pattern을 해결하려고하는지에 대한 많은 오해가 있습니다. 도메인 오브젝트에 액세스하기위한 회수와 같은 인터페이스를 사용하여 도메인 데이터 매핑 층간

에서 중재를 다음과 같이 정의된다.

여기서 중요한 점은 저장소는 도메인 계층에서 사용하기위한 것입니다.

그러나 많은 개발자가이를 쿼리의 그룹화 구조로 사용하기 때문에 저장소 패턴을 오용하는 경우가 많습니다. 리포지토리는 - 시스템에서 모든 쿼리를 대상으로하지 않습니다. 도메인이 인 검색어의 경우에만 필요합니다. 이러한 쿼리는 시스템에서 돌연변이에 대한 결정을 내릴 때 도메인을 지원합니다.

그러나 시스템에 필요한 대부분의 쿼리는 이러한 종류의 쿼리가 아닙니다. 코드는 좋은 예입니다.이 경우 도메인을 완전히 건너 뛰고 읽기 작업 만 수행하기 때문입니다.

이것은 저장소에 적합하지 않은 내용입니다. 그것을 솔리드 원칙과 다시 비교함으로써이를 검증 할 수 있습니다.

의 우리는 다음과 같은 저장소 인터페이스를 가지고 있다고 가정 해 봅시다 :

public interface IUserRepository 
{ 
    User[] FindUsersBySearchText(string searchText, bool includeInactiveUsers); 
    User[] GetUsersByRoles(string[] roles); 
    UserInfo[] GetHighUsageUsers(int reqsPerDayThreshold); 
    // More methods here 
} 

이것은 당신이 개발자가 쓰기 볼 전형적인 저장소 추상화입니다.때문에 이러한 추상화는 SOLID 원칙의 관점에서 문제가있다 :

  • 인터페이스 독방 원칙을 위반 인터페이스가 (많은 방법이) 넓은 그 인터페이스의 소비자 방법에 의존하도록 강요하고 있기 때문에, 그들이 돈 사용하지 마십시오.
  • 리포지토리 구현의 메서드가 매우 응집력이 없기 때문에 Single Responsibility Principle을 위반합니다. 그러한 방법을 관련시키는 유일한 사실은 그것들이 같은 개념이나 실체에 속한다는 사실입니다.
  • 디자인은 거의 항상 쿼리가 시스템에 추가되기 때문에 기존 인터페이스와 해당 구현을 변경해야하기 때문에 열기/닫기 원칙을 위반합니다. 모든 인터페이스에는 실제 구현 하나와 테스트 구현 중 적어도 두 가지 구현이 있습니다.

보안 수준, 감사, 로깅, 캐싱 등 교차 관심사를 적용하기가 어려워지기 때문에이 같은 디자인으로 인해 많은 어려움이 발생합니다.

그래서 이것은 저장소 패턴이 해결하려고하는 것이 아닙니다. 그런 디자인은 큰 SOLID 위반 일뿐입니다.

여기 해결책은 시스템에서 쿼리를 개별적으로 모델링하고 에 전혀 리포지토리를 사용하지 않는 것입니다. 이것에 관하여 쓰여지는 많은 기사가 있고, 당신은 이것에 나의 포획을 읽을 수있다 here.

디자인을 살펴보면 많은 유형의 쿼리를 처리 할 수있는 일반적인 쿼리 메서드가있는 것처럼 보이기 때문에 실제로 디자인과 닮았습니다. 그러나 쿼리 메시지 (ISearchRequest)는 Elastic Search에만 해당됩니다. 의존성 반전 원칙에 나와 있듯이,이를 막으려 고 노력해야합니다.

+0

나는 여전히 내 블로그 게시물 주위에있는 길을 찾고 있습니다. 아주 통찰력있는 읽기. 빠른 질문, 제 경우에는'searchText'를 전달하기보다는 탄성'검색 요청'을 작성하고 있습니다. 그렇다면이 논리를 어디에 넣을까요? 'IQuery '또는'IQueryHandler '? –

+0

@ no0b : 귀하의 질문을 이해할 수 있을지 모르겠습니까? TQuery는 요청할 수있는 것 (검색 기준을 포함하는 메시지)의 정의입니다. TQuery를 사용하면 IQueryHandler가 검색을 실행하고 TResult를 빌드합니다. – Steven

+0

저는 여전히 '더 좋은 디자인'의 시작 부분에 있습니다 :). 하지만 필자가 의도 한 바는'FindUsersBySearchTextQuery.SearchText'는'controller'에게 넘겨지는 검색 텍스트이고 그것을 포함하는 사용자 이름을 검색하는 데 사용됩니다. 탄성 당신은'_client.SearchAsync (searchRequest)'와 함께 사용하기 위해'SearchTest'에서 탄성'SearchRequest' 모델을 만들어야합니다. 그래서 제 질문은 당신이'FindUsersBySearchTextQuery' 또는'FindUsersBySearchTextQueryHandler' 또는 다른 곳에서 할 수 있습니다. –

관련 문제