YMC
YMC

Reputation: 5452

Good design to track changes in domain model

We have 2 separate existing applications that can only communicate through bus messaging system and database. Now we want to inform second app about any changes made to our domain model in the first app before or after db update: once we know there are real changes to be saved in a storage or have just been saved, we want to send specific message to a separate application. Message does not indicate what kind of changes are made.

Some considerations:

What approaches would you recommend us to use in the case in terms of application design? Is it good practice for Data Layer to submit such notifications via bus system? How could we know data were actually changed: can we know it through NHiberate session or we got to track changes inside domain model?

Upvotes: 2

Views: 1053

Answers (2)

Low Flying Pelican
Low Flying Pelican

Reputation: 6054

Is it good practice for Data Layer to submit such notifications via bus system?

No, but if you need to rasise such notification for every change, and if you could bind those events into the plumbing of the system without changging all repositories, its OK.

How could we know data were actually changed: can we know it through NHiberate session or we got to track changes inside domain model?

Easiest solution for this issue is to use an interceptor or an event. Something like this should solve your problem,

Event

(Please refer this for complete example)

    public class ChangeEventListener : IFlushEntityEventListener
    {
        public SetModificationTimeFlushEntityEventListener()
        {
            CurrentDateTimeProvider = () => DateTime.Now;
        }

        public void OnFlushEntity(FlushEntityEvent @event)
        {
            var entity = @event.Entity;
            var entityEntry = @event.EntityEntry;

            if (entityEntry.Status == Status.Deleted)
            {
                //raise event
            }
            var trackable = entity as ITrackModificationDate;
            if (trackable == null)
            {
                return;
            }
            if (HasDirtyProperties(@event))
            {
                //raise event
            }
        }

    }

Interceptor

public class NotificationInterceptor : EmptyInterceptor 
{

         public override bool OnFlushDirty(object entity, 
                                          object id, 
                          object[] currentState,
                          object[] previousState, 
                          string[] propertyNames,
                          IType[] types) 
        {
        //do check for changed states by comparing current and previous values, and raise event if changed
            return true
        }
 }

Upvotes: 1

ThePolisher
ThePolisher

Reputation: 379

Is it good practice for Data Layer to submit such notifications via bus system?

No, it is not. Although some frameworks support this out of the box, it is usually wrong to have or write on your own. The problem here is two fold -

  1. YAGNI - when you design a system upfront you tend to overwhelm it with mechanisms that are overestimated, this in turns effects the system efficiency and simplicity.
  2. Context is the key! it's too general to have a repository which notifies everything it does without context. Consider notifying whenever you insert a row to a table in order for the UI to change, now consider it in terms of syncing data from the cloud. There is strong coupling between the bulking of data to the DB and your UI refresh rate which obviously are two different things. Solving this problem and maintaining coherence becomes a drag.

How could we know data were actually changed: can we know it through NHiberate session or we got to track changes inside domain model?

There is some inconsistency with your presentation of the requirements and this question. You presented it like this - "It’s Ok if message is sent earlier than data are committed to db, even if they were finally rejected" And then you say that it is relevant to know the data was actually changed or not.

Anyways, if you save the data directly to the DBs it usually returns some indication, like the number of rows modified. When using ORM frameworks like NHibernate you can usually commit the transaction immediately and get the same indication.

In both ways you should let the other application know only when the data were actually changed in the DB, if the other application is retrieving it from the same DB.

What approaches would you recommend us to use in the case in terms of application design?

We solve this by publishing the event as part of the logical process and not as part of the persistence, because you may have some actions that will not require notifications. If you still want to do this in terms of data, I would not recommend to hard-code it in your repositories but rather use Martin fowler's Unit of work or the Transaction script patterns. They will allow you to decide which transactions of data are supposed to publish events and which are not, and when.

Upvotes: 3

Related Questions