You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为所有用例定义统一接口是否合理?流返回场景该如何处理?

关于Usecase接口设计的疑问解答

问题背景

我已定义了一个返回Future的Usecase接口,请问为所有用例统一使用该接口是否为合理方案?此外,若存在需要返回Stream的用例(例如监听Firebase Cloud Firestore集合快照),是否需要定义两个独立接口?

现有代码实现

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

问题解答

1. 统一使用返回Future的Usecase接口是否合理?

完全合理,原因如下:

  • 大部分业务用例属于单次执行的操作(比如获取单条数据、提交表单、触发一次性业务逻辑),Future<Either<Failure, Output>>的结构能完美适配这类场景:用Future表示异步执行,Either统一封装成功结果和失败错误,符合Clean Architecture中用例层的错误处理规范。
  • 你定义的Input/NoInput类已经统一了参数传递逻辑,避免了不同用例参数处理的混乱,进一步强化了接口的通用性。
  • 这种统一接口的设计能降低上层调用的学习成本,所有用例的调用方式一致(await usecase(input)),便于统一封装日志、异常捕获等横切关注点。

2. 返回Stream的用例是否需要独立接口?

建议定义独立的StreamUsecase接口,理由如下:

  • 语义差异:Future代表单次异步结果,Stream代表持续的数据流,两者的业务场景完全不同(单次请求 vs 实时监听),分开接口能让代码意图更清晰。
  • 使用方式不同:调用返回Future的用例用await,而Stream需要监听(listen/await for),如果强行复用同一个接口,要么返回Future<Stream<Either<Failure, Output>>>,会增加不必要的嵌套复杂度;要么破坏接口的单一职责。
  • 符合SOLID原则:单一职责原则要求每个类/接口只负责一种类型的逻辑,分开接口能让Usecase专注于单次操作,StreamUsecase专注于实时数据流。

示例:StreamUsecase接口定义

abstract class StreamUsecase<Input, Output> {
  Stream<Either<Failure, Output>> call(Input input);
}

监听Firestore集合快照的用例可实现该接口:

class ListenFirestoreCollectionUsecase extends StreamUsecase<CollectionInput, List<Document>> {
  final FirestoreRepository repository;

  ListenFirestoreCollectionUsecase(this.repository);

  @override
  Stream<Either<Failure, List<Document>>> call(CollectionInput input) {
    return repository.listenCollection(input.collectionPath);
  }
}

补充说明

如果想尽量减少接口数量,也可以尝试用泛型抽象返回类型,但会增加泛型复杂度,比如:

abstract class Usecase<Input, Output, R extends FutureOr<Stream<Either<Failure, Output>>>> {
  R call(Input input);
}

但这种方式会让接口的使用变得晦涩,不如分开两个接口直观,不推荐在业务代码中使用。

内容的提问来源于stack exchange,提问作者djalmafreestyler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 02:22:19