How to code good arguments for your function?
Smok Code Smok Code
15.1K subscribers
1,267 views
0

 Published On Oct 21, 2020

What are niladic functions? Is it better to use draw(x,y) or draw(Point)? All that and more in today's #QuickAnswer.

#programming #tech #softwaredevelopment #developer #sde

Clean Code (R. Martin) - US: https://amzn.to/3jVUEDU | UK: https://amzn.to/2Iij4Jz
Best Practices for Programmers - US: https://amzn.to/2SPRSEg | UK: https://amzn.to/2Fr2h6e

When reading a book about clean code, perhaps written by Uncle Bob - you may find that ideal functions are niladic which means they have no arguments at all. This sounds very controversial or even harsh, but what authors of Clean Code practices want to convey here is the fact that the less arguments your function has - the better.
Of course not all functions can be useful without arguments, but, argument (*wink*) can be made, that all functions should be useful with only a few of them, and that number is three.
So let’s take a look how different functions are called depending on their argument count. We have: niladic, monadic, dyadic, and triadic functions. Simple enough. But why does this actually matter?
Starting with a trivial example: we have a function that takes a filename and includes a header in it: includeHeader(file). Each time you see this function you’ll stop for a moment and think: is this a file handle, file descriptor or filename?
How much cleaner it would be to create a class stores the file reference (whatever it is), and offers a simple niladic function includeHeader(). Such function becomes obvious and our eyes just glide through it. This philosophy is easy to follow, but what if it doesn’t make sense to create a separate class just to wrap a one-time use argument? Enter monadic functions.
Single-argument functions are usually divided between ones that ask about the argument: meetsPasswordRequiremets(string), or produce a result from the argument: toUpper(string). Recommendation here is: pay attention and pick names that explain this well.
One other sin that I see in the code is using output arguments, instead of the return value. Mentioned before toUpper(str) should never be an in-place function, as the produced string is transformed into a totally new form.
Third case brought to my attention by Robert Martin are flag arguments. Here, let me give you an example you may encounter in the wild: draw(true) Can you tell immediately that the function signature is actually draw(boolean inFrame)? Of course you can’t, but if you had two functions: drawInFrame and drawInView - it would be obvious, wouldn’t it?
Dyadic functions should follow all the rules we mentioned before and more. Function could have less arguments when some of them are more related to each other than to the function itself. Let’s get back to the previously used name: draw(x,y). This could be wrapped in an object: draw(Point(x,y)). Such code is easier to reason about in simple cases, and will be much better with more complex things... Like drawing a rectangle, or a cube.
Quote straight from the Clean Code by Robert Martin says: Even obvious dyadic functions like assertEquals(expected, actual) are problematic. How many times have you put the actual where the expected should be? The two arguments have no natural ordering. The expected, actual ordering is a convention that requires practice to learn.
Triads give us way more room for errors and misinterpretation of argument ordering. General recommendation here is to avoid them wherever you can.
Good luck with your refactoring, subscribe, and I’ll see you in the next one, cheers!

show more

Share/Embed