Search code examples
flutterdart

Why should I avoid wrapping fields in getters and setters?


I am building a Flutter app. I have a class that looks like this:

class ToDo {
    String _title;
    bool _done;

    String get title => _title;
    void set title(String newTitle) { _title = newTitle; }

    bool get _done => _done
    void set done(bool done) { _done = done; }
}

But the Dart linter is complaining that I should "Avoid wrapping fields in getters and setters just to be safe". However, this doesn't make much sense to me. Right now the getters are useless, but what if in the future I need to do some kind of processing before accessing a variable from outside? All I'll have to do is update the getters. However, if the properties were public and being accessed directly, I would have to update the whole codebase if some business rule changed.

So what is the point of this warning? Or, in other words, why creating "useless getters" would be a bad practice?


Solution

  • However, if the properties were public and being accessed directly, I would have to update the whole codebase if some business rule changed.

    Ask yourself this: what exactly would you need to change in your Dart codebase if you had to change a public member to use an explicit getter and setter instead?

    In most languages, getters and setters look like method calls to consumers. If you wanted to replace a public data member with a public getter and setter, that would be a breaking API change, requiring changes to everything that uses it.

    Dart is not like that. Getters and setters do not look like method calls to consumers; they are indistinguishable from direct member access. (Having a public data member implicitly declares a corresponding getter and setter as part of the class's interface.) Changing a public data member to a public getter and setter would not require any changes to callers, so providing trivial getters and setters around private member variables provides no benefit.

    (This is also explained by the documentation for the unnecessary_getters_setters lint that you encountered.)

    Incidentally, the unnecessary_getters_setters lint should occur only if you provide both a getter and a setter (which is not what your example code does). If you provide only one, then it would no longer be equivalent to a public data member.