Building a powerful, first-class and scalable solution requires selecting the right tools and practices to deliver and maintain the product. One of the main tools to evaluate is your State Management solution. A lot has been said about it and in this article we would like to share why we use BloC for State Management and its benefits to the product and the development process.
Defining State and Its Transformation in BloC Pattern
Let's begin by defining what the state is. Generally, to define it, it’s convenient to conceive the application as a big component with attributes and behavior. In that sense, the state can be defined as the value of the application's attributes at a given point in time.
It’s through external stimuli - and sometimes internal ones as well - that we can make certain logical processes run in our application and ultimately the state is altered. We are the ones who stimulate the app through events when we interact with it.
Some examples of this are:
1. Tapping a Button
2. Filling a Text Field
3. Marking/Unmarking a Checkbox, etc.
Every time we trigger an event, in general, we are executing some process that modifies the internal state of our application. A clear example is when we activate/deactivate the Dark Theme. We can clearly see how the application drastically changes its look & feel.
Fundamental concepts
Let's continue by introducing some fundamental concepts in order to understand it better:
Event: An external (or sometimes internal) stimulus that an application receives.
State: The internal properties or attributes of an application. To make it a little more visual, let's think of the state as a shot of the values of the properties of an application.
Event - State Relationship: When the application receives an event, in general, some logic or process is executed that modifies the state of our application. It’s recommended to reflect these changes in the user interface.
As for Front-End developers, we want to have the ability to react to any change in the state at any time.
Choosing the Right State Management Tool in Flutter
In Flutter, we have different alternatives for managing the state. For instance, Flutter offers its own state management mechanism, but also there are third parties libraries such as Provider, flutter_bloc, Riverpod, and Redux.
For small projects, we can perfectly use the tools offered by the Framework (vanilla setState and StatefulWidget). The real problem arises when the project grows and needs to share certain information (which is part of the state) between different components (and in different places) throughout the application.
When we think about writing quality code, we have to present different concepts (non-functional requirements) such as: maintainability, scalability, testability and performance, among others.
Thanks to the Flutter Community that immensely grows every day, we can choose between different alternatives that offer us a solution to this problem, from using vanilla setState to big, important, matured, well-recognized libraries such as Provider, BloC, among others.
A brief introduction to BloC
BloC (Business Logic Component) is an architecture pattern created by Google and introduced at Google I/O 2018. Its main objective is to separate the business logic from the presentation layer through the use of Streams. This supports the Reactive Programming paradigm.
BloC promotes the separation of responsibilities. The Presentation layer interacts with the BloC by sending events, and it will be able to react to changes in the state by subscribing to the Stream of data that it exposes.
To implement this architecture pattern, we use the flutter_bloc package created by Felix Angelov from Very Good Ventures. This library is very useful since it provides a model of how a BloC should be implemented and how events and the state should be defined.
It also has a package that facilitates the creation of unit tests on BLoC's components. The library offers as well different variants, such as:
- hydrated_bloc (allows the state to persist through different life cycles apps)
- replay_bloc (allows to undo/redo the state).
In the following video, we can see how BloC also arises from the need to share code between different technologies such as Flutter and Angular, two Google technologies that share the same business logic. BloC enables the possibility to simplify and write less code in order to greatly increase its maintainability.
Some benefits of using BloC
Easy to understand
The fundamental concepts of BloC are well-known concepts which makes it comprehensive and accessible. In general, most programmers know what an event is, what the state is, and the benefits of separating responsibilities to achieve a high-quality code.
Reactive programming
By using Data Stream for the emission of states we are ready to react to it at any time. In particular, flutter_bloc library makes it easy to achieve reactive programming without the necessity of interacting with libraries that manage streams like rxdart.
Testing
There is a bloc_test library specifically created to test bloc components. This makes it easier to test BloC as it might be difficult to think how to approach when unit tested. We have to validate a sequence of states from which the BloC might have passed.
Maintenance
The library offers great support since improvements are included regularly and doubts are answered very fast by the community. Moreover, there have been new features and variations added over time such as Hydrated Bloc, among others.
The BloC pattern in action
In this simple example we strived to illustrate a possible implementation of the pattern by using the replay_bloc library previously mentioned. This way we were able to build the classic ¨to do list¨ but adding the possibility of undoing or redoing the changes. In order to see in depth the following example, here is the link of the GitHub repository. Moreover, the BloC library includes many others that you can check out here.
BloC pattern for scaling first-class applications
At Somnio Software we choose the BloC pattern for our state management solution for a number of reasons. To begin with, the team has developed trust in this solution and feels very confident and comfortable using it. We have achieved a considerable consistency in the work where every developer can easily navigate through the code, even if they aren’t the person who wrote it.
Furthermore, this has helped us drastically improve the productivity of our work and the quality of the code we create. We have a proven record that this pattern is a smart and safe choice when scaling world-class applications.