I've been writing some code in Dart. I really love the factory constructor, but I'm afraid that I'm abusing it's usefulness. In particular, when I write a value object class, I sometimes return null if the validation fails.
class EmailAddress {
static final RegExp _regex = new RegExp(...);
final String _value;
factory EmailAddress(String input) {
return _regex.hasMatch(input) ? new EmailAddress._internal(input) : null;
}
const EmailAddress._internal(this._value);
toString() => _value;
}
At first, this doesn't seem all that bad. However, when you actually use it, this is what you see.
methodThatCreatesAnEmailAddress() {
var emailAddress = new EmailAddress("definitely not an email address");
...
}
The argument why this is bad is that a developer coming from another statically typed language, such as Java or C++, would expect emailAddress
to always be initialized to a non-null value. The argument why this is perfectly acceptable is that the constructor is factory and, as such, is allowed to return a null
value.
So is this bad practice or taking advantage of a useful feature?
Please don't do this. As a user of a constructor I expect to receive an instance of the constructor's class. It's ok to return a pre-existing instance or an instance of a subtype in Dart, but don't return
null
.I'd recommend one of two options to do what you want here:
throw an exception on invalid inputs. This way at least the error is early, rather than later if you've stored the
null
somewhere.Use a static method instead of a constructor. Static methods can return
null
and not be as confusing.Provide a fallback path, such as
int.parse
does. You can accept a callback that will be called on an error.I prefer 1 or 3 myself. I'd like to know explicitly when something isn't valid.
Returning
null
value as result from a factory is acceptable because the builtinfactory
feature in Dart Factory software concept does not have any null-restriction.On the other hand I can rephrase your question "Is it acceptable to return null from a equality operator"
This is also acceptable because there is no such restriction that this operator cannot return the
null
value.But there is another question? Why do it and how to avoid it?
P.S.
My personal opinion that returning
null
fromfactory
in Dart is abad practice
because factories in Dart are very difficult to distinguish from contructors.From the outside they looks like contructors with the difference that they are more powerful because can construct different kinds of objects.
And they also have their restrictions but this is another story...
It's bad practice. When someone calls a constructor they expect a non-null value.
For your case I might do validation in a static method:
Now you get code reuse and nice semantics. For instance:
I'm going to dissent from other answers: at least for named
factory
constructors, I don't see anything wrong with returningnull
.The main differences between a
factory
constructor and astatic
method are that afactory
constructor can be used withnew
and can be the unnamed, default constructor. Usingnew
is now discouraged, so a namedfactory
constructor won't be distinguishable from astatic
method invocation at a callsite.I don't see anything wrong with a
static
method returningnull
, and therefore I don't see anything wrong with a namedfactory
constructor returningnull
either.If the
factory
constructor is unnamed, then I would agree that returningnull
is likely to be unexpected by the caller and probably should be avoided.