3

Let's say I have an processing pipeline. It receives a file, converts the file to data, interprets the data, and then persists it.

At every step of this way, I would need to collect statistics, so I can show a comprehensive "Import Report" at the end. Retrieving some of this data is not possible once the algorithm finished, and has to be collected while it is running. Implementing this cleanly shows to be very cubersome, though, because I end up with implementing this cross-cutting concern still in the algorithm itself.

A few approaches:

1: Create an statistical object. Pass it as parameter to every sub-method of the pipeline that has use for it. Fill it appropriatly there. While it keeps the pipeline stateless, it feels super yucky.

2: Create an statistical object. Save it as an private variable inside of the algorithm object itself. The object is now stateful and appropriate care has to be taken in terms of thread safety. A pain in the ass if the algorithm ever needs to be split into multiple objects down the road. But it keeps methods cleaner, I guess...?

3: Instead of passing a statistical object to a method, have it return the result as well as a statistical response object than can then be accessed by the caller. Not quite as yucky, but this just really moves the problem from one place to another, namely the caller.

4: Implement publishing events inside of the algorithm that spits out necessary events when something noteworthy happens inside of it. Decouples the statistic collection from the algorithm itself, still imposes this use case in the structure of the algorithm, seems incredibly overkill for my use case, and brittle to future changes.

Honestly, all of these approaches are incredibly ugly to me. Right now I'm using approach 1. But I'd like to use a cleaner version in the future.

5
  • FWIW, my mind instantly jumped to “raise events and have have something else collect that info”.
    – RubberDuck
    Commented Nov 27, 2019 at 10:38
  • Raising events might be runtime expensive. My preferred approach is either to use proper AOP (if available) or otherwise use a global variable (or a field in a method object if you're squeamish about global variables). Commented Nov 27, 2019 at 10:56
  • When using proper AOP, how would I be able to collect specific information? Wouldn't that require me to extract a method out of basically every primitive I want to have a statistic of, to be able to wrap a join point around it? (My AOP terminology is a bit rusty, I hope it's still understandable)
    – Joe
    Commented Nov 27, 2019 at 10:59
  • Maybe implement this with some logging library? Commented Nov 27, 2019 at 13:16
  • I guess this could be done with an DI'd custom logger that keeps track and allows me to extract an statistics object at the end. Might just be slightly dirty because I'd need to make sure the scope is appropriate at all times? I do like that idea though.
    – Joe
    Commented Nov 27, 2019 at 13:32

1 Answer 1

1

You should never introduce state to code that can be stateless. So option (2) and (3) are already out. Stateless code, that only depends on its input values, is much less troublesome and thread-safe by design. You can easily use it in multiple parallel pipelines at the same time. The compulsion to always introduce state to objects is a typical OO programmer sickness to me; they always feel that objects require a state because otherwise it seems unjustified that you can have multiple instances of that object. Yet you don't require to have multiple instances of a stateless object to begin with since it has no state, so it can as well be a singleton (doesn't have to, though, nothing is wrong to have multiple instances of the same stateless object, such objects hardly require any resources).

Option (4) is okay but it has no advantage over option (1) because publishing an event is hardly less work than writing the event info directly to a statistic object. Publishing an event will only require more runtime resources. Option (4) would only be interesting if you'd display the statistic information in an UI and require live updates while the file data is being processed.

This clearly leaves option (1) the cleanest by design IMHO. I don't see why it feels "super yucky" to you. Using AOP would lead to cleaner code as it hides all the complex details from the reader but internally it will work exactly as option (1).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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