Użyj pustego ciągu, zeruj lub usuń pustą właściwość w żądaniu / odpowiedzi API


25

W przypadku przesyłania obiektu przez interfejs API, jak w formacie JSON bez schematu, jaki jest idealny sposób na zwrócenie nieistniejącej właściwości ciągu? Wiem, że można to zrobić na różne sposoby, jak w przykładach w wymienionych poniżej linkach.

Jestem pewien, że w przeszłości używałem wartości null, ale nie mam dobrego powodu, aby to robić. Używanie wartości null w przypadku bazy danych wydaje się proste. Baza danych wydaje się jednak szczegółem implementacji, który nie powinien dotyczyć strony po drugiej stronie interfejsu API. Np. Prawdopodobnie używają magazynu danych bez schematu, który przechowuje tylko właściwości z wartościami (inne niż null).

Z punktu widzenia kodu ograniczenie funkcji łańcuchowych do pracy tylko z jednym typem, tj. string(Nie zerowym), ułatwia ich sprawdzenie; unikanie wartości null jest również powodem posiadania Optionobiektu. Więc jeśli kod, który generuje żądanie / odpowiedź nie używa wartości null, domyślam się, że kod po drugiej stronie interfejsu API nie będzie zmuszony do używania wartości null.

Raczej podoba mi się pomysł użycia pustego łańcucha jako łatwego sposobu na uniknięcie wartości null. Jednym argumentem, który usłyszałem o użyciu wartości null i przeciwko pustemu ciągowi jest to, że pusty ciąg oznacza, że ​​właściwość istnieje. Chociaż rozumiem różnicę, zastanawiam się również, czy jest to tylko szczegół implementacji i czy użycie pustego lub pustego łańcucha robi jakąkolwiek rzeczywistą różnicę. Zastanawiam się także, czy pusty ciąg znaków jest analogiczny do pustej tablicy.

Więc jaki jest najlepszy sposób rozwiązania tych problemów? Czy zależy to od formatu przesyłanego obiektu (schemat / schemat)?


2
Zauważ też, że Oracle traktuje puste łańcuchy i łańcuchy zerowe w ten sam sposób. I właśnie są: w kwestionariuszu papierowym, jak odróżnić brak odpowiedzi od odpowiedzi składającej się z pustego ciągu?
Bernhard Hiller

Jeśli używasz dziedziczenia, łatwo jest powiedzieć: if( value === null) { use parent value; } Jeśli jednak ustawisz wartość podrzędną, nawet na pusty ciąg znaków (np. Zastąpisz domyślną wartość nadrzędną spacją), to w jaki sposób „ponownie odziedziczysz” tę wartość? Dla mnie ustawienie wartości null oznaczałoby „odznacz tę wartość, abyśmy wiedzieli, że należy użyć wartości nadrzędnej”.
Frank Forte,

Ponieważ „Usuń pustą właściwość” jest również powodem „unikania” a null(prawdą jest, że nulljest to omijane jako takie), pytający oznacza „Zwróć wartość inną niż null” [Obiekt] (tj .: pusty ciąg, pusta tablica itp.), Gdy napisz „unikaj”.
cellepo

Odpowiedzi:


18

TLDR; Usuń właściwości null

Pierwszą rzeczą, o której należy pamiętać, jest to, że aplikacje na ich brzegach nie są obiektowe (ani funkcjonalne, jeśli programują w tym paradygmacie). Otrzymany JSON nie jest przedmiotem i nie powinien być traktowany jako taki. To tylko uporządkowane dane, które mogą (ale nie muszą) przekształcić w obiekt. Zasadniczo żaden przychodzący JSON nie powinien być zaufany jako obiekt biznesowy, dopóki nie zostanie zweryfikowany jako taki. Sam fakt, że został zdezrializowany, nie czyni go ważnym. Ponieważ JSON ma również ograniczone prymitywy w porównaniu do języków zaplecza, często warto utworzyć DTO z dopasowaniem JSON dla danych przychodzących. Następnie użyj DTO, aby zbudować obiekt biznesowy (lub próbę błędu) w celu uruchomienia operacji API.

