"How to gentle" zabić aplikacje.

0

Ostatnio implementując BufferedReader zastanowiła mnie taka sytuacja:

public interface ItemReader {
    List<String> read();
}
public class FlatFileItemReader implements ItemReader {
    private final String filePath;

    public FlatFileItemReader(String filePath) {
        this.filePath = filePath;
    }

    @Override
    public List<String> read() {
        List<String> dataList = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            for (String s; (s = br.readLine()) != null;) {
// BLA BLA - logika - jakas obróbka s
               dataList.add(s)
            }
        } catch (IOException e) {
            log.warning(e.getMessage());
            System.exit(1); // <-- TUTAJ
        }
        return dataList;
    }
}

Generalnie jest kilka opcji zczytywania danych, tutaj jest akurat implementacja czytanie z pliku. W przypadku jakiegokolwiek Exception (FileNotFoundException, zły format danych, czy cokolwiek innego) aplikacja ma być zatrzymana. Boli mnie ten System.exit(1), jakoś mi to strasznie nie pasuje. Myślałem pierw czy by metody read() nie przerobić na void, w klasie reader zmienną lokalną dataList zrobić jako zmienną klasową i udostępnić do niej dostęp, albo jakaś inna klasa i kompozycja. Co myślicie?

0

Nie wiem czy to appka Springowa czy nie, ale jeśli tak, to możesz np wcześniej jeszcze zamknąć context Springowy:
https://stackoverflow.com/questions/14423980/how-to-close-a-spring-applicationcontext

4

Myślałem pierw czy by metody read() nie przerobić na void, w klasie reader zmienną lokalną dataList zrobić jako zmienną klasową i udostępnić do niej dostęp, albo jakaś inna klasa i kompozycja.

Nie rozumiem jaki to ma związek z pytaniem.

Ad podstawionego problemu:

  • Albo rzucasz jakiś customowy wyjątek który składa aplikacje
  • Albo zwracasz jakieś Either<Error,Result> Pisałem ostatnio aplikacje która wykonuje N rożnych kroków i każdy z nich może failować i właśnie tak to zrobiłem, że każdy krok zwraca Either<T extends Error, S> i potem mam ładną kompozycje z map.map.map i jak coś po drodze sie wywali, to zwyczajnie przejdzie ci do końca programu.
1

ło-ja-cie. exit to ja chyba ostatni raz widziałem w tutorialach Perla 10 lat temu. Skrypt piszesz czy poważny program? Jak wyobrażasz sobie ewentualne testy jeśli masz System.exit?
Jest kilka rozwiązań:

  1. Stare, nie zawsze działające, z jakiegoś powodu niepolecane - zamień List<String> read() na List<String> read() throws IOException
  2. Normalne, uniwersalne, dla leniwych - zamień IOException na RuntimeException
  3. Monadyczne, Na topie i Najlepsze czyli to o którym pisze Shalom - zamień List<String> read() na Either<Error, List<String>> read()
2

Zmiana sygnatury metody na rzucanie runtimeexception nic nie da.

Po to jest RuntimeException żeby nie zmieniać sygnatury metody. Rozwiązanie 2. to:

public class FlatFileItemReader implements ItemReader {
    private final String filePath;

    public FlatFileItemReader(String filePath) {
        this.filePath = filePath;
    }

    @Override
    public List<String> read() {
        List<String> dataList = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            for (String s; (s = br.readLine()) != null;) {
// BLA BLA - logika - jakas obróbka s
               dataList.add(s)
            }
        } catch (IOException e) {
            log.warning(e.getMessage());
            throw new RuntimeException("",e );
        }
        return dataList;
    }
}

Tutaj mam do czynienia z Compilation Exception. Musiałbym rzucać całe drzewo - Exception. Imo to jest mega słabe

W ogóle tego zdania nie rozumiem. A programuję w Javie już 9 lat. A znasz jakieś nie Compilation Exception? może miało być Checked Exception? Rozwiązanie 1. to:

public class FlatFileItemReader implements ItemReader {
    private final String filePath;

    public FlatFileItemReader(String filePath) {
        this.filePath = filePath;
    }

    @Override
    public List<String> read() throws IOException {
        List<String> dataList = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            for (String s; (s = br.readLine()) != null;) {
// BLA BLA - logika - jakas obróbka s
               dataList.add(s)
            }
        } catch (IOException e) {
            log.warning(e.getMessage());
            throw e;
        }
        return dataList;
    }
}

Oczywiście zadziała tylko wtedy gdy interfejs może być:

public interface ItemReader {
    List<String> read() throws IOException;
}
1

W kwestii semantyki: w środowisku używa się okreslenia "graceful termination" a nie "gentle", np. można zabić proces na linuxie brutalnie albo właśnie "gracefully"

1 użytkowników online, w tym zalogowanych: 0, gości: 1