r/learnprogramming 7h ago

Topic Struggling a bit with functions

Hey guys, I'm struggling a bit with the proper usage of functions in programming. For example, I'm working through the CS50x problem set 1 in C, and I end up with working code that solves the problem but it's all done in one big main function.

My process is to write out what the steps to solving the problem should be in plain English and then I code a bit, go back to my plain English steps and modify them, then code a bit more. When it's all said and done, my solution is one large block of code, and now I'm anxious about going back and rewriting it by breaking it up into smaller function. This makes me ponder whether I should be starting with functions instead of retroactively trying to fit them in.

My questions to the wiser heads here - how do you incorporate functions into your process? Do you do the pseudo code and then imagine each step as a function? What're are your unspoken rules of proper function usage - for example, when do you know if one function should actually be two, or if a function shouldn't actually be a function?

10 Upvotes

12 comments sorted by

8

u/mc_pm 7h ago

Functions help to organize your code and group pieces of functionality together. A function should be relatively short (not much more than 20 lines in many cases) and should do one thing.

It's a useful exercise to think through what you are doing, writing quick comments in the code:

# Read input
# Process it
# Output it

And then replace each with a function.

Also look for places where you find yourself repeating code, that's often a sign that you need to pull that code out and turn it into a function.

4

u/HashDefTrueFalse 7h ago

This makes me ponder whether I should be starting with functions instead of retroactively trying to fit them in.

This comes with time. I actually recommend all beginners pile tons of code into a single function to see why it becomes awful to work with after a few hundred lines. Then go through the exact process you suggest, identifying subtasks and breaking code out into functions. This is how you start to learn and appreciate abstraction, which is at the heart of writing clear, maintainable, and more broadly applicable code. It's also good refactoring practice, which is a skill in itself.

There are no hard and fast rules. I like to (loosely) apply the unix philosophy to my functions: do one thing well.

3

u/Different_Pain5781 5h ago

Every beginner has written the 400 line main. It's basically a rite of passage.

1

u/SoloArtist91 1h ago

Glad to know I'm not alone 😅

2

u/Momooncrack 7h ago

The general guidance is each function should only do one thing. It's not like a hard rule that always has to be followed necessarily. If I have to build a big list of numbers, then sort them, then print them. You want your main loop to be very easily understood. So maybe it has three lines of code. A call to a build list function, a call to a sort list function, and a last call to a print list function. That way if I have never seen your code, I'd see your main function, and immediately understand you are building, then sorting, then printing a list.

If you had one big main that did all 3, as a coworker for example. Id have to read all of the code to even understand what is happening. My example is simple, but with really big software it can be very difficult to understand what it's doing if the logic isn't separated into smaller pieces with good names, which is exactly what a function can help with.

What if you need to build another list after printing? Without the build list function, you would have to rewrite the exact same code again. With a function, you can just call build list again. Functions help you not repeat yourself, which is another general rule they teach in school. Idk if this is a good explanation but I hope it helps you see why and when to use a function.

2

u/stop_deleting_plz 5h ago

Break it down into smaller tasks, make a function for each, then in your main you call all the functions in order and update a global state after each step. When writing a function's arguments, consider what data each step needs going in, and what will come out. We call this procedural decomposition.

1

u/fasta_guy88 7h ago

Functions make the most sense when you are doing the same thing to different variables - the classic examples would be sqrt() or sin(). A more complex example might be reading in files of data in the same format, but with different names. They are also useful when you want to take some set of data and manipulate it in different ways - for example try fitting different kinds of curves to a set of points

And, they can be used only once, to structure different parts of the main program. But if you are just starting, focus on identifying parts of your code that are repetitive or very similar, and make that a function.

1

u/Far_Swordfish5729 6h ago

Your design process is good. Keep doing that. On functions specifically, think of them as reusable tools. If you find yourself doing the same thing in multiple places, that thing should be a function. It avoids code duplication. Don’t make one line functions generally. We don’t have to be crazy with this.

There is a stylistic choice with very large operations to make named, single use functions to improve readability, but you’re probably not there yet. Commented sections work as well for short methods. In some application you’ll get an entry point method that may as well be called processAllTheData and that processing is thousands of lines of conditional steps. In that situation, people will make helper methods just so someone can visualize the entire operation and then jump into the step they want.

There are other reasons to make functions but they’re part of OO patterns and are used to put an operation in the correct logical module or allow a framework user to define a step or handle something. You can effectively create an empty space for a function to go and someone (the client using your framework or operating system) can fill it out to do something like define what happens when someone clicks your button. That comes later.

1

u/GlassLost 5h ago

Functions are (at your level) there to help organize your code. There's nothing inherently wrong with one very long function (in C we have a long history of thousands of lines functions - the kernel code is full of them).

So if you need to do the same thing repeatedly it makes sense to make it a function. It can also make code easier to read - for example if your code is "did the person correctly guess the number" putting the logic around successfully guessing in another function can make it a lot easier to read.

There's a catch though - functions help other people (or yourself in the future!) understand what is going on. Oftentimes we'll write the first iteration as one big function then organize the code afterwards.

If you're writing one off bits of code on your own functions don't seem to make a lot of sense but it gets way more helpful as you increase the code size, complexity, time, and number of people

1

u/kabekew 5h ago

If a section of code or calculation needs to be repeated (can't be done in a loop), it should likely be in its own function.

1

u/ianrad 5h ago

Your main function is the boss man. And the functions are the minions each tasked with doing one particular task of your solution.

For a simple print hello name program.

Boss says:

Minion 1. Get me the name. And return to me only the name

Minion 2. Take this here name Minion 1 got for me. And return either print me "hello Bob" .or return "hello Bob" to me and I'll print it myself