Skip to content

Commit 19246ed

Browse files
martinloesethjensenAtiqur Rahman
andauthored
feat: added Future<T>-based UseCase (#36)
* feat: added future based usecases and wrote documentation with examples for the usecases * Update lib/domain/common/use_case.dart Co-authored-by: Atiqur Rahman <[email protected]> * doc: private fields * feat: added `StreamOutputUseCase` and having the abstract classes extend the base `UseCase` and `OutputUseCase` Co-authored-by: Atiqur Rahman <[email protected]>
1 parent 1087afc commit 19246ed

File tree

1 file changed

+175
-1
lines changed

1 file changed

+175
-1
lines changed

lib/domain/common/use_case.dart

Lines changed: 175 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,185 @@
1+
/// Future output use case that would take in an [Input] and return [Output].
2+
///
3+
/// Used when we need to consider any inputs like filtering parameters etc.
4+
///
5+
/// Example:
6+
/// // import tuple
7+
/// typedef Input = Tuple<List<Story>, Query>;
8+
///
9+
/// ```dart
10+
/// class QueryStoriesUseCase extends UseCase<Input, List<Story>> {
11+
/// @override
12+
/// List<Story> run(Input input) {
13+
/// final stories = input.item1;
14+
/// final query = input.item2;
15+
/// return stories.where((story) => story.name.contains(query.name));
16+
/// }
17+
/// }
18+
///
19+
/// class Query {
20+
// final int age;
21+
// final String name;
22+
// final String author;
23+
//
24+
// Query(this.age, this.name, this.author);
25+
// }
26+
/// ```
27+
///
128
abstract class UseCase<Input, Output> {
229
Output run(Input input);
330
}
431

32+
/// Output use case that would return [Output].
33+
///
34+
/// Used when we don't need to consider any inputs like filtering parameters etc.
35+
///
36+
/// Example:
37+
///
38+
/// ```dart
39+
/// class AgeValidationUseCase extends OutputUseCase<bool> {
40+
/// AgeValidationUseCase({
41+
/// required this._user,
42+
/// });
43+
///
44+
/// final User _user;
45+
///
46+
/// @override
47+
/// bool run() {
48+
/// return _user.age >= 18;
49+
/// }
50+
/// }
51+
/// ```
52+
///
553
abstract class OutputUseCase<Output> {
654
Output run();
755
}
856

9-
abstract class StreamUseCase<Output> {
57+
/// Stream use case that would return [Output] as a [Stream].
58+
///
59+
/// Used when we want to get an async sequence of data.
60+
/// <https://dart.dev/tutorials/language/streams/>
61+
///
62+
/// Example:
63+
///
64+
/// ```dart
65+
/// class ObserveStoryPlayerStateUseCase extends StreamOutputUseCase<StoryPlayerState> {
66+
/// ObserveStoryPlayerStateUseCase({
67+
/// required this._storyPlayerPreferences,
68+
/// });
69+
///
70+
/// final StoryPlayerPreferences _storyPlayerPreferences;
71+
///
72+
/// @override
73+
/// Stream<StoryPlayerState> run() {
74+
/// return _storyPlayerPreferences
75+
// .getStoryPlayerStateStream()
76+
// .where((storyPlayerState) => storyPlayerState.hasStoryForPlayback);
77+
/// }
78+
/// }
79+
/// ```
80+
///
81+
abstract class StreamOutputUseCase<Output>
82+
extends OutputUseCase<Stream<Output>> {
83+
@override
1084
Stream<Output> run();
1185
}
86+
87+
/// Stream output use case that would take in an [Input] and return [Output] as a [Stream].
88+
///
89+
/// Used when we want to get an async sequence of data.
90+
/// <https://dart.dev/tutorials/language/streams/>
91+
///
92+
/// Example:
93+
///
94+
/// ```dart
95+
/// class ObserveStoryPlayerStateFromStoryIdUseCase extends StreamUseCase<Query, StoryPlayerState> {
96+
/// ObserveStoryPlayerStateFromStoryIdUseCase({
97+
/// required this._storyPlayerPreferences,
98+
/// });
99+
///
100+
/// final StoryPlayerPreferences _storyPlayerPreferences;
101+
///
102+
/// @override
103+
/// Stream<StoryPlayerState> run(Query input) {
104+
/// return _storyPlayerPreferences
105+
// .getStoryPlayerStateStreamFromStoryID(input.storyID)
106+
// .where((storyPlayerState) => storyPlayerState.hasStoryForPlayback);
107+
/// }
108+
/// }
109+
///
110+
/// class Query {
111+
// final String name;
112+
// final String author;
113+
// final int storyID;
114+
//
115+
// Query(this.name, this.author, this.storyID);
116+
// }
117+
/// ```
118+
///
119+
abstract class StreamUseCase<Input, Output>
120+
extends UseCase<Input, Stream<Output>> {
121+
@override
122+
Stream<Output> run(Input input);
123+
}
124+
125+
/// Future output use case that would take in an [Input] and return [Output] as a [Future].
126+
///
127+
/// Used when we need to consider any inputs like filtering parameters etc.
128+
///
129+
/// Example:
130+
///
131+
/// ```dart
132+
/// class QueryStoriesUseCase extends FutureUseCase<Query, List<Story>> {
133+
/// QueryStoriesUseCase({
134+
/// required this._storiesService,
135+
/// });
136+
///
137+
/// final StoriesService _storiesService;
138+
///
139+
/// @override
140+
/// Future<List<Story>> run(Query input) async {
141+
/// return _storiesService.queryStories(input);
142+
/// }
143+
/// }
144+
///
145+
/// class Query {
146+
// final int age;
147+
// final String name;
148+
// final String author;
149+
//
150+
// Query(this.age, this.name, this.author);
151+
// }
152+
/// ```
153+
///
154+
abstract class FutureUseCase<Input, Output>
155+
extends UseCase<Input, Future<Output>> {
156+
@override
157+
Future<Output> run(Input input);
158+
}
159+
160+
/// Future output use case that would return [Output] as a [Future].
161+
///
162+
/// Used when we don't need to consider any inputs like filtering parameters etc.
163+
///
164+
/// Example:
165+
///
166+
/// ```dart
167+
/// class GetAllStoriesUseCase extends FutureOutputUseCase<List<Story>> {
168+
/// GetAllStoriesUseCase({
169+
/// required this._storiesService,
170+
/// });
171+
///
172+
/// final StoriesService _storiesService;
173+
///
174+
/// @override
175+
/// Future<List<Story>> run() async {
176+
/// return _storiesService.fetchAllStories();
177+
/// }
178+
/// }
179+
/// ```
180+
///
181+
abstract class FutureOutputUseCase<Output>
182+
extends OutputUseCase<Future<Output>> {
183+
@override
184+
Future<Output> run();
185+
}

0 commit comments

Comments
 (0)