equatable icon indicating copy to clipboard operation
equatable copied to clipboard

Build runner for equatable

Open josiahsrc opened this issue 3 years ago β€’ 10 comments

This is an ease-of-use idea. I've been using the json_serializable pub package with the build_runner running, which automagically generates my from/to json methods. While I was doing this I thought, hey, wouldn't it be sweet if equatable did this too? This way I wouldn't forget to add fields to the props array.

The solution for this feature I'm envisioning: Before each class that you want to be equatable, you'd add an @equatable annotation. Then, with the build_runner running, the equatable fields are generated on the fly and store in another file my_model.g.dart (or something). (I believe this is possible using extension methods, but not 100% sure). Possible solution:

my_model.dart

@equtable
class MyModel {
  final String value;
}

my_model.g.dart (auto-generated)

extension on MyModel {
  bool operator ==(MyModel a, MyModel b) {
    return a.value == b.value; // and hash code stuff too
  }
}

Is this a sort of feature that would be feasible?

P.S Equatable is in my top 5 favorite packages, really awesome :raised_hands: :raised_hands: :raised_hands:

josiahsrc avatar Jul 16 '20 17:07 josiahsrc

Hi @HatFeather πŸ‘‹ Thanks for opening an issue and for the positive feedback!

I'll look into the level of effort to support this as soon as I can πŸ˜„

felangel avatar Jul 16 '20 17:07 felangel

@felangel Awesome, keep me posted! I'd be happy to help out with this feature as well, just say the word!

josiahsrc avatar Jul 16 '20 17:07 josiahsrc

@felangel I just played around with this idea a bit. I found that extension methods actually may not work. Extension methods only allow you to add methods that haven't been declared yet. The == and hashcode methods are declared by the Object class, so extensions can't be used here (as far as I can tell).

I took some inspiration from the json_serializable library and came up with another solution: The build runner would create a utility method in a generated dart file which creates an returns a props array that can be directly returned from the List<Object> get props; method. I created a short demo for a proposed solution:

josiahsrc avatar Jul 31 '20 06:07 josiahsrc

@HatFeather I like your idea. I just checked out your files. But, if this gets implemented, we may lose the feature called selective equality (Equality based on certain fields only). I guess, we can also include an annotation like @excludeEquals which will ignore that field in props array generated.

RaviKavaiya avatar Aug 05 '20 14:08 RaviKavaiya

@RaviKavaiya Thanks for your feedback! That is a good thought; I've updated the proposed solution to include the @excludeEquals you suggested. https://github.com/HatFeather/equatable/commit/599fa4e759d6279133608adff1c1b0f7e16c12d1

One thing I want to point out is that this solution doesn't remove any existing equatable functionality, it only provides a way to automatically generate an equality props array. So there should be no backwards compatibility issues πŸ˜„

josiahsrc avatar Aug 05 '20 15:08 josiahsrc

@felangel your thoughts?

RaviKavaiya avatar Aug 05 '20 16:08 RaviKavaiya

I don't like the build_runner. It will make equatable dependent on a package that takes more time to generate than typing it yourself. I skip the possible regressions of build_runner.

lsaudon avatar Oct 01 '20 07:10 lsaudon

Hey all πŸ‘‹

So far I’m not inclined to proceed with this change for several reasons:

  1. The primary goal of equatable was to solve the issue of value based equality comparisons without code generation β€” there are already several alternatives to equatable which use codegen like freezed and built_value.

  2. There are already extensions like Dart Data Class Generator which generate the Equatable props for you and are faster than build_runner.

  3. The level of effort to implement and maintain is non-trivial

Looking forward to hearing everyone’s thoughts πŸ‘

felangel avatar Nov 15 '20 22:11 felangel

@felangel You bring up some good points. My original motivation for the equatable build-runner was to make it so there was minimal thinking necessary for maintaining a suite of data models in your code base (E.g. if you change a model, you don't have to remember to update the equatable props as well). The existing equatable generators still require some forethought, as far as I'm aware. You'll still have to remember to regenerate the class once you update a field.

However, I can see that there's not a lot of traction for this idea, so I think we could go ahead and close this issue.

Thanks a ton for looking into this though πŸ˜„ πŸ‘

josiahsrc avatar Nov 16 '20 03:11 josiahsrc

@josiahsrc You can also try mek_data_class, I'm relying on equatable for this package always with an eye on generation performance

BreX900 avatar Mar 04 '22 13:03 BreX900