Non-Fatal Error — είναι ένα σφάλμα που δεν οδηγεί στον τερματισμό της εφαρμογής και επιτρέπει τη συνέχιση της εκτέλεσης του προγράμματος. Σε αντίθεση με το fatal error, τα μη θανατηφόρα σφάλματα μπορούν να εντοπιστούν, να αντιμετωπιστούν και να καταγραφούν χωρίς απώλεια της συνεδρίας του χρήστη. Σύμφωνα με τα δεδομένα Firebase Crashlytics Documentation, 2024, περίπου το 70% όλων των καταγεγραμμένων σφαλμάτων σε εφαρμογές παραγωγής είναι μη θανατηφόρα, αλλά η αγνόησή τους οδηγεί σε συσσώρευση τεχνικού χρέους και σταδιακή υποβάθμιση της εμπειρίας χρήστη. Η σωστή διαχείριση των σφαλμάτων non-fatal είναι μία από τις βασικές δεξιότητες ενός προγραμματιστή κινητών.
Βασικά σημεία
Non-Fatal Error — είναι μια εξαίρεση ή εσφαλμένη κατάσταση που δεν προκαλεί τον τερματισμό της διεργασίας. Η εφαρμογή συνεχίζει να λειτουργεί, αλλά μπορεί να βρίσκεται σε εσφαλμένη κατάσταση: τα δεδομένα δεν φορτώθηκαν, το αίτημα δεν στάλθηκε, το στοιχείο διεπαφής δεν εμφανίστηκε. Ο χρήστης είτε δεν παρατηρεί το σφάλμα είτε βλέπει ένα μήνυμα και συνεχίζει τη χρήση της εφαρμογής.
Ένα μη θανατηφόρο σφάλμα αφήνει πάντα στο πρόγραμμα μια διαδρομή ανάκαμψης. Ο χειριστής σφαλμάτων μπορεί να προσφέρει εναλλακτικά δεδομένα, να επαναλάβει τη λειτουργία ή να εμφανίσει ένα σύμβολο κράτησης θέσης διεπαφής. Το κύριο καθήκον είναι η αποτροπή της κατάρρευσης και η διατήρηση της εμπειρίας χρήστη σε αποδεκτό επίπεδο. Ο προγραμματιστής πρέπει να προβλέπει ρητά ένα σενάριο ανάκαμψης σε κάθε μπλοκ catch.
Σύμφωνα με τα δεδομένα Instabug 2024, το 65% των χρηστών διαγράφει την εφαρμογή μετά από δύο αποτυχημένες αλληλεπιδράσεις. Τα σφάλματα non-fatal που αγνοούνται συσσωρεύονται και μειώνουν τη συνολική ποιότητα λειτουργίας. Η συστηματική καταγραφή και διόρθωση μη θανατηφόρων σφαλμάτων είναι άμεσος δρόμος για την αύξηση της διατήρησης και τη βελτίωση των αξιολογήσεων χρηστών στα καταστήματα εφαρμογών.
Σφάλματα δικτύου — ο πιο συνηθισμένος τύπος σφαλμάτων non-fatal σε εφαρμογές κινητών. Λήξη χρονικού ορίου σύνδεσης, απώλεια δικτύου, εσφαλμένος κωδικός κατάστασης διακομιστή — όλες αυτές οι καταστάσεις εντοπίζονται και αντιμετωπίζονται χωρίς κατάρρευση. Στον χρήστη εμφανίζεται ένα μήνυμα σχετικά με τη μη διαθεσιμότητα της υπηρεσίας με πρόταση επανάληψης. Για τα σφάλματα δικτύου είναι τυπικό το μοτίβο επανάληψης με εκθετική καθυστέρηση.
Εσφαλμένη μορφή απόκρισης διακομιστή, απουσία υποχρεωτικού πεδίου, εσφαλμένος τύπος δεδομένων — σφάλματα ανάλυσης είναι μη θανατηφόρα αν η εφαρμογή χειρίζεται σωστά τα εσφαλμένα δεδομένα. Η τυπική προσέγγιση είναι η χρήση προεπιλεγμένων εφεδρικών τιμών και η καταγραφή του σφάλματος ανάλυσης με το πλαίσιο του αιτήματος για μεταγενέστερη ανάλυση στον διακομιστή.
Προβλήματα με τη φόρτωση εικόνων, εσφαλμένες γραμματοσειρές, σφάλματα διάταξης — όλα αυτά δεν είναι θανατηφόρα, αλλά υποβαθμίζουν την εντύπωση του χρήστη. Εικόνες κράτησης θέσης και τιμές fallback επιτρέπουν την αποφυγή κενών οθονών και καθιστούν τα σφάλματα λιγότερο αισθητά. Στο React Native για σφάλματα UI χρησιμοποιείται το Error Boundary με εμφάνιση εφεδρικού στοιχείου.
Σφάλματα σε υπολογισμούς, ασυμφωνία καταστάσεων, εσφαλμένες μεταβάσεις μεταξύ οθονών — λογικά σφάλματα συχνά δεν οδηγούν σε κατάρρευση, αλλά οδηγούν σε εσφαλμένη συμπεριφορά της εφαρμογής. Είναι δυσκολότερο να εντοπιστούν χωρίς συστηματική καταγραφή και παρακολούθηση, καθώς δεν δημιουργούν αναφορά κατάρρευσης και παραμένουν απαρατήρητα μέχρι το παράπονο του χρήστη.
Non-Fatal Error διαφέρει από το fatal στο ότι αφήνει στο πρόγραμμα τη δυνατότητα να συνεχίσει την εργασία. Fatal error — είναι μια κατάσταση από την οποία η εφαρμογή δεν μπορεί να ανακάμψει: αποαναφορά null δείκτη, υπερχείλιση στοίβας, έλλειψη μνήμης. Ένα σφάλμα non-fatal μπορεί να εντοπιστεί, να αντιμετωπιστεί και η εκτέλεση να συνεχιστεί, ενώ το fatal error απαιτεί επανεκκίνηση της εφαρμογής.
| Χαρακτηριστικό | Non-Fatal Error | Fatal Error |
|---|---|---|
| Τερματισμός εφαρμογής | Όχι | Ναι |
| Δυνατότητα ανάκαμψης | Ναι, μέσω μπλοκ catch | Όχι |
| Καταγραφή | Από τον κώδικα μέσω recordException | Μόνο από τον αναφορέα κατάρρευσης |
| Επίδραση UX | Προσωρινή ταλαιπωρία | Πλήρης απώλεια συνεδρίας |
| Παράδειγμα | Network timeout, parse error | NullPointerException, OOM |
Το όριο μεταξύ non-fatal και fatal μπορεί να εξαρτάται από την υλοποίηση. Χρονική λήξη δικτύου σε μία εφαρμογή αντιμετωπίζεται ως non-fatal (επανάληψη αιτήματος μετά από 1–2 δευτερόλεπτα), σε άλλη μπορεί να είναι θανατηφόρο (κατάρρευση απουσία χειριστή). Η ποιοτική διαχείριση σφαλμάτων μετατρέπει δυνητικά θανατηφόρες καταστάσεις σε μη θανατηφόρες, αυξάνοντας τη σταθερότητα της εφαρμογής. Ο σχεδιασμός του συστήματος διαχείρισης σφαλμάτων είναι ένα από τα βασικά αρχιτεκτονικά καθήκοντα κατά την ανάπτυξη εφαρμογής κινητού με υψηλές απαιτήσεις αξιοπιστίας. Το ενσωματωμένο σύστημα παρακολούθησης επιτρέπει στην ομάδα να εντοπίζει και να διορθώνει γρήγορα τα μη θανατηφόρα σφάλματα προτού επηρεάσουν σημαντικό αριθμό χρηστών.
Firebase Crashlytics — το κύριο εργαλείο για την καταγραφή μη θανατηφόρων σφαλμάτων σε εφαρμογές κινητών. Η μέθοδος recordException επιτρέπει την καταγραφή μιας εξαίρεσης non-fatal με πλήρη στοίβα κλήσεων και πλαίσιο εκτέλεσης, χωρίς διακοπή της λειτουργίας της εφαρμογής. Σε αντίθεση με τις αναφορές κατάρρευσης, η recordException μπορεί να κληθεί σε οποιοδήποτε σημείο του κώδικα για καταγραφή εντοπισμένων εξαιρέσεων.
fun fetchUserData(userId: String) {
try {
val response = apiService.getUser(userId)
updateUI(response)
} catch (e: IOException) {
Crashlytics.log("Network error for user $userId")
Crashlytics.recordException(e)
showRetryDialog()
} catch (e: JsonParseException) {
// Non-fatal: χρησιμοποιούμε εφεδρικά δεδομένα
Crashlytics.recordException(e)
showFallbackContent()
}
}
// Καταγραφή με κλειδιά χρήστη
Crashlytics.setCustomKey("screen", "Profile")
Crashlytics.setCustomKey("api_version", "v3")
Sentry — εναλλακτική λύση για το Crashlytics με πιο λεπτομερή διάγνωση σφαλμάτων non-fatal. Το Sentry SDK παρέχει τη μέθοδο captureException, η οποία στέλνει τις λεπτομέρειες της εξαίρεσης στον διακομιστή. Το βασικό πλεονέκτημα του Sentry είναι η ομαδοποίηση παρόμοιων σφαλμάτων non-fatal σε ένα issue, η ανάλυση συχνότητας επανάληψης και το πλαίσιο εκτέλεσης με τη μορφή breadcrumbs — της ακολουθίας ενεργειών του χρήστη πριν από το σφάλμα.
Δεν χρειάζεται να καταγράφονται όλα τα σφάλματα non-fatal. Αναμενόμενες καταστάσεις — απουσία δικτύου όταν δεν υπάρχει σύνδεση — μπορούν να καταγράφονται επιλεκτικά. Απροσδόκητα σφάλματα — NullPointerException σε διαχειριζόμενο κώδικα, εσφαλμένη μορφή δεδομένων, logic error — πρέπει να καταγράφονται πάντα. Κάθε ομάδα καθορίζει το όριο σημαντικότητας: κατά μέσο όρο 10 έως 20 μοναδικά σφάλματα non-fatal ανά 1000 χρήστες την ημέρα θεωρείται φυσιολογικό. Είναι σημαντικό να ρυθμιστούν ειδοποιήσεις για απότομη αύξηση του αριθμού σφαλμάτων non-fatal — αυτό μπορεί να υποδεικνύει προβλήματα με τη νέα έκδοση API ή παλινδρόμηση μετά από έκδοση.
Ο βασικός μηχανισμός διαχείρισης — try-catch, ο οποίος εντοπίζει την εξαίρεση και εκτελεί τον κώδικα ανάκαμψης. Για λειτουργίες δικτύου, το τυπικό μοτίβο είναι η επανάληψη του αιτήματος με εκθετική καθυστέρηση (retry with backoff). Για σφάλματα ανάλυσης — χρήση προεπιλεγμένων εφεδρικών τιμών και καταγραφή του πλαισίου για μεταγενέστερη ανάλυση στην πλευρά του διακομιστή.
func loadImage(from url: URL) -> UIImage? {
do {
let data = try Data(contentsOf: url)
return UIImage(data: data)
} catch {
Logger.shared.logError(error: "Image load failed: \(url)")
return UIImage(named: "placeholder")
}
}
func performRequest() async throws -> Data {
var lastError: Error? = nil
for attempt in 0..<3 {
do {
return try await URLSession.shared.data(from: url)
} catch {
lastError = error
try await Task.sleep(UInt64(pow(2, attempt)) * 1_000_000_000)
}
}
throw lastError ?? URLError(.unknown)
}
Τύποι Result — εναλλακτική προσέγγιση χωρίς εξαιρέσεις. Η συνάρτηση επιστρέφει μια sealed class Result με παραλλαγές Success και Failure. Ο καλών κώδικας χειρίζεται και τις δύο παραλλαγές ρητά, γεγονός που εξαλείφει τα μη διαχειριζόμενα σφάλματα. Οι τύποι Result είναι δημοφιλείς στην Kotlin (Result
Για κάθε τύπο σφάλματος non-fatal πρέπει να προβλέπεται μια στρατηγική ανάκαμψης: φόρτωση προσωρινά αποθηκευμένων δεδομένων σε σφάλμα δικτύου, χρήση προεπιλεγμένων τιμών σε σφάλμα ανάλυσης, εκ νέου αρχικοποίηση του στοιχείου σε σφάλμα UI. Καλή πρακτική είναι η εμφάνιση toast ή snackbar με μήνυμα σφάλματος στον χρήστη, αλλά όχι ο πλήρης αποκλεισμός της αλληλεπίδρασης με την εφαρμογή. Είναι σημαντικό να γίνεται διάκριση μεταξύ ανακτήσιμων (recoverable) και μη ανακτήσιμων σφαλμάτων — για τα δεύτερα η στρατηγική ανάκαμψης θα είναι διαφορετική, για παράδειγμα, πρόταση επανεκκίνησης της οθόνης ή εκκαθάρισης δεδομένων. Η προσωρινή αποθήκευση της προηγούμενης επιτυχημένης κατάστασης συχνά αποδεικνύεται ο απλούστερος και αποτελεσματικότερος τρόπος διαχείρισης σφαλμάτων non-fatal σε πλατφόρμες κινητών.
Συχνές ερωτήσεις
Warning — είναι μια προειδοποίηση του μεταγλωττιστή ή στατικού αναλυτή για ένα πιθανό πρόβλημα στον κώδικα. Non-fatal error — είναι μια εξαίρεση χρόνου εκτέλεσης που έχει ήδη συμβεί αλλά δεν οδήγησε σε κατάρρευση. Το warning μπορεί να εξαλειφθεί πριν από τη μεταγλώττιση, το non-fatal error — να αντιμετωπιστεί κατά την εκτέλεση μέσω μπλοκ catch.
Όχι, η υπερβολική καταγραφή μολύνει την παρακολούθηση. Αξίζει να καταγράφονται απροσδόκητα σφάλματα στην παραγωγή και να αγνοούνται αναμενόμενες καταστάσεις: η απουσία δικτύου όταν δεν υπάρχει σύνδεση καταγράφεται επιλεκτικά, ενώ το NullPointerException σε διαχειριζόμενο κώδικα — πάντα. Κάθε ομάδα καθορίζει το όριο σημαντικότητας βάσει του πλαισίου της εφαρμογής.
Στο SwiftUI χρησιμοποιείται ObservableObject με πεδίο @Published errorState για παρακολούθηση της κατάστασης σφάλματος. Το View εγγράφεται σε αλλαγές και εμφανίζει εναλλακτικό περιεχόμενο. Πριν από το iOS 17 εφαρμοζόταν το Combine με χειριστές, από το iOS 17 — SwiftData και μακροεντολές @Observable για αντιδραστική ενημέρωση UI.
Ναι, αν το σφάλμα προκαλεί αλυσιδωτή αντίδραση. Παράδειγμα: μια μη θανατηφόρα αποτυχία φόρτωσης εικόνας μπορεί να οδηγήσει σε εσφαλμένη κατάσταση UI, η οποία στη συνέχεια προκαλεί κατάρρευση κατά την προσπάθεια εμφάνισης. Η ποιοτική διαχείριση σφαλμάτων non-fatal σε κάθε επίπεδο αποτρέπει την κλιμάκωσή τους σε θανατηφόρο επίπεδο.
Στο iOS, τα σφάλματα non-fatal αντιμετωπίζονται μέσω do-catch με throw, στο Android — μέσω try-catch με εξαιρέσεις. Το iOS χρησιμοποιεί NSError με τομείς και κωδικούς σφαλμάτων, το Android — εξαιρέσεις Java/Kotlin. Το Crashlytics λειτουργεί το ίδιο και στις δύο πλατφόρμες μέσω recordException, παρέχοντας ενοποιημένη διεπαφή για παρακολούθηση.
Περίληψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης