Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add optional type argument to represent "from state" in on method #4217

Open
ishchhabra opened this issue Jul 27, 2024 · 5 comments
Open
Labels
enhancement candidate Candidate for enhancement but additional research is needed pkg:bloc This issue is related to the bloc package

Comments

@ishchhabra
Copy link

Description

In a state machine, state transitions occur from a particular state to another state. Currently, the on<...> method in BLoC does not provide an explicit way to specify the "from state" for a transition. The proposal suggests adding an optional type argument to the on<...> method to specify the state from which the transition is happening.

Motivation

Currently, BLoC code allows developers to identify the event that caused a transition (from the on<Event> method) and the state being transitioned to (from the emit(state) calls). However, the "from state" information is not explicitly captured, making it challenging to model the state machine directly from BLoC code. Developers often have to implement their own guardrails (e.g., with assertions or type casts) to enforce specific state transitions or rely on implicit assumptions about the BLoC's usage. Adding the "from state" parameter would eliminate the need for these custom guardrails, providing a complete picture of the state transitions directly within the BLoC code. This enhancement would also enable easy generation of visualizations of the state machine by parsing the on<> and emit calls..

@felangel
Copy link
Owner

Hi @ishchhabra 👋
Thanks for opening an issue!

This seems like it would be best suited as a different package (there are already some like https://pub.dev/packages/state_graph_bloc).

Let me know if that helps 👍

@felangel felangel added question Further information is requested waiting for response Waiting for follow up labels Jul 28, 2024
@ishchhabra
Copy link
Author

ishchhabra commented Jul 28, 2024

Hi @felangel,

Thanks for pointing out the existing alternatives. I explored some separate packages, but many diverge significantly from BLoC's API design, which forces a choice between different approaches. Including this functionality directly in BLoC as an opt-in feature avoids that problem. I believe BLoC’s API design is well-suited for this integration. I tried adding it as a separate package but was blocked by Dart’s lack of overloading. Given BLoC’s focus on predictable state management, integrating this feature seems like a natural fit, as it completes the mental model of a BLoC by including the state from which transitions occur.

What do you think?

@JavertArdo
Copy link

I'm using the BLoC library for the couple of years now. The same idea of explicit 'from state' declaration has been on my mind for a long time. During code implementation I always dealing with the complexity of the features and the code readability.

Let's have a look at simple example.

abstract class ExampleEvent {}

class FirstExampleEvent extends ExampleEvent {}
class SecondExampleEvent extends ExampleEvent {}
abstract class ExampleState {}

class DefaultExampleState extends ExampleState {}
class FirstExampleState extends ExampleState {}
class SecondExampleState extends ExampleState {}

To handle incoming events, usually the code is written like below. on<...> method registers the callback function, which should be executed when concrete event is dispatched. Additionally, events can be transformed to throttle them, delay, etc.

class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {
  ExampleBloc() : super(DefaultExampleState()) {
    on<FirstExampleEvent>(
      (event, emit) async {
        if (state is DefaultExampleState) {
          // do the rest
        }
        if (state is FirstExampleState) {
          // do the rest
        }
      },
      transformer: concurrent(),
    );
    on<SecondExampleEvent>(
      (event, emit) async {
        if (state is SecondExampleState) {
          // do the rest
        }
      },
      transformer: sequential(),
    );
  }
}

Wouldn't be easier for end-user to define explicitly on which event and in which state the logic should be executed? Instead of registering on<...> methods and creating weird if statements and unnecessarily nesting the code.

There could be some other benefit to transform events differently (a pair of event and state instead of only event).

class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {
  ExampleBloc() : super(DefaultExampleState()) {
    on<FirstExampleEvent, DefaultExampleState>(
      (event, emit) async {
        // do the rest
      },
      transformer: sequential(),
    );
    on<FirstExampleEvent, FirstExampleState>(
      (event, emit) async {
        // do the rest
      },
      transformer: concurrent(),
    );
    on<SecondExampleEvent, SecondExampleState>(
      (event, emit) async {
        // do the rest
      },
      transformer: sequential(),
    );
  }
}

Sometimes the if statements checking the states are much more complicated, excluding some states or substates.

The another benefit with explicit on<Event, State> declaration could be easier detection of abnormal code handling in wrong states. This might happen when multiple BLoC modules interact with each other and doing some code in parallel. If the code was executed on unexpected state, then throw exception to inform the developer about it, rather than do something unwanted.

What do you think about such improvement? I'm not an expert, so that is only the idea/concept.

@aayushchhabra1999
Copy link

aayushchhabra1999 commented Aug 10, 2024

+1 on this. We also significantly need this at https://github.com/thekniru/. We have been internally using hacks to achieve this. Adding it to Bloc would significantly simplify things.

@felangel
Copy link
Owner

felangel commented Sep 3, 2024

I'll think about this some more but as it is described, these changes would be very disruptive and breaking and there are many details of this type of API which require careful consideration.

@felangel felangel added enhancement candidate Candidate for enhancement but additional research is needed pkg:bloc This issue is related to the bloc package and removed question Further information is requested waiting for response Waiting for follow up labels Sep 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement candidate Candidate for enhancement but additional research is needed pkg:bloc This issue is related to the bloc package
Projects
None yet
Development

No branches or pull requests

4 participants