Powiedzmy, że chcę pokazać formularz, który reprezentuje 10 różnych obiektów na comboboxie. Na przykład chcę, aby użytkownik wybrał jednego hamburgera spośród 10 różnych zawierających pomidory.
Ponieważ chcę oddzielić interfejs użytkownika od logiki, musiałbym przekazać formularz reprezentujący ciąg hamburgerów w celu wyświetlenia ich na comboboxie. W przeciwnym razie interfejs użytkownika musiałby wkopać się w pola obiektów. Następnie użytkownik wybiera hamburguera z opakowania zbiorczego i przesyła go z powrotem do kontrolera. Teraz kontroler musiałby ponownie znaleźć wspomnianego hamburguera na podstawie reprezentacji łańcucha używanej przez formularz (może identyfikator?).
Czy to nie jest niewiarygodnie nieefektywne? Masz już przedmioty, z których chciałeś wybrać jeden. Jeśli przesłałeś do formularza całe obiekty, a następnie zwróciłeś określony obiekt, nie będziesz musiał go później odnawiać, ponieważ formularz już zwrócił odwołanie do tego obiektu.
Co więcej, jeśli się mylę i rzeczywiście powinieneś wysłać cały obiekt do formularza, jak mogę odizolować interfejs od logiki?
Odpowiedzi:
Po pierwsze, podany przez ciebie przykład nie jest niewiarygodnie nieefektywny; jest tylko nieznacznie nieefektywny; jego nieefektywność jest poniżej wyczuwalnego poziomu. Ale w każdym razie przejdźmy do pytania.
W moim rozumieniu, kiedy mówimy o oddzieleniu interfejsu użytkownika od logiki , mamy na myśli unikanie ścisłego sprzężenia .
Bliskie sprzężenie odnosi się do sytuacji, w której interfejs użytkownika zna (i wywołuje) logikę, a logika zna (i wywołuje) interfejs użytkownika. Aby uniknąć ścisłego połączenia, nie trzeba całkowicie rezygnować z połączenia. (Wydaje się, że celem tego jest wyburzenie interfejsu między nimi do interfejsu łańcucha znaków o najmniejszym wspólnym mianowniku.) Wystarczy zastosować luźne sprzęganie .
Luźne sprzężenie oznacza, że A zna B, ale B nie zna A. Innymi słowy, obie zaangażowane strony odgrywają różne role klienta i serwera , gdzie klient zna serwer, ale serwer nie zna klienta.
W przypadku interfejsu użytkownika i logiki najlepszym sposobem na zaaranżowanie tego jest moim zdaniem logika jako serwer, a interfejs użytkownika jako klient. Tak więc interfejs użytkownika jest zbudowany dla logiki, ma wiedzę na temat logiki i wywołuje logikę, podczas gdy logika nie wie nic o interfejsie użytkownika i po prostu odpowiada na otrzymane żądania. (I te żądania zdarzają się z interfejsu użytkownika, ale logika tego nie wie).
Mówiąc prościej, nigdzie w plikach kodu źródłowego logiki nie powinny znajdować się instrukcje dołączania / importu / używania, które odnoszą się do plików interfejsu użytkownika, podczas gdy pliki kodu źródłowego interfejsu użytkownika będą pełne dołączania / importu / używania instrukcje odnoszące się do plików logicznych.
Tak więc, aby wrócić do twojej sprawy, nie ma absolutnie nic złego w tym, że kod interfejsu użytkownika wypełniający pole kombi wie o klasie hamburgerów. Byłoby problem, gdyby klasa hamburgerów wiedziała coś o pudełkach kombinowanych.
Nawiasem mówiąc, ta konstrukcja pozwala na kolejną rzecz, której powinieneś oczekiwać od takiego systemu: powinna być możliwość podłączenia dowolnej liczby interfejsów użytkownika do logiki, a całość powinna nadal działać.
źródło
Należy oddzielić każdy element modelu, widoku i kontrolera, ale nie ma powodu, dla którego nie można (na przykład) przekazywać obiektów modelu między kontrolerem a widokiem.
W twoim przypadku
Hamburger
obiekty byłyby częścią Modelu. Następnie użyj kontrolera, aby pobrać wymaganą listęHamburger
s i przekazać te obiekty do widoku (combobox) w celu wyświetlenia. Gdy użytkownik wybierze hamburgera, możesz ponownie przekazaćHamburger
obiekt do kontrolera w celu przetworzenia.Chodzi o to, że nadal możesz testować jednostkowo
Hamburger
logikę „fetch s” i logikę „procesHamburger
” oddzielnie od rzeczywistego wyświetlania hamburgerów.źródło