2

Consider something like....

(Pseudocode Javascript like)

var capitalizeWord: function(word){
    word.toAllCaps(); 
}

What if now I need to do multiple words, but still sometimes only do one still. Is it better to do...

var capitalizeWords: function(words){
    _.forEach(words, function(word){
        capitalizeWord(word);
    }
}

var capitalizeWord: function(word){
    word.toAllCaps(); 
}

OR just have one function

var capitalizeWords: function(words){
    _.forEach(words, function(word){
        word.toAllCaps();
    }
}

And when I need to just capitalize one word....cast it to an array before calling capitalizeWords?

capitalizeWords([word]);
  • I didn't really know how to word this code style problem in a search...it may have already been answered :( – Carson Jan 2 at 16:42
  • Always make life easy for programmers consuming some API, which would seem to mean here supporting both single and multiple word scenarios each with their own function, rather than making the consumer put the word into an array and making them call the multi-word function. – Erik Eidt Jan 2 at 18:19
  • "Always make life easy for programmers consuming some API." can be bad advice. This often makes people produce API that won't be used. See YAGNI – Albuquerque Jan 2 at 19:37
  • 1
    I wish I could remember this quote: "One is a special case of many." – cbojar Jan 3 at 1:02
  • @Albuquerque I'd disagree. Making a code interface designed for usability has nothing to do with YANGI. I can code a good UI or a bad one that does or does not have unused methods, there is no causal relationship here. Having unused/redundant methods, in fact, is bad interface design because it's confusing to the programmer using your interface. – Bill K Jan 3 at 1:25
7

Having two methods is perfectly fine, as both are valid use cases. The key to this is to have one method call the other, as you have shown. You don't want to duplicate code.

Having a single method which operates on arrays is fine, too. If you find you are using that method to operate on a single word often, though, you may find the first option a little easier to write and cleaner to read.

Note that some languages (e.g., C#) allow methods to specify an unlimited number of parameters (in C#, via the params keyword), so if your language supports such a feature definitely use that.

| improve this answer | |
5

Better can only be defined in the context of your application. Usually, the public API you choose should reflect the use case of the application.

For that, let me present two different scenarios, in which for each of them I would give a different answer:


Scenario #1: capitalizing words is an user story

You are developing a text editing app, and there is a user story that says that the user can select words and capitalize them.

This is a scenario where capitalizeWords is part of the user story and it makes sense for it to be part of the public API. In that case, I would say that:

  • If selecting one word is just a special case of selecting N words (N=1), one could express this as just a function that receives a list.
  • If there is a special case where the user can edit just one word, and that is semantically different from editing many words, expressing those as two different functions make a lot of sense.

Scenario #2: capitalizing words is just an implementation detail

You are developing a web app, and there is a search by keyword function. You are calling capitalizeWord just as part of the requirement that the search should be case insensitive.

In that case, capitalizeWord is a implementation detail and, as a result, not part of the public API. This means that it really does not matter for the user stories which one you choose, as long as the public API searchByKeywords is working.

The only criteria for choosing to separate into more than one function would be so your code is cleaner.

In my opinion, the two options are both clean code (with the only exception that I would rename capitalizeWords to capitalizeWordList, so the difference is more obvious).


Given that usually capitalizing words are not a user story, I would assume that you are working with Scenario Two.

| improve this answer | |
1

Consider your problem domain, and what's the most common use case.

If 90% of the time, client code will be working with arrays or some other collection type, and if it is preferable to do it that way, say, to encourage cache locality, then it's probably better to just have the array version - it helps suggest how client code should be written.

If not, then have both (and based on your understanding of the most common use cases, performance requirements, etc., decide which version calls which). Or, if you think it makes more sense, have just the single-item version.

Rather then thinking about convenience in a generalized way, approach the API design in a more focused way: consider how the system is actually going to be used, and what the constraints on it are.

| improve this answer | |
0

This doesn't answer your actual style question, but note that, in ES6, you can use the rest / spread operator to simplify and arguably clarify your code. In the simplest case below, the caller must remember to spread their array before calling your function:

function capitalize(...words) {
  return words.map((word) => word.toUpperCase())
}

console.dir(capitalize());                    // []
console.dir(capitalize("hi"));                // [ 'HI' ]
console.dir(capitalize("hi", "there"));       // [ 'HI', 'THERE' ]
console.dir(capitalize(...["hi", "there"]));  // [ 'HI', 'THERE' ]

If it is important to also accept an unspread array, add a check

function capitalize(...words) {
   if (Array.isArray(words[0]))
     words = words[0];
   return words.map((word) => word.toUpperCase())
 }

console.dir(capitalize("hi"));                // [ 'HI' ]
console.dir(capitalize("hi", "there"));       // [ 'HI', 'THERE' ]
console.dir(capitalize(...["hi", "there"]));  // [ 'HI', 'THERE' ]
console.dir(capitalize(["hi", "there"]));     // [ 'HI', 'THERE' ]
console.dir(capitalize([]));                  // []

Note that in all cases the function returns an array.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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