2010-12-17 18 views
9

Mam metodę w repozytorium z bardzo złożoną logiką biznesową. Po prostu przeczytałem, że nie powinno być logiki biznesowej w repozytorium.Złożona logika biznesowa w repozytorium

Usunięcie logiki biznesowej z tej metody spowoduje, że będę musiał dystrybuować logikę między dwoma innymi repozytoriami (ponieważ obejmuje ona dwie inne jednostki).

Następnie moje pytanie brzmi: "w jaki sposób powinienem użyć tej złożonej logiki? Będzie musiał pochłonąć te trzy repozytoria, ale nie mogę umieścić go w kontrolerze, ponieważ muszę go ponownie użyć. Dziękuję za pomoc.

Odpowiedz

9

Złożona logika biznesowa zwykle przechodzi w warstwę usług. Usługa może zależeć od jednego lub więcej repozytoriów w celu wykonywania operacji CRUD na twoich modelach. Zatem jedna operacja usługi reprezentująca operację biznesową może zależeć od wielu prostych operacji. Następnie możesz ponownie użyć tej warstwy usługi w kontrolerach i innych aplikacjach.

Oczywiście twoja usługa nie powinna zależeć od konkretnych implementacji repozytoriów. Aby zapewnić słabsze sprzężenie między warstwą usługi a repozytoriami, można użyć interfejsów. Oto przykład:

public interface IProductsRepository { } 
public interface IOrdersRepository { } 
... 

public interface ISomeService 
{ 
    void SomeBusinessOperation(); 
} 

public class SomeServiceImpl: ISomeService 
{ 
    private readonly IProductsRepository _productsRepository; 
    private readonly IOrdersRepository _ordersRepository; 

    public SomeServiceImpl(
     IProductsRepository productsRepository, 
     IOrdersRepository ordersRepository 
    ) 
    { 
     _productsRepository = productsRepository; 
     _ordersRepository = ordersRepository; 
    } 

    public void SomeBusinessOperation() 
    { 
     // TODO: use the repositories to implement the business operation 
    } 
} 

Teraz pozostało tylko skonfigurować ramkę DI, aby wprowadzić tę konkretną usługę do kontrolera.

public class FooController : Controller 
{ 
    private readonly ISomeService _service; 
    public FooController(ISomeService service) 
    { 
     _service = service; 
    } 

    public ActionResult Index() 
    { 
     // TODO: Use the business operation here. 
    } 
} 

Możesz zobaczyć, w jaki sposób interfejsy pozwalają nam zapewnić słabe połączenie między warstwami. Cała instalacja hydrauliczna jest wykonywana w ramach DI i wszystko jest przejrzyste i łatwe do testowania jednostkowego.

+0

Darin w tym kontekście, co jest najlepszym sposobem, aby uzyskać dostęp do różnych repozytoriów z jednej usługi? Czy możesz mi również powiedzieć, jakie rozwiązanie byłoby na IoC/DI? – Chandu

+0

Dziękuję Darin! –

+0

Dzięki za wyjaśnienie Darin – Chandu

1

Myślę, że twoje super repozytorium po prostu złamie zasadę odpowiedzialności pojedynczej. Zostawiłbym repozytorium tak proste, jak to możliwe (wzór KISS;), i utworzyć drugą warstwę między kontrolerów i repozytorium, e.q. warstwa biznesowa.

Aby ponownie i uproszczenie kodu mieć spojrzenie na Dependency Injection (wdrożenie MKOl)

Właściwie chciałbym zaproponować, aby rzucić okiem na zasadach stałych.

2

Używałbym metody projektowania opartej na domenie. Bardzo dobra książka na temat DDD jest następująca: .NET Domain-Driven Design with C#: Problem-Design-Solution. Zobacz także książki Fowlers Enterprise Patterns i Evans Domain Driven Design. Podstawową ideą jest to, że repozytorium to w zasadzie infrastruktura. Cała logika domeny przechodzi do twojego modelu.

Przykład metoda repozytorium wygląda następująco:

public void InsertAddresse(Company company) 
{ 
    foreach (Address address in company.Addresses) 
    { 
     this.InsertAddress(address, company.Key, (company.HeadquartersAddress == address)); 
    } 
} 

Natomiast obiekt modelu wygląda następująco:

public class Contact : Person, IAggregateRoot, IHasAddresses 
{ 
    private string jobTitle; 
    private string email; 
    private string phoneNumber; 
    private string mobilePhoneNumber; 
    private string faxNumber; 
    private string remarks; 
    private Company currentCompany; 
    private IList<Address> addresses; 

    public Contact() 
     : this(null) 
    { 
    } 

    public Contact(object key) 
     : this(key, null, null) 
    { 
    } 

    public Contact(object key, string firstName, string lastName) 
     : base(key, firstName, lastName) 
    { 
     this.jobTitle = string.Empty; 
     this.email = string.Empty; 
     this.phoneNumber = string.Empty; 
     this.mobilePhoneNumber = string.Empty; 
     this.faxNumber = string.Empty; 
     this.remarks = string.Empty; 
     this.currentCompany = null; 
     this.addresses = new List<Address>(); 
    } 

    public string JobTitle 
    { 
     get { return this.jobTitle; } 
     set { this.jobTitle = value; } 
    } 

    public string Email 
    { 
     get { return this.email; } 
     set { this.email = value; } 
    } 

    public string PhoneNumber 
    { 
     get { return this.phoneNumber; } 
     set { this.phoneNumber = value; } 
    } 

    public string MobilePhoneNumber 
    { 
     get { return this.mobilePhoneNumber; } 
     set { this.mobilePhoneNumber = value; } 
    } 

    public string FaxNumber 
    { 
     get { return this.faxNumber; } 
     set { this.faxNumber = value; } 
    } 

    public string Remarks 
    { 
     get { return this.remarks; } 
     set { this.remarks = value; } 
    } 

    public Company CurrentCompany 
    { 
     get { return this.currentCompany; } 
     set { this.currentCompany = value; } 
    } 

    public IList<Address> Addresses 
    { 
     get { return this.addresses; } 
    } 

    protected override void Validate() 
    { 
     //some logic here 
    } 

    protected override BrokenRuleMessages GetBrokenRuleMessages() 
    { 
     return new ContactRuleMessages(); 
    } 
} 
+0

Dziękujemy, że było naprawdę wnikliwe! –