I have a parent object, with multiple child objects. Every child object is of the same type and has a "ChildMethod" that contains some child specific logic. If the ChildMethod is called on any child, i want to serialize the state of all children. I put that logic into the parent object. Also I implemented it with the observer pattern, the children being the subjects, and the parent the observer. It works fine so far. Now I need another method "CallAllChildMethods", that basically calls the ChildMethod on every child, yet I want to avoid multiple serializations, since it is necessary to do it only once.

The only solution I see at the moment is to unsubscribe to all subjectevents before calling CallAllChildMethods, then resubscribe again. That works but is a heavy design smell. Are there, from a design standpoint, cleaner ways to handle that case?

  • Sounds like you want something similar to debouncing seen in UI event listeners sometimes. That's usually handled with a timeout of some kind or else a lock on the function that turns it into a noop until it's completed. – Paul Apr 2 '17 at 1:33

Oof, sounds like that object has become very tangled.

I would re-evaluate your criteria. Its not as simple as 'serialise after every change' so hard coding that into your object design will only mean you having to hack around it later.

It sounds like you want an equivalent of transaction scope, allowing you to execute the child changes one at a time by default, but also to group them together in a transaction if required.

You could pass this scope object in to the child.Change methods, but it will be ugly. If you are injecting a repository object to implement the saving, you could perhaps expose a transaction scope on that.

By the event would still fire repository.Save() but in your batch method you would do something like..

repository.BeginTransaction() //flags Save() to be ignored
foreach(child in childern) {
    child.Change(); //calls repository.Save()
repository.CommitTransaction() //removes flag and calls Save()

Obviously there are some complexities around threading and stuff you might need to consider. But you get the idea

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.