ASP.NET MVC - czy logika biznesowa powinna istnieć w kontrolerach?

97

Derik Whitaker opublikował artykuł kilka dni temu, w którym dotarł do punktu, którego ciekawiło mnie od jakiegoś czasu: czy logika biznesowa powinna istnieć w kontrolerach?

Jak dotąd wszystkie prezentacje ASP.NET MVC, które widziałem, umieszczały dostęp do repozytorium i logikę biznesową w kontrolerze. Niektórzy nawet wrzucają tam również walidację. Powoduje to dość duże, nadęte kontrolery. Czy to naprawdę sposób na użycie frameworka MVC? Wygląda na to, że skończy się to na dużej ilości zduplikowanego kodu i logiki rozproszonej po różnych kontrolerach.

Kevin Pang
źródło
Link do artykułu jest martwy - web.archive.org/web/20150906064521/http://devlicio.us/blogs/… to kopia z archive.org dla wszystkich zainteresowanych.
Stuart Moore

Odpowiedzi:

75

Logika biznesowa naprawdę powinna być w modelu. Powinieneś dążyć do grubych modelek, chudych kontrolerów.

Na przykład zamiast mieć:

public interface IOrderService{
    int CalculateTotal(Order order);
}

Wolałbym mieć:

public class Order{
    int CalculateTotal(ITaxService service){...}        
}

Zakłada się, że podatek jest obliczany przez usługę zewnętrzną i wymaga, aby model wiedział o interfejsach do usług zewnętrznych.

To sprawi, że twój kontroler będzie wyglądał mniej więcej tak:

public class OrdersController{
    public OrdersController(ITaxService taxService, IOrdersRepository ordersRepository){...}

    public void Show(int id){
        ViewData["OrderTotal"] = ordersRepository.LoadOrder(id).CalculateTotal(taxService);
    }
}

Czy jakoś tak.

jonnii
źródło
1
Czy zatem wstrzykniesz Usługi do kontrolerów zamiast do repozytoriów? Jak w takim przypadku ma zastosowanie zasada jednostki pracy?
Kevin Pang,
Napisałem więcej rzeczy, mam nadzieję, że to ma więcej sensu. Możesz również przeczytać: weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model. Mimo że dotyczy Railsów, nadal jest bardzo przydatny.
jonnii
Osobiście nazwałbym repozytorium usługą.
Brad Wilson,
Z pewnością są rodzajem usługi, ale są przeznaczone specjalnie do dostępu do danych. To jest po prostu konwencja, której używam, a nie coś, za czym się specjalnie opowiadam.
jonnii
1
To sprawi, że Twój model będzie ściśle powiązany z ITaxService. Jeśli chcesz ponownie wykorzystać model w innym projekcie lub innym dll, musisz mieć implementację lub odniesienie ITaxService, w przeciwnym razie twój model zostanie uszkodzony, co spowoduje naruszenie zasad SOLID. ITaxService powinien mieć odniesienie do Twojego modelu. W ten sposób możesz ponownie wykorzystać swój model w innym projekcie bez konieczności odwoływania się do ITaxService.
Mehmet Ali Sert
65

Podoba mi się diagram przedstawiony przez Microsoft Patterns & Practices . I wierzę w przysłowie „Obraz jest wart tysiąca słów”.

Diagram przedstawia architekturę warstw MVC i usług biznesowych

AlejandroR
źródło
6
To naprawdę przydatne! Czy możesz mi powiedzieć, gdzie na tej stronie znalazłeś ten schemat?
Rob Church
2
To pochodzi z „Wdrażania po stronie serwera” firmy Microsoft msdn.microsoft.com/en-us/library/hh404093.aspx
Justin,
OK, ale powiedzmy w aplikacji MVC - gdzie idzie logika biznesowa? Wygląda na to, że potrzebujemy dodatkowej warstwy usługowej czy czegoś takiego ?!
niico
14

To fascynujące pytanie.

Myślę, że to interesujące, że duża liczba przykładowych aplikacji MVC w rzeczywistości nie jest zgodna z paradygmatem MVC w sensie prawdziwego umieszczenia „logiki biznesowej” w modelu. Martin Fowler zwrócił uwagę, że MVC nie jest wzorem w sensie Gang Of Four. Raczej jest to paradygmat, że programista musi dodać wzorce do jeżeli są one tworząc coś poza app zabawek.

