One function vs Multiple Functions

Right now I am trying to do some projects with node js and express.
But I got stuck because I am not sure what is the correct way to do my functions, for example:
(I am not using Promises, I wanted to do it the old way with callbacks and then make it using promises / async await so I can learn how to use callbacks too)

For example, there is a function that gets a user from the database. I can do it like this:

const getUserByUsername = (username, callback) => {
....
}

But sometimes I want to do it using email, or ID instead so I could have 2 other functions: getUserByEmail, getUserById

Or, I can do it in a single function. Also, the database I am using let me specific what I want in return while querying so I can also add another parameter to specify what i want from the User table, like email or password hash.

const getUser = (byThis, getThis, callback) => {
if (byThis === 'username') {
    if(getThis === 'email') {
    ....
    }
.....
}}

But finally I also though: Well I can even just make a function called getFromDB, and also add one parameter to specify what table I want to get and so I will make even less functions! something like this:

const getFromDB (fromThisTable, getThis, byThis, callback) { 
..
}

And then add a lot of if’s and else’s.
What would be the better way to do it?

In this particular case, I suggest you implement all of your suggestions. That might sound a little mad, but let me explain.

Let’s consider your last function first:

function getFromDB (fromThisTable, getThis, byThis, callback) 
{
  var tableName;
  switch (fromThisTable.toLowerCase()) {
    case 'shop': tableName = 'OnlineShopUser';
    ...
  }
  var fieldName;
  switch (byThis.toLowerCase()) {
    case 'byemail': fieldName = 'EmailAddress';
    ...
  }
  ... // fetch from database, e.g.:
  return axios.get(...).then(callback);
}

Now we can declare several more specialised functions that make use of the above one:

function getUserByUsername (username, callback) => {
  return getFromDB ('shop', username, 'byUsername', callback);
}
function getUserByEmail (username, callback) => {
  return getFromDB ('shop', username, 'byEmail', callback);
}

The principle is that you start off defining general-purpose functions, and then you define more specialised functions using them. You might declare even more specialised functions in terms of those, and so on.

The idea is that the more general-purpose functions ‘factor out’ a certain amount of code that you would otherwise simply repeat again and again in the more specialised functions. However, calling the specialised functions is better, because there are fewer parameters to give, and so there is less to go wrong.

The more specialised functions also help a little with ‘self-documentation’, in that they are better at saying what they do (or, indeed, what they are intended to do). You should generally augment self-documentation with useful comments, by the way.

The functions at every level should be unit tested.

Having functions declared at many levels tends to aid unit testing, because unit tests on a particular function cannot test faults in the calls to that function (they can only test what happens inside the function). If calls to that function are wrapped inside another function, you can unit test the outer (wrapper) function and so test (most or all of) the calls to the inner function. Or, in other words, the more functions, the more ‘surface area’ you have for unit testing. That tends to be good.

In other circumstances, it can be a question of careful choice as to what level you pitch your functions (and other abstractions) at. The idea is to choose functions that say what they do, as concisely and strongly as possible. 99 times out of 100 the most important thing is making your code easy for other programmers to understand. The odd 1 in 100 case is where you need to do something unintuitive for the sake of speed or compatibility. In such cases, ensure you use comments or other documentation to explain what is going on.

HTH

1 Like