For the non-retarded programmers here (revsited)

Everything todo with programming goes HERE.
Post Reply

Who's side are you on?

The Loony Programmer
1
14%
The Perfectly Sane Programmer
6
86%
 
Total votes: 7

User avatar
Lucifer
Project Developer
Posts: 8640
Joined: Sun Aug 15, 2004 3:32 pm
Location: Republic of Texas
Contact:

For the non-retarded programmers here (revsited)

Post by Lucifer »

So what's better? Here are the two opposing arguments.

The loony, psychotic argument goes like this:
The Loony Programmer wrote: Long functions are ugly, so I prefer to make little functions of 1-3 lines of code that only ever get called once from within a function that would otherwise be very large.
Now the other side:
The Perfectly Sane Programmer wrote: Long functions aren't inherently good or bad, but a series of little functions of 1-3 lines that exist solely to prevent a function from getting long adds extra complexity, extra room for error, increases the difficulties of troubleshooting the code, and slows the program down. I would prefer to have a long function than the alternative.
So who do you side with?
Image

Be the devil's own, Lucifer's my name.
- Iron Maiden
User avatar
Lucifer
Project Developer
Posts: 8640
Joined: Sun Aug 15, 2004 3:32 pm
Location: Republic of Texas
Contact:

Post by Lucifer »

Ok, I figured out how to anonymize it a bit. :)

Function A and B do different things, but part of B's return value is identical to all of the return value of A.

Function A calls Function 1 to get its return value. Function B calls Function 1a to get that same part of its return value.

Functions 1 and 1a are identical, but they're not the same function. They even appear one after the other in the source.

I need a couple of features added to Function A. The Loony Programmer adds them to Function 1a, doesn't test it, says it works and its done and we can release.

So I need to troubleshoot why it doesn't actually work when it's actually tested, and I find some interesting things. Functions 1 and 1a both call Function 2 to format the return value. Function 2 takes 5 parameters and returns them as a keyed array, with 3 of those parameters unmodified. Functions 1 and 1a declare and assign a value to a global variable right before calling Function 2. Functions 1 and 1a give as the 5 parameters 5 elements of a keyed array, and the keys are identical to the keys that Function 2 returns.

Now then, Function 2 calls Function 3, which uses that previously mentioned global variable in order to call Function 4 and return it's return value back to Function 2 which inserts it as #4 in the keyed array. Function 2 calls Function I for parameter 5.

So, I remove Function 1 and redirect Function A to call Function 1a instead and comment out FUnction 1. (I'll leave out the part about how 1 and 1a were mysteriously *not* interchangeable even though they were identical because that still blows my mind).

Then, since I was trying to get Function A to return the new features that were added and it wasn't, I eliminated Function 2 by just making an array() call. For paramter 4 of the array, since I was now in the function in scope that initialized the global variable previously used by Function 3, I eliminated Function 3 entirely and called Function 4 directly in my array() call. For parameter #5 I called Function I directly because it was a benign and useful function.

Total lines eliminated: I didn't count, but at least 30, probably closer to 50.
Levels of complexity eliminated: 4
Lines added to Function 1a: 4
Factoring complete, modularization in that part of the code achieved.

So the Loony Programmer looks at it and says "Long functions are ugly and you made a long function longer. I wrote all those functions so that Function 1a wouldn't get needlessly long." (Evidently the Loony Programmer is still unaware that Functions 1 and 1a were identical and he added the features I needed to a different context so I couldn't use them)

Hence the poll. :)

Edit: I think my daughter would have done better. It is only php and she is almost in first grade, after all.
Image

Be the devil's own, Lucifer's my name.
- Iron Maiden
User avatar
LETE
Core Dumper
Posts: 128
Joined: Sat May 21, 2005 5:40 am
Location: Hey if i'm not here i'm most likely on the grid

Post by LETE »

The whole purpose of functions is to make a block of code that can hopefully be used later on in a different program, its a piece set apart to do a specific task, when you break it down into smaller unusable components, your totally botching your program, you'll never be able to reinstate that code again, if its chopped up so small that you have to pass things in and out all over the place when one function would do, your shooting yourself in the foot. I know they had us micro manage functions in the very beginning, when we learned how to program, but that was to get used to passing values, and calling functions. So yah, cutting up a function like that basically makes it un-useable, if not to you, than to your co-workers. :o :evil:

lets not say "for non-retarded programmers", and then proceed to spell revisited wrong. :roll: J/k j/k
Image
User avatar
Lucifer
Project Developer
Posts: 8640
Joined: Sun Aug 15, 2004 3:32 pm
Location: Republic of Texas
Contact:

Post by Lucifer »

LETE wrote:The whole purpose of functions is to make a block of code that can hopefully be used later on in a different program, its a piece set apart to do a specific task, when you break it down into smaller unusable components, your totally botching your program, you'll never be able to reinstate that code again, if its chopped up so small that you have to pass things in and out all over the place when one function would do, your shooting yourself in the foot. I know they had us micro manage functions in the very beginning, when we learned how to program, but that was to get used to passing values, and calling functions. So yah, cutting up a function like that basically makes it un-useable, if not to you, than to your co-workers. :o :evil:
I'm with you. I've actually developed a little discipline I use to prevent me from GratuitousFunctionCreation. I class myself as a bonsai programmer, and I guess that makes me sympathetic to XP. If you've ever seen the Karate Kid, you already know what a bonsai programmer is. :) If not, here's a brief overview:

In the movie, Miyagi has a little bonsai tree that he gives to his student. The student says "I don't know what to do with this." Miyagi instructs him to not look at the tree but instead to develop a picture in his head of what the tree should look like. Then he hands him the scissors and in one of Hollywood's few bursts of wisdom says "Make look like picture".

So that's what I do. :) And while I'm hacking away at it, to prevent GratuitousFunctionCreation, I firmly establish that I will write every line of code the function uses within the function. If I need the same code (or a slight variant) a second time, I will copy and paste that code. If I need it a third time (or if it develops bugs and I have to keep fixing it in two places), then I will factor it into a function. When I write a function, I do whatever I can to make sure that the complete logical unit of work that function accomplishes is clear in the code of that function. You should not have to go chasing around global variables or even tracing different contextual threads unless you determine those threads are the problem. (Not threads as in lightweight processes, threads as in threads of thought) You should be able to go into the function understanding what the inputs are by looking at the parameters (no global variables) and decipher it.

Naturally I have trouble understanding code that's not anywhere near my own center of self the same way Miyagi wouldn't understand a tree that was haphazardly and randomly chopped into worthless bits and died.
lets not say "for non-retarded programmers", and then proceed to spell revisited wrong. :roll: J/k j/k
Since you're new here, I'll cut you a little break, but I was following in the footsteps of a predecessor. :)

