Allmänt om felhantering

Sven-Olof Nyström
OOP med Java våren -25
Informationsteknologi
Uppsala Universitet

Skansholm: Kapitel 11

Allmänt om felhantering

Efter att ha studerat kod med god och mindre god felhantering insåg jag att den här frågan förtjänade mer uppmärksamhet.

Låt oss börja med att lista några rimliga önskemål om felhantering.

Låt oss betrakta ett enkelt exempel. Din applikation hanterar ett antal hinkar, numrerade från 0 till n-1. Du ska implementera ett antal operationer på hinkarna, bland annat en metod

void töm(int k)

som tömmer (nollställer) hink nummer k. Vi antar att hinkarna representeras med en array av int med storlek n.

Vi kommer att titta på några exempel på hur operationen töm() kan implementeras.

Lösning nummer 1

Den allra enklaste lösningen:

void töm(int k) {
    hinkar[k] = 0;
}+

Vad händer om man frågar efter hink nummer -1 eller hink n+1?

Du får en exception, ArrayIndexOutOfBoundsException.

Det här är ofta en rimlig lösning. Det viktiga är att om programmet försöker att tömma en hink som inte finns kommer vi att uptäcka det. Det undantag som kastas är ej specifikt för applikationen men orsaken till felet är lätt att lokalisera. (Hur lokaliserar man orsaken?)

Lösning nummer 2

Här kollar programmet att index är inom arrayen.

void töm(int k) {
    if (0 <= k && k < hinkar.size)
        hinkar[k] = 0;
}-

Vi har lagt ner mer arbete och fått en sämre lösning! Vi gömmer ju eventuella problem. Om programmet skickar fel index till metoden töm() får vi ingen feedback på att ett fel har inträffat.

Lösning nummer 3

Samma sak gäller om man skriver så här:

void töm(int k) {
    try
        hinkar[k] = 0;
    catch (Exception e){}
}-

Den här lösningen är sämre än den föregående eftersom den också döljer alla andra fel som kan uppträda i metoden. Nu är ju vårt exempel extremt enkelt så risken att andra fel uppträder är minimal, men i en mer komplex applikation finns det en uppenbar risk att man fångar andra fel som man inte var medveten om.

Lösning nummer 4

Denna lösning är inte heller så bra:

boolean töm(int k) {
    if (0 <= k && k < hinkar.size) {
        hinkar[k] = 0;
        return true;
    }
    else return false;
}-

Tanken är alltså att metoden töm() returnerar false om index var fel.

Vem ska testa om metoden töm() returnerar true eller false? Om den som anropar glömmer att testa upptäcks inte felet.

Lösning nummer 5

Om man konstruerar ett bibliotek kan följande vara rimligt:

void töm(int k) throws BucketsOutOfBoundsException {
    if (0 <= k && k < hinkar.size) {
        hinkar[k] = 0;
    }
    else throw new BucketsOutOfBoundsException();
}+

Här framgår det omedelbart att felet har att göra med en operation på hinkar, vilket kan vara till hjälp.

Lösningarna märkta med + är bra, de märkta med - är mindre bra.