2

Hopefully, I'm not asking a duplicate. I tried searching and didn't find anything, but it could have been my keyword choice (I can't think of what keywords to use).

Frequently, while I am coding, I encounter situations like the following:

public void doStuff() {
    String sharedValue = getValue();
    
    // code block 1 that uses sharedValue
    
    // code block 2 that uses sharedValue
}

private String getValue() {
    // code to get sharedValue
}

For example, this could be a hash table class, and getValue() corresponds to the hashing function.

Ideally, code block 1 and code block 2 would be modularized into two separate methods like so:

public void useValue1() {
    String sharedValue = getValue();
    
    // code block that uses sharedValue
}

public void useValue2() {
    String sharedValue = getValue();
    
    // code block that uses sharedValue
}

Now, the problem is that if we call useValue1() and then useValue2(), getValue() runs twice. Using Java's HashMap as an example:

public class Clazz {
    Map<String, List<String>> map = new HashMap<String, List<String>>();

    public void ensureListExists(String key) {
        if (!map.containsKey(key))
            map.put(key, new ArrayList<String>());
    }
}

HashMap.containsKey() and HashMap.put() calculate the same hash key twice. In this case, calculating a hash key is not too expensive of an operation, but it would not be too hard to imagine something that is much more expensive.

Objective: I would like to decouple two blocks of code that share some information but are semantically distinct (without recalculating the information).

Here are a few solutions I thought of and why I don't like them:

> Use a cache: This would be my solution of choice in some cases, perhaps for long-lived objects (e.g. keep a cache of all database queries done and their results). On a smaller scale, I don't like the idea of creating an instance variable solely to serve as a cache for a couple methods and that will only be used maybe once or twice. Plus, a cache comes with its own overhead.

> Extract String sharedValue into a parameter for useValue1(String) and useValue2(String) and call getValue() from the calling method like so:

public void useValue1(String sharedValue) {
    // code block that uses sharedValue
}

public void useValue2(String sharedValue) {
    // code block that uses sharedValue
}

String sharedValue = getValue();
useValue1(sharedValue);
useValue2(sharedValue);
  1. This forces getValue() to be public and forces the calling method to handle sharedValue manually. It should be automatic and hidden as an implementation detail - not all Maps are implemented as hash tables.
  2. This doesn't work if sharedValue is multiple variables. Everyone knows multiple return values sucks (in Java at least). We could create another class that encapsulates all of the variables, but that creates even more clutter than using instance variables.

Can anyone think of an elegant solution to this problem? I see it all the time. Perhaps there is no other solution and I'm just being too picky. I'm willing to accept that as an answer.

Note: I recognize this may seem like pre-optimization, but I think I see it enough to warrant having a nice solution handy for whenever it happens.

Community
  • 1
  • 1
Hau
  • 443
  • 6
  • 13
  • What is wrong with the parameter approach? `getValue` can be private and you would have had to call it anyways as shown in your first code-blocks – OneCricketeer Feb 05 '16 at 20:59
  • The statement that it requires the value to be `public` says there's piece to this puzzle missing. In other words - "why isn't the method public in the original approach?" This question is hard to address as it's so abstract. My gut is to agree with @cricket_007 and simply pass parameters. – ash Feb 05 '16 at 21:11
  • The problem I have with the `public` approach can be demonstrated by the Map/HashMap example. Given the following code: `Map map = new HashMap()`, `map` has no idea that HashMap has a hashing method for getting values since the `Map` interface has no such method. Another qualm I have with the `public` approach is that you are forcing the user to work around your implementation rather than hiding it away. Sorry about the vagueness. I do have a more concrete example. I may edit it into the question later. – Hau Feb 05 '16 at 23:10

0 Answers0