Krótka odpowiedź brzmi więc, że „logika biznesowa” rzeczywiście nie powinna istnieć w kontrolerze, ponieważ kontroler ma dodatkową funkcję zajmowania się widokiem i interakcjami użytkownika, a my chcemy tworzyć obiekty tylko w jednym celu.

Dłuższą odpowiedzią jest to, że przed przeniesieniem logiki z kontrolera do modelu należy przemyśleć projekt warstwy modelu. Być może poradzisz sobie z całą logiką aplikacji za pomocą REST, w takim przypadku projekt modelu powinien być dość przejrzysty. Jeśli nie, powinieneś wiedzieć, jakie podejście zamierzasz zastosować, aby zapobiec rozdęciu modelu.

Joe Soul-bringer
źródło
14

Możesz sprawdzić ten niesamowity samouczek Stephena Walther, który pokazuje Validating with a Service Layer .

Dowiedz się, jak przenieść logikę walidacji z akcji kontrolera do osobnej warstwy usług. W tym samouczku Stephen Walther wyjaśnia, w jaki sposób można zachować ostry rozdział problemów, izolując warstwę usług od warstwy kontrolera.

Leniel Maccaferri
źródło
2
To jest najbardziej poprawna odpowiedź. Osobiście dalej zalecam, aby nie ujawniać usług kontrolerowi, wybierając zamiast tego użycie koncepcji ViewModel, takiej jak we wzorcu MVVM. Wyobraź sobie scenariusz, w którym chcesz napisać aplikację biznesową z interfejsem pulpitu (powiedzmy, formularze Windows lub WPF), a także interfejsem internetowym. Rozwiązanie tego problemu prowadzi do wzorca „chudego kontrolera”, który jest zalecany również tutaj. Podsumowując: nigdy nie umieszczaj logiki biznesowej w modelu lub kontrolerze i nie umieszczaj w kontrolerze niczego, czego również nie masz.
Sam
9

Logika biznesowa nie powinna być zawarta w kontrolerach. Kontrolery powinny być tak chude, jak to tylko możliwe, najlepiej podążać za wzorcem:

  1. Znajdź jednostkę domeny
  2. Działaj na rzecz podmiotu domeny
  3. Przygotuj dane do przeglądania / zwracania wyników

Dodatkowo kontrolery mogą zawierać logikę aplikacji.

Więc gdzie umieścić logikę biznesową? W modelu.

Co to jest model? To dobre pytanie. Zobacz artykuł o wzorcach i praktykach firmy Microsoft (pochwały dla AlejandroR za doskonałe wyniki). Tutaj są trzy kategorie modeli:

  • Model widoku : jest to po prostu zbiór danych, z minimalną logiką przekazywania danych zi do widoków, jeśli w ogóle, zawiera podstawową walidację pola.
  • Model domeny : model gruby z logiką biznesową, działa na jednej lub wielu jednostkach danych (tj. Jednostka A w danym stanie niż akcja na jednostce B)
  • Model danych : model uwzględniający pamięć masową, logika zawarta w pojedynczej encji odnosi się tylko do tej jednostki (tj. Jeśli pole a to pole b)

Oczywiście MVC to paradygmat, który występuje w różnych odmianach. To, co tutaj opisuję, to MVC zajmujące tylko górną warstwę, zobacz ten artykuł w Wikipedii

Obecnie MVC i podobny model-view-prezenter (MVP) to wzorce projektowe separacji obaw, które mają zastosowanie wyłącznie do warstwy prezentacji większego systemu. W prostych scenariuszach MVC może stanowić podstawowy projekt systemu, sięgający bezpośrednio do bazy danych; Jednak w większości scenariuszy kontroler i model w MVC mają luźną zależność od usługi lub warstwy / warstwy danych. Chodzi o architekturę klient-serwer

Jacek Glen
źródło
-1

Jeśli używasz Dependency Injectors, Twoja logika biznesowa przejdzie do nich, dzięki czemu otrzymasz schludne i czyste kontrolery.

chandresh patel
źródło