views:

60

answers:

3

I'm trying to learn effective DDD practices as I go, but had a fundamental question I wanted to get some clarity on.

I am using ASP.NET WebForms and I am creating a situation where a user places an order. Upon order submission, the code-behind retrieves the user, builds the order from the inputs on the form, calls the User.PlaceOrder() method to perform add the order object to the user's order collection, and calls the repository to save the record to the database. That is fairly simply and straightforward.

Now I need to add logic to send an order confirmation email, and I'm not really sure the proper place to put this code or where to call it. In the olden days I would simply put that code in the code-behind and call it at the same time I was building the order, but I want to get a step closer to solid proper architecture so I wanted to get some information.

Thanks for your help!

A: 

What I do is introduce a logic layer for all the logic the codebehind is only for handling requests and the repository is only for crud operations that way you have perfectly seperated the logic from the rest of the application and is easily testable

Chino
I could just be misreading your answer, but at first glance it seems a little bit like an [Anemic Domain Model](http://en.wikipedia.org/wiki/Anemic_Domain_Model)
R0MANARMY
No you did not misread it :P Also I must note that the entities will also contain their own validation code to force validation but keep in mind that validation should occur on multiple places
Chino
A: 

Sending a confirmation email is best done asynchronously after the order has bees saved to database. I would introduce some kind of message bus (like NServiceBus) to handle such a case. In the same transaction as you save order, you publish a message on the bus "Order has been created". These is a handler that subscribes to this message and sends emails to customers.

Why asynchronously? Because SMTP servers have a tendency to fail and sending emails can be pretty lengthy task and blocking database tables for such a long period of time can introduce deadlocks. I encourage you to look at Udi Dahan's blog: he is the author of NServiceBus and blogs a lot about cases similar to your confirmation emails.

Szymon Pobiega
+2  A: 

For me, I keep everything as close to the entity as possible. After a while, you will start to see that things just fit better in some places versus others. For example, business logic that can be determined based solely on a given instance of the entity should be in the entity. If it requires more knowledge of the domain, then perhaps it belongs in the domain service.

I bucket my logic into three areas, for the most part:

  • Entity Logic
  • Domain Service Logic
  • Application Service Logic

The application logic is where I would register domain events, for example. I do not think that emailing belongs in the domain, personally. It is a requirement, rather than a piece of logic. If I have a listener at that point, the domain might raise an OrderSubmitted() event, and the listener has the responsibility of acting on it. The event belongs in the domain, because it is describing a significant event in the context of the domain. How the application responds to that, however, is different, in my opinion.

As mentioned by Syznmon, Udi's blog is a good resource. I strongly recommend, though, both the Evan's book, and the presentation he gave with lessons learned, as well.

joseph.ferris