-
Notifications
You must be signed in to change notification settings - Fork 11
Description
Here are some examples from the PHP world inside for instance from the @dddinphp book under "Value Equality":
Or by @spriebsch:
{
public function equals(Money $money)
{
if ($this->currency != $money->getCurrency()) {
return false;
}
return $this->amount = $money->getAmount();
}
}
Or by @lorenzomar :
public function sameValueAs(ValueObjectInterface $valueObject)
{
return $this->iso31661Alpha2Code->sameValueAs($valueObject->iso31661Alpha2Code()) &&
$this->iso31661Alpha3Code->sameValueAs($valueObject->iso31661Alpha3Code()) &&
$this->englishName->sameValueAs($valueObject->englishName()) &&
$this->phoneNumberPrefix->sameValueAs($valueObject->phoneNumberPrefix);
}- https://hotexamples.com/de/examples/valueobject.geography.country/Iso31661Alpha2Code/-/php-iso31661alpha2code-class-examples.html
- https://github.com/lorenzomar/valueobject
Unfortunately implementing the interface in PHP can get tricky because of type-hinting.
Here is a SWIFT example by @twostraws:
struct User: Equatable {
let value: String
init?(string: String) {
guard string.trimmingCharacters(in: .whitespacesAndNewlines).count >= 3 else {
return nil
}
let illegalCharacters = ["@", "-", "&", "."]
guard illegalCharacters.contains(where: string.contains) == false else {
return nil
}
self.value = string
}
}
Some thoughts from the .NET world by @jbogard:
Override the Equals method, to implement equality instead of identity, which is the default Additionally, Framework Design Guidelines has some additional requirements I must meet:
Provide a reflexive, transitive, and symmetric implementation of Equals
...
Implement IEquatable
Override the equality operators
Generic ImplementationWhat I wanted was a base class that would give me all of the Framework Design Guidelines requirements as well as the Domain Driven Design requirements, without any additional logic from concrete types. Here’s what I ended up with:
public abstract class ValueObject<T> : IEquatable<T>
where T : ValueObject<T>
{
public override bool Equals(object obj)
{
if (obj == null)
return false;
T other = obj as T;
return Equals(other);
}
IEquatable of T is designed to avoid boxing/unboxing of .NET value types during equality comparison. Its main purpose is to be used on structs.
In classes, there's no benefit in implementing Equals(MyValueObject obj) over the standard Equals(object obj), hence I don't use this interface due to YAGNI.
- Unknown source
@EresDev states:
With improvement in my ideas, experience and knowledge, I no longer agree with having an interface for a Value Object. I don’t write interface for Value Objects anymore. The most solid reason for this is given by Kent Beck.
Some final thoughts by @vkhorikov:
There's no need in implementing IEquatable, this interface was introduced specifically to avoid boxing/unboxing of .NET value types (structs) when dealing with comparison.
As long as you implement ValueObject as class, you can safely omit implementing IEquatable.
Related discussion on Twitter: