I am working on a project for fun, and I recently found the use of functions to be very helpful when organizing my code. However, I find myself over using them, often for task that only need to be completed once. I was wondering if there was some unsung rule regarding the use of functions in a program.
You are supposed to over-use them; it's considered good programming practice. And the overhead of simple functions is pretty low. AND the compiler will often notice that functions are only used once, and inline them (especially if you declare them as "static"), in which case there is no overhead at all.
I was wondering if there was some unsung rule regarding the use of functions in a program.
Use them! Anytime you have two or more lines of code that constitute a capability, create a function. Debug the function, and then use it with confidence.
I've seen some silly function with one line of code, but that is the only thing that should be avoided. And, even then, that is not a hard-and-fast rule. In a class, there are often getters and setters that are a single line, but that is preferable to exposing the field as public.
I don't know if there are any rules, but I organize functions by task. A "cohesive" function is one whose task you can describe in one or two sentences. Most people make function too complex, going for the Swiss Army knife approach. If you have a short task that you can describe clearly and think it might be used again, perhaps in the future, make it a function.
Another consideration is the impact on efficiency. Calling functions in a tight loop is less efficient in terms of speed that inline code. That might be a consideration in time-sensitive applications.
At least consider The Five Program Steps as functions:
Initialization (setup()...what's done to set the program's environment)
Input...what has to be done to get the input*...loop()*
Processing...how are the inputs altered
Output...is the new data displayed, sent to another process
Termination...release the resources, often undoing Step 1. Microcontrollers usually don't reach this
step.
Some of the steps may call for functions, they may not, but at least it's a way to start the organization of a program.
Finally, I think functions make it easier to read a program because you've broken it down into small tasks. If need be, you can study each task as necessary. Doing all the code inline is usually messier and more difficult to read.
I've seen some silly function with one line of code, but that is the only thing that should be avoided.
It's currently quite in-style to have "accessor functions" for structures; it's one of the ways to get "plain C" to be more object-oriented:
int mystruct_get_length(mystruct_t *s) { return s->length;}
The idea is that you can stick all the intelligence about handling "mystruct" off in a library somewhere, and your higher-level code doesn't need to know anything about the internals of "mystruct_t", turning it from a C-style structure to an OOP-style encapsulated and opaque object.
I'm not terribly fond of this, myself. But it does have proponents.
I like to use functions to keep the code for a particular action in a block that can be tested in isolation from the rest of the code. Then when it works I can just forget about it and concentrate on other parts. I also like to have the minimum of code in loop() so that a quick read of it gives you a pretty good idea how the whole program works.
Putting code in functions also allows the actions to be separated from the logic.
And using meaningful names for the functions usually means that the code is self-documenting. My goal is to write code that I can understand 6 months later after reading it once.
Along with the other benefits of functions mentioned in this thread I particularly like the fact that they can be given meaningful names. That combined with meaningful variable names can go a long way to making code more readable.
One additional advantage of functions is that you can use them to help turn your psuedocode into real code. When you need something done in your code that you haven't figured out yet, you can assume a function that does it. Later, that function gets filled in, but it lets you get your higher level logic sorted out without worrying about the details.
During testing, a stub version of the function can be used that returns a constant value or just prints a message to the serial port or perhaps does just enough of its job to enable some of your test cases.
In small programs (i.e. most arduino sketches), I'll often use this method of functional decomposition to build the code - just keep adding the non-existent functions I need to build the function I'm working on and then write those supporting functions, which may in turn spawn others.
Bob and Robin are correct: Names do matter...a lot. Beginning programmers sometimes miss what constitutes a good function name. Good function names are task oriented, like FormatPhoneNumber(), SearchList(), etc. As a rule, they should not be method oriented. That is, BinarySearchList() is less desirable because it conveys how something is done inside the black box rather than what is being done. For example, your first effort at writing a WordSearch() function might just use a brute force approach. Later, you discover the Boyer-Moore algorithm and change the code to use it instead. All the user knows is that it's faster than before, but the code isn't broken. If you had given the search function a name that indicated the algorithm being used, it becomes more nettlesome to change the algorithm without renaming the function. Another example: a SortList() function may call a BubbleSort() function to complete its task. Later on, you might replace the BubbleSort() function with InsertionSort(). Either way, SortList() continues to work. In this example, it's okay to use method names for the type of sort, as that is the host algorithm and it likely won't change any time soon. However, most programming problems are task oriented, which is why SortList() is a better function name. (BTW, the Bubble Sort gets more bad press than it may deserve. First, it's easy for beginning programmers to understand it, and second, if a list is in sorted order and you're adding a new element to that list, the lowly Bubble Sort outperforms almost every other sort.)
G3t_M3ssy:
I am working on a project for fun, and I recently found the use of functions to be very helpful when organizing my code. However, I find myself over using them, often for task that only need to be completed once. I was wondering if there was some unsung rule regarding the use of functions in a program.
Many thanks,
G3t_M3ssy
G3t_M3ssy,
Sad to say you gotten a lot of crock so far. I've read most of the replies they left me to wonder about quality.
If I were to answer your question directly, no doubt I would fanning the flames which will follow this post. So in short, follow some of the theories you'll read, and make up your own mind.
jessemonroy650:
In any case, the two most important themes to consider are modular programming and coupling.
Have you considered the practical implications of writing code for a device with 2k of SRAM rather than 2GB?
All of the examples I have posted in this Forum are modular - different functions for different activities. I don't think any of the advice (from anyone) in this Thread contradicts that approach.
jessemonroy650:
G3t_M3ssy,
Sad to say you gotten a lot of crock so far. I ... wonder about quality.
Lets' hear why you think that.
If I were to answer your question directly....
Do, please.
We're all ears...everyone here is eager to learn, so perhaps you should shit or get off the pot there Jess and elaborate rather than sitting snidely by.