2

Is there a best practice or commonly accepted pattern to name methods that "adds" something to a collection on an immutable object with fluent style for Java API?

Here is a code example:

public class GivenUUIDGenerator {
    private final ImmutableList<String> playbackUUIDs;

    public GivenUUIDGenerator(List<String> playbackUUIDs) {
        this.playbackUUIDs = ImmutableList.copyOf(playbackUUIDs);
    }

    public GivenUUIDGenerator howShouldINameThisMethod(String uuid){
        return new GivenUUIDGenerator(ImmutableList.<String>builder().addAll(playbackUUIDs).add(uuid).build());
    }
}

This is coming from a Pull Request on a project I'm developing, and we already had a discussion on the best naming option for this method, but being both french doesn't help to choose a good name.

I've tried to find prior art or best practices, here is what I've found so far:

Other suggestions I got:

  • original PR proposition: withAddedXXX
  • another proposition: withAdditionalXXX
femtoRgon
  • 32,893
  • 7
  • 60
  • 87
  • 1
    I'd like to suggest 'append(...)' here – Jk1 Aug 27 '13 at 20:27
  • Generally speaking, method names should reflect its function. This question appears to be fairly subjective considering the variations of describing something in different languages. – Josh M Aug 27 '13 at 20:28
  • I was wondering if my question was too subjective indeed, that's why I tried to ask for best practice / prior art / naming convention. Pretty much like the convention for getters/setters which is widely accepted in Java, I'm asking if there is something similar for this case. – Xavier Hanin Aug 27 '13 at 20:34
  • Finally the answers provided helped me as well as the answers on the closed questions here: http://stackoverflow.com/questions/521893/whats-the-best-name-for-a-non-mutating-add-method-on-an-immutable-collection?rq=1 - Not really a definitve good answer though, my question was too subjective I guess, sorry for that. – Xavier Hanin Aug 29 '13 at 20:47

3 Answers3

2

I would suggest and, and not modify the original list. Therefore, you could have something like:

GivenUUIDGenerator.with(originalList).and(a).and(b).and(c).generate();

This is what the class would look like:

public class GivenUUIDGenerator {
    public static GivenUUIDGenerator with(List<String> playbackUUIDs) {
        return new GivenUUIDGenerator(playbackUUIDs);
    }

    private final ImmutableList<String> playbackUUIDs;

    private GivenUUIDGenerator(List<String> playbackUUIDs) {
        this.playbackUUIDs = ImmutableList.copyOf(playbackUUIDs);
    }

    public GivenUUIDGenerator and(String uuid){
        return new GivenUUIDGenerator(ImmutableList.<String>builder().addAll(playbackUUIDs).add(uuid).build());
    }

    public ... generate() {
        // ... do here whatever it is you want to do with your list
    }
}
Jan Dörrenhaus
  • 6,581
  • 2
  • 34
  • 45
  • This works fine for a builder like API, but here I need to build a new `GivenUUIDGenerator` based on an existing one. – Xavier Hanin Aug 27 '13 at 20:39
  • @XavierHanin I have edited my post to add an example of what I mean. – Jan Dörrenhaus Aug 27 '13 at 21:04
  • OK, I better understand, I confused the `generate` method with a builder one. I really like the `and` used as you show, but is less expressive when called on an object obtained from somewhere else, eg a parameter. Would `void doSgWith(GivenUUIDGenerator generator) { generator.and(a).generate(); }` be clear? – Xavier Hanin Aug 27 '13 at 21:13
  • @XavierHanin No, but that is sort of an inherent flaw with most fluent APIs. They are meant to be used as a whole. If you want parts of it transferred to other methods, you might get a lot clearer results with a non-fluent API. – Jan Dörrenhaus Aug 27 '13 at 21:35
0

I think putting the verb add or append at the beginning of the method name are good options. I'm not a fan of with because it doesn't convey as much information as add or append. My intro CS professor always made it a point that we name our method names with a verb in the beginning as a quick cue for people to understand it's a method (and not a variable, for example).

Most people seeing a String type should also know strings are immutable so you should be fine. But just in case they don't, you'd probably want to comment it and add that note in the Javadoc with /** insert comments here */

Anna
  • 19
  • 6
0

append is an okay choice, although there are counter-examples. For instance, Java's StringBuilder is mutable, and defines several append methods which mutate the instance.

The popular date and time library, JodaTime, uses with in some of it's immutable classes (e.g. DateTime) where the method returns a copy with some fields modified. Though I'm sure there's counter-examples for that too.

Perhaps instead of, or as well as a naming convention, you may want to use annotations. The (albeit defunct) JSR 305 defined some annotations for this use case. You could annotate GivenUUIDGenerator with @Immutable and the method append/with with the annotation @CheckReturnValue.

@Immutable documents that the instance can't be modified once created.

@CheckReturnValue is more subtle, it documents that a method has no side-effects, so if you call it without assigning the result to something, you probably misunderstand how it works. E.g. myString.substring(5) vs String result = myString.substring(5), here a new instance of String is created and immediately discarded, nothing has changed about myString. FindBugs can detect this and flag an error if it happens. Some more info on this useful blog post.

Grundlefleck
  • 124,925
  • 25
  • 94
  • 111