I’ve created an interface for my use cases that returns a Future, Is it good approach to have an interface for all use cases?
What if I need a Usecase to return Streams instead of a single return (Future), for example listen to snapshots from Firebase Cloud Firestore collection, should I have two interfaces?
import 'package:equatable/equatable.dart';
import '../errors/failure.dart';
import 'package:dartz/dartz.dart';
abstract class Usecase<Input, Output> {
Future<Either<Failure, Output>> call(Input input);
}
class Input<T> extends Equatable {
final T parameter;
Input(this.parameter);
@override
List<Object?> get props => [parameter];
}
class NoInput extends Equatable {
@override
List<Object?> get props => [];
}
2
Answers
Your use cases only need interfaces if you want to hide the implementation of your use case from its callers (usually the controllers) OR when you want to replace the implementation later on, e.g. at run-time based on some configuration). My use cases often don’t have any interfaces.
If your use case has multiple "clients" and you want to keep those logically separated then interface segregation could be useful. If you only have e.g. one controller calling multiple APIs on your use case then a single interface is usually good enough.
Usually you don’t need an interface, since you do not need to inverse the dependency from the controllers to the use cases.
But it might be a good idea if you want to test the use case clients in isolation. E.g. if you want to test a controller it’s easier to create a use case mock if you have an interface. The mock is just another implementation. Other clients for you cases might be message queue adapters.
Yes, if you have different types you need different use cases. You usually have dedicated interfaces for each use case (interface segregation principle), so the question you asked will not occur if you apply the interface segregation principle.