NULL Object Pattern (Special Case)

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.

6 thoughts on “NULL Object Pattern (Special Case)”

  1. 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
    }
    }

  2. 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?

  3. @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.

Leave a Reply

Your email address will not be published.