Wartość NULL w programowaniu stanowi specjalny przypadek. Jakiekolwiek operację na null spowodują wyrzucenie wyjątku. W pewnych przypadkach uzasadnione jest użycie obiektu zamiast zamiast klasycznych null. Stanowi to kolejny krok w stronę programowania obiektowego – tym razem nawet NULL jest obiektem.
Załóżmy, że na stronie internetowej możemy oceniać różne produkty i nasz dotychczasowy kod wygląda następująco:
Product product = repository.GetProductById(4); if( product != null) product.RateIt(userRating);
Zawsze musimy sprawdzać czy GetProductById nie zwrócił null. W przypadku NULL object pattern, tworzymy nowy obiekt dla wartości NULL:
abstract class ProductBase { public abstract void RateIt(int value); } class Product:ProductBase { public override RateIt(int value) { // aktualziacja oceny } } class NullProduct:ProductBase { public override RateIt(int value) { //do nothing } }
Teraz nie musimy już martwić się o NULL:
ProductBase product = repository.GetProductById(4); product.RateIt(userRating);
Oczywiście należy odpowiednio zaktualizować GetProductById aby zwracać NullProduct zamiast klasycznego null. Koniecznie w NullObject należy przeładować wszelkie metody i właściwości tak aby obiekt odróżniał się od prawdziwych obiektów.
Warto jednak zastanowić się czy NULL object pattern jest dobry dla danego scenariusza. Zauważyłem, że w niepoprawnym kodzie, często wyłącznie przykrywa problem. Jeśli w danym scenariuszu nie rozważamy NULL lepiej aby aplikacja wyrzuciła wyjątek niż działała dalej, ukrywając tym samym jakiś błąd. Dobrym zwyczajem jest również zaimplementowanie wzorca jako Singleton.
Hej, wydaje mi się, że tutaj powinno być:
ProductBase product = repository.GetProductById(4);
product.RateIt(userRating);
albo
class NullProduct:Product
{
public override RateIt(int value)
{
//do nothing
}
}
Racja. Poprawione, dzieki.
Pozdrawiam
Piotr
w ogóle to w tym przypadku to nawet lepszy by był interfejs 😉 ale to tam tylko szczegóły jeśli chodzi o przykład to daje radę.
Możesz w ogóle opisać w jakich miejscach i czemu tylko przykrywa błąd?
@nilphilus :
W przypadku produktu to duzo lepsza jest klasa abstrakcyjna niz interfejs poniewaz produkt to rowniez kupa danych – nie tylko zachowanie i prawdopodobnie bedzie czesc nieabstrakcyjna w takiej klasie.
A co do przykrywania. Zbyt czesto kod “dziala”, zaden wyjatek nie zostal wyrzucony itp a dopiero po jakims czasie okazuje sie ze cos nie dziala – np. ostatnio po bledach bindingu w WPF okazalo sie, ze tworzony zostal NullObject dla DataContext.
Parametr metody to typ prosty, w wypadku przekazania null pojawi sie blad