This context provides a tutorial on using the built value package to achieve immutability in Flutter application implementations.
Abstract
The text begins with an introduction to the importance of immutability in Flutter application development, emphasizing its advantages in avoiding concurrency headaches and achieving clean architecture. The author then introduces the built value package, explaining its purpose and features. The tutorial uses the plain Flutter counter app as an example, demonstrating how to set up the pubspec and analysis options file for using the built value package. The author then explains the core structure of immutable entities and immutable object models, which include abstract class, Built class, BuiltValueField, factory, and private constructor. The tutorial provides code snippets to illustrate how to create an abstract class for the CounterEntity and generate an auto-generated class using the build_runner build command. The author also demonstrates how to use the immutable entity in the UI, emphasizing the separation of the state or behavior of the API from the domain entity. The conclusion highlights that this is just the first step towards achieving clean architecture and suggests future steps, such as defining a repository interface in the domain layer and its repository implementation in the data layer.
Bullet points
The built value package is introduced to achieve immutability in Flutter application implementations.
The tutorial uses the plain Flutter counter app as an example.
The pubspec and analysis options file need to be set up for using the built value package.
The core structure of immutable entities and immutable object models is explained.
Code snippets are provided to illustrate how to create an abstract class for the CounterEntity and generate an auto-generated class.
The use of the immutable entity in the UI is demonstrated.
The conclusion suggests future steps towards achieving clean architecture.
Immutable Entities And Object Models In Flutter Clean Architecture
The relationship between the domain API and the implementation as the data layer are implemented by an entity interface and often a data layer model. By making the underlying atomic units immutable, we can avoid concurrency headaches and get one step closer to clean architecture in flutter application implementations.
Let me show you how to use the built value package to achieve this.
Why Built Value
Two reasons for built value. Let’s do reason one first.
Dart was designed conservatively as they had to fit it into a small VM that could run in a browser as the use case was the Google webapps everyone uses. Thus, it unlike languages like haskell does not have immutables by default.
But, immutables are preferred as they are less expensive performance-wise than mutables.
The reason the package is called built value instead of just immutable values is that those values have to be built so that the immutableness of the data structure underlying it is maintained.
Let’s See Built Value In Action
I am just using the plain flutter counter app, and you can find the source in this repo:
And you need to add a code gen exclusion in the analysis options file:
Now, both immutable entities and immutable object models have the exact same core structure:
- abstract class
- implements the Built class
- contains one annotated BuiltValueField
- contains one factory
- sets the constructor to private to produce the immutable behavior
Here is how the CounterEntity abstract class looks:
And when you run this command:
flutter packages pub run build_runner build
You will get this auto-generated class:
Now, if you look at the top, you see two import pairings; part and part of. That pairs these two files together as a sort of sub-library and they are treated as one unit.
And we can use it in this way:
Notice that I make another local instance called value and use build to create the initial value by:
int value = CounterEntity((dynamic b) => b..value = 0) as int;
That means the state or behavior of the API is now not in the domain entity, it’s now within the UI. It’s just a micro-step towards getting to implementing a clean architecture and figuring out how we want to control the data-flow and thus implement our state management solution. But, it is a step we need to take and is a good first step.
If we had more attributes, then we would have an entity and then a data layer model to assist in defining the relationship between the domain API and the data layer model as far as hooks in which a repository interface and implementation could be created.
Then I will get into separating out the behavior of the UI into its own component separate from the UI layout.
Conclusion
This is only the first mini-step towards clean architecture. Next, up is defining a repository interface in the domain layer and its repository implementation in the data layer.
About Me, Fred Grott
Unlike Raywenderlich, I am a contributor to the Flutter Ecosystem and contribute to plugins such as these: