सार्वजनिक जानकारी से बना चयन मार्गदर्शन। केवल संदर्भ हेतु।
Built_Value एक Dart लाइब्रेरी है जो निर्मित बिल्डर, एनुम-जैसे क्लासेस और सीरियलाइज़ेशन के साथ अपरिवर्तनीय, प्रकार-सुरक्षित मूल्य वस्तुओं के निर्माण की अनुमति देती है। यह अपरिवर्तनीयता को बल देकर और संकलन-समय बॉयलरप्लेट उत्पन्न करके साफ और बनाए रखने योग्य कोड को बढ़ावा देती है। ठोस डेटा अखंडता और प्लेटफॉर्म के बीच कुशल सीरियलाइज़ेशन की आवश्यकता वाले एप्लिकेशन में डेटा मॉडल प्रबंधन के लिए आदर्श है।
उपयोग
अपरिवर्तनीय डेटा मॉडल का प्रबंधन
अनुक्रमण एल्गोरिथ्म कोड उत्पन्न करना
एनम-जैसे क्लासेस बनाना
जटिल वस्तुओं का सुरक्षित निर्माण
क्रॉस-प्लेटफॉर्म डेटा एक्सचेंज
मुख्य विशेषताएँ
अपरिवर्तनीय मूल्य प्रकार
वस्तु निर्माण के लिए बिल्डर पैटर्न
संकलन समय कोड उत्पादन
JSON सीरियलाइज़ेशन का समर्थन
एनुम-जैसी क्लास परिभाषाएं
इनके लिए उपयुक्त
डेटा-भारी एप्लिकेशन
ताकद टाइपिंग की आवश्यकता वाले ऐप्स
कोड सुरक्षा के प्रति अग्रणी टीमें
JSON APIs का उपयोग करने वाले प्रोजेक्ट्स
क्रॉस-प्लेटफ़ॉर्म विकास
विचार योग्य बातें
कोड जनरेशन की आवश्यकता है
बिल्डर्स के लिए सीखने का वक्र
अतिरिक्त बिल्ड चरण की आवश्यकता है
सीमित रनटाइम लचीलापन
build_runner पर निर्भरता
मूल README
संबंधित सोर्स रिपॉज़िटरी के मूल README का स्नैपशॉट। नवीनतम सामग्री के लिए रिपॉज़िटरी देखें।
For an end to end example see the
chat example, which was
demoed at the Dart Summit 2016.
The
data model,
used both client and server side, uses value types, enums and serialization from
built_value.
Codegen is done using dart run build_runner build for one-off builds.
To continuously watch your source and update the generated output when it changes, use dart run build_runner watch.
Note that you need a dev dependency on built_value_generator and build_runner. See the example
pubspec.yaml.
Value Types
Value types are, for our purposes, classes that are considered
interchangeable if their fields have the same values.
Common examples include Date, Money and Url. Most code introduces
its own value types. For example, every web app probably has some
version of Account and User.
Value types are very commonly sent by RPC and/or stored for later
retrieval.
The problems that led to the creation of the Built Value library have
been
discussed at great length
in the context of
AutoValue
for Java.
In short: creating and maintaining value types by hand requires a lot of
boilerplate. It's boring to write, and if you make a mistake, you very
likely create a bug that's hard to track down.
Any solution for value types needs to allow them to participate in object
oriented design. Date, for example, is the right place for code that
does simple date manipulation.
AutoValue
solves the problem for Java with code generation, and Built Values does
the same for Dart. The boilerplate is generated for you, leaving you to
specify which fields you need and to add code for the behaviour of the
class.
Generating boilerplate for Value Types
Value types require a bit of boilerplate in order to connect it to generated
code. Luckily, even this bit of boilerplate can be automated using code
snippets support in your favourite text editor. For example, in IntelliJ you
can use the following live template:
Using this template, you would only have to manually enter a name for your data
class, which is something that can't be automated.
Enum Class
Enum Classes provide classes with enum features.
Enums are very helpful in modelling the real world: whenever there are a
small fixed set of options, an enum is a natural choice. For an object
oriented design, though, enums need to be classes. Dart falls short here,
so Enum Classes provide what's missing!
Design:
Constants have name and toString, can be used in switch statements,
and are real classes that can hold code and implement interfaces
Generated values method that returns all the enum values in a BuiltSet (immutable set)
Generated valueOf method that takes a String
Serialization
Built Values comes with JSON serialization support which allows you to
serialize a complete data model of Built Values, Enum Classes and
Built Collections. The
chat example shows
how easy this makes building a full application with Dart on the server and
client.
Here are the major features of the serialization support:
It fully supports object oriented design: any object model that you can
design can be serialized, including full use of generics and interfaces.
Some other libraries require concrete types or do not fully support generics.
It allows different object oriented models over the same data. For
example, in a client server application, it's likely that the client and server
want different functionality from their data model. So, they are allowed to have
different classes that map to the same data. Most other libraries enforce a 1:1
mapping between classes and types on the wire.
It requires well behaved types. They must be immutable, can use
interface but not concrete inheritance, must have predictable nullability,
hashCode, equals and toString. In fact, they must be Enum Classes, Built
Collections or Built Values. Some other libraries allow badly behaved types to
be serialized.
It supports changes to the data model. Optional fields can be added or
removed, and fields can be switched from optional to required, allowing your
data model to evolve without breaking compatbility. Some other libraries break
compatibility on any change to any serializable class.
It's modular. Each endpoint can choose which classes to know about;
for example, you can have multiple clients that each know about only a subset of
the classes the server knows. Most other libraries are monolithic, requiring all
endpoints to know all types.
It has first class support for validation via Built Values. An important
part of a powerful data model is ensuring it's valid, so classes can make
guarantees about what they can do. Other libraries also support validation
but usually in a less prominent way.
It's pluggable. You can add serializers for your own types, and you can add
plugins
which run before and after all serializers. This could be used to
interoperate with other tools or to add hand coded high performance serializers
for specific classes. Some other libraries are not so extensible.
It was designed to be multi language, mapping to equivalent object models in
Java and other languages. Currently only Dart is supported. The need for other
languages didn't materialize as servers are typically either written in Dart
or owned by third parties. Please open an issue if you'd like to explore
support in more languages.
Common Usage
While full, compiled examples are available in
example/lib,
a common usage example is shown here. This example assumes that you are writing
a client for a JSON API representing a person that looks like the following:
The corresponding dart class employing built_value might look like this. Note
that it is using the
@BuiltValueField
annotation to map between the property name on the response and the name of the
member variable in the Person class.
import'package:built_value/built_value.dart';
import'package:built_value/serializer.dart';
import'package:built_collection/built_collection.dart';
part'person.g.dart';
abstractclassPersonimplementsBuilt<Person, PersonBuilder> {
staticSerializer<Person> get serializer => _$personSerializer;
intget id;
int?get age;
@BuiltValueField(wireName: 'first_name')
String? get firstName;
BuiltList<String> get hobbies;
Person._();
factoryPerson([voidFunction(PersonBuilder) updates]) = _$Person;
}
FAQ
How do I check a field is valid on instantiation?
The value class private constructor runs when all fields are initialized and
can do arbitrary checks:
abstractclassMyValue{
MyValue._() {
if (field < 0) {
throwArgumentError(field, 'field', 'Must not be negative.');
}
}
How do I process a field on instantiation?
Add a hook that runs immediately before a builder is built. For example, you
could sort a list, so it's always sorted directly before the value is created:
abstractclassMyValue{
@BuiltValueHook(finalizeBuilder: true)
staticvoid_sortItems(MyValueBuilder b) =>
b..items.sort();
How do I set a default for a field?
Add a hook that runs whenever a builder is created:
abstractclassMyValue{
@BuiltValueHook(initializeBuilder: true)
staticvoid_setDefaults(MyValueBuilder b) =>
b
..name = 'defaultName'
..count = 0;
Should I check in and/or publish in the generated .g.dart files?
See the build_runner
docs. You usually should not check in generated files, but you do need to publish
them.
Features and bugs
Please file feature requests and bugs at the issue tracker.