refactor(architecture)!: rework/modernize wyatt architecture

This commit is contained in:
Hugo Pointcheval 2023-10-12 21:17:11 +02:00
parent 993c8b60ac
commit 4b04a3acdf
Signed by: hugo
GPG Key ID: 3AAC487E131E00BC
19 changed files with 115 additions and 257 deletions

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP // Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details. // Please see the AUTHORS file for details.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP // Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details. // Please see the AUTHORS file for details.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
@ -14,24 +14,43 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
/// {@template app_exception} /// {@template app_exception}
/// [AppException] is a base class for all exceptions in the wyatt architecture. /// [AppException] is a base class for all exceptions in the wyatt architecture.
/// {@endtemplate} /// {@endtemplate}
abstract class AppException implements Exception { abstract class AppException implements Exception {
/// {@macro app_exception} /// {@macro app_exception}
const AppException([this.message]); const AppException({this.message, this.underlyingException});
/// {@macro app_exception}
///
/// Constructs an [AppException] from an [Exception].
factory AppException.from(Object e) {
if (e is AppException) {
return e;
} else {
return ClientException(underlyingException: e);
}
}
/// The message of the exception.
final String? message; final String? message;
/// The exception which triggered this exception being thrown.
final Object? underlyingException;
@override @override
String toString() { String toString() {
if (message.isNotNullOrEmpty) { final str = StringBuffer(runtimeType.toString());
return '$runtimeType: $message'; if (message != null && message!.isNotEmpty) {
str.write(': $message');
} else { } else {
return '$runtimeType: An exception occured'; str.write(': An exception occured');
} }
if (underlyingException != null) {
str.write('\n$underlyingException');
}
return str.toString();
} }
} }
@ -41,7 +60,7 @@ abstract class AppException implements Exception {
/// {@endtemplate} /// {@endtemplate}
class ClientException extends AppException { class ClientException extends AppException {
/// {@macro client_exception} /// {@macro client_exception}
const ClientException([super.message]); const ClientException({super.message, super.underlyingException});
} }
/// {@template server_exception} /// {@template server_exception}
@ -50,5 +69,5 @@ class ClientException extends AppException {
/// {@endtemplate} /// {@endtemplate}
class ServerException extends AppException { class ServerException extends AppException {
/// {@macro server_exception} /// {@macro server_exception}
const ServerException([super.message]); const ServerException({super.message, super.underlyingException});
} }

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP // Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details. // Please see the AUTHORS file for details.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
@ -14,4 +14,4 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'entity.dart'; export 'data_sources/data_sources.dart';

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP // Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details. // Please see the AUTHORS file for details.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP // Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details. // Please see the AUTHORS file for details.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
@ -15,5 +15,5 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'base_data_source.dart'; export 'base_data_source.dart';
export 'local/local.dart'; export 'local/base_local_data_source.dart';
export 'remote/remote.dart'; export 'remote/base_remote_data_source.dart';

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP // Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details. // Please see the AUTHORS file for details.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/src/domain/data_sources/base_data_source.dart'; import 'package:wyatt_architecture/src/data/data_sources/base_data_source.dart';
/// {@template base_local_data_source} /// {@template base_local_data_source}
/// [BaseLocalDataSource] is a base class for all local data sources in the /// [BaseLocalDataSource] is a base class for all local data sources in the

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP // Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details. // Please see the AUTHORS file for details.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/src/domain/data_sources/base_data_source.dart'; import 'package:wyatt_architecture/src/data/data_sources/base_data_source.dart';
/// {@template base_remote_data_source} /// {@template base_remote_data_source}
/// [BaseRemoteDataSource] is a base class for all remote data sources in the /// [BaseRemoteDataSource] is a base class for all remote data sources in the

View File

@ -1,17 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'base_local_data_source.dart';

View File

@ -1,17 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'base_remote_data_source.dart';

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP // Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details. // Please see the AUTHORS file for details.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'data_sources/data_sources.dart'; export 'entities/entity.dart';
export 'entities/entities.dart'; export 'repositories/base_repository.dart';
export 'repositories/repositories.dart';
export 'usecases/usecases.dart'; export 'usecases/usecases.dart';

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP // Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details. // Please see the AUTHORS file for details.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP // Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details. // Please see the AUTHORS file for details.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify

View File

@ -1,17 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'base_repository.dart';

View File

@ -1,26 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/src/domain/entities/entity.dart';
/// {@template no_param}
/// [NoParam] is a class that is used when a use case does not require any
/// parameters.
/// {@endtemplate}
class NoParam extends Entity {
/// {@macro no_param}
const NoParam();
}

View File

@ -1,45 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'dart:async';
import 'package:wyatt_architecture/wyatt_architecture.dart';
/// Usecase observers
mixin Observer<Parameters, ReturnType> {
/// Called before usecase is runned.
/// Useful to check the preconditions
FutureOr<void> onStart(Parameters? params) {}
/// Called when error occures during main scenario
/// Useful to run alternative scenario
FutureOr<void> onError(AppException? error) {}
}
/// Specific observer for classic usecase
mixin AsyncObserver<ReturnType> {
/// Called when usecase is completed
FutureOr<void> onComplete(ReturnType? data) {}
}
/// Specific observer for stream case usecase
mixin StreamObserver<ReturnType> {
/// Replaces the data event handler of this subscription.
void onDone() {}
/// Replaces the done event handler of this subscription.
void onData(ReturnType? data) {}
}

View File

@ -1,100 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'dart:async';
import 'package:wyatt_architecture/src/core/exceptions/exceptions.dart';
import 'package:wyatt_architecture/src/domain/usecases/observers.dart';
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
typedef FutureOrResult<T> = FutureOr<Result<T, AppException>>;
typedef StreamResult<T> = Stream<Result<T, AppException>>;
/// {@template base_usecase}
/// Abstract class of any use case.
/// {@endtemplate}
abstract class BaseUseCase<Parameters, ReturnType> {
/// {@macro base_usecase}
const BaseUseCase();
/// Run use case scenarios
ReturnType call(Parameters parameters);
/// Private function to implement main scenario
/// of your usecase.
ReturnType execute(Parameters params);
}
/// {@template usecase}
/// Abstract class of a use case that deals specifically
/// with the response and its state.
/// {@endtemplate}
abstract class UseCase<Parameters, ReturnType>
extends BaseUseCase<Parameters?, FutureOrResult<ReturnType>>
with Observer<Parameters, ReturnType> {
/// {@macro usecase}
const UseCase();
FutureOr<void> _onSuccess(ReturnType data);
/// Supports the result of the main scenario and integrates
/// some alternative scenarios if necessary.
@override
FutureOrResult<ReturnType> call(Parameters? parameters) async {
try {
await onStart(parameters);
final response = await execute(parameters);
if (response.isErr) {
await onError(response.err);
} else if (response.isOk && response.ok != null) {
await _onSuccess(response.ok as ReturnType);
}
return response;
} catch (e) {
return Err(ClientException(e.toString()));
}
}
}
/// {@template async_usecase}
/// Abtstract classic usecase bases on futures
/// {@endtemplate}
abstract class AsyncUseCase<Parameters, ReturnType>
extends UseCase<Parameters?, ReturnType> with AsyncObserver<ReturnType> {
/// {@macro async_usecase}
const AsyncUseCase();
@override
FutureOr<void> _onSuccess(ReturnType data) => onComplete(data);
}
/// {@template stream_usecase}
/// Abstract specific usecase bases on streams
/// {@endtemplate}
abstract class StreamUseCase<Parameters, ReturnType>
extends UseCase<Parameters?, Stream<ReturnType>>
with StreamObserver<ReturnType> {
/// {@macro stream_usecase}
const StreamUseCase();
@override
FutureOr<void> _onSuccess(Stream<ReturnType> data) {
data.listen(
onData,
onDone: onDone,
);
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP // Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details. // Please see the AUTHORS file for details.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
@ -14,6 +14,67 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'no_param.dart'; import 'dart:async';
export 'observers.dart';
export 'usecase.dart'; import 'package:generic_usecase/generic_usecase.dart' as uc;
import 'package:sealed_result/sealed_result.dart';
import 'package:wyatt_architecture/src/core/exceptions/exceptions.dart';
typedef FutureOrResult<T> = FutureOr<Result<T, AppException>>;
typedef StreamResult<T> = Stream<Result<T, AppException>>;
/// {@template result_usecase}
/// A usecase that requires params of type [Input] and returns a result of type
/// [Output] or an error of type [AppException].
/// {@endtemplate}
abstract class Usecase<Input, Output>
extends uc.Usecase<Input, Result<Output, AppException>> {
/// {@macro result_usecase}
const Usecase() : super();
@override
FutureOrResult<Output> onException(Object e) =>
Result.err(AppException.from(e));
}
/// {@template no_params_result_usecase}
/// A usecase that does not require any params, but returns a result of type
/// [Output] or an error of type [AppException].
/// {@endtemplate}
abstract class NoParamsUsecase<Output>
extends uc.NoParamsUsecase<Result<Output, AppException>> {
/// {@macro no_params_result_usecase}
const NoParamsUsecase() : super();
@override
FutureOrResult<Output> onException(Object e) =>
Result.err(AppException.from(e));
}
/// {@template result_stream_usecase}
/// A stream usecase that requires params of type [Input] and returns a
/// stream of [Output] or [AppException].
/// {@endtemplate}
abstract class StreamUsecase<Input, Output>
extends uc.StreamUsecase<Input, Result<Output, AppException>> {
/// {@macro result_stream_usecase}
const StreamUsecase() : super();
@override
FutureOrResult<Output> onException(Object e) =>
Result.err(AppException.from(e));
}
/// {@template no_params_result_stream_usecase}
/// A stream usecase that does not require any params, but returns a
/// stream of [Output] or [AppException].
/// {@endtemplate}
abstract class NoParamsStreamUsecase<Output>
extends uc.NoParamsStreamUsecase<Result<Output, AppException>> {
/// {@macro no_params_result_stream_usecase}
const NoParamsStreamUsecase() : super();
@override
FutureOrResult<Output> onException(Object e) =>
Result.err(AppException.from(e));
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP // Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details. // Please see the AUTHORS file for details.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
@ -15,4 +15,5 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'core/core.dart'; export 'core/core.dart';
export 'data/data.dart';
export 'domain/domain.dart'; export 'domain/domain.dart';

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP // Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details. // Please see the AUTHORS file for details.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify