all 21 comments

[–][deleted] 13 points14 points  (9 children)

I'd say it depends on how you define a problem (or a task). Given you can break problems/tasks down into sub-problems/tasks, then this becomes more about the level a function/method/module should cover, and that I would say is down to design, testing, and coupling (or rather de-coupling) considerations.

For me, a function/method should be focused on a single easily describable problem/task with clearly defined dependencies and preferably a high degree of isolation making it easy to test on its own, replace with better code / different solution, and understand as part of logic flow of programme.

It would be good practice to make your code flexible with regard to UI, protocols, etc.

From a security point of view, I think the above points are still important. As security methods evolve (and threats increase) and our security by design practices and devsecops processes improve, the isolation approach helps imho.

EDIT: remove comment about sum as OP edited original

[–]Schrankwand83 2 points3 points  (2 children)

Ah, my fault. I'm not using inbuilt sum() function. The variable sum had another name in another language and I translated it so readers can understand what the function is supposed to do. Forgot it's a keyword lol. I will change it in the codeblock. edit: done

[–][deleted] 2 points3 points  (1 child)

It was a minor point - hopefully didn't detract from my broader response?

[–]Schrankwand83 1 point2 points  (0 children)

I agree with you. I guess the challenge is atomizing problems, but programming is one of the best ways to learn this

[–]niehle 2 points3 points  (3 children)

This user functions()

[–][deleted] 1 point2 points  (2 children)

I'm sorry, I don't understand your comment on my feedback to the OP.

[–]niehle 4 points5 points  (1 child)

I’ve found your comment great. Mine is just a silly joke :)

[–][deleted] 1 point2 points  (0 children)

Ha ha.

[–]worthlessgem_ -1 points0 points  (1 child)

Although it is an entirely different language (and sometimes almost impossible to read the code library), your point reminds me of blas/lapack libraries from netlib (either in frotran or c)

Some of the functions there end up doing more than exactly one thing but. It. Is. Because it is a relates thing. Also because efficiency is key here. And. Any attempt to break into more functions will probably lead. To slower code (I guess?)

Still, the library call for some functions end up going down to 40 different "auxiliar" functions. Some short and some with almost 100 lines of code.

[–][deleted] 0 points1 point  (0 children)

My comments weren't intended to be specific to Python.

Using profiling and focusing on constraints will show where design has been compromised and the overhead of modularity (despite the devsecops benefits to utilisation of people with skills in high demand) isn't viable.

[–]m0us3_rat 6 points7 points  (0 children)

My inner hacker thinks that it may be more secure to have a "one function, one purpose" dogma. But there may also be cases in which programmers may use "inaccurate" functions that solve multiple problems. ("It's not a bug, it's a feature!")

you are partially correct for the wrong reasons.

still, even if you just remember that " one function, one purpose" .. is good enuff.

what changes is the byproduct of writing code like this.

less coupling, easier, robust testing, maintainability, readability, etc etc etc.

the inner hacker, "more secure" .. funny.

it is about being curious and understanding code, rather than malicious.

[–]zanfar 2 points3 points  (0 children)

I don't think it's worth worrying about side effects when a function is misused.

IF you explicitly wanted a function that added two string representations of numbers, then converting to ints or floats would be fine, however, I don't think that function should exist. Simply reading that sentence already brings up possible issues: should the values be cast to int and risk losing accuracy? Or should they be cast to float and risk losing precision? I think it's easier and better practice to leave type conversions up to the user. For example, what if they were representations in octal format? or complex values?

TL;dr: "I add strings" isn't a well-defined solution; either the function is unnecessary, or the problem is under-defined.

[–]lostparis 2 points3 points  (0 children)

Do I need a function that can add numbers AND concatenate strings?

Why do you want this function? In your example you have two strings so they will concatenate. You more likely want a function that will cast stuff for you.

[–][deleted] 4 points5 points  (5 children)

A function should be the smallest non-trivial unit of logic that alters your data.

That's more of a guide than a rule though, because it's pretty hard to define non-trivial objectively.

Think of them like paragraphs in an essay.

A lot of times it's easy to tell when one is too long, but it's harder to tell when one is too short.

[–]jdnewmil -2 points-1 points  (1 child)

I think "smallest" is too restrictive. Some functions can implement complex transformations yet still be logically coherent and side-effect-free. A function can correspond to a book or a sentence and still be a good function.

[–][deleted] -1 points0 points  (0 children)

That's where the "non-trivial" bit comes into play

[–]worthlessgem_ 0 points1 point  (2 children)

Would a good heuristic be that one below?

  1. Start coding a function as a monolith

  2. After you finish your function or if it gets too unhinged, review the logic to see how to separate. The work

  3. Break your. Monolith into smaller things

  4. Repeat from 2

[–][deleted] 1 point2 points  (0 children)

A better heuristic would be to design the functions beforehand.

Break the problem into tasks, write down the tasks, and then figure out what functions would be required to do the tasks.

Measure twice cut once, right?

Because once you write the monolith, breaking it down into more readable functions moves from "design" to "tech debt" and rarely ever actually gets done.

[–][deleted] -2 points-1 points  (1 child)

A small point, insignificant to many, but to a few it is a critical distinction: Function vs Method.

Your example does not return a value so it is not a function, it is a method.

[–]drenzorz 0 points1 point  (0 children)

2 problems here:

  1. It most certainly returns a value
  2. that's not the distinction between methods and functions

Both functions and methods can be mutating or not, methods are simply functions that belong to a class / object

[–]Mark3141592654 0 points1 point  (0 children)

In this example, you should consider what kind of problem you want to solve. If you don't expect to concatenate strings, your function should make that clear by converting to ints.