Hmmm, oh yeah, for reference, in case anyone was curious (and most of you know this already), I don't have a degree in CS. I don't want a degree in CS. I'm not currently going to school to get a degree in CS. I started programming when most kids were still learning to read and 8 bits at home was hot shit, global variables were all you had, and functions had yet to be seen on such a small computer because it didn't have enough stack to do functions, at least not functions the way we think of them now. So when asked these days where I went to school to learn how to program, I give the only appropriate answer, the School of Hard Knocks. ;)
Image

Be the devil's own, Lucifer's my name.
- Iron Maiden
User avatar
Z-Man
God & Project Admin
Posts: 11587
Joined: Sun Jan 23, 2005 6:01 pm
Location: Cologne
Contact:

Post by Z-Man »

I think you can't make a general decision here. Long unstructured functions are bad all by themselves because their complexity goes with the square of the number of lines (you get a certain amount of variables per line on average that have a scope of the length of the function and you have to understand what every one of these variables does over the whole function), but of course, there are other ways to reduce the complexity.
I use this rule of thumb when deciding whether some small portion of code should be an extra function: If I can give it a name that describes well what it does*, it's worth an extra function. Even if two blocks of code are completely identical in two places, I don't factor it out into a function unless there would be a good name for it, because if there's no good name, chances are that some time in the future, I'll have to modify one of the blocks of code and not the other.

Well, and just yesterday, I split a function into an inner and an outer part because the outer part had a variable I wanted to hide from the inner part.

Of course, in this particular case (functions that just shuffle arguments? Using globals to pass arguments? arguing that this is good?) the loony programmer should spend some time at the asylum.

* and is considerably shorter than the code. I don't do

Code: Select all

void IncreaseByOne( int & var ){ ++var; }
:D
User avatar
Lucifer
Project Developer
Posts: 8640
Joined: Sun Aug 15, 2004 3:32 pm
Location: Republic of Texas
Contact:

Post by Lucifer »

z-man wrote:I think you can't make a general decision here.
It's just a general approach, I guess. You make strategic decisions and you make tactical decisions, and you have a general approach that aides you in making those decisions. :) In a special case, you vary from your general approach. If you're varying a lot from your general approach, then you're either asking the wrong questions or your approach is wrong for the situation.
* and is considerably shorter than the code. I don't do

Code: Select all

void IncreaseByOne( int & var ){ ++var; }
:D
I've seen that construct so many times.... :(
Image

Be the devil's own, Lucifer's my name.
- Iron Maiden
Post Reply