diff --git a/packages/wyatt_architecture/README.md b/packages/wyatt_architecture/README.md index 6a0e2acb..2ca22855 100644 --- a/packages/wyatt_architecture/README.md +++ b/packages/wyatt_architecture/README.md @@ -7,7 +7,7 @@ * 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, + * 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. @@ -31,10 +31,10 @@ The Wyatt Architecture for Flutter. ## Features -* Usecase -* Repository -* DataSource -* Entity +- Usecase +- Repository +- DataSource +- Entity ## Usage @@ -73,19 +73,20 @@ abstract class PhotoRepository extends BaseRepository { } ``` -> Here the repository is just a proxy of the data sources with result type (to have beautiful error handling). +> Here the repository is just a proxy of the data sources with result type (to have beautiful error handling). -And finaly create your different usecases by using `UseCase` : +And finaly create your different usecases : + +Several use cases are supported : + +- Classic usecase : ```dart -class RetrieveAllPhoto extends UseCase> { - final PhotoRepository _photoRepository; - - RetrieveAllPhotos(this._photoRepository); +class Test extends AsyncUseCase>> { @override - FutureResult> call(QueryParameters params) { - final photos = _photoRepository.getAllPhotos( + FuturOrResult>> call(QueryParameters? params) { + final photos = _photoRepository.getAllPhotos( start: params.start, limit: params.limit, ); @@ -94,6 +95,54 @@ class RetrieveAllPhoto extends UseCase> { } ``` +You can add alternatve scenarios and check pre/post conditions using our extensions : + +```dart +class SearchPhotos extends AsyncUseCase>> { + + @override + FutureOrResult>> call(QueryParameters? params) { + final photos = _photoRepository.getAllPhotos( + start: params.start, + limit: params.limit, + ); + return photos; + } + + + @override + FutureOr onStart(QueryParameters? params) { + if(params.start == null || params.limit == null){ + throw ClientException('Préconndition non valides'); + } + } + +} +``` + +You can implement error scenarios overriding `onError`, or check postconditions by overriding `onComplete` . + +- Stream usecase : + +```dart +class SearchPhotos extends StreamUseCase>> { + + @override + FutureOrResult>>> call(QueryParameters? params) { + final photos = _photoRepository.getAllPhotos( + start: params.start, + limit: params.limit, + ); + return photos; + } + +} +``` + +On this case, observers allow you to add alternative scénarios when data changed, overriding `onData` or `onDone`. + +Please note that to use handlers, call `execute` methodes instead of `call`. + > In fact, here we need a new parameter object, so let's create it: ```dart @@ -171,4 +220,4 @@ class PhotoRepositoryImpl extends PhotoRepository { } ``` -That's all. \ No newline at end of file +That's all. diff --git a/packages/wyatt_architecture/example/lib/data/repositories/photo_repository_impl.dart b/packages/wyatt_architecture/example/lib/data/repositories/photo_repository_impl.dart index 3f85aff2..7cec10fa 100644 --- a/packages/wyatt_architecture/example/lib/data/repositories/photo_repository_impl.dart +++ b/packages/wyatt_architecture/example/lib/data/repositories/photo_repository_impl.dart @@ -35,46 +35,47 @@ class PhotoRepositoryImpl extends PhotoRepository { ); @override - FutureResult addPhotoToFavorites(Photo photo) => Result.tryCatchAsync( + FutureOrResult addPhotoToFavorites(Photo photo) => Result.tryCatchAsync( () => _favoriteLocalDataSource.addPhotoToFavorites(photo), (error) => ClientException('Cannot add photo to favorites.'), ); @override - FutureResult checkIfPhotoIsInFavorites(int id) => Result.tryCatchAsync( + FutureOrResult checkIfPhotoIsInFavorites(int id) => + Result.tryCatchAsync( () => _favoriteLocalDataSource.checkIfPhotoIsInFavorites(id), (error) => ClientException('Cannot check if photo `$id` is in favorites.'), ); @override - FutureResult deletePhotoFromFavorites(int id) => Result.tryCatchAsync( + FutureOrResult deletePhotoFromFavorites(int id) => Result.tryCatchAsync( () => _favoriteLocalDataSource.deletePhotoFromFavorites(id), (error) => ClientException('Cannot delete photo `$id` from favorites.'), ); @override - FutureResult getAlbum(int id) => Result.tryCatchAsync( + FutureOrResult getAlbum(int id) => Result.tryCatchAsync( () => _albumRemoteDataSource.getAlbum(id), (error) => ServerException('Cannot retrieve album $id.'), ); @override - FutureResult> getAllAlbums({int? start, int? limit}) => + FutureOrResult> getAllAlbums({int? start, int? limit}) => Result.tryCatchAsync( () => _albumRemoteDataSource.getAllAlbums(start: start, limit: limit), (error) => ServerException('Cannot retrieve all albums.'), ); @override - FutureResult> getAllPhotos({int? start, int? limit}) async => + FutureOrResult> getAllPhotos({int? start, int? limit}) async => Result.tryCatchAsync( () => _photoRemoteDataSource.getAllPhotos(start: start, limit: limit), (error) => ServerException('Cannot retrieve all photos.'), ); @override - FutureResult> getAllPhotosFromFavorites() async { + FutureOrResult> getAllPhotosFromFavorites() async { try { final response = []; final favorites = @@ -95,13 +96,13 @@ class PhotoRepositoryImpl extends PhotoRepository { } @override - FutureResult getPhoto(int id) => Result.tryCatchAsync( + FutureOrResult getPhoto(int id) => Result.tryCatchAsync( () => _photoRemoteDataSource.getPhoto(id), (error) => ServerException('Cannot retrieve photo $id.'), ); @override - FutureResult> getPhotosFromAlbum( + FutureOrResult> getPhotosFromAlbum( int albumId, { int? start, int? limit, diff --git a/packages/wyatt_architecture/example/lib/domain/repositories/photo_repository.dart b/packages/wyatt_architecture/example/lib/domain/repositories/photo_repository.dart index b57b4689..7bc195ea 100644 --- a/packages/wyatt_architecture/example/lib/domain/repositories/photo_repository.dart +++ b/packages/wyatt_architecture/example/lib/domain/repositories/photo_repository.dart @@ -19,17 +19,17 @@ import 'package:architecture_example/domain/entities/photo.dart'; import 'package:wyatt_architecture/wyatt_architecture.dart'; abstract class PhotoRepository extends BaseRepository { - FutureResult getAlbum(int id); - FutureResult> getAllAlbums({int? start, int? limit}); - FutureResult getPhoto(int id); - FutureResult> getAllPhotos({int? start, int? limit}); - FutureResult> getPhotosFromAlbum( + FutureOrResult getAlbum(int id); + FutureOrResult> getAllAlbums({int? start, int? limit}); + FutureOrResult getPhoto(int id); + FutureOrResult> getAllPhotos({int? start, int? limit}); + FutureOrResult> getPhotosFromAlbum( int albumId, { int? start, int? limit, }); - FutureResult addPhotoToFavorites(Photo photo); - FutureResult deletePhotoFromFavorites(int id); - FutureResult> getAllPhotosFromFavorites(); - FutureResult checkIfPhotoIsInFavorites(int id); + FutureOrResult addPhotoToFavorites(Photo photo); + FutureOrResult deletePhotoFromFavorites(int id); + FutureOrResult> getAllPhotosFromFavorites(); + FutureOrResult checkIfPhotoIsInFavorites(int id); } diff --git a/packages/wyatt_architecture/example/lib/domain/usecases/photos/add_photo_to_favorites.dart b/packages/wyatt_architecture/example/lib/domain/usecases/photos/add_photo_to_favorites.dart index 7e88cdc3..7a936d44 100644 --- a/packages/wyatt_architecture/example/lib/domain/usecases/photos/add_photo_to_favorites.dart +++ b/packages/wyatt_architecture/example/lib/domain/usecases/photos/add_photo_to_favorites.dart @@ -1,31 +1,40 @@ // 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 . +import 'dart:async'; + import 'package:architecture_example/domain/entities/photo.dart'; import 'package:architecture_example/domain/repositories/photo_repository.dart'; import 'package:wyatt_architecture/wyatt_architecture.dart'; -class AddPhotoToFavorites extends UseCase> { +class AddPhotoToFavorites extends AsyncUseCase> { final PhotoRepository _photoRepository; AddPhotoToFavorites(this._photoRepository); @override - FutureResult> call(Photo params) async { - await _photoRepository.addPhotoToFavorites(params); + FutureOrResult> call(Photo? params) async { + await _photoRepository.addPhotoToFavorites(params!); return _photoRepository.getAllPhotosFromFavorites(); } + + @override + FutureOr onStart(Photo? params) { + if (params == null) { + throw ClientException('Photo cannot be null'); + } + } } diff --git a/packages/wyatt_architecture/example/lib/domain/usecases/photos/check_if_photo_is_in_favorites.dart b/packages/wyatt_architecture/example/lib/domain/usecases/photos/check_if_photo_is_in_favorites.dart index d955d4f1..1bb9efd9 100644 --- a/packages/wyatt_architecture/example/lib/domain/usecases/photos/check_if_photo_is_in_favorites.dart +++ b/packages/wyatt_architecture/example/lib/domain/usecases/photos/check_if_photo_is_in_favorites.dart @@ -14,15 +14,24 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +import 'dart:async'; + import 'package:architecture_example/domain/repositories/photo_repository.dart'; import 'package:wyatt_architecture/wyatt_architecture.dart'; -class CheckIfPhotoIsInFavorites extends UseCase { +class CheckIfPhotoIsInFavorites extends AsyncUseCase { final PhotoRepository _photoRepository; CheckIfPhotoIsInFavorites(this._photoRepository); @override - FutureResult call(int params) async => - _photoRepository.checkIfPhotoIsInFavorites(params); + FutureOrResult call(int? params) async => + _photoRepository.checkIfPhotoIsInFavorites(params!); + + @override + FutureOr onStart(int? params) { + if (params == null) { + throw ClientException('id cannot be null'); + } + } } diff --git a/packages/wyatt_architecture/example/lib/domain/usecases/photos/display_favorites.dart b/packages/wyatt_architecture/example/lib/domain/usecases/photos/display_favorites.dart index 545c09e5..733e2dbd 100644 --- a/packages/wyatt_architecture/example/lib/domain/usecases/photos/display_favorites.dart +++ b/packages/wyatt_architecture/example/lib/domain/usecases/photos/display_favorites.dart @@ -1,16 +1,16 @@ // 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 . @@ -18,13 +18,13 @@ import 'package:architecture_example/domain/entities/photo.dart'; import 'package:architecture_example/domain/repositories/photo_repository.dart'; import 'package:wyatt_architecture/wyatt_architecture.dart'; -class DisplayFavorites extends UseCase> { +class DisplayFavorites extends AsyncUseCase> { final PhotoRepository _photoRepository; DisplayFavorites(this._photoRepository); @override - FutureResult> call(void params) { + FutureOrResult> call(void params) { final photos = _photoRepository.getAllPhotosFromFavorites(); return photos; } diff --git a/packages/wyatt_architecture/example/lib/domain/usecases/photos/display_photo.dart b/packages/wyatt_architecture/example/lib/domain/usecases/photos/display_photo.dart index 3c5da43d..3a41eeb2 100644 --- a/packages/wyatt_architecture/example/lib/domain/usecases/photos/display_photo.dart +++ b/packages/wyatt_architecture/example/lib/domain/usecases/photos/display_photo.dart @@ -14,18 +14,27 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +import 'dart:async'; + import 'package:architecture_example/domain/entities/photo.dart'; import 'package:architecture_example/domain/repositories/photo_repository.dart'; import 'package:wyatt_architecture/wyatt_architecture.dart'; -class DisplayPhoto extends UseCase { +class DisplayPhoto extends AsyncUseCase { final PhotoRepository _photoRepository; DisplayPhoto(this._photoRepository); @override - FutureResult call(int params) { - final photo = _photoRepository.getPhoto(params); + FutureOrResult call(int? params) { + final photo = _photoRepository.getPhoto(params!); return photo; } + + @override + FutureOr onStart(int? params) { + if (params == null) { + throw ClientException('id cannot be null'); + } + } } diff --git a/packages/wyatt_architecture/example/lib/domain/usecases/photos/open_album.dart b/packages/wyatt_architecture/example/lib/domain/usecases/photos/open_album.dart index 926d5331..a1053a15 100644 --- a/packages/wyatt_architecture/example/lib/domain/usecases/photos/open_album.dart +++ b/packages/wyatt_architecture/example/lib/domain/usecases/photos/open_album.dart @@ -14,24 +14,33 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +import 'dart:async'; + import 'package:architecture_example/domain/entities/photo.dart'; import 'package:architecture_example/domain/repositories/photo_repository.dart'; import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart'; import 'package:wyatt_architecture/wyatt_architecture.dart'; -class OpenAlbum extends UseCase> { +class OpenAlbum extends AsyncUseCase> { final PhotoRepository _photoRepository; OpenAlbum(this._photoRepository); @override - FutureResult> call(QueryParameters params) { + FutureOrResult> call(QueryParameters? params) { final photos = _photoRepository.getPhotosFromAlbum( - params.albumId, + params!.albumId, start: params.start, limit: params.limit, ); return photos; } + + @override + FutureOr onStart(QueryParameters? params) { + if (params == null) { + throw ClientException('params cannot be null'); + } + } } diff --git a/packages/wyatt_architecture/example/lib/domain/usecases/photos/remove_photo_from_favorites.dart b/packages/wyatt_architecture/example/lib/domain/usecases/photos/remove_photo_from_favorites.dart index 90012646..e706beea 100644 --- a/packages/wyatt_architecture/example/lib/domain/usecases/photos/remove_photo_from_favorites.dart +++ b/packages/wyatt_architecture/example/lib/domain/usecases/photos/remove_photo_from_favorites.dart @@ -14,18 +14,27 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +import 'dart:async'; + import 'package:architecture_example/domain/entities/photo.dart'; import 'package:architecture_example/domain/repositories/photo_repository.dart'; import 'package:wyatt_architecture/wyatt_architecture.dart'; -class RemovePhotoFromFavorites extends UseCase> { +class RemovePhotoFromFavorites extends AsyncUseCase> { final PhotoRepository _photoRepository; RemovePhotoFromFavorites(this._photoRepository); @override - FutureResult> call(int params) async { - await _photoRepository.deletePhotoFromFavorites(params); + FutureOrResult> call(int? params) async { + await _photoRepository.deletePhotoFromFavorites(params!); return _photoRepository.getAllPhotosFromFavorites(); } + + @override + FutureOr onStart(int? params) { + if (params == null) { + throw ClientException('id cannot be null'); + } + } } diff --git a/packages/wyatt_architecture/example/lib/domain/usecases/photos/retrieve_all_albums.dart b/packages/wyatt_architecture/example/lib/domain/usecases/photos/retrieve_all_albums.dart index c8a02e86..560abe93 100644 --- a/packages/wyatt_architecture/example/lib/domain/usecases/photos/retrieve_all_albums.dart +++ b/packages/wyatt_architecture/example/lib/domain/usecases/photos/retrieve_all_albums.dart @@ -14,22 +14,31 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +import 'dart:async'; + import 'package:architecture_example/domain/entities/album.dart'; import 'package:architecture_example/domain/repositories/photo_repository.dart'; import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart'; import 'package:wyatt_architecture/wyatt_architecture.dart'; -class RetrieveAllAlbums extends UseCase> { +class RetrieveAllAlbums extends AsyncUseCase> { final PhotoRepository _photoRepository; RetrieveAllAlbums(this._photoRepository); @override - FutureResult> call(QueryParameters params) { + FutureOrResult> call(QueryParameters? params) { final albums = _photoRepository.getAllAlbums( - start: params.start, + start: params!.start, limit: params.limit, ); return albums; } + + @override + FutureOr onStart(QueryParameters? params) { + if (params == null) { + throw ClientException('params cannot be null'); + } + } } diff --git a/packages/wyatt_architecture/lib/src/domain/usecases/observers.dart b/packages/wyatt_architecture/lib/src/domain/usecases/observers.dart new file mode 100644 index 00000000..370546fe --- /dev/null +++ b/packages/wyatt_architecture/lib/src/domain/usecases/observers.dart @@ -0,0 +1,44 @@ +// 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 . + +import 'dart:async'; + +import 'package:wyatt_architecture/wyatt_architecture.dart'; + +/// Usecase observers +mixin Observer { + /// Called before usecase is runned. + /// Usefull to check the preconditions + FutureOr onStart(Parameters? params) {} + + /// Called when error occures during main scenario + /// Usefull to run alternative scenario + FutureOr onError(AppException? error) {} +} + +/// Specific observer for classic usecase +mixin AsyncObserver { + FutureOr onComplete(ReturnType? data) {} +} + +/// Specific observer for stream case usecase +mixin StreamObserver { + /// Replaces the data event handler of this subscription. + void onDone() {} + + /// Replaces the done event handler of this subscription. + void onData(ReturnType? data) {} +} diff --git a/packages/wyatt_architecture/lib/src/domain/usecases/usecase.dart b/packages/wyatt_architecture/lib/src/domain/usecases/usecase.dart index 3e2a39f4..893e962b 100644 --- a/packages/wyatt_architecture/lib/src/domain/usecases/usecase.dart +++ b/packages/wyatt_architecture/lib/src/domain/usecases/usecase.dart @@ -1,27 +1,80 @@ // 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 . +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 FutureResult = Future>; +typedef FutureOrResult = FutureOr>; typedef StreamResult = Stream>; -typedef Res = Result; -// ignore: one_member_abstracts -abstract class UseCase { - FutureResult call(Parameters params); +/// Abstract class of a use case +abstract class BaseUseCase { + /// Run use case scenarios + ReturnType execute(Parameters parameters); + + /// Private function to implement main scenario + /// of your usecase. + ReturnType call(Parameters params); +} + +/// Abstract class of a use case that deals specifically +/// with the response and its state. +abstract class UseCase + extends BaseUseCase> + with Observer { + FutureOr _onSuccess(ReturnType data); + + /// Supports the result of the main scenario and integrates + /// some alternative scenarios if necessary. + @override + FutureOrResult execute(Parameters? parameters) async { + try { + await onStart(parameters); + final response = await call(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())); + } + } +} + +/// Abtstract classic usecase. +abstract class AsyncUseCase + extends UseCase with AsyncObserver { + @override + FutureOr _onSuccess(ReturnType data) => onComplete(data); +} + +/// Abstract specific usecase bases on streams +abstract class StreamUseCase + extends UseCase> + with StreamObserver { + @override + FutureOr _onSuccess(Stream data) { + data.listen( + onData, + onDone: onDone, + ); + } } diff --git a/packages/wyatt_architecture/lib/src/domain/usecases/usecases.dart b/packages/wyatt_architecture/lib/src/domain/usecases/usecases.dart index 593f9df9..445b2682 100644 --- a/packages/wyatt_architecture/lib/src/domain/usecases/usecases.dart +++ b/packages/wyatt_architecture/lib/src/domain/usecases/usecases.dart @@ -15,4 +15,5 @@ // along with this program. If not, see . export 'no_param.dart'; +export 'observers.dart'; export 'usecase.dart'; diff --git a/packages/wyatt_architecture/models/class_model.png b/packages/wyatt_architecture/models/class_model.png new file mode 100644 index 00000000..ce666665 Binary files /dev/null and b/packages/wyatt_architecture/models/class_model.png differ diff --git a/packages/wyatt_architecture/models/class_model.puml b/packages/wyatt_architecture/models/class_model.puml new file mode 100644 index 00000000..d8f143b6 --- /dev/null +++ b/packages/wyatt_architecture/models/class_model.puml @@ -0,0 +1,86 @@ +@startuml +set namespaceSeparator :: + +abstract class "wyatt_architecture::src::core::exceptions::exceptions.dart::AppException" { + +String? message + +String toString() +} + +"dart::core::Exception" <|-- "wyatt_architecture::src::core::exceptions::exceptions.dart::AppException" + +class "wyatt_architecture::src::core::exceptions::exceptions.dart::ClientException" { +} + +"wyatt_architecture::src::core::exceptions::exceptions.dart::AppException" <|-- "wyatt_architecture::src::core::exceptions::exceptions.dart::ClientException" +class "wyatt_architecture::src::core::exceptions::exceptions.dart::ServerException" { +} + +"wyatt_architecture::src::core::exceptions::exceptions.dart::AppException" <|-- "wyatt_architecture::src::core::exceptions::exceptions.dart::ServerException" + +abstract class "wyatt_architecture::src::domain::repositories::base_repository.dart::BaseRepository" { +} + +abstract class "wyatt_architecture::src::domain::data_sources::local::base_local_data_source.dart::BaseLocalDataSource" { +} + +"wyatt_architecture::src::domain::data_sources::base_data_source.dart::BaseDataSource" <|-- "wyatt_architecture::src::domain::data_sources::local::base_local_data_source.dart::BaseLocalDataSource" + +abstract class "wyatt_architecture::src::domain::data_sources::base_data_source.dart::BaseDataSource" { +} + +abstract class "wyatt_architecture::src::domain::data_sources::remote::base_remote_data_source.dart::BaseRemoteDataSource" { +} + +"wyatt_architecture::src::domain::data_sources::base_data_source.dart::BaseDataSource" <|-- "wyatt_architecture::src::domain::data_sources::remote::base_remote_data_source.dart::BaseRemoteDataSource" + +class "wyatt_architecture::src::domain::usecases::no_param.dart::NoParam" { +} + +"wyatt_architecture::src::domain::entities::entity.dart::Entity" <|-- "wyatt_architecture::src::domain::usecases::no_param.dart::NoParam" + +abstract class "wyatt_architecture::src::domain::usecases::observers.dart::Observer" { + +FutureOr onStart() + +FutureOr onError() +} + +abstract class "wyatt_architecture::src::domain::usecases::observers.dart::AsyncObserver" { + +FutureOr onComplete() +} + +abstract class "wyatt_architecture::src::domain::usecases::observers.dart::StreamObserver" { + +void onDone() + +void onData() +} + +abstract class "wyatt_architecture::src::domain::usecases::usecase.dart::BaseUseCase" { + +ReturnType execute() + +ReturnType call() +} + +abstract class "wyatt_architecture::src::domain::usecases::usecase.dart::UseCase" { + -FutureOr _onSuccess() + +FutureOr> execute() +} + +"wyatt_architecture::src::domain::usecases::usecase.dart::BaseUseCase" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::UseCase" +"wyatt_architecture::src::domain::usecases::observers.dart::Observer" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::UseCase" + +abstract class "wyatt_architecture::src::domain::usecases::usecase.dart::AsyncUseCase" { + -FutureOr _onSuccess() +} + +"wyatt_architecture::src::domain::usecases::usecase.dart::UseCase" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::AsyncUseCase" +"wyatt_architecture::src::domain::usecases::observers.dart::AsyncObserver" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::AsyncUseCase" + +abstract class "wyatt_architecture::src::domain::usecases::usecase.dart::StreamUseCase" { + -FutureOr _onSuccess() +} + +"wyatt_architecture::src::domain::usecases::usecase.dart::UseCase" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::StreamUseCase" +"wyatt_architecture::src::domain::usecases::observers.dart::StreamObserver" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::StreamUseCase" + +abstract class "wyatt_architecture::src::domain::entities::entity.dart::Entity" { +} + + +@enduml \ No newline at end of file