Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the Ideal Way to Define Singular vs Plural Gets in a Storage API?

I've got an internal storage layer in my application, which handles Foo objects. During Get operations, the data layer has significant benefits to clustering gets, but I only actually do multiple gets about 10% of the time. Here are various approaches I've considered:

Approach A:

interface FooStorage {
  Foo getFoo(String name);
  List<Foo> getFoos(List<String> names);
}

Approach B:

interface FooStorage {
  List<Foo> getFoos(List<String> names);
}
class StorageUtility {
  public static <T> T firstOrNull(List<T> data) { ... }
}

Approach C:

interface FooStorage {
  List<Foo> getFoos(String... names);
}
class StorageUtility {
  public static <T> T firstOrNull(List<T> data) { ... }
}

The downside to Approach A is having a larger surface that I need to support.
The downside to Approach B is having the consumer build a List when 90% of the time I don't need it. The downside to Approach C is the overhead of copying a list to an array 10% of the time.

Is there a canonical right way to do this?

like image 601
Hounshell Avatar asked Oct 18 '11 17:10

Hounshell


1 Answers

In this type of situation, I would tend go with the following construct:

Foo getFoo(String name) {
    return firstOrNull(getFoos(name));
}
List<Foo> getFoos(String ... names) {
    return getFoos(Arrays.asList(names));
}
List<Foo> getFoos(List<String> names) {
    ....
}

Your client should use the most appropriate method each time, and if you latter discover that performance requires a more targeted approach for getFoo(name), you can re-implement that single method.

I would argue that it is more important to keep the consumer code readable (avoid creating lists just to satify the API), than saving a few lines of code in the interface/implementation of the storage system.

like image 144
andypandy Avatar answered Oct 20 '22 21:10

andypandy