Gdy patrzysz na JSON jako na format transmisji, sensowniejsze jest pominięcie właściwości, które nie są ustawione. Przesyłanie za pośrednictwem drutu jest mniejsze. Jeśli Twój język zaplecza nie używa domyślnie wartości NULL, prawdopodobnie możesz skonfigurować swój deserializator tak, aby wyświetlał błąd. Na przykład moja wspólna konfiguracja dla Newtonsoft.Json tłumaczy wartości null / brakujące właściwości optiontylko na typy F # i w przeciwnym razie wystąpi błąd. Daje to naturalną reprezentację, które pola są opcjonalne (te z optiontypem).

Jak zawsze uogólnienia prowadzą do tej pory. Prawdopodobnie zdarzają się przypadki, w których właściwość domyślna lub null pasuje lepiej. Ale kluczem nie jest spojrzenie na struktury danych na brzegu systemu jako obiekty biznesowe. Obiekty biznesowe powinny mieć gwarancje biznesowe (np. Podać co najmniej 3 znaki) po pomyślnym utworzeniu. Ale struktury danych oderwane od drutu nie mają żadnych rzeczywistych gwarancji.


3
Chociaż większość współczesnych serializatorów ma pola opcjonalne, pominięcie wartości zerowych w odpowiedzi nie zawsze jest dobrym pomysłem, ponieważ może wprowadzić dodatkową złożoność do obsługi pól zerowalnych. Dlatego tak naprawdę zależy to od wielkości liter , w zależności od tego, jak biblioteka serializacji obsługuje wartości zerowe, oraz czy (potencjalna) dodatkowa złożoność obsługi tych wartości zerowych jest naprawdę warta zaoszczędzenia kilku bajtów na żądanie. Musisz ciężko pracować, aby przeanalizować swoje sprawy biznesowe.
Chris Cirefice

@ChrisCirefice Tak, uważam, że ostatni akapit to opisuje. Są przypadki, w których lepiej będzie zastosować różne strategie.
Kasey Speakman

Zgadzam się, że JSON jest używany tylko jako format transmisji, nie przepuszcza on obiektu przez przewody takie jak CORBA. Zgadzam się również, że właściwości można dodawać i usuwać; reprezentacje mogą się zmieniać, kontrolki mogą się zmieniać, szczególnie w Internecie.
imel96

15

Aktualizacja: Trochę zredagowałem odpowiedź, ponieważ mogła prowadzić do zamieszania.


Przejście z pustym ciągiem jest definitywnym „nie”. Pusty ciąg nadal jest wartością, jest po prostu pusty. Brak wartości należy oznaczyć przy konstrukt, który reprezentuje niczego null.

