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);
- This forces
getValue()
to bepublic
and forces the calling method to handlesharedValue
manually. It should be automatic and hidden as an implementation detail - not all Maps are implemented as hash tables. - 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.