MATLAB – Błędy i funkcje – walidacja danych

W jaki sposób ulepszyć samodzielnie pisane funkcje w MATLABie? Jak łatwo zaimplementować obsługę błędów związaną z przekazywanymi do funkcji argumentami (zmiennymi)? W tym wpisie zajmę się względnie nową funkcjonalnością MATLABa czyli walidacją argumentów funkcji za pomocą struktury arguments .. end.

Tworząc własną funkcję, realizującą dane obliczenia, warto zadbać o obsługę błędów, która jest związana z przyjmowanymi przez funkcję argumentami. Jeżeli na przykład rozmiar lub typ przekazanego do funkcji argumentu (zmiennej) nie jest zgodny z zamysłem twórcy funkcji, może to spowodować błąd i przerwanie programu bez szczegółowego komunikatu o przyczynie. Taka sytuacja może mieć miejsce kiedy argument funkcji powinien być skalarem, a przekazujemy wektor lub kiedy zmienna powinna być typu numerycznego, a przekazujemy tekst, itp.

Dlatego dobrą praktyką jest aby każda funkcja posiadała obsługę błędów i jednocześnie szczegółowo komunikowała programiście o przyczynie takiej sytuacji. Do niedawna w MATLABie do tego celu używało się zestawu warunków if.. elseif.. end oraz funkcji nargin, nargout, isnumeric i innych. Powodowało to, że fragment funkcji związany z obsługą błędów argumentów wejściowych był długi i nieczytelny. Weźmy poniższy przykład. Mamy prosty program, zawierający funkcję, która realizuje mnożenie zmiennych xin i yin przez wartość zdefiniowaną w zmiennej param.

clear all; close all; clc

x = [0 1 2 3 4];
y = [10 11 12 13 14];

param = 2;

[X,Y] = myfunc(x,y,param)


%%
function [xout,yout] = myfunc(xin,yin,param)

% myfunc ....


% Obsługa błędów
if nargin < 2
    error('za mało argumentów wejściowych')
end

if nargin > 2
    if ~isnumeric(xin) || ~isnumeric(yin)
        error('x oraz y muszą być liczbami')
    end
end

if nargin == 2
    param = 2;
end

if nargin == 3 && (~isscalar(param) || ~isnumeric(param))
    error('flag musi być skalarem i liczbą')
end

% Program funkcji
xout = param * xin;
yout = 2 * param * yin;

end

Jak widać treść funkcji to dwie linijki związane z mnożeniem, a obsługa błędów to 17 linii programu. Czy da się to uprościć?

Funkcja arguments i walidacja błędów

Na szczęście od kilku edycji MATLABa do obsługi wyżej wymienionych błędów można używać funkcji arguments, która w prosty i czytelny sposób realizuje walidację argumentów wejściowych danej funkcji.

Walidacja błędów argumentów wejściowych funkcji powinna być wykonana przed głównym programem funkcji realizującym obliczenia, stąd fragment walidacyjny (i wywołanie arguments) musi być umieszczone w pierwszej linijce funkcji.

Funkcja arguments pozwala w sposób automatyczny nałożyć ograniczenia na rozmiar, typ i inne cechy argumentów (zmiennych przekazywanych do funkcji). W przypadku niezgodności tych cech z zadeklarowanymi, otrzymujemy szczegółowe informacje o występującym błędzie.

Sposób użycia funkcji arguments wyjaśnia poniższy rysunek:

Na dany argument przekazywany do funkcji można więc nałożyć następujące ograniczenia:

  • Size – rozmiar argumentu (zmiennej),
  • Class – klasa argumentu (zmiennej),
  • Functions – inne ograniczenia zdefiniowane za pomocą dodatkowych funkcji, które umożliwiają na przykład sprawdzenie czy: argument przyjmuje wartości dodatnie, ujemne, skończone, rzeczywiste, całkowite, itd., czy argument ma wartości, większe, mniejsze, zawarte w pewnym przedziale, czy argument jest określonego typu i tym podobne.

Daje to duże możliwości kontroli nad przekazywanymi do funkcji zmiennymi, a w przypadku niezgodności cech zmiennej z deklaracją, na zgłoszenie błędu lub na automatyczną konwersję cech zmiennej do żądanego typu.

Popatrzmy na poniższy przykład. Mamy w nim funkcję podwojenie, która przyjmuje 5 argumentów. Rysuje ona rysunek dla wektorów x i y o kolorze kolor1, następnie podwaja wartości zmiennej y (i dodaje szum) oraz rysuje wektor o podwojonych wartościach w kolorze kolor2.

clear all; close all; clc;

x_data = 0:pi/20:2*pi;
y_data = sin(x_data);

kolor1 = 'r'
kolor2 = 'g'

sigma = 0.1;
podwojenie(x_data,y_data,sigma,kolor1,kolor2)


function [] = podwojenie(x,y,sigma,kolor1,kolor2)


% Obsługa błedów
arguments 
    x (1,:) double {mustBeInRange(x,0,10)} 
    y (1,:) double 
    sigma (1,1) double 
    kolor1 (1,1) char  
    kolor2 (1,1) char 
end

% Program funkcji

figure; plot(x,y,kolor1)

y = 2 * y + sigma*randn(size(y));

hold on; plot(x,y,kolor2)

end




Zwróćmy uwagę na fragment zawarty pomiędzy arguments .. end. Na zmienne przyjmowane przez funkcje mamy nałożone ograniczenia:

  • Zmienna x musi być wektorem wierszowym o rozmiarze (1,:), typu double, oraz musi przyjmować wartości z zakresu 0 do 10,
  • Zmienna y, ma podobne ograniczenia, lecz nie ma ograniczenia na zakres wartości,
  • Zmienne kolor1 i kolor2 muszą być typu char.

Widzicie jakie to proste? Bez używania warunków if.. elseif.. end i dodatkowych funkcji w łatwy sposób zostały zdefiniowane ograniczenia na zmienne. Co więcej w przypadku niezgodności cech zmiennej z deklaracją, automatycznie otrzymamy komunikat o błędzie.

Zachęcam do stosowania w funkcjach struktury arguments … end. Obsługa błędów może znacznie ułatwić życie na etapie używania funkcji. Szczegółowy opis znajdziecie w dokumentacji MATLABa.

(Visited 464 times, 1 visits today)

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *