ResoCoder/flutter-tdd-clean-architecture-course

Params

maltsavkiryl opened this issue · 1 comments

Hey ResoCoder!

I am currently working on a flutter project, and have applied your architecture. It was hard in the beginning, but atm I have a pretty good understanding of it! I have one struggle though.

When working on the [feature]_bloc file, where everything comes together. I get an error when importing/injecting multiple usecases that there are multiple imports that have a "Params" class. VSCode suggests using prefixes to seperate them. I this the right solution or is there a better/less code solution?

this is my solution.

import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:dartz/dartz.dart';
import 'package:njoy_shopping_app/constants/error_constants.dart';
import 'package:njoy_shopping_app/core/error/failures.dart';
import 'package:njoy_shopping_app/features/merchants/data/models/merchant_model.dart';
import 'package:njoy_shopping_app/features/merchants/domain/usecases/get_merchant_by_id.dart'
    as _merchantById;
import 'package:njoy_shopping_app/features/merchants/domain/usecases/get_merchants.dart'
    as _merchants;
import 'package:njoy_shopping_app/features/merchants/domain/usecases/get_merchants_by_name.dart'
    as _merchantByName;
import './bloc.dart';
import 'package:meta/meta.dart';

class MerchantBloc extends Bloc<MerchantEvent, MerchantState> {
  final _merchantById.GetMerchantById getMerchantById;
  final _merchantByName.GetMerchantsByName getMerchantsByName;
  final _merchants.GetMerchants getMerchants;

  MerchantBloc({
    @required _merchantById.GetMerchantById getMerchantById,
    @required _merchantByName.GetMerchantsByName getMerchantsByName,
    @required _merchants.GetMerchants getMerchants,
  })  : assert(getMerchantById != null),
        assert(getMerchantsByName != null),
        assert(getMerchants != null),
        getMerchantById = getMerchantById,
        getMerchantsByName = getMerchantsByName,
        getMerchants = getMerchants;

  @override
  MerchantState get initialState => InitialMerchantState();

  @override
  Stream<MerchantState> mapEventToState(
    MerchantEvent event,
  ) async* {
    if (event is SearchByMerchantNameEvent) {
      yield MerchantsLoading();

      final failureOrMerchants =
          await getMerchantsByName(_merchantByName.Params(name: event.name));

      yield* _eitherLoadedMerchantsOrErrorState(failureOrMerchants);
    } else if (event is SearchMerchantsEvent) {
      yield MerchantsLoading();

      final failureOrMerchants = await getMerchants(_merchants.Params(
        lat: event.lat,
        lng: event.lng,
        rad: event.rad,
        cat: event.cat,
      ));

      yield* _eitherLoadedMerchantsOrErrorState(failureOrMerchants);
    } else if (event is GetMerchantByIdEvent) {
      yield MerchantsLoading();

      final failureOrMerchant =
          await getMerchantById(_merchantById.Params(merchantId: event.id));

      yield* _eitherLoadedMerchantOrErrorState(failureOrMerchant);
    }
  }

  Stream<MerchantState> _eitherLoadedMerchantsOrErrorState(
    Either<Failure, List<MerchantModel>> failureOrMerchants,
  ) async* {
    yield failureOrMerchants.fold(
        (failure) => Error(message: _mapFailureToMessage(failure)),
        (merchants) => MerchantsLoaded(merchants: merchants));
  }

  Stream<MerchantState> _eitherLoadedMerchantOrErrorState(
    Either<Failure, MerchantModel> failureOrMerchants,
  ) async* {
    yield failureOrMerchants.fold(
        (failure) => Error(message: _mapFailureToMessage(failure)),
        (merchant) => MerchantLoaded(merchant: merchant));
  }

  String _mapFailureToMessage(Failure failure) {
    switch (failure.runtimeType) {
      case ServerFailure:
        return SERVER_FAILURE_MESSAGE;
      case CacheFailure:
        return CACHE_FAILURE_MESSAGE;
      default:
        return 'Unexpected error';
    }
  }
}

Do you just need to avoid a namespace collision?