Z punktu widzenia dewelopera API istnieją tylko dwa typy właściwości:

  • wymagane (MUSZĄ mieć wartość określonego typu i NIE MUSZĄ być nigdy puste),
  • opcjonalne (MOGĄ zawierać wartość określonego typu, ale MOGĄ również zawierać null.

To wyjaśnia, że ​​gdy właściwość jest obowiązkowa, tj. wymagane, nigdy nie będzie null.

Z drugiej strony, jeśli opcjonalna właściwość obiektu nie zostanie ustawiona i pozostanie pusta, wolę zachować je w odpowiedzi i tak z nullwartością. Z mojego doświadczenia ułatwia klientom API implementowanie analizy składniowej, ponieważ nie są oni zobowiązani do sprawdzania, czy właściwość faktycznie istnieje, czy nie, ponieważ zawsze tam jest, i mogą po prostu przekonwertować odpowiedź na niestandardowe DTO, traktując nullwartości jako opcjonalne.

Dynamiczne włączanie / usuwanie pól z sił odpowiedzi, w tym dodatkowe warunki na klientach.


Tak czy inaczej, niezależnie od tego, który wybierzesz, upewnij się, że jest spójny i dobrze udokumentowany. W ten sposób tak naprawdę nie ma znaczenia, czego używasz w interfejsie API, o ile zachowanie jest przewidywalne.


Tak, pusty ciąg znaków jest wartością i używam go nulldo odwołań. Jednym z moich problemów jest mieszanie wartości z referencjami. Jak odróżnić pola opcjonalne nullod nie opcjonalnych pól łańcuchowych o nullwartości? Parsując, czy nie testowanie istnienia właściwości powoduje, że parser jest bardziej delikatny?
imel96

2
@ imel96 Opcjonalne pola NIGDY nie mogą mieć wartości NULL. Jeśli coś nie jest opcjonalne, MUSI zawsze zawierać wartość (określonego typu).
Andy,

3
To. Jako częsty konsument interfejsów API, nienawidzę, gdy mam do czynienia z „dynamicznymi” strukturami, które do mnie wracają, nawet jeśli jest to opcjonalne pominięcie pola. (również zgodzili się, że istnieje duża różnica między ZLS a Null). Z radością przyjmuję wartości zerowe przez cały dzień. Jako autor interfejsu API jednym z moich celów jest sprawienie, aby zużycie klienta było jak najbardziej bezbolesne, a to oznacza zawsze posiadanie oczekiwanych struktur danych.
jleach

@DavidPacker, więc jeśli dobrze rozumiem, możesz nullpodać, że wartość jest opcjonalna. Tak więc, gdy zdefiniujesz obiekt, który ma nie opcjonalną właściwość ciągu, a konsument nie ma tej właściwości, musi wysłać pusty ciąg dla tej właściwości. Czy to prawda?
imel96

2
@GregoryNisbet Nie rób tego, proszę. To nie ma sensu.
Andy,

3

null Użycie zależy od aplikacji / języka

Ostatecznie wybór, czy użyć nulljako 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. nullmoż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ń.

  1. Czy planuję dodać przyszłe typy wartości? Jeśli tak, Optionprawdopodobnie będzie lepiej dla twojego projektu interfejsu.
  2. 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. Optionprawdopodobnie 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 nullwartości ciągu, więc prawdopodobnie odłożę się z powrotem do pierwszego wiersza zapytania: ile typów wartości ma / chcę reprezentować.
  3. Czy nulloznacza to błąd programisty w moim języku programowania? Niestety nullczęsto jest domyślną wartością niezainicjowanych (lub nie zainicjowanych jawnie) wskaźników lub odniesień w niektórych językach. Czy nulljako wartość domyślna można zaakceptować wartość? Czy jest to wartość domyślna bezpieczna ? Czasami nullwskazuje 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 nullTwój interfejs jest odpowiedni.

Przykład 1

  1. Twoja aplikacja ma kluczowe znaczenie dla bezpieczeństwa
  2. Używasz jakiegoś rodzaju inicjalizacji sterty podczas uruchamiania i nulljest to możliwa wartość ciągu przekazywana z powrotem w przypadku nieprzydzielenia miejsca na ciąg.
  3. Istnieje potencjał, że taki ciąg uderzy w twój interfejs

Odpowiedź: nullprawdopodobnie nie jest właściwe

Uzasadnienie: nullw 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

  1. Używasz struktury C, która ma char *członka.
  2. Twój system nie korzysta z alokacji sterty i używasz sprawdzania MISRA.
  3. Twój interfejs przyjmuje tę strukturę jako wskaźnik i sprawdza, czy struktura nie wskazuje NULL
  4. Domyślną i bezpieczną wartość char *członka dla twojego API można wskazać pojedynczą wartościąNULL
  5. Po zainicjowaniu struktury użytkownika, użytkownik chciałby zapewnić użytkownikowi możliwość nie jawnego inicjowania char *członka.

Odpowiedź: NULLmoże być odpowiedni

Uzasadnienie: Istnieje niewielka szansa, że ​​Twoja struktura przejdzie NULLtest, 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ę, NULLjest wartością domyślną nieokreślonego elementu w inicjalizatorze struktury. Dlatego NULLmoż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.

  1. Czy nullwskazuje na potencjalny błąd po stronie klienta? W przypadku JSON w JavaScript jest to prawdopodobnie nie, ponieważ nullniekoniecznie 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 nullna nulltyp macierzysty . W takim przypadku rozpoczyna się dyskusja na temat tego, czy nullużycie natywne jest odpowiednie dla danego połączenia języka, analizatora składni i serializatora.
  2. Czy wyraźny brak wartości nieruchomości wpływa na więcej niż jedną wartość nieruchomości? Czasami a nulloznacza, ż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

nullnie 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?

1

Oto moja osobista analiza tych pytań. Nie jest poparta żadną książką, papierem, opracowaniem czy czymkolwiek innym, tylko moim osobistym doświadczeniem.

Puste ciągi jak null

To dla mnie nie do przyjęcia. Nie mieszaj semantyki pustych łańcuchów z tymi, które nie są zdefiniowane. W wielu przypadkach mogą one być idealnie wymienne, ale możesz natknąć się na przypadki, w których niezdefiniowane i zdefiniowane-ale-puste oznaczają coś innego.

Głupi przykład: powiedzmy, że istnieje atrybut, który przechowuje klucz obcy, a ten atrybut nie jest zdefiniowany lub jest null, co oznaczałoby, że nie ma zdefiniowanej relacji, podczas gdy pusty ciąg ""może być rozumiany jako zdefiniowana relacja i Identyfikatorem zagranicznego rekordu jest ten pusty ciąg.

Nie zdefiniowano vs null

To nie jest czarny lub biały temat. Oba podejścia mają wady i zalety.

Na rzecz jednoznacznego zdefiniowania nullwartości istnieją następujące zalety:

  • Wiadomości są bardziej opisowe, ponieważ poznaje się wszystkie klucze, patrząc na dowolną wiadomość
  • W związku z poprzednim punktem łatwiej jest kodować i wykrywać błędy w odbiorcy danych: łatwiej jest wykryć błędy, jeśli pobierzesz niewłaściwe klucze (być może błędy ortograficzne, może zmieniony interfejs API itp.).

Za przyjęciem nieistniejącego klucza odpowiada semantyka null:

  • Niektóre zmiany są łatwiejsze do zaakceptowania. Na przykład, jeśli nowa wersja schematu komunikatu zawiera nowy klucz, możesz zakodować konsumenta informacji, aby pracował z tym przyszłym kluczem, nawet jeśli producent wiadomości nie został zaktualizowany i nie obsługuje jeszcze tych informacji.
  • Wiadomości mogą być mniej szczegółowe lub krótsze

W przypadku, gdy interfejs API jest w jakiś sposób stabilny i dokładnie go udokumentujesz, myślę, że można całkowicie stwierdzić, że nieistniejący klucz jest równy znaczeniu null. Ale jeśli jest bardziej chaotyczny i chaotyczny (jak to często bywa), myślę, że możesz uniknąć bólów głowy, jeśli wyraźnie zdefiniujesz każdą wartość w każdej wiadomości. Tj. W razie wątpliwości staram się podążać za podejściem pełnym.

To powiedziawszy, najważniejsza rzecz: jasno określ swoje intencje i bądź konsekwentny. Nie rób jednej rzeczy tutaj, a drugiej tam. Oprogramowanie przewidywalne to lepsze oprogramowanie.


Przykład użycia pustych ciągów jest tym, co rozumiem przez szczegół implementacji, tj. Zakładając, że interfejs API jest używany do wyświetlania wierszy bazy danych. Czy zrobi to różnicę, jeśli nie będzie dotyczyła bazy danych i służyłaby wyłącznie do przesyłania reprezentacji obiektów?
imel96

Nie musi to być szczegół implementacji. Mój przykład faktycznie mówi o PK powiązanych z DB, ale starałem się wyjaśnić, że pusty ciąg nie ma wartości zero / nic / null. Kolejny przykład: w grze istnieje obiekt postaci i atrybut „partner”. nullPartnerem wyraźnie oznacza, że nie ma partnera w ogóle, ale ""można zrozumieć, ponieważ nie jest partnerem, którego nazwa jest "".
bgusach

Nie przeszkadza mi to, że odwołanie do partnera jest zerowe, oznacza to, że nie ma partnera, a odwołanie nie jest łańcuchem. Ale nazwa partnera jest łańcuchem, nawet jeśli dopuszczasz null jako nazwę partnera, czy nie złapałbyś tego null i zastąpiłbyś go pustym łańcuchem w pewnym momencie?
imel96

Jeśli nie ma partnera, nie zmieniłbym nullna pusty ciąg. Może renderowanie w formie, ale nigdy w modelu danych.
bgusach

Nie miałem na myśli żadnego partnera, partner byłby przedmiotem. To partner name, o którym mówiłem. Czy pozwoliłbyś, aby nazwa partnera była zerowa?
imel96

1

Podałbym pusty ciąg w sytuacji, gdy łańcuch jest obecny, a zdarza się, że jest to pusty ciąg. Podałbym wartość null w sytuacji, w której chcę wyraźnie powiedzieć „nie, tych danych nie ma”. I pomiń klucz, aby powiedzieć „brak danych, nie przejmuj się”.

Ty oceniasz, która z tych sytuacji może się zdarzyć. Czy ma sens, aby Twoja aplikacja miała puste ciągi znaków? Czy chcesz rozróżnić między jawnym mówieniem „brak danych” przy użyciu wartości null i domyślnie przez brak wartości? Powinieneś mieć obie możliwości (zero i brak klucza) tylko wtedy, gdy klient musi je rozróżnić.

Teraz pamiętaj, że chodzi o przesyłanie danych. Odbiorca robi z danymi swoją działalność i zrobi to, co jest dla nich najwygodniejsze. Odbiornik powinien być w stanie obsłużyć wszystko, co na niego rzucisz (być może poprzez odrzucenie danych) bez awarii.

Jeśli nie ma żadnych innych względów, przesyłam to, co jest najwygodniejsze dla nadawcy, i dokumentuję to. Wolałbym wcale nie wysyłać nieobecnych wartości, ponieważ prawdopodobnie poprawi to szybkość kodowania, przesyłania i analizowania JSON.


Podoba mi się twój punkt w „jeśli klient chce go odróżnić”.
imel96

0

Chociaż nie mogę powiedzieć, co jest najlepsze , prawie na pewno nie jest to prosty szczegół implementacji , zmienia on strukturę interakcji z tą zmienną.

Jeśli coś może mieć wartość NULL , powinieneś zawsze traktować to tak, jakby w pewnym momencie miało ono wartość NULL , więc zawsze będziesz mieć dwa przepływy pracy , jeden dla wartości NULL i jeden dla prawidłowego ciągu. Podzielony przepływ pracy niekoniecznie jest złą rzeczą, ponieważ istnieje całkiem sporo obsługi błędów i specjalnych przypadków, które można wykorzystać, ale powoduje to zaciemnienie kodu.

Jeśli zawsze będziesz wchodził w interakcje z ciągiem w ten sam sposób , prawdopodobnie funkcjonalność pozostanie w twojej głowie .

Podobnie jak w przypadku każdego pytania „co jest najlepsze”, pozostaje mi odpowiedź: to zależy . Jeśli chcesz podzielić przepływ pracy i wyraźniej uchwycić, gdy coś nie jest ustawione, użyj null. Jeśli wolisz, aby program nadal działał tak, jak robi, użyj pustego ciągu. Ważne jest, abyś był konsekwentny , wybierał wspólny zwrot i trzymał się tego.

Biorąc pod uwagę, że tworzysz interfejs API, zalecałbym trzymanie się pustego ciągu, ponieważ użytkownik ma mniej do zrekompensowania, ponieważ jako użytkownik interfejsu API nie znam wszystkich powodów, dla których interfejs API może dać mi wartość zerową, chyba że „ są bardzo dobrze udokumentowane, czego niektórzy użytkownicy i tak nie przeczytają.


„Podział przepływu pracy” jest zły. Powiedzmy, że po stronie producenta wszystko jest czyste, metody typu string zwracają tylko strings, nigdy null. Jeśli interfejs API używa wartości null, to w pewnym momencie producent musi go utworzyć, nullaby był zgodny z interfejsem API. Wtedy konsument też musi się tym zająć null. Ale myślę, że mam to, co mówisz, po prostu zdecyduj i zdefiniuj API z autorytetem, prawda? Czy to oznacza, że ​​nie ma w tym nic złego?
imel96

Tak, cokolwiek zrobisz w swoim interfejsie API, wpłynie na to, jak użytkownik będzie musiał ustrukturyzować swój kod, więc biorąc pod uwagę swój projekt pod kątem użytkownika interfejsu API, powinieneś być w stanie określić, który sposób jest najlepszy. Ostatecznie jest to Twój interfejs API. Po prostu bądź konsekwentny. Tylko Ty możesz zdecydować o zaletach i wadach tego podejścia.
Erdrik Ironrose

0

Dokument!

TL; DR>

Rób, co uważasz za stosowne - czasem kontekst, w którym jest używany, ma znaczenie. Przykład: Powiązanie zmiennych do Oracle SQL: Pusty ciąg interpretowany jest jako NULL.

Po prostu powiedziałbym - upewnij się, że udokumentowałeś każdy wymieniony scenariusz

  • ZERO
  • Puste (puste)
  • Brakuje (usunięto)

Twój kod może działać na różne sposoby - udokumentuj reakcję kodu:

  • Niepowodzenie (wyjątek itp.), Może nawet nie powiedzie się sprawdzanie poprawności (być może sprawdzony wyjątek) vs nie może poprawnie obsłużyć sytuacji (NullPointerException).
  • Podaj uzasadnione wartości domyślne
  • Kod zachowuje się inaczej

Oprócz tego - od Ciebie zależy, czy będziesz się zachowywał konsekwentnie i ewentualnie zastosował niektóre z twoich najlepszych praktyk. Dokumentuj to spójne zachowanie. Przykłady:

  • Traktuj Null i Missing to samo
  • Traktuj pusty ciąg dokładnie tak. Tylko w przypadku powiązania SQL można to uznać za puste. Upewnij się, że Twój SQL zachowuje się spójnie i zgodnie z oczekiwaniami.

Problem polega na tym, że bez uwzględnienia obaw sporność zdarzała się dość często. Rozważmy w środowisku zespołowym, decyzja musi być decyzją zespołu, wiele razy oznacza to, że będzie spór. Gdy masz wiele zespołów, każdy zespół ma prawo do własnych decyzji. Widziałem interfejsy API, które mogę tylko zgadywać, że są wdrażane przez różne zespoły, które się ze sobą nie zgadzają. Jeśli ktoś może zgodzić się na jedną rzecz, udokumentowanie jej jest banalne.
imel96

0

tl; dr - jeśli go użyjesz: bądź konsekwentny w jego znaczeniu.

Jeśli to podasz null, co by to oznaczało? Istnieje wszechświat rzeczy, co to może znaczyć. Jedna wartość to po prostu za mało, aby przedstawić brakującą lub nieznaną wartość (a są to tylko dwie z niezliczonych możliwości: np. Brakujące - zostało zmierzone, ale jeszcze tego nie wiemy. Nieznane - nie próbowaliśmy mierzyć to.)

W przykładzie, na który natknąłem się ostatnio, pole może być puste, ponieważ nie zgłoszono, aby chronić czyjąś prywatność, ale było znane po stronie nadawcy, nieznane po stronie nadawcy, ale znane pierwotnemu reporterowi lub nieznane obu stronom. I wszystko to miało znaczenie dla odbiornika. Tak więc zwykle jedna wartość nie wystarcza.

Przy założeniu, że świat jest otwarty (po prostu nie wiesz o rzeczach nie powiedzianych), po prostu pominiesz go i może to być cokolwiek. Przy założeniu, że zamknięty świat (rzeczy nie wymienione są fałszywe, na przykład w SQL) lepiej wyjaśnij, co nulloznacza, i zachowaj zgodność z tą definicją, jak możesz ...

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.