CloudTableClient should use Iterator instead of Iterable. #55
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The Problem
CloudTableClient#execute(TableQuery<?>, ..)
overloads returnIterable
, which implies a collection that can be iterated over multiple times. However, the return value is implemented as anIterator
that implementsIterable
by returningthis
, which is generally regarded as a Bad Thing. More on this.The temptation to do this is common given the seductive lure of being able to use your iterator in a foreach loop:
But, because
execute
returns anIterator
under the hood, this breaks down if you try to do it twice:Iterable
expects this to work, as does mountains of client code that consumeIterable
instances. The fact thatIterator
can't normally be used in this way is a warning and reminder to users that iterators are single pass only.In general, methods that return a result that can only be iterated once should return
Iterator
, notIterable
. This pull request implements that policy forCloudTableClient
, at the cost of breaking client code.Alternative solutions
If breaking client code is not an option, the following alternatives can be explored:
Deprecate the old code, and add new methods
This option keeps the broken old behavior but deprecates it, so that end user expectations aren't changed. New methods that return
Iterator
could be added to indicate the single-pass semantics.Keep the old interface, but make it support the correct semantics.
Iterable
should return a new iterator for each call toiterator
. There are some options for how to achieve this, such as (a) caching the results, or (b) issuing a new query to the service. Each choice has trade-offs, which is why dropping or deprecating the API should be preferred. But a correctly functioning API that has trade-offs is better than an incorrect one.