-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Il problema secondario ma non risolto perchè è un BrakingChange è in produzione, questo approccio alle use case basato sugli Either porta ad alcuni problemi:
- Sulla Failure bisogna mantenere lo StackTrace del punto di creazione della failure che se non è necessaria non serve e questo è molto pesante in termini di performance
- La gestione dell'Either e' complicata e prolissa anche quando dovrebbe essere molto semplice
Lanciare le Failure con throw porterebbe a notevoli vantaggi, le failure non gestite andrebbero direttamente sul logger e verebbe creato lo stackTrace solo quando il logger riceve l'errore inoltre i tipi sarabbero sicuri e la scrittura del codice verebbe piu breve e leggibile.
Either:
- 🔴 Più posti dove viene gestita la failure con lo stesso codice, si puo ovviare scrivendo estensioni apposta per i futuri
- 🔴 E' necessario controllare il tipo della failure con il costrutto
if ( is )per ogni failure - 🔴 Se non si vuole gestire la failure bisogna inviarla al logger ottenendo cosi uno stackTrace astruso
- 🟢 E' possibile utilizzare "facilmente" la use case con il pacchetto
providerma richiede una scrittura prolissa per il recupero del valorefinal res = context.read<Either<Failure, Success>>()e poco usabile/usato lato presentation
ThrowCatch: - 🟢 Un unico posto dove gestire la failure
- 🟢 Non è necessario controllare il tipo della failure dato che è presente la keywork
on - 🟢 Se non si vuole gestire la failure non serve far nulla, viene catturata dal logger con lo stackTrace corretto e chiaro
- 🟢 Non si ottiene codice anidadato o codice prolisso con molti controlli di tipo
- 🔴 Non sempre è possibile passare avanti nella catena l'errore, l'utilizzo diretto con il pacchetto
providernon è possibile. E' veramente necessario? No, dovresti passare sempre per ilblocappena la logica diventa complicata la quale necessita l'utilizzo diprovider
Sono mostrati solo esempi sicuri da scrivere, che non possono presentare errori di tipo
Con Either:
Esempio 1:
final result = await myUseCase.call(MyUseCaseParams());
result.fold((failure) {
if (failure is SpecificFailure) {
// Handle my specific failure
return;
}
// Handle a failure
}, (myRes) async {
final result = await myUseCase.call(MyUseCaseParams());
result.fold((failure) {
// Stesso codice della precedente gestione della failure
}, (myRes) {
// Hendle result
})
})Esempio 2:
final result = await myUseCase.call(MyUseCaseParams());
if (result is Left<Failure, MyResultType>) {
final failure = result.value;
if (failure is SpecificFailure) {
// Handle my specific failure
return;
}
// Handle a failure
return;
}
final result = await myUseCase.call(MyUseCaseParams());
if (result is Left<Failure, MyResultType>) {
// Stesso codice della precedente gestione della failure
return;
}
// Handle all resultsCon throw e catch
Esempio 3:
try {
final result = await myUseCase.call(MyUseCaseParams());
final result = await myUseCase.call(MyUseCaseParams());
} on SpecificFailure {
// Handle my specific failure
} on Failure {
// Handle failure
// Un unico posto dove gestire la failure
}- Ci sono altri vantaggi o svantaggi nell'uso di uno di questi due approcci?
- Per esperienza personale quale di questi approcci è stato più corretto e con meno bug?
Altri problemi conosciuti sono stati presentati in parte in questa PR #12.
Come dovresti far per recuperare la UI da un errore in aspettato con i diversi casi di utilizzo?
Con Either: Esempio 1:
try {
final result = await myUseCase.call(MyUseCaseParams());
result.fold((failure) {
if (failure is SpecificFailure) {
// Handle my specific failure
return;
}
// Handle a failure
}, (myRes) async {
// Hendle result
})
} catch (error) {
// Recupera la UI in caso fosse necessario
retrhow; // Invia l'errore al logger perchè non gestito
}Con throw e catch: Esempio 2:
try {
final result = await myUseCase.call(MyUseCaseParams());
} on Failure {
// Handle failure
} catch (error) {
// Recupera la UI in caso fosse necessario
retrhow; // Invia l'errore al logger perchè non gestito
}Non è molto chiaro mischiare i due casi di gestione dell'errore per quanto riguarda l'esempio 1 invece nell'esempio 2 rimane tutto molto chiaro