3 ms·
> "A Customer can CreateReport(), a Report can RenderAsEmail(), and an Email can Send()" Until you need to generate a different type of report for the customer
by valdiorn 11y ago
> "A Customer can CreateReport(), a Report can RenderAsEmail(), and an Email can Send()"
Until you need to generate a different type of report for the customer, render a different format email, or send the email via another process. At that point, you have 3 options:
1. inherit and override. So you end up with
* SpecialReportCustomer : Customer,
* NewEmailStyleReport : Report,
* SendViaProxyEmail : Email
It should be pretty obvious that this won't scale... at all.
2. Inject the desired sender or report generator into your object, depending on what implementation of the report builder or email sender you want. But why would the object have to know how to print itself, or send itself? Separation of concerns, people!
3. Break the interface of your class, make the methods accept a special reportBuilder or EmailSender... but why do that, when you can just do literally the opposite of what the author says, and have option 4:
4. Use an CustomerReportBuilder.Create(customer), or EmailSender.Send(email).
...and then you see why option #4 is your best choice, and why this article is objectively wrong in every way.
- dandlift 11y agoAgree, I also find useful to split between domain concerns and application concerns. A report is something that belongs to business, but the fact that it could be sent via email is totally accidental and depending on the technology we use (as it is the persistence layer, or the protocol which exposes the app). Domain concerns live on domain object (which knows only other domain objects), while application concerns live in services. And here is where you have interfaces, concrete implementations and, where necessary, factories to switch or add the implementation at the flip of a switch. Eg: a ReportMailSender which implements a ReportSender, that someday get replaced with a SlackSender implementing the same interface. You want both? Wrap them on a AggregatedSender. Now your DI framework is getting really useful.