programing

서비스 계층이 저장소 구현에 어떻게 적합합니까?

cafebook 2023. 8. 21. 21:37
반응형

서비스 계층이 저장소 구현에 어떻게 적합합니까?

POCO 모델 클래스와 지속성을 처리하는 저장소 클래스를 만들었습니다.POCO가 저장소에 액세스할 수 없기 때문에 저장소에 비즈니스 로직 작업이 많이 있는데, 이 작업은 올바르지 않은 것 같습니다.제가 읽은 바로는 UI 소비자와 저장소 계층 사이에 있는 서비스 계층이 필요한 것 같습니다.제가 정확히 어떻게 작동하는지는 잘 모르겠습니다.

서비스 계층 외에도 별도의 비즈니스 논리 계층이 있어야 합니까? 아니면 서비스 계층의 역할입니까?

리포지토리당 하나의 서비스가 있어야 합니까?

UI에서 모델 개체를 인스턴스화할 수 있는 유일한 방법은 서비스 계층입니까? 아니면 저장소에서 새 모델 인스턴스를 서비스에 제공합니까?

입력이 유효한지 확인하고 업데이트하기 전에 업데이트할 항목이 데이터베이스에 있는지 확인하는 매개 변수, 모델 및 기타 유효성 검사를 서비스 계층에 입력해야 합니까?

모델, 리포지토리 및 UI가 모두 서비스 계층에 호출할 수 있습니까? 아니면 UI만 사용할 수 있습니까?

서비스 계층은 모두 정적 메서드여야 합니까?

UI에서 서비스 계층을 호출하는 일반적인 방법은 무엇입니까?

모델과 서비스 계층에 대해 어떤 검증을 수행해야 합니까?

다음은 기존 레이어의 샘플 코드입니다.

public class GiftCertificateModel
{
    public int GiftCerticiateId {get;set;}
    public string Code {get;set;}
    public decimal Amount {get;set;}
    public DateTime ExpirationDate {get;set;}

    public bool IsValidCode(){}
}


public class GiftCertificateRepository
{
    //only way to access database
    public GiftCertificateModel GetById(int GiftCertificateId) { }
    public List<GiftCertificateModel> GetMany() { }
    public void Save(GiftCertificateModel gc) { }
    public string GetNewUniqueCode() { //code has to be checked in db }

    public GiftCertificateModel CreateNew()
    {
        GiftCertificateModel gc = new GiftCertificateModel();
        gc.Code = GetNewUniqueCode();
        return gc;
    }              
}

업데이트: 현재 웹 양식과 클래식 ADO를 사용하고 있습니다.NET. 저는 MVC와 EF4로 이동하고 싶습니다.

업데이트: @Lester의 훌륭한 설명에 감사드립니다.이제 각 저장소에 대해 서비스 계층을 추가해야 한다는 것을 알게 되었습니다.이 계층은 UI 또는 다른 서비스가 리포지토리와 통신할 수 있는 유일한 방법이며 도메인 개체에 맞지 않는 유효성 검사(예: repo를 호출해야 하는 유효성 검사)를 포함합니다.

public class GiftCertificateService()
{

    public void Redeem(string code, decimal amount)
    {
        GiftCertificate gc = new GiftCertificate();
        if (!gc.IsValidCode(code))
        {
            throw new ArgumentException("Invalid code");
        }

        if (amount <= 0 || GetRemainingBalance(code) < amount)
        {
            throw new ArgumentException("Invalid amount");
        }

        GiftCertificateRepository gcRepo = new GiftCertificateRepository();
        gcRepo.Redeem(code, amount);
    }

    public decimal GetRemainingBalance(string code)
    {
        GiftCertificate gc = new GiftCertificate();            
        if (!gc.IsValidCode(code))
        {
            throw new ArgumentException("Invalid code");
        }

        GiftCertificateRepository gcRepo = new GiftCertificateRepository();
        gcRepo.GetRemainingBalance(code);
    }

    public SaveNewGC(GiftCertificate gc)
    {
        //validates the gc and calls the repo save method
        //updates the objects new db ID
    }

}

문의사항

  1. 모델(금액, 코드 등)에 있는 것과 동일한 속성을 서비스에 추가하거나 GiftCertificate 개체 및 직접 매개 변수를 수락하는 방법만 제공합니까?

