29 March 2013

Go functional the Java way (2)

During day job, I've encountered some scenario and I solved it using functional way, I'll show you the problem and my solution to it.


public void updateUserProfile(long userId, UserProfile userProfile){

    String currencyCode = userProfile.getCurrencyCode();
    if (currencyCode != null && currencyCode.trim().length() > 0){
        Util.setCurrency(currencyCode);
    }
    
    String langCode = userProfile.getLangCode();
    if (langCode != null && langCode.trim().length() > 0){
        Util.setLang(langCode);
    }

}


What if some one wants to modify this function to set a new user preferences, and he forget to check the string to be empty?


public void updateUserProfile(long userId, UserProfile userProfile){

    String currencyCode = userProfile.getCurrencyCode();
    if (currencyCode != null && currencyCode.trim().length() > 0){
        Util.setCurrency(currencyCode);
    }
    
    String langCode = userProfile.getLangCode();
    if (langCode != null && langCode.trim().length() > 0){
        Util.setLang(langCode);
    }

    String address = userProfile.getAddress();
    Util.setAddress(address);   // logic error here, the business says, do not ever allow the user to clear the values of his profile throw this method call
}


So, What is the solution?

I think about it, and I imagine it as we need to create a new function that takes the new value as the first parameter, and take the function that need to applied on the value as the second parameter, so the sedo-code will look like:


public void updateUserProfile(long userId, UserProfile userProfile){

    setNewValue(currencyCode, Util.setCurrency);
    setNewValue(langCode, Util.setLang);
}

private void setNewValue(String newValue, Function1<T> f){
    if (newValue != null && newValue.trim().length() > 0)
        f.apply(newValue);
}



But passing functions is not allowed until java8, so, I had to use interfaces for this functionality:


public void updateUserProfile(long userId, UserProfile userProfile){

    setNewValue(currencyCode, new ProfileSetter(){
        apply(String newValue){
            Util.setCurrency(newValue);
        }
    });
    
    setNewValue(langCode, new ProfileSetter(){
        apply(String newValue){
            Util.setLang(newValue);
        }
    });
}

private void setNewValue(String newValue, ProfileSetter f){
    if (newValue != null && newValue.trim().length() > 0)
        f.apply(newValue);
}

interface ProfileSetter{
    apply(String newValue);
}


That's all.

No comments: