null
Użycie zależy od aplikacji / języka
Ostatecznie wybór, czy użyć null
jako prawidłowej wartości aplikacji, zależy w dużej mierze od twojej aplikacji i języka programowania / interfejsu / krawędzi.
Na poziomie podstawowym zaleciłbym próbę użycia różnych typów, jeśli istnieją różne klasy wartości. null
może być opcją, jeśli twój interfejs na to pozwala i istnieją tylko dwie klasy właściwości, które próbujesz reprezentować. Pominięcie właściwości może być opcją, jeśli pozwala na to Twój interfejs lub format. Nowy typ agregatu (klasa, obiekt, typ komunikatu) może być inną opcją.
Na przykład, jeśli jest to język programowania, zadam sobie kilka pytań.
- Czy planuję dodać przyszłe typy wartości? Jeśli tak,
Option
prawdopodobnie będzie lepiej dla twojego projektu interfejsu.
- Kiedy muszę sprawdzać poprawność połączeń od klientów? Statycznie? Dynamicznie? Przed? Po? W ogóle? Jeśli Twój język programowania obsługuje go, skorzystaj z zalet pisania statycznego, ponieważ pozwala to uniknąć ilości kodu, który musisz utworzyć w celu sprawdzenia poprawności.
Option
prawdopodobnie najlepiej wypełnia ten przypadek, jeśli ciąg nie ma wartości zerowej. Jednak prawdopodobnie i tak będziesz musiał sprawdzić dane wejściowe użytkownika pod kątem null
wartości ciągu, więc prawdopodobnie odłożę się z powrotem do pierwszego wiersza zapytania: ile typów wartości ma / chcę reprezentować.
- Czy
null
oznacza to błąd programisty w moim języku programowania? Niestety null
często jest domyślną wartością niezainicjowanych (lub nie zainicjowanych jawnie) wskaźników lub odniesień w niektórych językach. Czy null
jako wartość domyślna można zaakceptować wartość? Czy jest to wartość domyślna bezpieczna ? Czasami null
wskazuje na zwolnione wartości. Czy powinienem informować konsumentów mojego interfejsu o potencjalnych problemach z zarządzaniem pamięcią lub inicjalizacją w ich programie? Jaki jest tryb awarii takiego połączenia w obliczu takich problemów? Czy osoba dzwoniąca jest w tym samym procesie lub wątku co moja, więc takie błędy stanowią duże ryzyko dla mojej aplikacji?
W zależności od odpowiedzi na te pytania prawdopodobnie będziesz w stanie dopracować, czy null
Twój interfejs jest odpowiedni.
Przykład 1
- Twoja aplikacja ma kluczowe znaczenie dla bezpieczeństwa
- Używasz jakiegoś rodzaju inicjalizacji sterty podczas uruchamiania i
null
jest to możliwa wartość ciągu przekazywana z powrotem w przypadku nieprzydzielenia miejsca na ciąg.
- Istnieje potencjał, że taki ciąg uderzy w twój interfejs
Odpowiedź: null
prawdopodobnie nie jest właściwe
Uzasadnienie: null
w tym przypadku jest faktycznie używane do wskazania dwóch różnych typów wartości. Pierwsza może być wartością domyślną, którą użytkownik interfejsu może chcieć ustawić. Niestety druga wartość jest flagą wskazującą, że system nie działa poprawnie. W takich przypadkach prawdopodobnie chcesz zawieść tak bezpiecznie, jak to możliwe (cokolwiek to oznacza dla twojego systemu).
Przykład 2
- Używasz struktury C, która ma
char *
członka.
- Twój system nie korzysta z alokacji sterty i używasz sprawdzania MISRA.
- Twój interfejs przyjmuje tę strukturę jako wskaźnik i sprawdza, czy struktura nie wskazuje
NULL
- Domyślną i bezpieczną wartość
char *
członka dla twojego API można wskazać pojedynczą wartościąNULL
- Po zainicjowaniu struktury użytkownika, użytkownik chciałby zapewnić użytkownikowi możliwość nie jawnego inicjowania
char *
członka.
Odpowiedź: NULL
może być odpowiedni
Uzasadnienie: Istnieje niewielka szansa, że Twoja struktura przejdzie NULL
test, ale nie zostanie zainicjowana. Jednak Twój interfejs API może nie być w stanie to uwzględnić, chyba że masz jakąś sumę kontrolną wartości struktury i / lub sprawdzania zakresu adresu struktury. Lintery MISRA-C mogą pomóc użytkownikom interfejsu API, oznaczając użycie struktur przed ich inicjalizacją. Jednakże, tak jak w przypadku char *
elementu, jeśli wskaźnik do struct wskazuje na zainicjalizowaną strukturę, NULL
jest wartością domyślną nieokreślonego elementu w inicjalizatorze struktury. Dlatego NULL
może służyć jako bezpieczna, domyślna wartość dla elementu char *
struct w aplikacji.
Jeśli jest na interfejsie serializacji, zadałbym sobie następujące pytania dotyczące tego, czy użyć null w ciągu znaków.
- Czy
null
wskazuje na potencjalny błąd po stronie klienta? W przypadku JSON w JavaScript jest to prawdopodobnie nie, ponieważ null
niekoniecznie jest używany jako wskaźnik niepowodzenia alokacji. W JavaScript jest używany jako wyraźne wskazanie braku obiektu w referencji, która ma być problematycznie ustawiona. Istnieją jednak parsery i serializatory inne niż javascript, które mapują JSON null
na null
typ macierzysty . W takim przypadku rozpoczyna się dyskusja na temat tego, czy null
użycie natywne jest odpowiednie dla danego połączenia języka, analizatora składni i serializatora.
- Czy wyraźny brak wartości nieruchomości wpływa na więcej niż jedną wartość nieruchomości? Czasami a
null
oznacza, że masz całkowicie nowy typ wiadomości. Dla klientów korzystających z formatu serializacji może być czystsze określenie tylko zupełnie innego rodzaju komunikatu. Zapewnia to, że ich sprawdzanie poprawności i logika aplikacji mogą mieć czystą separację między dwoma wyróżnieniami komunikatów udostępnianymi przez interfejs sieciowy.
Ogólna rada
null
nie może być wartością na krawędzi lub interfejsie, który jej nie obsługuje. Jeśli używasz czegoś, co jest bardzo luźne w naturze przy wpisywaniu wartości właściwości (np. JSON), spróbuj wypchnąć jakąś formę schematu lub walidację w oprogramowaniu krawędziowym konsumenta (np. Schemat JSON ), jeśli możesz. Jeśli jest to interfejs API języka programowania, sprawdź poprawność wprowadzanych danych przez użytkownika, jeśli to możliwe (przez pisanie na klawiaturze) lub tak głośno, jak to możliwe w środowisku wykonawczym (czyli ćwicz programowanie obronne na interfejsach konsumenckich). Co ważne, udokumentuj lub zdefiniuj krawędź, aby nie było wątpliwości, czy:
- Jakie typy wartości przyjmuje dana właściwość
- Jakie zakresy wartości obowiązują dla danej właściwości.
- Jak powinna wyglądać typ agregatu. Jakie właściwości muszą / powinny / mogą występować w typie agregującym?
- Jeśli jest to jakiś rodzaj kontenera, ile przedmiotów może lub powinien pomieścić pojemnik i jakie są wartości tego pojemnika?
- Jakie zamówienie, jeśli w ogóle, jest zwracane właściwości lub wystąpienia typu kontenera lub agregatów?
- Jakie są skutki uboczne ustalania określonych wartości i jakie są skutki uboczne odczytywania tych wartości?