  2. 서비스 생성자가 호출될 때 GiftCertificate 엔티티의 기본 인스턴스를 생성하거나 필요에 따라 새 인스턴스를 생성합니까(예: 엔티티의 유효성 검사 메서드를 호출해야 하는 서비스의 유효성 검사 메서드의 경우)?또한 기본 리포지토리 인스턴스 생성에 대한 동일한 질문...?

  3. 서비스를 통해 레포의 기능을 노출하는 것을 알고 있습니다. 엔티티의 메소드도 노출합니까(예: IsValidCode 등)?

  4. UI는 서비스를 거치지 않고 새 GiftCertificate 개체를 직접 생성할 수 있습니다(예: 엔티티에서 매개 변수 유효성 검사 메서드 호출).그렇지 않다면, 어떻게 시행합니까?

  5. UI 계층에서 새 상품권을 생성하려는 경우 UI 계층에서 모델/서비스 유효성 검사(예: IsValidExpirationDate 등)를 직접 호출하거나 개체에 먼저 수분을 공급한 다음 유효성 검사를 전달하여 일종의 유효성 검사 요약을 UI로 반환합니까?

또한 UI 계층에서 상환을 원할 경우 먼저 UI에서 모델/서비스 검증 방법을 호출하여 사용자 피드백을 제공한 다음 내부적으로 동일한 검사를 다시 실행하는 상환 방법을 호출해야 합니까?

UI에서 상환 작업을 수행하기 위해 서비스를 호출하는 예:

string redeemCode = RedeemCodeTextBox.Text;

GiftCertificateService gcService = new GiftCertificateService();
GiftCertificate gc = new GiftCertificate(); //do this to call validation methods (should be through service somehow?)

if (!gc.IsValid(redeemCode))
{
    //give error back to user
}

if (gcService.GetRemainingBalance(redeemCode) < amount)
{
    //give error back to user
}

//if no errors
gcService.Redeem(code,amount);

UI에서 새 상품권을 만드는 예:

GiftCertificateService gcService = new GiftCertificateService();
GiftCertificate gc = new GiftCertificate();

if (!gc.IsValidExpDate(inputExpDate))
{
    //give error to user..
}

//if no errors...
gc.Code = gcService.GetNewCode();
gc.Amount = 10M;
gc.ExpirationDate = inputExpDate;
gcService.SaveNewGC(gc);
//method updates the gc with the new id...

GC가 생성되는 방식과 엔티티/서비스 간에 검증이 분리되는 방식에 대해 뭔가 잘못된 느낌이 듭니다.사용자/소비자는 어떤 유효성 검사가 어디에 있는지에 대해 걱정할 필요가 없습니다.조언?

S#arp Architecture를 살펴보십시오.이는 ASP 구축을 위한 모범 사례 아키텍처 프레임워크와 같습니다.NET MVC 응용 프로그램.일반적인 아키텍처 패턴은 데이터 액세스만 담당하는 엔터티당 하나의 리포지토리와 비즈니스 로직만 담당하고 컨트롤러와 서비스 간의 통신을 담당하는 리포지토리당 하나의 서비스를 갖는 것입니다.

S#arp Architecture를 기반으로 질문에 답변하기

서비스 계층 외에도 별도의 비즈니스 논리 계층이 있어야 합니까? 아니면 서비스 계층의 역할입니까?

모델은 현장 수준 검증(예: 필수 필드 속성 사용)을 담당해야 하며 컨트롤러는 저장 전에 데이터를 검증할 수 있습니다(예: 저장 전 상태 확인).

저장소당 하나의 서비스 계층이 있어야 합니까?

예 - 저장소당 서비스가 하나씩 있어야 합니다(리포지토리당 서비스 계층이 하나가 아님).

UI에서 모델 개체를 인스턴스화할 수 있는 유일한 방법은 서비스 계층입니까? 아니면 저장소에서 새 모델 인스턴스를 서비스에 제공합니까?

리포지토리 및 서비스는 필요에 따라 단일 엔티티, 엔티티 모음 또는 데이터 전송 개체(DTO)를 반환할 수 있습니다.컨트롤러는 이 값을 모델의 정적 생성자 메서드에 전달하여 모델의 인스턴스를 반환합니다.

ex DTO 사용:

GiftCertificateModel.CreateGiftCertificate(int GiftCerticiateId, string Code, decimal Amount, DateTime ExpirationDate)

입력이 유효한지 확인하고 업데이트하기 전에 업데이트할 항목이 데이터베이스에 있는지 확인하는 매개 변수, 모델 및 기타 유효성 검사를 서비스 계층에 입력해야 합니까?

모델은 필드 수준 값을 검증합니다. 필수 필드, 나이 또는 날짜 범위 등을 확인하여 입력이 유효한지 확인합니다.서비스 부서는 모델 값 ex 외부에서 확인해야 하는 모든 필요한 검증을 수행해야 합니다.상품권 미상환 확인, 상품권 대상 매장 속성 확인).

