What's the correct way to implement dependency inversion with single-method interfaces in Dart?

158 Views Asked by At

I'm implementing Clean Architecture so I'm using use cases. Let's say:

abstract interface class UploadAssetUseCase{
  Future<(AssetUploadFailure?, Url?)> execute(Uint8List data);
}

For this interface, Dart analyzer throws this warning:

Unnecessary use of an abstract class. Try making 'execute' a top-level function and removing the class.

Because of that, I switched to this approach:

typedef UploadAssetUseCase=  Future<(AssetUploadFailure?, Url?)> Function(Uint8List data);

This actually makes sense and is kind of testable (I need to create an extra abstract class for mocking it).

The problem comes when I try to implement this.

class FirebaseStorageUploadAssetUseCase implements UploadAssetUseCase{
  
}

This, obviously, throws an Exception since UploadAssetUseCaseis a Function, so it can't be implemented. To implement it, I need to create a class to be implemented instead of the Function itself, leading to the very same warning that I mentioned before:

abstract interface class _IUploadAssedUseCase {//Getting the warning that I was trying to avoid
  Future<(AssetUploadFailure?, Url?)> call(
    Uint8List document,
  );
}

class FirebaseStorageUploadAssetUseCase implements _IUploadAssedUseCase{
  const FirebaseStorageUploadAssetUseCase(this.storage);
  final FirebaseStorage storage;

  @override
  Future<(AssetUploadFailure?, Url?)> call(
    Uint8List document,
  ){
   
  }
}

So, in this context, what's the best approach for this? Should I just ignore the warning and keep using classes instead of top-level Functions? Is there any other way to do this that I'm not aware of?

I'm using analysis options 3.1.0 with this configuration (if you guys want to replicate):

analyzer:
  errors:
    invalid_use_of_visible_for_testing_member: error
    const_eval_throws_exception: ignore
linter:
  rules:
    public_member_api_docs: false
    library_private_types_in_public_api: false
    lines_longer_than_80_chars: false
1

There are 1 best solutions below

5
Hedwin On

To avoid this warning, you can add an empty constructor to your abstract class.

abstract interface class _IUploadAssedUseCase {
  _IUploadAssedUseCase();
  //Getting the warning that I was trying to avoid
  Future<(AssetUploadFailure?, Url?)> call(
    Uint8List document,
  );
}