Open MarcelGarus opened 5 years ago
I like the approach taken by https://pub.dev/packages/sum_types. You could then do the following:
@DataClass
mixin _User {
String get firstName;
String get lastName;
@nullable String get photoUrl;
}
The generated code would then be:
class User with _User {
const User({
@required this.firstName,
@required this.lastName,
this.photoUrl,
});
}
When NNBD finally lands one could just replace the @nullable
annotations with the new syntax and everything would continue to work.
Interesting approach!
But a possible problem I see with this is that it doesn't work well with generators of other packages, for example hive
and json_serializable
, because mixins are treated as abstract class and thus can't be instantiated by the generated code.
True, that wouldn't be covered.
If only constructors of extended classes would just call the super class with the same args. It could be so easy:
class User extends _UserBase {
String get firstName;
String get lastName;
@nullable String get photoUrl;
}
abstract class _UserBase {
String firstName;
String lastName;
String photoUrl;
_UserBase({
this.firstName,
this.lastName,
this.photoUrl,
});
}
This does compile, but completely forgets the parameters.
We implemented the mixin idea of @tvh in https://github.com/factisresearch/sum_data_types The code in that repo is based on data_classes but the interface is not compatible with data_classes.
Btw: was it intentionally that you use the 4-clause BSD license for data_classes_generator, but BSD 3-clause license for data_classes? It would be easier for us if everything was under BSD 3. Is it possible that you also license the generator part under BSD 3?
Oh sorry, that was not intentional. To be honest, I didn't pay too much attention to the license clauses. Now I changed both to BSD 3.
The package could then generate the
copy
,==
,hashCode
andtoString
methods as static extension methods on the User type.
Oh nooooo, seems like that's not possible. Extensions can't declare members with the same name as a member declared by Object
.
Okay, I re-evaluated the current ecosystem and it seems like there are really cool alternatives in the data class code generation market. There's, of course, built_value by Google, freezed which has some really cool factory constructor syntax to declare fields and others, like hive are thinking about requiring data classes in the future.
The freezed package, in particular, does many things right and address the same market like this one. All in all, it's more elegant than this one and makes some bold design decisions (like making the copyWith
method not type-safe in order to support nullable fields) that make it more intuitive to use.
So, I've been thinking a bit about the future of this package and I believe the best thing to do is to try to get as close to the vision of this issue as possible: support developers writing their own data classes. There's not much tooling in this regard in the existing ecosystem, so I believe this will be a valuable addition to the Dart community rather than another competing framework.
Here's what this package could offer:
==
, hashCode
and toString
that developers still have to incorporate into their code manually.copyWith
extension method similar to freezed's one with no type-safety in favor of nullable fields.Using this package would look like this:
@DataClass()
class Fruit {
User({
@required this.name,
@required this.color,
this.amount = 1,
});
final String name;
final Color color;
final int amount;
operator ==(Object other) => _$equals(other);
int get hashCode => _$hashCode;
String toString() => _$toString();
}
void main() {
var apple = Fruit(name: 'Apple', color: Colors.red);
print(apple.toString());
var badApple = apple.copyWith(color: Colors.brown);
badApple.hasNoName; // false
}
For a new version of the package, I consider completely overhauling the API of this package.
Fundamental problems of this package
built_value
package, not offering any unique benefits.So, what's the future of this package? The Dart team actively works on bringing static extension methods and non-nullability by default (NNBD) to Dart. That would allow this package to be even more lightweight and enable a workflow like the following:
Mark your class with an
@DataClass()
annotation:Because of NNBD the constructor is equivalent to the current one;
@required
annotations and non-null assertions are no longer needed. The package could then generate thecopy
,==
,hashCode
andtoString
methods as static extension methods on theUser
type.Benefits
copy
method, causing less confusion like #1.Downsides
I'm welcoming any opinions on whether this is a worthy tradeoff.