Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Notification Services Distinguished From Logging Services

Freely admitting my naïveté and rookie/booter/redshirt status , I ask a simple question:

Why are messaging services such as logging often implemented via a pattern employing some kind of globally accessible object, yet similar services for passing messages from a domain model (perhaps using a Notification pattern) up to a client typically shown with handling inside of a controller/presenter try...catch statement?

I realize this is one of those error-prone 'one-size-fits-all' questions. It just seems like logging is messaging and so is notification, so why do we pass strings to calling clients for notifying them of the results of their actions while we have frameworks and static objects writing our log messages?

I experimented with an Notification-like object which was bound to my Unit of Work so that events/messages that needed to get communicated to the user would get aggregated and flushed after the unit of work was complete. This 'worked' by letting me simplify and standardize but I himmed-n-hawwed (redneck design technique) about the wisdom of that and in my current app haven't implemented it again.

Consider something like this, where we are using a globally accessibly Log object and have a 'Client' method that writes the message not to a log file, but is aggregated for consumption later depending on the client type:

Log.For(MyObject.GetType()).Client('The biz rule prevents this from happening.');

The objections I can come up with are:

  1. Doing something like this in your Domain Model violates keeping a clean separation between Domain and Client.
  2. If something can't happen as expected it IS an exception and so should be handled in traditional try..catch block

But then my answers are

  1. I am logging things that happen in my domain, so how is that different than sending client messages out? Obviously I won't be passing stack traces to this 'Client' and the messages would be 'prettier' but I'd want to notify things like specification constraint violations, side-effects which were intended and noteworthy,  and so on, so why is throwing and exception for that (so that my client will catch it) better?
  2. I know the common view of exceptions is that things that can't be executed as expected are exceptional and so should be in a try..catch and handled appropriately. Ok, but I expect users to attempt some operations that due to some rule are not valid.  I am not talking about invalid or missing data, but rather rules which perhaps due to the results of other data make the current request invalid. Or perform some operation that changes state in many objects which is not invalid or exceptional.

I use DTOs to pass from my Tasks layer (application services in DDD-speak I believe) up to my controller and its not overwhelming to just standardize and implement these common message carriers on up the chain, but there are many times when I'd like to notify the client of many changes that occurred due to the action they just took . For example, we have Materials Tests that can have retests, creating a parent-child relationship. Assigning a retest automatically removes it from one parent to another parent. This all happens and the new DTO is passed to the controller, but I want to let them know all the side-effects this action caused. Something like 'Test# 32 removed from Test#45.  Sample Numbers have been regenerated for this project. ' 

I commonly am writing repetitive code to place messages into some kind of hash that is parsed and displayed to the user, and page design changes can make a lack of common practice painful when there is much repetition like this. Even though I keep actions as atomic as possible, there are still bound to be many state changes that are worth reporting to the user, no?

There are a ton of things I am sure I am not considering and I really don't want a slough of staticy global "Manager"-type objects doing infrastructure stuff invading my domain, but I'd love to hear how other folks implement client messages up the chain while promoting code-reuse in the controller/client layers or point out considerations I am no doubt missing.


Posted 02-11-2008 1:23 AM by Michael Nichols
Filed under:

[Advertisement]

Comments

Derik Whittaker wrote re: Notification Services Distinguished From Logging Services
on 02-11-2008 7:48 AM

Mike,

I feel your pain.  I have been here many of times, and often have wanted to know what is the 'right' way to to do this.  

I personally don't see the harm in what you are doing.  Sure, it may kinda feel 'dirty' but it is reasonable to think  that every layer of the system will have its own checks and balances.  And if checks fail it is reasonable to think that they need to explained to the user in some way.

I would say that the way you have abstracted the message brokering is good as it separates the messaging from the layer (can use the same broker every place).

Derik

Christopher Bennage wrote re: Notification Services Distinguished From Logging Services
on 02-11-2008 9:35 AM

You definitely have me thinking.

Bill Pierce wrote re: Notification Services Distinguished From Logging Services
on 02-11-2008 9:39 AM

Hey Mike,

An idea I pulled completely out of the air.  Assuming you are using log4net, you should be able to programmatically add an appender before you kick into your 'Tasks' layer.  This would be a memory appender that essentially writes log messages to a string which you could then display to your user.  Still maintains any other logging you have (to a file, email, etc).  Totally untested crazy theory.

What I have used in practice for "exceptional" situations is to create an Exception class (ala UserException) with the understanding that if a UserException is thrown, the Message will be shown to the user as is (rather than a generic 'error occured' for unexpected exceptions).  Not quite as flexible but still gives the user the necessary feedback.

Mike wrote re: Notification Services Distinguished From Logging Services
on 02-11-2008 11:16 AM

Wow! Thanks everyone...

@Derik - I'm glad I am not the only one that has wrestled with The Right Way of doing something....I get myself shipwrecked with that and forget to be pragmatic. Blogging is therapy for me :)

@Bill - How flexible would an log4net appender be ( I am using log4net)? A similar thot I had was to just intercept my calls to ILogger and write the calls to 'Client' method directly to an NotificationDTO.Errors object that is stored in Flash/Session (if I am doing monorail for example) then just have a ViewComponent format all these things real pretty or have my AjaxFilter convert to JSON to display if an XHR.

Ayende Rahien wrote re: Notification Services Distinguished From Logging Services
on 03-11-2008 11:38 AM

The problem is that unless you are writing command line app, this is not sufficient in many cases.

You need to know where to show and how to show it.

Mike wrote re: Notification Services Distinguished From Logging Services
on 03-11-2008 5:36 PM

I am using a notification provider interface that has an implementation on my current web project similar to an ILogger implmentation accessed via a kind of 'static gateway'.

Except instead of writing to an appender, the gateway brokers the message to a meaningful flash collection and my message center view component renders these notifications to the user via an Filter.

It is up to the app implementor to take care of the where and how to show it and my domain remains agnostic on how its messages are consumed.

How do you prefer to deliver meaningful messages from the domain to a client?

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)