2

While this might seem more like a piece of an easy task to others, it's honestly not easy for me. At this stage, I find myself wandering how best to version my functions/methods.

What does this mean?

I have a function that does one thing and one thing alone. It saves Contacts to a local DB e.g RealmDb. This function is named addContacts and it's pretty easy and straightforward until now.

Now I need to optimize this function, the issue is the function is called in so many parts of the code and I'm quite cautious of not breaking anything to I have decided not to touch the function but rather create a similar function with optimized functionality and then I will deprecate the first function.

The main issue is I am not sure how best to name this new function. I have decided to name my new function "AddContactsV1" and point to it as a replacement for the first function.

Does this make any sense and if there is a better way around this kindly share.

Previous:

/**
 * Add An Array of Contacts Once.
 * @deprecated refer to @function addContactsV1
 */
async addContacts(constactsArray, callBack)
{
 //enter code here
}

New:

/**
 * Saves contacts to local data storage for offline access.
 * @param constactsArray is the contacts array object to be saved.
 * @returns a promise with an empty resolved or rejected with possible reasons.
 */
addContactsV1(contactsArrayObject)
{
   return new Promise((resolved, rejected)=>{
     //enter code here
   });
}

3 Answers 3

5

As far as i understood, you plan to replace the old function completly by the new one in the long run.

Personaly i would avoid "versioning" in the names. The reason is that if i allow a addContacts_V2 in my code base, then there is no real reason not to allow a addContacts_V3. Or so say it plain: When i am allowed to "version" functions, i am not forced to finish the refactoring. If you are quite strong minded and always code with the highest goals in mind, this may not be a problem for you. In my experience small things like that let people start their good intention, but they then jump to the next good idea without finishing their work.

If the old method is only used directly in my own code base, then i would let my IDE rename the old method. For example to "addContacts_REPLACE_ME". Then the new method could already start with the nice name.
But this procedure has the problem, that if the method is called in an indirect way (means, the IDE does not realize that usage), then this change will break your application.

If i am not sure, i would create the new method with a unique name addition to it. In most cases i work on the same code base with multiple developers. And quite often there exists a lot of methods with similar names. Therefore, i would not use addContacts_V1, because if a colleague wants do so a similar refactoring on HIS addContacts method we may run in problems. Because of that i often add the Jira-Ticket (or whereever i document this long running refactoring) in the name. Even if addContacts_REFACTORING_65783 is not a nice name, its quite unique. After i have finished my refactoring and depricated the old function, the new one gets renamed. Because of the unique name, this is normaly quite easy.

At the end, for me the key points are:

  • The new name must be unique (it makes the renaming much easier)
  • The new name is temporary and will be renamed to the old name

Depending on the context you have to apply additional steps.
For example if your method may be called indirectly, then i would change all occurances i know to the new method. And then add a logging statement to the old method. If in the next weeks / months (in production) no such log is created, then i would finish the clean up. If such a log appear, then i have to dig deeper.

If quite a lot of people work in the same codebase the uniqueness of the new name must be choosen more carefully.

1
  • Nicely said, I ended up giving the function a new name and after I was done testing the implementation and cool with the result, I find it tempting to replace the old function with the new implementation(logic)....well I did and get ride of the new function, that name will be needed somewhere else. Thank you.
    – Wale
    Commented Jun 29, 2021 at 9:38
4

If your language supports overloading, then you can have both functions with the same names:

/**
 * Add An Array of Contacts Once.
 * @deprecated refer to @function addContacts(contactsArrayObject)
 */
addContacts(constactsArray, callBack)
{
 //enter code here
}


/**
 * Saves contacts to local data storage for offline access.
 * @param constactsArray is the contacts array object to be saved.
 * @returns a promise with an empty resolved or rejected with possible reasons.
 */
addContacts(contactsArrayObject)
{
   return new Promise((resolved, rejected)=>{
     //enter code here
   });
}

Using overloading lets you have two "versions" of a function that are distinguished by their parameters, not by a "v1" in the name. The code is cleaner this way, and you can have details in the documentation explaining the differences.


If your language does not support overloads, try giving the new method a name that's somewhat descriptive of the difference. I don't know the technical differences of your two functions so it's hard to make a suggestion, but maybe optimizedAddContacts or enhancedAddContacts.

Another option, depending on the language & environment might be to put both functions in separate files/libraries where the version is a part of how you reference the file/library. So you could have addContacts-1.0 for your old function and addContacts-1.1 for your new function.

7
  • My bad, I forgot to mention, my language does not support method overloading natively(Javascript). I use this in Java a lot and it saves me a headache. However, Javascript seems to give a few f about that.
    – Wale
    Commented Jun 28, 2021 at 17:18
  • @Wale Not being able to overload does make this a bit more difficult. Commented Jun 28, 2021 at 17:32
  • you're right, thank you. So, I have decided to change the name to something like saveContacts() and basically refer to it from the deprecated function. I will stick to this for now until I find a better way.
    – Wale
    Commented Jun 28, 2021 at 17:37
  • If signatures were exactly the same but for the number of arguments it would be easier but since both functions are different, I wouldn't strive to overload the function's name. An alternative could be checking if "callback" is set. If so, then execute the old code, if not, then execute the new one calling the new function. Once all the callers are migrated, you can remove the if and the old code.
    – Laiv
    Commented Jun 29, 2021 at 8:24
  • 1
    @Wale JavaScript definitely allows equivalent of method overloading by checking parameters... whether it is good idea or not is an open question - worked wonders for JQuery (aka $). Commented Jun 29, 2021 at 18:21
0

One way of handling this is via a feature flag (or version flag in your case, I guess). These are also known as feature toggles. It lets you add a variable, the value of which will determine what version of your function is run. One popular implementation is as follows (in Java):

 //The value here will determine if your function runs the old version or the new.
private boolean isNewVersion

Foo runFunc(Bar bar){
   if(isNewVersion == true) {
      Foo newVersion(myBar);
   }else{
      Foo oldVersion(myBar);
   }
}

This will let you build new versions without worrying about breaking anything. Additionally, you have the option to switch between versions based on whatever logic you need.

To solve your issue, you can switch out your version for an enum which will let you define version numbers as keys, and define the actual function names as values. This way you are not muddling up your naming conventions with version numbers, which are meaningless in the scope of the implementation. However, you will still be able to track your entire version history.

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.