모델, 리포지토리 및 UI가 모두 서비스 계층에 호출할 수 있습니까? 아니면 UI만 사용할 수 있습니까?

컨트롤러 및 기타 서비스는 서비스 계층에 전화를 거는 유일한 서비스여야 합니다.서비스는 리포지토리에 전화를 거는 유일한 서비스여야 합니다.

서비스 계층은 모두 정적 메서드여야 합니까?

그럴 수도 있지만 그렇지 않다면 유지보수 및 확장이 더 쉽습니다.엔티티에 대한 변경 및 하위 클래스 추가/제거는 엔티티/하위 클래스당 하나의 서비스가 있는 경우 변경하기가 더 쉽습니다.

UI에서 서비스 계층을 호출하는 일반적인 방법은 무엇입니까?

컨트롤러가 서비스 계층을 호출하는 몇 가지 예:

giftCertificateService.GetEntity(giftCertificateId); (which in turn is just a call to the giftCertificateRepository.GetEntity(giftCertificateId)

giftCertificateService.Redeem(giftCertificate);

모델과 서비스 계층에 대해 어떤 검증을 수행해야 합니까?

위에서 이미 답변했습니다.

갱신하다

WebForms를 사용하기 때문에 일부 개념을 파악하는 것이 조금 어려울 수 있지만, 제가 설명하는 것은 일반적인 MVC 패러다임이기 때문에 제가 언급한 모든 것이 적용 가능합니다.데이터 액세스를 위한 ADO.NET은 저장소를 통해 데이터 액세스가 분리되므로 중요하지 않습니다.

모델(금액, 코드 등)에 있는 것과 동일한 속성을 서비스에 추가하거나 GiftCertificate 개체 및 직접 매개 변수를 수락하는 방법만 제공합니까?

서비스를 컨트롤러가 호출할 수 있는 작업인 서비스 이름이 의미하는 것과 동일하게 보아야 합니다.모델에서 이미 사용할 수 있으므로 모델에 정의된 속성이 필요하지 않습니다.

서비스 생성자가 호출될 때 GiftCertificate 엔티티의 기본 인스턴스를 생성하거나 필요에 따라 새 인스턴스를 생성합니까(예: 엔티티의 유효성 검사 메서드를 호출해야 하는 서비스의 유효성 검사 메서드의 경우)?또한 기본 리포지토리 인스턴스 생성에 대한 동일한 질문...?

컨트롤러와 서비스에는 각각 서비스와 리포지토리에 대한 개인 필드가 있어야 합니다.모든 작업/방법을 인스턴스화해서는 안 됩니다.

서비스를 통해 레포의 기능을 노출하는 것을 알고 있습니다. 엔티티의 메소드도 노출합니까(예: IsValidCode 등)?

무슨 말인지 잘 모르겠어요.서비스가 엔티티를 반환하는 경우 엔티티의 메서드는 이미 노출되어 있습니다.만약 그들이 DTO를 반환한다면, 그것은 당신이 특정 정보에만 관심이 있다는 것을 의미합니다.

검증을 위해 모델 및 기타 유형의 검증이 서비스에서 직접 수행되기 때문에 귀하가 우려하는 이유를 알 수 있습니다.제가 사용한 경험에 따르면 검증에 DB에 대한 호출이 필요한 경우 서비스 계층에서 수행해야 합니다.

UI는 서비스를 거치지 않고 새 GiftCertificate 개체를 직접 생성할 수 있습니다(예: 엔티티에서 매개 변수 유효성 검사 메서드 호출).그렇지 않다면, 어떻게 시행합니까?

UI 계층에서 새 상품권을 생성하려는 경우 UI 계층에서 모델/서비스 유효성 검사(예: IsValidExpirationDate 등)를 직접 호출하거나 개체에 먼저 수분을 공급한 다음 유효성 검사를 전달하여 일종의 유효성 검사 요약을 UI로 반환합니까?

이 두 가지 질문에 대해 시나리오를 살펴보겠습니다.

사용자가 새 인증서를 만들기 위한 정보를 입력하고 제출합니다.필드 수준 유효성 검사가 있으므로 텍스트 상자가 null이거나 달러가 음수이면 유효성 검사 오류가 발생합니다.합니다.gcService.Save(gc).

그 서비스는 그 가게가 이미 너무 많은 상품권을 발행했는지와 같은 다른 사업 논리를 확인할 것입니다.오류 코드가 여러 개 있는 경우 상태에 대한 열거형을 반환하거나 오류 정보와 함께 예외를 발생시킵니다.

마침내, 서비스는 전화를 합니다.gcRepository.Save(gc).

  1. 엔티티별로 리포지토리를 생성할 필요는 없습니다. 자세한 내용은 여기를 참조하십시오.

    일반적으로 도메인의 Aggregate당 하나의 리포지토리를 정의합니다.즉, 엔티티별 저장소가 없습니다!단순 주문 입력 시스템을 살펴보면 주문은 주문 집계의 루트일 수 있습니다.따라서 주문 저장소를 갖게 됩니다.

  2. 리포지토리당 하나의 서비스가 있어야 합니까? -> 한 서비스에서 여러 리포지토리를 사용할 수 있기 때문에 항상 그런 것은 아닙니다.

  3. 서비스는 모델 인스턴스를 생성하지만 리포지토리는 모델과 상호 작용하지 않습니다. 실제로는 후속 모델을 사용할 엔티티를 반환합니다.

  4. 입력/범위 등의 유효성 확인을 UI 수준(javascript 또는 기타 라이브러리 사용 가능)에서 처리하고 서비스가 비즈니스 측면만 처리하도록 합니다.속성의 이점을 얻을 수 있으며 이를 통해 동일한 이점을 얻을 수 있습니다.

  5. UI->Service->Respository, 리포지토리가 서비스를 호출하는 경우 잘못된 IMO여야 합니다.


코드가 바뀌면,

  1. 모델과 리포지토리를 구분합니다.

    public class GiftCertificateModel
    {
    }
    public class GiftCertificateRepository
    {
       //Remove Model related code from here, and just put ONLY database specific code here, (no business logic also). Common methods would be Get, GetById, Insert, Update etc. 
    
        Since essence of Repository is to have common CRUD logic at one place soyou don't have to write entity specific code. 
        You will create entity specific repository in rare cases, also by deriving base repository.
    
    }
    
    public class GiftCertificateService()
    {
        //Create Model instance here
        // Use repository to fill the model (Mapper)
    
    }
    

상품권 서비스라는 서비스를 만들 수 있습니다.

이렇게 하면 상품권 모델의 책임에 속하지 않는 모든 작업을 상품권 모델의 서비스로 조정할 수 있습니다.(WCF 서비스와 혼동하지 마십시오.)

서비스는 UI(또는 호출자)가 서비스에 정의된 방법을 사용하도록 모든 작업을 제어합니다.

그런 다음 이 서비스는 모델에서 메소드를 호출하고, 저장소를 사용하고, 트랜잭션을 생성하는 등의 작업을 수행합니다.

예를 들어, (제공한 샘플 코드를 기반으로 함):

public class GiftCertificateService 
{
   public void CreateCertificate() 
   {
      //Do whatever needs to create a certificate.
      GiftCertificateRepository gcRepo = new GiftCertificateRepository();
      GiftCertificateModel gc = gcRepo.CreateNew();
      gc.Amount = 10.00M;
      gc.ExpirationDate = DateTime.Today.AddMonths(12);
      gc.Notes = "Test GC";
      gcRepo.Save(gc);
   }
}

UI가 CreateCertificate 메서드(인수 전달 등)를 호출하고 메서드가 무언가를 반환할 수도 있습니다.

참고: 클래스를 UI에 적용하려면 컨트롤러 클래스(MVC를 수행하는 경우) 또는 발표자 클래스(MVVM을 수행하는 경우)를 만들고 해당 클래스의 GiftCertificateService를 사용합니다.

언급URL : https://stackoverflow.com/questions/6138660/how-does-a-service-layer-fit-into-my-repository-implementation

반응형