Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding abstract classes and inheritance

consider I am having an Event with Invitations (each "invited person" represents an Invitation, so multiple Invitations are out for a single Event):

Diagram

[«aggregate root»;Invitation]<>1..*-[«value object»;EventIdentifier]
[«value object»;EventIdentifier]-<>[«aggregate root»;Event]
[«value object»;Invitee|emailAddress;facebookIdentifier]-<>[«aggregate root»;Invitation]

The Invitee, however, can bei either an Email Address or a facebookIdentifier, that's the nature of the business logic. Usually I would have made an AbstractInvitee with FacebookInvitee and EmailInvitee, and created an association to the abstract, but that's evil as I know now.

Should I, instead, have actually FacebookInvitee and EmailInvitee and the Invitation has each a facebookInvitee and an emailInvitee property; and a Service or so would merge them together, if necessary?

Thanks for your advice!

Edit

I just came to the following idea which looks rather neat,

Diagram

[«value object»;Invitee|type;identifier]-<>[«aggregate root»;Invitation]

The type is somehow a constant with FACEBOOK and EMAIL, and the identifier then is the FB UID or the email address respectively.

like image 469
Adrian Föder Avatar asked Feb 02 '26 20:02

Adrian Föder


2 Answers

Usually I would have made an AbstractInvitee with FacebookInvitee and EmailInvitee, and created an association to the abstract, but that's evil as I know now.

Inheritance is not that evil.

If your classes FacebookInvitee and EmailInvitee have the same interface I see no reason to avoid inheritance. Inheritance adds complexity if interfaces are different and casting to concrete types is needed.

The type is somehow a constant with FACEBOOK and EMAIL, and the identifier then is the FB UID or the email address respectively.

Your example is very similar to Replace Subclass with Fields refactoring. Anyway it will be needed to write if-else code-block to check invitee type and use its identifier for sending an invitation somewhere. Who should be responsible for it? In your solution Invitee is simply a DTO without behaviour. If Invitee has behaviour and can Send() an invitation itself then I would use inheritance and implement Send() for every concrete class (e.g. FacebookInvitee, EmailInvitee).

like image 60
Ilya Palkin Avatar answered Feb 05 '26 10:02

Ilya Palkin


I'd still keep an abstract Invitee value object with 2 derivatives EmailInvitee and FacebookInvitee.

Each type of Invitee can raise its own flavor of WasNotified Domain Event which is then captured by an Infrastructure layer notification service that knows how to handle it.

like image 43
guillaume31 Avatar answered Feb 05 '26 11:02

guillaume31