How to use/size functions in Python

Dear all,

I have “discovered” functions in python (I am a CS Student) and now I am using them for everything, kid in a candy store style.

My question is how do you guys size them?
Have one function that does everything?
Or dozens of small functions?

How do you decide when one function is over and the next one starts?

Kind regards, and thanks for the help

If you ever plan on cutting code professionally, you will learn to modularize things so that you can reuse code in other projects. Basically you start making modular templates that do something, one thing, very well and you can then copy and paste then around and modify them to suit the needs.

It is better to have core functions that perform a specific task and give back specific information. You can then make helper functions that will manipulate and massage the data that you are feeding to and retrieving from the function that acts as an interface to the task at hand.

Does that make sense? Have you covered deterministic machines or discreet mathematics or finite automata yet?

god I’m glad it has ended

read Clean Code if you can, you’ll understand more about functions

but functions are good, they can be used many times and they’re your friend

search for SOLID principles, that also should answer your question

get a function to do only one thing and do it well, then call it whenever you need that action

some software can be mostly made of functions, and basically a REST API is a bunch of functions tied to endpoints

how far into programming are you?

1 Like

I would advise reading Pragmatic Programmer 2nd edition contains a chapter about DRY (don’t repeat yourself) principle and why it’s not what people think it is. It’s important to note that reflection of what not to do is in 2nd edition only because people misunderstood it and made way more problems than improvements.

Also some lectures about DDD (domain driven design) and functional programming would be nice in their abstract sense of what they want to achieve and less of a how.

Now why would I suggest such “big stuff” to a student? Because your problems are found in many code-bases where seniors work. No amount of mathematics and philosophy about these and those machines will help you there - just a simple approach everybody hates: “use your head”. In fact knowing too much can also hurt because your head get’s fuzzy and you can’t decide.

Anyway, function name should be as clear as possible for a given context - this is why you separate them into modules or encapsulate in classes given you style of programming. For simplicity you can make everything global and just spread across properly named files.

Let’s say you have some code for accounting. It’s easy to make mistake and use DRY in the wrong way given example (I admit not the best example but you can find one in mentioned book:

function changeAmount(int amount) {
 if (amount < 0) {
  if (currentAmount < -1 * amount)  raise Exception("Insuficient funds");
  currentAmount += amount; // + because amount is negative
 } else {
  currentAmout += amount;
 }
return currentAmount;
}

So we use same method to change currentAmount and we follow DRY right? Now what’s wrong here? We’ll let’s say you have bunch of code and now given some positive value want to withdraw from the account

function sendMoney(accountFrom, accountTo, int amount) {
     amountFrom = accountFrom.changeAmount(-1 * amount);
     amountTo = accountTo.changeAmount(amount);
     .....
     sendMessage("left on account " + amountFrom); 
     sendMessage("account balance to " + amountTo");
}

Now this is obviously bad since we need to think all the time about which amount should be positive, which negative. This can lead to confusion and even errors which cannot be detected as both - and + values are accepted and decide what to do with the value. Code in the function is ugly and less readable. Also description of the method “changeAmount” doesn’t tell us anything about domain of application - we don’t know how would it be explained in real world.

We can do a bit better with 2 functions

function withdraw(int amount) {
 if (amount <= 0) raise Exception("Illegal value");
 if (currentAmount < amount)  raise Exception("Insuficient funds");
  currentAmount -= amount;
 return currentAmount;
}

function deposit(int amount) {
  if (amount <= 0) raise Exception("Illegal value");
  currentAmount += amount;
 return currentAmount;
}

function sendMoney(accountFrom, accountTo, int amount) {
     amountFrom = accountFrom.withdraw(amount);
     amountTo = accountTo.deposit(amount);
     .....
     sendMessage("left on account " + amountFrom); 
     sendMessage("account balance to " + amountTo");
}

Note: code is not from any language just my attempt to make example pythonic as possible :D.

Although example isn’t the best one you can see from the new code why would someone get tricked into using 1 function. sendMoney didn’t change much except that it calls 2 different methods now. However maintaining large codebase is the reason why to keep it as descriptive as possible. There’s less chance of error since all the requested amounts must be positive. Code clearly states what should happen in the real world. We do have 2 lines of same code - one for throwing exception on negative values and return of the current value. Second way is preferred way of splitting things even though you’re effectively changing the same value. However consider others reading your code and trying to figure out where the bug might be or such. Sending in amount of -50 from external parties would result in accountFrom being increased due to -1 * amount trigger and decreasing accountTo which is reverse of what we want. If you send -50 in second scenario it fails always as transactions must always have positive value of transfer.

This is all under assumption that you’re working on “average” type of software. Applications for embedded systems or such are forced sometimes to use different styles.

Sorry for the long answer here’s a potato :potato:

2 Likes

boy you messed me up with that currentAmount thrown outta nowhere

lmao

@katmai28 don’t be scared

dozens of small functions, each one doing it’s own job

and keep DRY in mind too, also DDD, and other design patterns

although most of it will be decided by the project managers in the real world, I believe

just chill and go slow

1 Like

Thank you very much everyone, really appreciate the advice

1 Like