Ответ
В архитектуре Flutter-приложения, например, при использовании Clean Architecture, Use Case (или Interactor) — это класс, который инкапсулирует одну конкретную бизнес-правило или действие. Он находится в слое домена и координирует поток данных между репозиториями (данные) и презентерами/блоками (UI).
Пример Use Case для аутентификации пользователя:
// domain/use_cases/login_user_use_case.dart
import '../repositories/auth_repository.dart';
class LoginUserUseCase {
final AuthRepository _authRepository;
LoginUserUseCase(this._authRepository);
// Выполняет конкретное бизнес-действие
Future<void> execute({required String email, required String password}) async {
// Валидация может быть здесь или в отдельном ValueObject
if (email.isEmpty || password.isEmpty) {
throw const FormatException('Email and password cannot be empty');
}
// Делегируем фактическую логику аутентификации репозиторию
await _authRepository.login(email: email, password: password);
}
}
Как это используется в слое презентации (например, с Bloc):
// presentation/login/bloc/login_bloc.dart
class LoginBloc extends Bloc<LoginEvent, LoginState> {
final LoginUserUseCase _loginUserUseCase;
LoginBloc(this._loginUserUseCase) : super(LoginInitial()) {
on<LoginButtonPressed>((event, emit) async {
emit(LoginLoading());
try {
await _loginUserUseCase.execute(
email: event.email,
password: event.password,
);
emit(LoginSuccess());
} catch (e) {
emit(LoginFailure(error: e.toString()));
}
});
}
}
Преимущества такого подхода:
- Чистое разделение ответственности: UI не знает, откуда берутся данные (сеть, локальная БД).
- Простота тестирования: Use Case можно легко протестировать, подменив
AuthRepositoryмоком. - Повторное использование: Одна бизнес-логика может быть использована в разных местах приложения (например, в мобильном и веб-интерфейсе).
- Ясность: Каждый Use Case соответствует одной пользовательской истории.
Ответ 18+ 🔞
Слушай, а вот этот ваш Clean Architecture — это вообще ёперный театр какой-то. Ну ладно, объясню на пальцах, как будто ты только вчера из деревни приехал и Flutter для тебя — это про птиц.
Представь, у тебя есть приложение. В нём куча всего происходит: пользователь тыкает кнопки, данные откуда-то прилетают, куда-то улетают. Так вот, чтобы в этом всём не захлебнуться как последний бздун, умные дядьки придумали слои. И в самом центре, в святая святых, в домене, живут Use Case'ы.
Что это за зверь? Use Case — это, блядь, конкретное дело. Одно. Не «сделай всё», а «сделай вот это». Например, «залогинь пользователя». Всё. Больше он нихуя не должен делать. Это не бог и не царь, а просто работяга, который знает, кого попросить выполнить его маленькую задачку.
Вот смотри, как это выглядит в коде. Не пугайся, я поясню.
// domain/use_cases/login_user_use_case.dart
import '../repositories/auth_repository.dart';
class LoginUserUseCase {
final AuthRepository _authRepository;
LoginUserUseCase(this._authRepository);
Future<void> execute({required String email, required String password}) async {
// Сначала проверим, че нам пришло. А то вдруг пустые поля?
if (email.isEmpty || password.isEmpty) {
throw const FormatException('Email and password cannot be empty');
}
// А если всё ок — кидаем эту обузу на репозиторий. Пусть он парится.
await _authRepository.login(email: email, password: password);
}
}
Видишь? Весь его гениальный план — спросить у репозитория: «Э, сабака сука, залогинь-ка этого чела». Сам он в сеть не лезет, в базу не тыкается — у него для этого есть специально обученный AuthRepository. Use Case просто координирует, как менеджер-полупидор, который только и знает, что говорить «сделай».
А теперь, как этим пользуются наверху, в презентационном слое, где вся красота и кнопки мигают. Допустим, у нас Bloc.
// presentation/login/bloc/login_bloc.dart
class LoginBloc extends Bloc<LoginEvent, LoginState> {
final LoginUserUseCase _loginUserUseCase;
LoginBloc(this._loginUserUseCase) : super(LoginInitial()) {
on<LoginButtonPressed>((event, emit) async {
emit(LoginLoading());
try {
// Всё! Блоку похуй, КАК логиниться. Он просто говорит Use Case: "Выполняй!"
await _loginUserUseCase.execute(
email: event.email,
password: event.password,
);
emit(LoginSuccess());
} catch (e) {
emit(LoginFailure(error: e.toString()));
}
});
}
}
Блок, по сути, тупая мартышлюшка: нажали кнопку — он вызвал Use Case. Получилось — радуется, не получилось — плачет. Он даже не в курсе, логинимся мы через Firebase, через свой бэкенд или через телепатию. Это же, бля, овердохуища удобно!
Итак, нахуя это всё? Давай списком, а то у тебя уже волнение ебать в глазах:
- Разделение ответственности. UI — это UI. Данные — это данные. Use Case — это мостик между ними, который не даёт им спутаться в грешном теле. UI не лезет в базу, как хитрая жопа, а репозиторий не рисует кнопки.
- Тестирование — просто пиздец как легко. Хочешь потестить Use Case? Подсунул ему фейковый репозиторий-муляж и смотришь, как он себя ведёт. Никаких реальных сетевых запросов, всё чисто и быстро.
- Повторное использование. Написал Use Case «получить погоду» — и тащи его и в телефон, и в веб, и в чайник умный. Бизнес-логика одна, а интерфейсы могут быть какие угодно.
- Ясность, мать её. Открываешь папку
use_casesи видишь:LoginUserUseCase,FetchWeatherUseCase,BuyCoffeeUseCase. Сразу понятно, что это приложение умеет делать. Прямо как список дел на холодильнике, только для кода.
Короче, Use Case — это не какая-то мудрёная хуйня, а просто способ не превратить свой код в большую, вонючую кучу, где всё зависит ото всего. Попробуй, а то потом сам от себя охуеешь, когда начнёшь рефакторить свой старый спагетти-код.