Dlaczego null jest taki straszny?
Jako developerzy musimy więc świadomie zwracać wartość null lub umieć przewidzieć, gdzie może ona wystąpić i odpowiednio zabezpieczyć nasz kod.
W Apexie zazwyczaj zabezpieczamy się przed taką sytuacją za pomocą klauzuli if:
W powyższym przykładzie musimy sprawdzić, czy metoda getProfileUrl nie zwróci nam nulla, zanim zwrócony URL będziemy mogli poddać dalszej obróbce (w tym przypadku użyć na nim metody toExternalForm).
Gdybyśmy spróbowali wykonać przypisanie do zmiennej profileUrl bez sprawdzenia, co zwraca nam metoda getProfileUrl, moglibyśmy otrzymać wyjątek NullPointerException.
Innym przykładem może być zabezpieczenie kodu przed pobraniem elementu z pustej listy lub tablicy:
Jeżeli zapytanie do bazy nie zwróci nam żadnego rekordu, to lista będzie pusta, a tym samym pobranie z niej pierwszego elementu (o indeksie zero) spowoduje rzucenie przez system wyjątku List index out of bounds. Niezbędne jest więc sprawdzenie wielkości listy i ewentualnie przerwanie dalszego procesowania kodu, gdy będzie ona pusta.
Safe Navigation Operator na ratunek!
W Winter’21 release Salesforce postanowił nieco ułatwić życie developerom, wprowadzając Safe Navigation Operator. Dodanie nowego operatora do języka pozwala zredukować ilość pisanego kodu, a tym samym sprawia, że jest on czytelniejszy i bezpieczniejszy.
Składnia nowego operatora wygląda następująco:
Jak to działa?
Jeżeli wyrażenie po lewej stronie jest nullem, to wyrażenie po prawej stronie nie jest w ogóle ewaluowane.
Pierwszy przykład można więc zapisać z wykorzystaniem nowego operatora w jednej linijce kodu:
Jeżeli lewa strona wyrażenia, w tym przypadku wartość zwracana z metody getProfileUrl, jest nullem, to prawa strona wyrażenia nie jest w ogóle ewaluowana, a tym samym mamy pewność, że nie użyjemy metody toExternalForm na nullu.
Używając tego operatora, drugi przykład możemy zapisać jako:
Tak jak poprzednio: jeżeli zapytanie do bazy nie zwróci nam rekordu, a tym samym lewa strona wyrażenia będzie nullem, to nie będziemy ewaluować wyrażenia po prawej stronie, w tym przypadku – wyciągać pola Name.
Inną ciekawostką związaną z nowym operatorem jest to, że działa on również w wyrażeniach łączonych, czyli w tzw. expression chaining.
Załóżmy, że mamy do wykonania metodę na elemencie listy:
Wszystko zadziała prawidłowo pod warunkiem, że tablica tab posiada element o indeksie x, na którym wywołanie metody method zwróci odpowiedni obiekt, a z niego da się wyodrębnić pole field. Jeżeli któryś z elementów łańcucha będzie nullem, to system rzuci wyjątek.
Jak widzieliśmy wcześniej, zabezpieczenie tablicy jest jedną z możliwości, jednak nadal możemy spodziewać się nulla jako wyniku działania metody. Tutaj z pomocą przychodzi łączenie operatorów:
Taka konstrukcja zapewni nam bezpieczne wywołanie kodu, ponieważ na każdym kolejnym etapie ewaluacji sprawdzamy, czy to, co mamy po lewej stronie wyrażenia nie jest nullem. Gdybyśmy chcieli zapisać to samo bez Safe Navigation Operatora, musielibyśmy każdą z sekwencji sprawdzić osobno, np.:
Należy zwrócić uwagę na jeszcze jeden aspekt powyższego zapisu. Metoda method wywołuje się dwa razy w przypadku, gdy spełnione są pierwsze dwa warunki! Można oczywiście odpowiednio zapisać rezultat działania tej metody i sprawdzić go w warunku w klauzuli if, ale często zdarza się, że w kodzie widzimy właśnie takiego oto potworka. Powinniśmy unikać podobnych zapisów.
Gdzie nie użyjemy nowego operatora?
Safe Navigation Operatora można używać w metodach, polach, w rzutowaniu, jako rezultat zapytania czy w łańcuchach wywołań. Jest jednak kilka przypadków, gdzie użycie operatora nie zadziała:
- w typach i statycznych wyrażeniach z kropką, takich jak np. Trigger.new.
- w wywołaniach zmiennych i metod statycznych, np. Klasa.metoda() lub Klasa.pole.
- przy przypisywaniu wartości do wyrażenia, np. foo?.bar = 42; lub ++foo?.bar;
- w przypisywaniu wyrażeń wewnątrz zapytania SOQL, np. [SELECT Name FROM Account WHERE Name = :someName?.query]
Podsumowanie
Nowoczesne obiektowe języki programowania są obecnie projektowane jako języki null-safety. Jest to pewien trend, który stara się ułatwić developerom zabezpieczanie kodu przed przypadkowym lub celowym wystąpieniem wartości null. Salesforce, wprowadzając nowy operator do Apexa, sprawił, że odwieczna walka z nullem stała się nieco łatwiejsza.
- Salesforce Developer
-
W Craftware od 2017 roku jako programista Salesforce, jednak amatorsko programuje od czasu swojego pierwszego komputera – Commodore 64. Pasjonat technologii mobilnych oraz astronomii. Prywatnie fan horrorów i kina o tematyce zombie. W wolnych chwilach tworzy własne gry i majsterkuje.