Coding Tips: Functions

karlboghossian.com functions

“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” — Martin Fowler

Functions are used pretty much everywhere in our code, but there’s a difference between writing a clean function vs a dirty function that “smells”. I will share a few tips on writing a clean abstract function.

Functions need to perform 1 thing well

  • You want to avoid writing a function that does many things.
  • It will be hard to write unit tests for it, as you will have to worry about “setting up the world” with different edge cases in order to test them.
  • Plus it makes it hard to debug where the problem is when you have for example some business logic entangled with some util logic, etc.
  • So, having a function that does some database calls, then sorts a few things perhaps, then validates something, then returns the result. All that starts to “smell” as bad code. You want to avoid it.
  • What you want is to break down all those steps into atomic functions that each is responsible of 1 thing. That thing could be a database call + database validation, or it could be business logic validation, etc.

Fewer comments means better hygiene

  • I used to write a lot a comments, when I say a LOT, I mean there will be more lines of comments than actual code. 😬
  • At first, it felt good that anyone reading my code will be able to understand what I’m doing.
  • With time, I realized that having to explain what each “section” of code was doing means that I’m better off pulling that “section” into its own function, instead of having to maintain a really long function that can’t be unit tested easily.
  • Doing so, helped me reduce the amount I had to invest into explaining what the code was attempting to do.

Abstraction is key to allow any human to read the code

  • Sure you could have a function that checks for a few things, fetches data from the database, filters some array then return the result. But if anyone is looking at that function, they will have to focus hard in order to understand all the pieces the function is doing.
  • Imagine instead of having all those inlined into the function, instead have smaller functions that you will call from the main function:
function main () {
  let result = fetchFromDatabase();
  result = filterBasedOnSomeLogic(result);
  return result;
}
  • That’ll make it much more readable, and abstracts away all the little details into their corresponding functions.

Have two or fewer parameters

  • You can usually tell whether a function might be doing more things than needed, by looking at its parameters.
  • If you got 3 or more parameters, think if you can break the function down into smaller functions.
  • Some rare methods will usually require 3 parameters, like a function that takes a 3D vector (x, y, z). That is fine.
  • If that function needs to have more than 2 parameters, it would be best if you can convert them into an object with its properties being the parameters:
function updateSterio (settings) {
  // settings.base, settings.volume, etc...
}

Balance optimization vs cleaniness

  • Start clean then optimize only if needed!
  • Perhaps sometimes having many functions can lead to performance loss due to the compiler spending CPU cycles to move control to the smaller functions, etc.
  • Most of the time you won’t need to optimize and worry about those, unless you’re writing some core engine logic that will be executed several times per second…
  • That’s why it’s better to have a clean code that anyone can contribute to, easier to debug in case of a bug, and saves everyone’s time when you need to look back at a piece of code you wrote more than a year ago.

I hope you found this post useful, please feel free to drop a comment below. Cheers 🍻

5