3

I have an algorithm with mostly invariant parts that needs to be reused within one class so as to stay DRY.

Code duplication with repeating method structure

public void save(String key, int value) {
    try {
        if (isValidWrite()) {
            // Only variable part
            editor.putInt(key, value);
            if (!writeOnDisable){
                write(editor);                    
                Log.v(TAG, "Saved " + key + " | "+ value);
            }
        }
    } catch (Exception e) {
        Log.e(TAG, "save", e);
    }
}

public void save(String key, String value) {
    try {
        if (isValidWrite()) {
            // Only variable part
            editor.putString(key, value);
            if (!writeOnDisable){
                write(editor);
                Log.v(TAG, "Saved " + key + " | "+ value);
            }
        }
    } catch (Exception e) {
        Log.e(TAG, "save", e);
    }
}

Solution?

  • The template method pattern is not applicable, because it requires sub-classing.
  • Strategy - do I really need to create an interface and provide different implementations to pass into a generalized method as a delegate? Maybe I'm just complaining about proper support for delegates in Java.. (in C# could just use a generic Action<>)
2
  • 1
    If you can't subclass your own class, maybe you can make the method generic and make editor.put() generic to match? Commented Feb 21, 2013 at 14:03
  • @KilianFoth that would work if I had access to editor source, but it happens to be part of Android framework.. And it would probably require a bunch of type-checking if statements, which impacts sense of elegance
    – Cel
    Commented Feb 21, 2013 at 14:07

2 Answers 2

2
protected void applyParameters(Editor editor, Object [] parameters) {
    for(Object param : parameters) {
        if(param instanceof Integer) {  
            editor.putInt(key, param);
        } else if (param instanceof String) {
            editor.putString(key, param);
        } else {
            // case for unknown type?
        }
    }
}
public void save(String key, Object ... params) {
    try {
        if (isValidWrite()) {
            if(params != null) 
                applyParameters(editor, params);

            if (!writeOnDisable){
                write(editor);                    
                Log.v(TAG, "Saved " + key + " | "+ value);
            }
        }
    } catch (Exception e) {
        Log.e(TAG, "save", e);
    }
}

Try this. Essentially, you cannot generalize "putInt" and "putString", but you can at least extrapolate them into their own method. Just provide a case for parameters you do not recognize as valid.

1

This is al alternate solution, you expose two methods, one for ints and one for Strings.

A private method receives both kind of values and decides what to save.

public void save(String key, int value) {
    save(key, new Integer(value), null); // pass null in String param
}


public void save(String key, String value ) {
    save(key, null, value); // pass null in Integer param
}

private void save(String key, Integer intVal, String strVal){
    String strToLog="";
    try {
        if (isValidWrite()) {
            if ( intVal != null) {
                editor.putInt(key, intVal);
                strToLog = intVal.toString();
            } else if ( strVal != null) {
                editor.putInt(key, strVal);
                strToLog = strVal;
            }               

            if (!writeOnDisable){
                write(editor);                    
                Log.v(TAG, "Saved " + key + " | "+ strToLog);
            }
        }
    } catch (Exception e) {
        Log.e(TAG, "save", e);
    }       
}
1
  • Thanks! I actually have additional save methods with more types, which makes me prefer Neil's implementation.
    – Cel
    Commented Feb 21, 2013 at 15:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.