Skip to content

Instantly share code, notes, and snippets.

@MariaMelnik
Created October 29, 2020 15:52
Show Gist options
  • Save MariaMelnik/978369143ec7bab07fba94da94085160 to your computer and use it in GitHub Desktop.
Save MariaMelnik/978369143ec7bab07fba94da94085160 to your computer and use it in GitHub Desktop.
just for fun
import 'package:meta/meta.dart';
void runner() {
try {
repository();
} on RepositoryException catch (error, stackTrace) {
// Usually here you not only can log it but show some meaningfull information
// based on [RepositoryException.type]. So you don't even need to know how works // repository inside.
print('error: $error\nStackTrace:$stackTrace');
}
}
void repository() {
try {
provider();
// Usually repository called from logic for special business data.
// If we would know reason of that call we could provide better error handling here with
// meaningfull errors.
// But in this example we have what we have.
} on ProviderException catch (e, stackTrace) {
final resultStackTrace;
bool hasOrigStackTrace = e.stackTrace != null;
resultStackTrace = hasOrigStackTrace
? StackTrace.fromString(e.stackTrace.toString() + stackTrace.toString())
: stackTrace;
final exceptionType;
switch(e.type) {
case ProviderException.incorrectTocken:
exceptionType = RepositoryExceptionType.incorrectTocken;
break;
case ProviderException.noConnection:
exceptionType = RepositoryExceptionType.noConnection;
break;
case ProviderException.noAccess:
exceptionType = RepositoryExceptionType.noAccess;
break;
case ProviderException.noResourse:
exceptionType = RepositoryExceptionType.noResourse;
break;
case ProviderException.timeout:
exceptionType = RepositoryExceptionType.timeout;
break;
case ProviderException.unknown:
exceptionType = RepositoryExceptionType.unknown;
break;
}
throw RepositoryException(type: exceptionType, original: e, stackTrace: resultStackTrace);
} on dynamic catch (e, stackTrace) {
throw RepositoryException(type: RepositoryExceptionType.unknown);
}
}
void provider() {
try {
client();
// Usually provider catches original exception.
// But in this example for some reasons we have wrapper [ClientException] so continue // working with this.
} on ClientException catch (e, stackTrace) {
final resultStackTrace;
bool hasOrigStackTrace = e.stackTrace != null;
resultStackTrace = hasOrigStackTrace
? StackTrace.fromString(e.stackTrace.toString() + stackTrace.toString())
: stackTrace;
final exceptionType;
switch(e.type) {
case ClientExceptionType.incorrectTocken:
exceptionType = ProviderException.incorrectTocken;
break;
case ClientExceptionType.noConnection:
exceptionType = ProviderException.noConnection;
break;
case ClientExceptionType.noAccess:
exceptionType = ProviderException.noAccess;
break;
case ClientExceptionType.noResourse:
exceptionType = ProviderException.noResourse;
break;
case ClientExceptionType.timeout:
exceptionType = ProviderException.timeout;
break;
case ClientExceptionType.unknown:
exceptionType = ProviderException.unknown;
break;
}
throw ProviderException(type: exceptionType, original: e, stackTrace: resultStackTrace);
} on dynamic catch (e, stackTrace) {
throw ProviderException(type: ProviderExceptionType.unknown);
}
}
void client() {
// Usually client never throws any wrapped exception.
// Don't know why it is done here this way.
throw ClientException();
}
/// It looks litle bit silly to have RepositoryException wrapper.
/// Because no need to wrap any client's exception.
/// Usually wrappers are meaningfull and depends on operation user would like to achive,
/// but now with "layers" he touches.
class RepositoryException extends MariaException {
final RepositoryExceptionType type;
const ClientException({
@required this.type,
Object original,
StackTrace stackTrace
}) : super(error: original, stackTrace: stackTrace)
}
/// It looks litle bit silly to have ProviderException wrapper.
/// Because no need to wrap any client's exception.
/// Usually wrappers are meaningfull and depends on operation user would like to achive,
/// but now with "layers" he touches.
class ProviderException extends MariaException {
final ProviderExceptionType type;
const ProviderException({
@required this.type,
Object original,
StackTrace stackTrace
}) : super(error: original, stackTrace: stackTrace)
}
/// It looks litle bit silly to have ClientException wrapper.
/// Because no need to wrap any client's exception.
/// Usually wrappers are meaningfull and depends on operation user would like to achive,
/// but now with "layers" he touches.
class ClientException extends MariaException {
final ClientExceptionType type;
const ClientException({
@required this.type,
Object original,
StackTrace stackTrace
}) : super(error: original, stackTrace: stackTrace)
}
abstract class MariaException implements Exception {
final Object error;
final StackTrace stackTrace;
const MariaException({this.error, this.stackTrace});
}
enum ClientExceptionType{
incorrectTocken,
noConnection,
noAccess,
noResourse,
timeout,
unknown
}
enum ProviderExceptionType{
incorrectTocken,
noConnection,
noAccess,
noResourse,
timeout,
unknown
}
enum RepositoryExceptionType{
incorrectTocken,
noConnection,
noAccess,
noResourse,
timeout,
unknown
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment