| Termin | Definicja |
|---|---|
| Zwracany typ danych | Zwracany typ danych określa format wartości, jaką funkcja przekazuje do kodu wywołującego. Zwracany typ danych jako opis wyniku funkcjiZwracany typ danych informuje, jaką postać ma wartość przekazywana przez funkcję do miejsca, z którego została wywołana. Dzięki temu można przewidzieć, czy wynikiem będzie liczba, tekst, wartość logiczna, pojedynczy obiekt, kolekcja elementów, para wartości, rekord albo brak użytecznego rezultatu. Jest to część umowy programistycznej funkcji, obok jej nazwy, parametrów oraz reguł działania. Kod wywołujący może wtedy prawidłowo odebrać wynik, przypisać go do odpowiedniej zmiennej, przekazać dalej lub wykorzystać w wyrażeniu. Przykładowo funkcja obliczająca sumę może zwracać liczbę całkowitą albo zmiennoprzecinkową, funkcja wyszukująca użytkownika może przekazywać obiekt opisujący znaleziony rekord, a funkcja sprawdzająca poprawność danych może zwrócić wartość logiczną. W wielu językach typ wyniku zapisuje się bezpośrednio w deklaracji funkcji. W innych wynika on z wartości zwracanej w kodzie lub jest ustalany podczas wykonywania programu. Niezależnie od składni sens pozostaje podobny: odbiorca wyniku powinien wiedzieć, z jakimi danymi ma do czynienia. Nie należy utożsamiać typu zwracanego z samą zawartością wyniku. Dwie funkcje mogą zwracać liczby, ale jedna może przekazywać liczbę całkowitą oznaczającą liczbę elementów, a druga liczbę zmiennoprzecinkową oznaczającą temperaturę lub odległość. Typ opisuje możliwości wartości i operacje, które można na niej wykonać, natomiast znaczenie biznesowe wynika z nazwy funkcji, dokumentacji oraz kontekstu programu. Zwracany typ danych w kontekście typowania i porównańW językach statycznie typowanych zwracany typ danych jest zwykle sprawdzany przed uruchomieniem programu. Jeżeli funkcja została zadeklarowana jako zwracająca tekst, a jedna ze ścieżek wykonania przekazuje liczbę, kompilator może zgłosić błąd. Takie ograniczenie zwiększa przewidywalność kodu i pozwala wcześniej wykrywać pomyłki. W praktyce szczególnie przydatne jest to w większych modułach, gdzie funkcję wywołuje wiele innych fragmentów programu. W językach dynamicznie typowanych typ wyniku może być rozpoznawany podczas działania. Zwiększa to elastyczność, ale wymaga większej uwagi przy korzystaniu z wartości. Ta sama funkcja może w określonych warunkach zwrócić tekst, a w innych wartość pustą albo obiekt błędu. Jeżeli kod wywołujący nie sprawdzi takiej możliwości, może dojść do wyjątku dopiero podczas pracy aplikacji. Z tego powodu dokumentowanie możliwych wyników pozostaje ważne również wtedy, gdy język nie wymaga formalnej deklaracji typu. Istotne jest rozróżnienie między wartością pustą, brakiem wyniku i komunikatem o błędzie. Funkcja zwracająca pusty tekst nadal przekazuje tekst. Funkcja przekazująca wartość logiczną równą fałsz nadal zwraca wynik, choć wynik oznacza niespełnienie warunku. Z kolei brak wartości może być reprezentowany przez specjalny typ, na przykład null, None, undefined albo dedykowany wariant typu opcjonalnego. W dojrzałym projekcie sposób reprezentowania takich sytuacji powinien być jednoznaczny. Na typ zwracany można spojrzeć także przez porównanie z typem parametrów. Parametry opisują dane wejściowe, a zwracany typ opisuje dane wyjściowe. Funkcja może przyjmować tekst i zwracać liczbę, przyjmować listę i zwracać pojedynczy element albo przyjmować obiekt konfiguracji i zwracać wynik operacji. Jasny podział wejścia oraz wyjścia ułatwia testowanie, ponowne użycie funkcji i późniejszą zmianę implementacji bez naruszania kodu korzystającego z jej interfejsu. Zwracany typ danych a typowe problemy w programieJednym z częstszych problemów jest niezgodność typu wyniku z oczekiwaniem kodu wywołującego. Funkcja może zwracać tekst zawierający cyfry, podczas gdy dalsza część programu oczekuje liczby i próbuje wykonać dodawanie. W zależności od języka otrzyma się błąd, nieoczekiwaną konkatenację albo automatyczną konwersję. Podobne trudności pojawiają się przy wartościach logicznych, gdy tekst „false” zostaje potraktowany jako prawda, ponieważ sam tekst jest niepusty. Inny problem wynika z niepełnego zwracania wyniku. Jeżeli funkcja przekazuje wartość tylko w jednej gałęzi warunkowej, a w pozostałych kończy działanie bez instrukcji zwrotu, rezultat może być pusty albo nieokreślony. Takie zachowanie warto sprawdzać podczas przeglądu kodu i testów dla każdego możliwego przypadku. Dotyczy to zwłaszcza funkcji obsługujących dane z formularzy, plików, urządzeń wejściowych lub zewnętrznych interfejsów. Ryzyko stwarza także zwracanie zbyt ogólnego typu. Wynik określony jako dowolny obiekt może chwilowo ułatwić implementację, lecz utrudnia zrozumienie kodu i ogranicza możliwości automatycznego sprawdzania. Lepszym rozwiązaniem jest opisanie konkretnych pól, dopuszczalnych wariantów oraz sytuacji wyjątkowych. Jeżeli wynik może należeć do kilku typów, warto zastosować typ sumaryczny, opcjonalny albo wspólny interfejs z jasno opisanymi właściwościami. Warto zwrócić uwagę na mutowalność wyniku. Funkcja może zwracać nową strukturę danych albo referencję do struktury używanej wewnątrz modułu. W drugim przypadku kod wywołujący może przypadkowo zmienić stan, od którego zależą kolejne operacje. Jasna dokumentacja informuje, czy wynik można bezpiecznie modyfikować, czy należy traktować go jako tylko do odczytu. Dobrze zaprojektowany typ nie tylko mówi, co zwrócono, ale także ogranicza niejednoznaczne użycie. Zwracany typ danych w praktycznych wskazówkachPrzy projektowaniu funkcji warto rozpocząć od pytania, jaki rezultat będzie najbardziej naturalny dla osoby korzystającej z danego interfejsu. Funkcja obliczeniowa zwykle powinna zwracać wartość gotową do dalszych obliczeń, funkcja wyszukująca powinna jasno sygnalizować znalezienie albo brak elementu, a funkcja wykonująca operację bez danych wyjściowych powinna mieć wyraźnie opisany brak rezultatu. Im mniej wyjątkowych interpretacji pozostaje po stronie wywołującego, tym mniejsze ryzyko błędu. Dobrym zwyczajem jest unikanie mieszania typów w pozornie prostych funkcjach. Przekazywanie liczby przy powodzeniu i tekstu z błędem w razie niepowodzenia zmusza każdy fragment kodu do rozpoznawania dwóch niezależnych znaczeń. Czytelniejszy model zakłada jeden opisany typ wyniku oraz osobny mechanizm sygnalizowania błędu, na przykład wyjątek, obiekt rezultatu lub wariant zawierający stan powodzenia i szczegóły problemu. W dokumentacji warto podać nie tylko nazwę typu, lecz także przykład znaczenia poszczególnych pól, zakres dopuszczalnych wartości oraz zachowanie dla pustych danych. Przydatne jest określenie, czy kolejność elementów kolekcji ma znaczenie, czy wynik może być pusty, czy pola są zawsze obecne i czy format tekstu podlega konkretnym regułom. Takie informacje pomagają osobom rozwijającym kod oraz ograniczają konieczność odczytywania implementacji w celu ustalenia zasad działania. Podczas testów należy sprawdzić typ wyniku dla danych zwykłych, granicznych, pustych i błędnych. Należy również zweryfikować każdą gałąź warunkową, obsługę braku elementu oraz sytuację, w której dane wejściowe mają nieprawidłowy format. Test nie powinien ograniczać się do sprawdzenia samej wartości. Warto potwierdzić także strukturę wyniku, typ pól, kolejność kolekcji i stabilność zachowania po zmianie danych. W przypadku podejrzenia, że nieprawidłowe działanie aplikacji wynika z problemu sprzętowego, pomocne może być skonsultowanie urządzenia z Warszawskim Pogotowiem Komputerowym 24/7, gdzie dostępna jest darmowa diagnoza laptopa. Sama diagnoza urządzenia nie zastępuje analizy kodu, ale pozwala oddzielić usterkę środowiska pracy od błędu w programie. Kiedy sprawdzić zwracany typ danych w serwisieWeryfikacja zwracanego typu danych jest szczególnie potrzebna wtedy, gdy program przestaje poprawnie wyświetlać informacje, obliczenia dają zaskakujące rezultaty albo część funkcji działa tylko dla określonych danych. Przed zmianą kodu warto ustalić, jaki wynik faktycznie przekazuje funkcja, jaki wynik zakłada kod wywołujący oraz w którym miejscu następuje ewentualna konwersja. Pomocne bywają komunikaty kompilatora, logi, podgląd wartości podczas debugowania i małe testy odtwarzające problem. Do zgłoszenia sprawy warto przygotować opis objawów, przykład danych wejściowych, oczekiwany rezultat oraz rzeczywistą wartość otrzymaną przez program. Jeżeli problem pojawia się tylko na jednym urządzeniu, należy odnotować system, używane środowisko programistyczne i moment wystąpienia błędu. Takie informacje ułatwiają rozdzielenie problemu typów danych od problemu konfiguracji, uszkodzenia nośnika, niestabilnej pamięci lub nieprawidłowej pracy podzespołów. Jeżeli analiza wskazuje na sprzęt, a nie na samą funkcję, można zgłosić urządzenie do serwisu komputerowego w Warszawie. W pierwszej kolejności warto jasno opisać, czy problem dotyczy uruchamiania programu, odczytu danych, zapisywania wyników, spowolnienia pracy czy powtarzających się komunikatów. Precyzyjne przedstawienie objawów pomaga dobrać właściwy zakres sprawdzenia i ograniczyć ryzyko błędnej interpretacji problemu. |