Przede wszystkim widziałem wiele pytań na ten temat, ale niewystarczające uzasadnienie. Jeśli moje pytanie nie jest wystarczająco dobre i powinno zostać usunięte, zrozumiem.
Przyjrzałem się na przykład temu i ponad 45 głosowanej odpowiedzi mówi, że radzi on umieścić logikę biznesową w modelu, co brzmi całkiem logicznie.
Jednak mój pierwszy duży projekt zrobiłem z całym moim BL w pełni w kontrolerach, ponieważ nie kwestionowałem tych rzeczy i patrzyłem, jak to się robi w tym, AccountController
który jest automatycznie dodawany, jeśli wybierzesz MVC z uwierzytelnianiem formularza. Wszystkie metody wyglądają na całkiem wypchane BL. A może jest to najmniejsza ilość kodu, jaką udało mi się dodać i coś przeoczam?
Ktoś na youtube zapytał mnie, czy ma rację, umieszczając całą logikę w swoich modelach i na początku nie! Wtedy zacząłem myśleć, że może miał rację !?
Więc w końcu gdzie umieścić swoją logikę biznesową? Jeśli jest w klasach modeli, to ile kodu należy uznać za zdrową ilość w metodzie, która jest w kontrolerze? Jedna linia do wywołania co najwyżej jakiejś metody z modelu w kontrolerze, a potem powrót do widoku?
źródło
Odpowiedzi:
Wolę umieścić logikę domeny w modelu z kilku powodów.
Model nie powinien zawierać kodu interfejsu użytkownika, a zatem powinien być łatwiejszy do przetestowania. Zawsze, gdy jest to możliwe, wolę mieć w pełni działający model (co oznacza pełne pokrycie testami) przed napisaniem kodu interfejsu użytkownika. Kontroler może ufać, że model działa właściwie i po prostu radzi sobie z problemami związanymi z interfejsem użytkownika.
Jeśli umieścisz logikę domeny w kontrolerze, udostępnianie jej między różnymi aplikacjami lub nawet między różnymi kontrolerami nie będzie tak łatwe.
źródło
#2
ponieważ sam ciężko mi było dzielić się między kontrolerami (musiałem używać takich metod jak statyczne)!Lubię utrzymywać moje modele w czystości, tj. Tylko z właściwościami i bez logiki biznesowej. Zawsze uważam, że dobrze jest wstrzyknąć zależności do kontrolera, a te zależności zawierają logikę, którą wykonuję na moich modelach. Lubię trzymać się zasady pojedynczej odpowiedzialności tam, gdzie to możliwe, i uważam, że modele z mnóstwem metod bardzo szybko się rozrastają. W obu przypadkach są plusy i minusy, wstrzyknięcie wielu zależności wiąże się z narzutem, ale pozwala na testowanie w izolacji i sprawia, że zajęcia są proste, a skończy się to na szczuplejszych kontrolerów. Pomimo mojej logiki, która tak naprawdę nie istnieje w moim modelu jako członkowie klasy, nadal jest to logika biznesowa. Zwykle nie mam zdefiniowanej logiki biznesowej w kontrolerze, ponieważ kpiny, takie jak Httpcontext, są trochę koszmarem i niepotrzebne.
źródło
Plik Biznesowych logika należy do domeny problemu i wszystko, co należy do dziedziny problemu przechodzi do modelu w MVC.
Plik Kontroler powinien być odpowiedzialny za przekazywanie danych z modelu do widoku iz widoku Powrót do modelu. Kontroler jest więc pomostem między tym, z czym użytkownik wchodzi w interakcje, a sposobem modelowania i zapisywania stanu problemu przez program. Hydraulika , że tak powiem.
Kluczem jest tutaj rozróżnienie między logiką biznesową a logiką hydrauliczną. Moim zdaniem to, co robi automatycznie generowany kontroler konta, to głównie hydraulika, a nie logika biznesowa. Należy pamiętać, że logika hydrauliczna niekoniecznie jest w ogóle krótka, więc nie trzeba narzucać sztucznych ograniczeń (np. „X liczba wywołań maksymalnie w kontrolerze”).
źródło
Mój zespół po przeniesieniu się do MVC z formularzy internetowych (asp.net) przeprowadził wiele badań i opracował następującą strukturę. Według mnie nie chodzi o to, jak duża czy mała jest aplikacja. Chodzi o to, aby kod był czysty i przejrzysty.
DALProject
AccountsDAL.cs --- > Calls SP or any ORM if ur using any
BLLProject
WebProject
Model AccountsModel --- > Contains properties And call BLL Controllers IndexController ---> Calls Models and returns View Views Index
Kontrolerzy powinni odpowiadać za przekazywanie danych między modelem a widokiem. Poza tym nie powinno być żadnego zbędnego kodu. Na przykład, jeśli rejestrujesz, należy to zrobić na poziomie modelu, a nie na kontrolerze.
źródło
Wydaje się, że istnieje pewne zamieszanie wokół tego tematu. W większości wydaje się, że ludzie mylą wzorzec MVC z architekturą N-warstwową jako sytuację „albo / albo”. W rzeczywistości te dwa podejścia mogą być używane razem, ale jedno nie jest zależne od drugiego i żadne nie jest wymagane.
Architektura N-warstwowa polega na rozdzielaniu aplikacji na wiele warstw. Prostym przykładem jest podzielenie aplikacji na warstwę prezentacji, warstwę logiki biznesowej i warstwę dostępu do danych.
MVC to wzorzec projektowy dotyczący warstwy prezentacyjnej aplikacji. Całkowicie możliwe jest zaprojektowanie aplikacji zgodnie z podejściem MVC bez oddzielania logiki biznesowej i logiki dostępu do danych od warstwy prezentacji, a tym samym uzyskanie projektu jednopoziomowego.
W rezultacie, jeśli postępujesz zgodnie z podejściem MVC bez oddzielania aplikacji na warstwy, uzyskujesz modele, widoki i kontrolery, które mają bity reguł biznesowych i logiki dostępu do danych zmieszane z resztą logiki.
Z definicji w architekturze N-warstwowej warstwa prezentacji powinna być w stanie komunikować się tylko z warstwą logiki biznesowej, więc powinna utrzymywać, że dowolny z komponentów MVC może komunikować się tylko z warstwą logiki biznesowej.
Jeśli budujesz aplikację, która nie wymaga prezentacji, a więc nie jest warstwą prezentacji, nie powinieneś przejmować się wzorcem MVC. Jednak bardzo dobrze możesz nadal podzielić aplikację na wiele warstw, a tym samym podążać za projektem N-warstwowym, nawet jeśli nie jest to wymagana warstwa prezentacji.
źródło
Ogólnie rzecz biorąc, logika biznesowa nie powinna znajdować się w żadnym z odtwarzaczy MVC; powinien być używany tylko przez akcje kontrolera.
Jak wiele osób wspomniało, najlepiej jest utworzyć bibliotekę do obsługi logiki biznesowej jako zestaw niezależnych od klienta komponentów wielokrotnego użytku.
Robiąc to w ten sposób, znacznie zwiększamy możliwość ponownego użycia, kompatybilność, skalowalność i testowalność z naszym oprogramowaniem. Zmniejszamy również naszą zależność od niektórych funkcji frameworka, co ułatwia migrację do nowszych / innych technologii.
Abstrahowanie naszej logiki biznesowej w samodzielny zespół (lub zespoły) dobrze nam służyło przez lata. Nasza logika biznesowa może być następnie używana przez praktycznie każdą technologię .NET (ASP.NET MVC / API / Core, WPF, Win Forms, WCF, UWP, WF, Console itp.).
Ponadto lubimy, gdy nasza warstwa środkowa obsługuje reguły biznesowe i logikę walidacji, aby zmniejszyć nasze zależności od platformy .NET MVC Framework. Na przykład unikamy korzystania z pomocników walidacji .NET MVC i zamiast tego polegamy na własnych. To kolejny czynnik, który pozwala nam łatwo wykorzystać naszą logikę biznesową z dowolnej technologii .NET.
Logiczne zaprojektowanie naszej środkowej warstwy w ten sposób umożliwiło nam łatwe osiągnięcie takiej architektury fizycznej:
Został napisany za pomocą Peasy.NET i dobrze nam służył przez lata. Tak dobrze, że zdecydowaliśmy się to otworzyć.
Jeśli ktoś jest ciekawy, jak wygląda nasza środkowa kondygnacja, oto próbka od klienta warstwy biznesowej. Przedstawia również jego użycie przez wielu klientów .NET (ASP.NET MVC, Web Api i WPF).
Mam nadzieję, że to komuś pomoże!
źródło
Logika biznesowa nie powinna być umieszczana w widokach modeli ani kontrolerach. Powinna istnieć oddzielna warstwa logiki biznesowej ; jedynym celem tej warstwy jest obsługa logiki biznesowej. Jest to bardziej zgodne z SOLID .
Jeśli umieścisz logikę biznesową w MV lub C, otrzymasz kod, który jest trudny do przetestowania / ponownego wykorzystania.
To jest złe rozwiązanie.
Skończy się w piekło zależności gdzie obiekty polegać na obiektach.
Nawet jeśli masz martwą prostą funkcję, nadal będziesz musiał spełnić wszystkie zależności, aby ją wywołać.
Spowoduje również, że niepotrzebne i niewykorzystane dane będą przekazywane bez powodu.Może to również wpłynąć na wydajność w zależności od tego, jak bardzo się pogorszy.
Powinienem również wspomnieć, że testowanie jednostkowe staje się uciążliwe w a **, ponieważ musisz mockować wiele obiektów, aby przetestować prostą funkcję.
Obowiązujące zasady czystego kodu
Kontrolery
W kontrolerze powinno być możliwe użycie iniekcji zależności w celu wstrzyknięcia warstwy logiki biznesowej . Upewnij się, że kontroler jest używany tylko do kierowania informacji do warstwy logiki biznesowej. Kontroler NIE powinien mieć bezpośrednio w sobie logiki biznesowej. Wszelkie walidacje muszą być obsługiwane przez
IValidatable
model. Każda logika biznesowa musi być skierowana do oddzielnej warstwy.źródło
Payment
iProduct
jako zmienną instancji? Jak nazwiesz ten obiekt? Jeśli model nie jest używany w widoku, nie jest już modelem. Jest częścią osobnej warstwy. Idealnie byłoby, gdyby ta klasa, którą tworzysz, obejmowała tylko to, czego potrzebuje z płatności i produktu, aby wykonać swoją pracę. Jeśli potrzebuje tylkoproductName
iprice
, powinien przyjąć tylko te dwa parametry, a nie cały obiekt.Ogólna odpowiedź jest taka, że logika biznesowa zwykle mieści się w dwóch kategoriach:
Logika biznesowa zorientowana obiektowo: jest modelowana jako obiekty (w modelu), zwykle wstrzykiwane jako repozytoria.
Proceduralna logika biznesowa: przechodzi do usługi z interfejsem, który można wstrzyknąć do kontrolera.
Logika kontrolera: Logika, która kontroluje, w jaki sposób polecenia są odbierane i przekazywane do modeli / usług, a następnie w jaki sposób te wyniki są przekazywane do widoku.
Kontrolery nie powinny mieć logiki biznesowej , jest to bardzo specyficzna część wzorca projektowego służąca do kontrolowania sposobu, w jaki interfejs użytkownika przekazuje dane wejściowe do modeli obsługujących logikę biznesową (lub usług, jeśli problemy mają charakter bardziej proceduralny).
źródło
Lubię również utrzymywać moje modele w czystości (ref: @Mark Walsh). Problem braku możliwości ponownego użycia logiki osadzonej w kontrolerach można łatwo rozwiązać poprzez wstrzyknięcie zależności lub, jeśli uważasz, że byłoby tego za dużo, ujawnij logikę biznesową / domenową za pośrednictwem interfejsów i użyj wzorca fasady w kontrolerach. W ten sposób uzyskasz potrzebną funkcjonalność, ale zarówno kontrolery, jak i model będą ładne i czyste.
źródło
Wolałbym również, aby modele były czyste. Kontrolery MVC powinny być używane tylko do wykonywania połączeń i powinny być również utrzymywane w czystości. Tak więc w zależności od możliwości ponownego wykorzystania, wrażliwości i trafności logika biznesowa może zostać zapisana
1. Kontroler WebApi: Zaletą korzystania z kontrolera webapi jest to, że możesz później udostępnić je jako usługi innym urządzeniom, dzięki czemu kod będzie można ponownie wykorzystać.
2. BAL / Commonent: Istnieją pewne logiki, które mają określone zastosowanie i nie mogą być ujawniane jako API, które mogą być wypychane w tej klasie.
3. Repozytorium: Wszystkie zapytania dotyczące bazy danych są dodawane do repozytorium. Może istnieć repozytorium ogólne, które będzie implementowało wszystkie funkcje (operacje CRUD) lub określone repozytoria dla każdej tabeli. W zależności od operacji do wykonania.
źródło
Jak napisał ahanusa, powinieneś umieścić swoją logikę biznesową w oddzielnej bibliotece DLL lub osobnym katalogu.
Często używam katalogu o nazwie Logika na tym samym poziomie modeli i kontrolerów, w którym umieszczam klasy obsługujące logikę biznesową.
W ten sposób wyczyściłem zarówno modele, jak i kontrolery.
źródło
Wiem, że chodzi o MVC, ale myślę, że podany przeze mnie przykład (Web API) będzie przydatny.
Tworzę mój pierwszy internetowy interfejs API i ponownie używam logiki biznesowej z innych aplikacji. Mówiąc dokładniej, pochodzi z zewnętrznej biblioteki DLL, więc moje API służy tylko do „rozmowy” z rozwiązaniem SAP, odbierania żądań z PO i wysyłania odpowiedzi z powrotem.
Jak mogę umieścić moją logikę (już zaimplementowaną) w kontrolerze? Nie potrzebuję tego. Mój kontroler będzie tylko odbierał, sprawdzał żądania i tworzył odpowiedzi w celu odesłania danych.
Pracuję z klasami ViewModel i wszystko, co muszą mieć, to funkcja mapowania, tylko po to, aby odczytać informacje z TransferObjects (które pochodzą z zewnętrznej biblioteki DLL) i przetłumaczyć na ViewModel.
Nie czuję się komfortowo, gdy moja aplikacja (w tym przypadku Web API) trzyma logikę biznesową, myślę, że w ten sposób utracona zostanie możliwość ponownego użycia.
Traktuję swoją logikę biznesową jako zależność, którą wstrzykuję do kontrolera.
Dokonałem wielu refaktoryzacji w przeszłości, aby zapewnić rozwiązanie do testowania jednostkowego, musiałem stworzyć wiele interfejsów i zaimplementować pewne wzorce projektowe do starszych wersji, aby zapewnić to rozwiązanie.
Z mojego punktu widzenia warstwa biznesowa musi znajdować się poza aplikacją, najlepiej w innej bibliotece klas. Dzięki temu w Twojej aplikacji zostanie wdrożona prawdziwa koncepcja separacji.
Oczywiście, jeśli CORE (biznes) to Twoja aplikacja (API / WebSite) , reguły biznesowe zostaną zaimplementowane w Twoich klasach MVC. Ale w przyszłości, jeśli będziesz chciał stworzyć nową aplikację, a niektóre reguły biznesowe będą takie same, założę się, że będziesz miał wiele problemów z utrzymaniem tej samej logiki zaimplementowanej w obu aplikacjach.
źródło