Search code examples
flutterdartclean-architectureuse-case

Is it good approach to have an interface for all usecases?


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 => [];
}

Solution

  • 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.

    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?

    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.