Czytam książkę „Learning TypeScript” Remo Jansena. W jednej sekcji autor opisuje, jak stworzyć bardzo prosty framework MVC typu proof-of-concept, w tym jak stworzyć Model
klasę i mówi:
Do modelu należy podać adres URL usługi internetowej, z której korzysta. Użyjemy dekoratora klasy o nazwie ModelSettings, aby ustawić adres URL usługi, która ma być używana. Możemy wstrzyknąć adres URL usługi za pośrednictwem konstruktora, ale uważa się za złą praktykę wstrzykiwanie danych (w przeciwieństwie do zachowania) za pomocą konstruktora klasy .
Nie rozumiem tego ostatniego zdania. W szczególności nie rozumiem, co to znaczy „wstrzykiwać dane”. Wydaje mi się, że w prawie wszystkich wprowadzeniach do klas JavaScript wykorzystujących zbyt uproszczone przykłady dane są wprowadzane („wstrzykiwane”?) Do konstruktora za pomocą jego parametrów. Na przykład:
class Person {
constructor(name) {
this.name = name;
}
}
Z pewnością myślę o name
danych, a nie o zachowaniu, i są one powszechnie zawarte w tym przykładzie jako parametr konstruktora, i nigdy nie ma wzmianki, że jest to zła praktyka. Zakładam więc, że nie rozumiem czegoś w powyższym cytacie, co oznacza „dane”, „zastrzyk” lub coś innego.
Twoje odpowiedzi mogą zawierać wyjaśnienia, kiedy, gdzie, jak i dlaczego używać dekoratorów w JavaScript / TypeScript, ponieważ mocno podejrzewam, że ta koncepcja jest ściśle związana ze zrozumieniem, którego szukam. Co ważniejsze, chcę bardziej ogólnie zrozumieć, co oznacza wstrzykiwanie danych za pomocą konstruktora klas i dlaczego jest to złe.
Aby dać więcej kontekstu powyższemu cytatowi, taka jest sytuacja: Model
tworzona jest klasa, która w tym przykładzie zostanie wykorzystana do stworzenia modeli giełdowych, jednej dla NASDAQ i jednej dla NYSE. Każdy model wymaga ścieżki usługi sieciowej lub pliku danych statycznych, który dostarczy surowych danych. Książka stwierdza, że do tych informacji należy użyć dekoratora, a nie parametru konstruktora, co prowadzi do:
@ModelSettings("./data/nasdaq.json")
class NasdaqModel extends Model implements IModel {
constructor(metiator : IMediator) {
super(metiator);
}
...
}
Po prostu nie rozumiem, dlaczego powinienem dodawać adres usługi za pośrednictwem dekoratora, a nie tylko jako parametr dla konstruktora, np.
constructor(metiator : IMediator, serviceUrl : string) {...
źródło
Odpowiedzi:
Dam autorowi wątpliwość i być może tak właśnie wygląda maszynopis, ale w innych środowiskach jest to całkowicie bezpodstawne twierdzenie, którego nie należy brać na poważnie.
Z czubka głowy potrafię wymyślić różne sytuacje, w których przekazywanie danych przez konstruktor jest dobre, niektóre neutralne, ale żadne nie jest złe.
Jeśli konkretna klasa zależy od określonego elementu danych, aby być w prawidłowym stanie i działać poprawnie, sensowne jest żądanie tych danych w konstruktorze. Klasa reprezentująca port szeregowy może przyjąć nazwę portu, obiekt pliku może wymagać nazwy pliku, rysunku obszaru roboczego wymagającego jego rozdzielczości itp. O ile nie przekazujesz danych do konstruktora, możliwe jest, że obiekt może mieć nieprawidłowy stan, który należy obserwować i sprawdzać. W przeciwnym razie możesz sprawdzić tylko przy tworzeniu instancji obiektu, a następnie przyjąć, że działa on w przeważającej części. Autorzy twierdzą, że ta korzystna sytuacja jest niemożliwa.
Dodatkowo decyzja o zakazie przekazywania danych w konstruktorze uniemożliwia praktycznie wszystkie niezmienne obiekty. Niezmienne obiekty mają wiele zalet w wielu sytuacjach, a wszystkie z nich zostałyby wyrzucone zgodnie z polityką autora.
Nawet jeśli zmienne obiekty są tym, czego chcesz, jaka jest ta zła praktyka:
na rzecz:
Czy autor naprawdę uważa, że pierwszy to zła praktyka i zawsze powinienem wybierać opcję 2? Myślę, że to szalona rozmowa.
Ponieważ więc nie mam tej książki i nie przeczytałbym jej, nawet gdybym ją miał, z dużym podejrzeniem przeglądałbym to stwierdzenie i prawie wszystkie ogólne stwierdzenia w nim zawarte.
źródło
Myślę, że to zależy od kontekstu, jaki model jest tutaj omawiany. Nie mam książki Remo, ale sądzę, że model jest rodzajem modelu usługi, który musi pobierać dane ze zdalnej usługi internetowej. W takim przypadku, będąc modelem usługi sieciowej, lepiej przekazać wszystkie dane wymagane jako argumenty w metodach usługi sieciowej, co czyni usługę bezstanową.
Usługa bezstanowa ma kilka zalet, na przykład każdy, kto czyta wywołanie metody usługi, nie musi wyszukiwać, gdy usługa jest zbudowana, aby poznać szczegóły wywoływanej usługi. Wszystkie szczegóły są przedstawione w argumentach używanych w wywołaniu metody (oprócz zdalnego adresu URL).
źródło
Tylko zgaduję.
Gdybym usłyszał „wstrzykiwanie zachowania, a nie danych”, pomyślałbym, zamiast robić to:
(Przepraszamy za przykład w pseudokodzie):
Aby to zrobić:
W ten sposób możesz zawsze zmienić zachowanie hałasu, ustawić go losowo, zależnie od jednej zmiennej wewnętrznej ...
Myślę, że chodzi tu o zasadę „faworyzuj kompozyt nad dziedziczenie”. To wspaniała zasada, muszę powiedzieć.
NIE OZNACZA to, że nie można „wstrzyknąć” nazwy do obiektu „Osoba”, oczywiście, ponieważ ta nazwa jest wyłącznie danymi biznesowymi. Ale na przykład, że dajesz, usługę internetową, adres URL jest coś trzeba wygenerować coś jakoś , która łączy usługi. To w jakiś sposób jest zachowanie: jeśli wstrzykujesz adres URL, wstrzykujesz „dane” niezbędne do zbudowania „zachowania”, więc w takim przypadku lepiej jest zrobić zachowanie na zewnątrz i wstrzyknąć je gotowe do użycia: Zamiast tego wstrzyknij adres URL użyteczne połączenie lub użyteczny konstruktor połączeń.
źródło