felangel / bloc

A predictable state management library that helps implement the BLoC design pattern
https://bloclibrary.dev
MIT License
11.86k stars 3.4k forks source link

feat: Toggle the use of part / part of #4218

Open klausmyrseth opened 4 months ago

klausmyrseth commented 4 months ago

Description

When trying to keep within the recomended code practices its annoying to remove all the part and part of on the code generation, I would love to get a feature where you can toggle part and part of with includes to ensure proper isolation of classes. Right now its actually just as easy to use the snippets to generate the classes manually instead of actually getting what you need from the plugin out of the box.

Edit: This is for the extension for vs code :)

Desired Solution

An easy to access dropdown in the plugin settings where you can choose the style of generation, part/part of or include so its easy to choose how the code generation is done. When you then generate a new bloc you get the bloc with part/part of or with includes based on your settings.

Alternatives Considered

I do not really see an alternative to this.

Additional Context

I really like the rest of the features of the plugin but this part is eating on me every time I make a new bloc.

felangel commented 4 months ago

Hi @klausmyrseth 👋 Thanks for opening an issue!

I would love to get a feature where you can toggle part and part of with includes to ensure proper isolation of classes.

Can you elaborate a bit on why you prefer to isolate the state, event, and bloc classes? I generally recommend using part/part of because the bloc, state, and event are all tightly coupled and using part/part of just helps organize the code while still allowing you to access all the relevant code with a single import. Otherwise, you’d need to import the bloc, state, and event classes separately (3 imports instead of 1).

klausmyrseth commented 4 months ago

I like seperation, its not a big deal in a small project but in a big project or when you librarise for reuse its good to seperate things properly. Easier when you revisit a year old code. Hence why I would like the option to configure as in a small quick one you can even use the same file if you want to (which in essense is what part and part of means, while in a big one seperation is power, short files readable code as it makes code so much easier to go through when you revisit at a later stage or when you work in a team.

edit: you can still access everything in a single import using export files for the bloc module ;) Its also not recomended from a dart perspective to use the part and part of, and rather use export files instead to get all the same advantages without the access to privates across the board.

felangel commented 3 months ago

I like seperation, its not a big deal in a small project but in a big project or when you librarise for reuse its good to seperate things properly. Easier when you revisit a year old code. Hence why I would like the option to configure as in a small quick one you can even use the same file if you want to (which in essense is what part and part of means, while in a big one seperation is power, short files readable code as it makes code so much easier to go through when you revisit at a later stage or when you work in a team.

edit: you can still access everything in a single import using export files for the bloc module ;) Its also not recomended from a dart perspective to use the part and part of, and rather use export files instead to get all the same advantages without the access to privates across the board.

Thanks for the response! It would really help if you're able to provide an example in which using part/part of is problematic. I just want to make sure I fully understand the problem we're solving, thanks! 🙏

klausmyrseth commented 3 months ago

// bad_bloc_bloc.dart

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';

part 'bad_bloc_event.dart';
part 'bad_bloc_state.dart';

class BadBlocBloc extends Bloc<BadBlocEvent, BadBlocState> {
  BadBlocBloc() : super(BadBlocInitial()) {
    on<BadBlocEvent>((event, emit) {
      print(event._internalMojo); // Breaking all visibility rules, thats part/partof for ya. supabad oop
    });
  }
}

// bad_bloc_event.dart

part of 'bad_bloc_bloc.dart';

sealed class BadBlocEvent extends Equatable {
  final String _internalMojo = 'very internal, should never be accessed from the outside.';

  const BadBlocEvent();

  @override
  List<Object> get props => [];
}

// bad_bloc_state.dart

part of 'bad_bloc_bloc.dart';

sealed class BadBlocState extends Equatable {
  const BadBlocState();

  @override
  List<Object> get props => [];
}

final class BadBlocInitial extends BadBlocState {}

To enforce visibility I just remove part of and use export files, not a big job but it would be nice to not have to, because if you forget - the option to do bad behavior is there, and if its there it will be used at some point esp in a team.

// bad_bloc.dart - export file example

export 'bad_bloc_bloc.dart';
export 'bad_bloc_event.dart';
export 'bad_bloc_state.dart';

Then you can still import the entire bloc by running import 'package:bloc/bad_bloc/bad_bloc.dart' and privates are still privates. I hope you see my point.

tenhobi commented 3 months ago

seperate things properly

@klausmyrseth I think that depends a lot of technology. It's worth a note that many technologies does not have this concept of part fiels. Part files are useful for separating concerns, but also keeping together essentially one piece, since bloc, event nor state does not have meaning of it's own. I therefore see no point of calling it "bad way". But you are also free to follow whichever practice you choose.

For the IDE extension I agree there could be change to have a setting not to use part files. It's relatively cheap to do so and if there are people wanting it, why not I guess? You could even create a PR for such request yourself.