tags:

views:

151

answers:

4

When your domain layer or business layer (whatever you want to call it) is completely separate from your UI, how does it gather the information it needs to complete a request?

For example, suppose the UI issues a request to add a line to a purchase order, and the business rules determine that you need an authorization code for some reason. How does the domain layer communicate this back? Return some kind of response code indicating it requires authorization? Fire a "need authorization" event and see if anyone responds? Accept some sort of IAuthorizationProvider that the UI will implement?

All of these seem okay, but I struggle with having an explosion of possible things that the business could need. Just continuing with the purchase order example, what if some items need a color? Some need a hazardous materials declaration id? Some need a simple "this is rare, are you sure?". The list could go on and on. It feels like deciding you need this info definitely belongs in the domain layer. In a non-layered app, you'd just pop up a dialog and get what you need. How do you do it in a properly layered application?

+1  A: 

The presenter or the controller, depending if you do MVC or MVP should know about it, not the domain, the domain will assert ( defensive coding ) is as all needed values ok, or throw an exception, not ask for it.

So let say you don't supply the number, your model throw a AuthorizationNumberRequiredException, then your presenter handle it from there. So your domain is not coupled to the presenter, it simply throw errors, your presenter must know how to handle it, but it not duplicating the logic.

pmlarocque
But these are clearly business rules. Why would they be in the presenter, which is concerned with the UI. Suppose I use this domain in a service, where there is no presenter -- would I duplicate the rules in the service?
Eddie Deyo
+1  A: 

The UI somewhere has to pass the information into the Business Layer at somepoint. Whether you're going through an intermediate object such as a controller or not. The business layer needs to determine whether the PO is in a valid state. If not, then return the information stating what's wrong. This can either take place from the PurchaseOrder.AddLineItem method call or perhaps a PurchaseOrder.Validate method. My preference would be to return validation information from the PurchaseOrder.AddLineItem method so you can determine that the object state is invalid right there.

Micah
+2  A: 

"... the business rules determine that you need an authorization code for some reason. How does the domain layer communicate this back?"

That's what an API is for. You have several choices.

  1. The business rule API simply lists the various things the business rules need. The UI is responsible for making complete requests. These things aren't dynamic. It's not like the business rules change randomly. There is version control for this kind of thing.

  2. Exceptions work well. The request raises an exception because it's incomplete. The API specifies the exceptions and how to make a "complete" request free of exceptions.

  3. An AuthorizationProvider's not a bad plan, either. The API would be defined to clarify which requests exercised the AuthorizationProvider.

"I struggle with having an explosion of possible things ... The list could go on and on." Actually, it doesn't. Just define an appropriate API that fits the problem domain.

If -- for some reason -- you're afraid you can't define an API, then you can't define the problem either.

"But what about..." for example, what about some items which have color or an MSDS. What about a confimation dialog?

  1. Color -- or other details like MSDS. First, the model has a "requires color" setting. The UI simply checks if the color dialog is needed. There are only a finite number of these, all of which are part of the problem you're solving, and all can be enumerated.

  2. Confirmation for rare things. Again, the business rules have a "requires confirmation" property or method. The UI checks this. There are only a finite number of these, all of which are part of the problem you're solving, and all can be enumerated.

You don't pop up a new dialog. With separate UI and business rules, you now do two things:

  • Add the information to the business rules;
  • Make the UI check for that an pop the dialog.

You're not adding a HUGE amount of code. The business rule property is a few lines of code. The UI check is a line of code.

S.Lott
A: 

I've done some more reading and found the Notification Pattern from Martin Fowler which seems to be geared towards solving this problem as well as Domain Centric Validation with the Notification Pattern by Jeremy Miller.

This is Fowler's description of Notification, which describes pretty much exactly what I was looking for:

An object that collects together information about errors and other information in the domain layer and communicates it to the presentation.

Eddie Deyo
In some cases the notification is implemented with an Exception. In other cases, it's an ErrorDictionary with attributes names and an ErrorList (or List<String>) with the individual error messages.
S.Lott