What does a Consumer consume?
t.muenz at xdev-software.de
Thu Apr 11 01:19:14 PDT 2013
Bike shedding alert :)
While I think Java 8 is pretty optimal from what I saw so far (I know it can't be perfect considering Java history), there's one particular thing that worries me so much that I feed compelled to bother you with it.
Please bear with me.
I strongly appeal to rename the type Consumer to a more approriate name, like maybe Procedure.
A consumer is an entity that consumes another entity, meaning removes it from its context. Best example is a collection that is used for inter-thread communication: the producer/supplier thread puts a new item in the queue and the consumer thread removes the item from the queue, hence _consumes_ it.
Consuming generally implies that the entity it is applied to is _consumed_, made gone, removed. Also see the meaning of consumer in the economy: consumers (we) take and buy stuff, remove things from their shelf and then use/digest/etc. them until they're gone.
But this core meaning of the term is absolutely not the case with the functional type that currently carries this name. It's just a procedure, not a consumer.
It MAY be used to consume entities from a collection (which depends on the method called, not the passed function instance), but it may and will be used many times more to just iterate them and apply a logic to them in general busines logic.
I must say was very happy to see that the old, compiler-specific-oriented name "Block" has been given up (already wanted to post about it, but the problem solved itself, thankfully).
But only to be replaced by an apparently concurrency-specific-oriented name like "Consumer".
But why not just take the general functional way of thinking to find a name for a general functional element in the first place?
Can('t?) you imagine the hundreds of questions from beginners and not so talented developer colleagues like "If I apply the consumer to the collection, is the collection empty afterwards?"? ... and the hundreds of times we will sigh, start explaining "No, you see, this is just a ..." and think "why oh why did they give it that name?" and then start to explain time and time again?
This won't be a sign of missing understanding of the asker, but it's a sign for confusing naming in the official API.
Also, a very good indicator that Consumer is an unlucky choice can be found in its own JavaDoc:
"An operation which accepts a single input argument and returns no result."
If you instantly have to switch to another term to even begin to explain it, then why did you chose the unfitting term in the first place? Why not then call it "Operation" right away? Or as "Operation" might be ambiguous, something even more fitting, like said "Procedure".
And again: where is the reference to the name, to the process of consuming in the java doc? It's missing for a good reason: because nothing is consumed in the first place.
I have function types in my own (sry: next generation start-over) collection framework that I use very successfully for years now, namely:
Predicate<E> with boolean apply(E)
Function<I,O> with O apply(I)
Procedure<E> with void apply(E)
(Plus a couple of others like Aggregator<E, R> extends Procedure<E> which for me is a much more elegant, flexible and efficient concept than a reducer, but that doesn't matter here much).
Those are very thoroughly thought through names, based on the following rationale:
1.) Procedure correlates very good with the other type Function when it comes to building the mental conception of different functional types.
They are both very similar, but Function returns something, Procedure does not. Like "brothers". Very intuitive, very straight forward. At first I named it "Operation" (like mentioned above), but because of this point, procedure appeared to be much more fitting.
2.) All the functional types have a unifiedly named method "apply". A function is applied to an entity. A predicate can apply to an entity (honestly: who says "the predicate tests the entity" in common speaking? I think 90% say "if the predicate applies to the entity, then...")
As a side node: colliding method names are irrelevant because in practice you never come accross a case where a concrete implementation has to implement a procedure and a predicate or so. Such cases are done by internal separated delegates anyway, not by directly implementing multiple interfaces.
Me personally (however much that is worth), I will happily delete my proprietary "Function" and refactor everything to use the standard one the moment Java 8 goes live. I'm all for standard conformity if it's at least "okay" to use it.
I'm currently struggling with myself to accept the standard Predicate with it sub-optimal "test()" as well for sake of standard conformity, but I think I'll get there in the end.
But I cannot in good conscious replace an intuitive, easy understandable "Procedure" in my private and professional work with a confusion-prone "Consumer" and explain my customers and colleagues endless times that it doesn't really do what it implies but instead is just an ordinary procedure/operation/routine. The reaction of anyone having even a little reservation about functional programming will instantly be "Aha, this doesn't sound very thought-out, I knew it, functional programming is crap, go away".
I'd rather stick to my proprietary Procedure type and tell them to better not use the standard mechanism from the JDK because it does more harm than good. Sadly, I do this a lot and I hate to do it every time. Maybe this time, I hope I can prevent it ...
Alternatives fitting the concept instead of Procedure might be "Routine" or even more abstract "Logic" or "Action", but really, please consider that in practice, on a daily business logic designing level instead of a language design working bench, "Consumer" is the second worst and confusing choice right behind "Block". Why not pick a term from the upper end of fitting terms instead of the lower end and save everyone several tons of hazzle in the coming years?
Thank you for your attention.
Regards and thanks very much for the 99% pretty optimal rest :-). Can't wait to see it go live.
More information about the lambda-dev