Adding a logging-feature to an existing system

303 views
Skip to first unread message

featurefabrik

unread,
Sep 18, 2013, 3:54:03 AM9/18/13
to clean-code...@googlegroups.com
Hi Clean Code Discussion board,

another question arose the other day while implementing a new feature on an already deployed and running system.

The request was to track all changes, the logged in user makes to the system. At a first glance I thought to myself: "Nice, we can let the gateways do this, without adding additional knowledge to the core system and its use cases."

That sounded reasonable and simple to me at first. But than it struck me. The log has to store not only what has changed, it also has to change who changed it, damn!

The next idea for a possible implementation was "Let's add it to the use cases which change the state of the entities. This feature is strongly correlated to the changing use cases, it should be in a central place of the system."

But this brought up another problem: Most of the use cases had no idea, "who" is currently using them. Since no changes to the system required any kind of a user context. All access control lays behind the log in wall of the delivery layer.
We did not want to add the current user information to every request object of the regarded use cases, so this second approach was also kind of "not implementable".

We came up with a specific logging use-case, which accepted the users identifier, the name of the action that is to be logged (like "update_event") and an arbitrary bag of data, that is associated with the change.
At least, know we had separated this logic from the rest of the system.

But this approach still has its downsides. We have know logical information,(which action is to be logged) about our business values laying around in the delivery layer. That does not feel right to me.

Since I did not came up with a better solution, I am eager to hear your opinions about this specific problem. I cant be the first one struggling with this! :)

Greetings

Uncle Bob

unread,
Sep 23, 2013, 12:09:02 PM9/23/13
to clean-code...@googlegroups.com
featurefabrik,

You are not the only one pondering this issue.  In fact this is a very big and current issue that's gaining more and more attention with every passing year.    But before I get into that, let's just talk about your solution.

The controllers, on the UI side, are the ones who figure out which use cases to activate.  They also know who is activating those use cases.  So they are in the best position to do the logging you are talking about.  They could simply log the user, the request object, and the use case operation to be performed.  Indeed, you could create a command object that activates the use case, and add a log method to the Command interface.

Now, on to the larger issue.  More and more teams are realizing that it is better to store events in the database, than it is to store state.  State can always be recreated from events, but events can never be recreated from state.  So event->state is a trap-door function (a function that cannot be reversed).  Recomputing state from events may seem processor intensive; but processors are plentiful and cheap; and you can always take state snapshots ever day, or every hour, to keep the processing load down.  

The benefit of this approach is that CRUD application suddenly become CR applications.  When you save events and calculate state, you _never_ update and you _never_ delete.  And if you don't update and delete, you don't need database transactions.  You can't have concurrent update problems if you never update!  This means consistency all but disappears as an issue.

Do a google search for CQRS.  In particular, watch some of the videos by Greg Young.  

featurefabrik

unread,
Sep 30, 2013, 4:45:18 AM9/30/13
to clean-code...@googlegroups.com
Thanks for the insight, Uncle Bob.

I do agree with you, that events supersedes state.

From this perspective, the controllers _ARE_ the spot where the logging has to occur. Perhaps, if I consider the specific event logging strongly related to the web-delivery, it is not so problematic that it is decoupled from the core app. I don't think, a console application with this behavior would need this kind of logging.

Thanks for taking the time to answer my questions, again!

Svemir Brkic

unread,
Sep 30, 2013, 9:24:06 AM9/30/13
to clean-code...@googlegroups.com
I probably have no business evaluating Uncle Bob's words, but this was extremely well said. I hope you don't mind me quoting this to every developer I know:

On Monday, September 23, 2013 12:09:02 PM UTC-4, Uncle Bob wrote:
 
...More and more teams are realizing that it is better to store events in the database, than it is to store state.  State can always be recreated from events, but events can never be recreated from state.  So event->state is a trap-door function (a function that cannot be reversed).  Recomputing state from events may seem processor intensive; but processors are plentiful and cheap; and you can always take state snapshots ever day, or every hour, to keep the processing load down.  

The benefit of this approach is that CRUD application suddenly become CR applications.  When you save events and calculate state, you _never_ update and you _never_ delete.  And if you don't update and delete, you don't need database transactions.  You can't have concurrent update problems if you never update!  This means consistency all but disappears as an issue...
Reply all
Reply to author
Forward
0 new messages