17

Assume an interface containing these methods :

Car find(long id);

List<Car> find(String model);

Is it better to rename them like this?

Car findById(long id);

List findByModel(String model);

Indeed, any developer who use this API won't need to look at the interface for knowing possible arguments of initial find() methods.

So my question is more general : What is the benefit of using overloaded methods in code since it reduce readability?

S.Robins
  • 11,385
  • 2
  • 36
  • 52
Mik378
  • 3,838
  • 7
  • 33
  • 60
  • 4
    Either method is acceptable as long as you are consistent. – ChrisF Jan 29 '12 at 15:17
  • There is a relationship between overloading and overriding a method. However this article favors your suggestion - It may be of interest: http://www.roseindia.net/javatutorials/overloading_considered_harmful.shtml – NoChance Jan 29 '12 at 20:41

4 Answers4

26

This is a relatively minor issue compared to many other bad readability practices you could be susceptible to, so I'd say it's mostly a matter of taste how you name your methods.

With that said, if you are going to do something about it, I would follow this practice:

  • Overload if...

    The methods obey nearly the same contract but simply operate on different input (imagine a phone operator who can look up your account by your personal tax ID number, your account number, or your name and birthday). This includes returning the same type of output.

  • Use a different name if...

    The methods do substantially different things or return different output (like your case). You might consider using a different name if one accesses the database and one does not.

    In addition, if the type returned is different, I would also change the verb to indicate that:

    Car findById(long id);
    
    List findAllByModel(String model);
    
Nicole
  • 28,111
  • 12
  • 95
  • 143
  • 3
    FWIW, I would word that a little more strongly: "The methods obey _exactly_ the same contract..." I.e. the argument type/count doesn't matter - the semantics of the function call are identical regardless. If the argument type/count matters, then you shouldn't overload. – mcmcc Jan 30 '12 at 17:12
  • @mcmcc Isn't varying argument type/count the whole reason for overloading? Aka it's basically a workaround for a lack of generics. – Charles Wood Aug 21 '23 at 15:09
5

I would recommend using a different name, in every case. It's possible that at some time in the future, you'll want to add another method, say List<Car> findByMake(String make), in contrast to List<Car> findByModel(String model). So suddenly, calling everything find stops making sense. Your methods also less likely to inadvertently be used incorrectly, if their names give more information as to how they should be used.

Dawood ibn Kareem
  • 1,852
  • 12
  • 14
  • 3
    To be fair, this wouldn't be as much as an issue if the functionality were more explicitly represented by objects: `find(Make val)` and `find(Model val)`. Then, convenience methods such as `findByMake(String val)` would be much more clear what they are actually doing. After all, a `String` is not either a make or a model, so the method ought to explain what it is really doing. – Nicole Jan 29 '12 at 23:48
4

If you rename a method, it is no longer going to be overloaded. In and of itself, overloading doesn't necessarily make code less readable, however it can make the implementation more difficult to follow if the syntax isn't clear.

Many languages use method overloading as a means to present an interface to functionality where the parameters may be optional and defaults for the optional parameters are implied. This is particularly true for languages that do not support a default parameter syntax in the method declaration.

So doing this:

void MyMethod(int param1, int param2 = 10)
{
    ...
}

saves you from doing this:

void MyMethod(int param1)
{
    MyMethod(param1, Param2Default);
}

void MyMethod(int param1, int param2)
{
    ....
}

As to which is more readable, that really comes down to you. Personally I prefer the second option, particularly when the parameter list is getting a little long, but I suppose it doesn't really matter so long as you are consistent throughout your API.

The difficulty with overloading comes when you want functions that do essentially the same thing, and where you want the parameter lists to be the same, but the return types to be different. Most languages don't know how to differentiate between two methods named the same, but with different return types. At this point, you need to think about either using generics, changing the parameter interface, or renaming one of your methods to indicate the difference in return type. This is where readability can become a big issue, if you don't settle on a simple and clear naming scheme to deal with situations like this.

Naming your overloaded methods GetSomething() and GetSomethingEx() isn't going to say a lot about what the differences are between your methods, particularly if it is the return types that are the only differences between them. On the other hand, GetSomethingAsInt() and GetSomethingAsString() tell you a little more about what the methods are doing, and while not strictly an overload, do indicate that the two methods do similar things, yet return different value types. I know that there are other ways you could name methods, however for the purposes of illustrating the point, these crude examples should do.

In the OPs example, the rename isn't strictly necessary because the method parameters are different, however it does make things a little clearer to name a method more specifically. In the end, it really comes down to the type of interface you wish to present to your users. A decision on whether on not to overload should not be made solely based on your own perception of readability. Overloading methods can for example simplify an API interface and reduce the number of methods that a developer might need to remember, on the other hand, it can obfuscate the interface to a degree which then requires a developer to read the method documentation to understand which form of method to use, whereas having a number of similarly yet descriptively named methods can make it more apparent just be reading a method name as to its purpose.

S.Robins
  • 11,385
  • 2
  • 36
  • 52
0

Favor overloading as long as the methods return the same thing and follow the same contract. Overloading frees the calling code from committing unnecessarily to the parameter type.

Suppose the calling function receives a search query as a parameter and performs some other processing before and/or after the call to find.

void tryToSellCars(String which) {
    /* grab an airhorn, inflatable tube guy... */
    List<Car> cars = find(which);
    /* expound virtues of each car in detail... */
}

If you want to change the type of that query for whatever reason down the road (for instance from a simple ID string to a fully-featured query object of some sort) you can make that change in the calling function just by changing the function signature to accept the new parameter type without worrying about changing the method it calls on your class.

void tryToSellCar(CarQuery which) {
    /* grab airhorn, inflate tube guy... */
    List<Car> cars = find(which)
    /* expound virtues of each car in detail... */
}

If you implement findById and findByQueryObject separately, you would have to hunt down every call to make that change. In the example, I only changed one word and I was done.

sqykly
  • 219
  • 1
  • 7
  • This answer assumes, of course, that you are using a language that supports overloading with compile-time errors for an invalid parameter. If you're writing JavaScript or Ruby or any other language that doesn't natively support overloading, I would always use the verbose `findByFoo` to catch type mismatches earlier. – sqykly Oct 29 '13 at 15:39