Temat: Połączenie z bazą
No i tutaj jest problem, operacje B, C, D zaleza bezposrednio od operacji A. Context stal sie globalnym namespace'm, a kontrola jego poprawnosci zrzucona zostala na kod wywolujacy (to jest anty-pattern). To bardzo niebezpieczna praktyka.
Dokładnie tak. W przykładzie który podałeś:
MHO context objects sa bardziej niebezpieczne niz singleton, wyobraz sobie prosty przyklad gdy kontrakty wywoluja sie nawzajem A->B->C->D.
Cały łańcuch B, C, D jest zależny od A.
Ale w przypadku kontekstu, nie jest globalnym namespace, z tego względu, że dostęp do niego mają tylko A, B, C i D (czyli tylko te komponenty, którym przekażę ten obiekt) a E już nie ma dostępu - co czyni go nieglobalnym.
Kontrola poprawności jest zrzucana na obiekt wywołujący, który wywołuję inne elementy systemu. To prawda. To jest IoC, IoC nie jest anty-patternem.
Twoj przyklad z context'em bedzie mial duzo gorsze skutki w systemie, bo kod wywolywany nie tylko zalezy od stanu obiektu, ale rowniez od poprzednich "budowniczych".
Z tym, że po każdym z "budowniczych" jestem w stanie sprawdzić czy dalej jest poprawny i odpowiednio zareagować w przypadku kiedy by nie był poprawny.
/->C \
O -> A -> B -> E
\->D /
O, jest obiektem który budujemy i staramy się opakować w singleton albo kontekst. W przypadku kiedy jest to obiekt kontekstowy i kontrolę nad tym ma system, możemy po wykonaniu B sprawdzić stan obiektu i zastosować strategię awaryjną i np. przekazać go co C a w przypadku kiedy jest poprawny przekazujemy go do D.
W takiej konfiguracji, C i D nie muszą wiedzieć o swoim istnieniu, tak samo jak i reszta obiektów. Więc D nie musi sprawdzać czy O jest poprawny i wysyłać go do C jeśli nie, bo zrobi to za niego system.
Nie możesz zakładać, że osoba pisząca komponent D będzie na tyle sprytna żeby zaimplementować strategię awaryjną. Ta osoba może być nowa w projekcie i nie wiedzieć jeszcze, że jest C, że trzeba tam to przekierować a tak, to tylko zaimplementuję funkcjonalność D (przy podstawowej weryfikacji wartości O) i ma zadanie wykonane.
W przypadku singletona, komponenty musza wiedzieć o całej reszcie systemu i je uwzględniać co niepotrzebnie zwiększa powiązania pomiędzy klasami a dodatkowo i tak każde wywołanie zależy od poprzednich (tego nie przeskoczymy w żadnym modelu, można jedynie nad tym sprytnie zapanować).
To jest koncepcyjny problem, z kontekstu zrobiles globalna przestrzen nazw. To zdecydowanie anty-pattern, a singleton nie ma tu nic do rzeczy.
J/w. Dodatkowo, Singletonowi bliżej do zmiennych globalnych. Nie ma sposobu na dokładną kontrolę tego kto ma do niego dostęp.
Tak, sprawdzam zawsze czy Request jest nullem, ale kazdy element jest opakowany w implementacje zalezne od platformy.
Zobacz:
http://msdn.microsoft.com/en-us/library/ms178472.aspx
Sprawdzanie w Page.Load czy Request jest nullem jest bez sensu (nigdy nie będzie) dlatego, że ASP.NET nie dopuści do wykonania tego kroku jeśli te założenie nie jest spełnione. Właśnie o takim czymś mówię, przekazywanie piłeczki dalej do kolejnych kroków.
Budowanie kontekstow jest bardzo ciezko testowalne, czesto praktycznie niewykonalne. Powod jest prozaiczny, nie jestes w stanie przewidziec jak A, B i C dokladaja sie do kontekstu. W praktyce musisz testowac mockami, a to jak wiemy najprzyjemniejsze (najszybsze) nie jest.
Nie ma problemu z Mockami, używam TypeMock do tego i jest to bardzo proste. (Inne frameworki Mocków też ułatwiają mockowanie).
Za to, wiem, że kolejne unit testy nie wpłyną mi na stan obiektu kontekstowego. W przypadku Singletona trudniej nad tym zapanować.
I wręcz przeciwnie, w przypadku obiektu kontekstowego, jestem w stanie tak spreparować obiekt kontekstu w przypadku unit testów aby symulować poprawną kolejność wykonania komponentów. Tym sposobem poprawnie testuję obiekty przez to, że testuję tylko jeden czynnik, zamrażając pozostałe.
Ogólnie dzięki za fajną wymianę zdań :)
Raczej nikt z nas drugiego nie przekona ale przynajmniej będzie co poczytać jak ktoś wejdzie na to forum zastanawiając się jak zbudować system. Będzie miał porównanie dwóch różnych podejść do problemu.
Pozdrawiam