|
I am, pretty much the same. Thanks.
"Rock journalism is people who can't write interviewing people who can't talk for people who can't read." Frank Zappa 1980
|
|
|
|
|
This discussion is quite fascinating. Back in my youth (when dinosaurs roamed the earth), languages restricted both length of variable names and enforced type based on initial (or even only!) letters.
So, I to N would be integer, everything else floating point. This is, I believe the origin of the common use of i,j,k for integer loop variables etc, and x,y,z (also algebraic) for common floats.
Someone I once employed would have complex calculations etc using variables like x, xx, xxx, xxxx and y,yy,yyy,yyyy etc - write only code if ever there was any.
The advent of unrestricted variable names led to the opposite extreme, where variable (and function) names became so long and complex
eg:
doubleCalculateOffsetForWaveFunction(intScaleFactorForWaveFunction,floatWaveFunctionSeedValue)
doubleCalculateOffsetForInverseWaveFunction(intScaleFactorForWaveFunction,floatWaveFunctionSeedValue)
with variations on camelCase, "_" separators etc) that code became tedious to type correctly and especially to refactor before the rise of the modern IDE; impossible to read and understand because of the effort needed to parse the variable names, especially when lots were very similar in structure etc etc.
(How would you know from reading the two declarations above whether the parameters were the correct variables eg: you might indeed want to use the same seeds here, or it might need different ones, so why not just use 'seed' etc)
BUT, you have to beware of making anything other than throwaway variable names too specific to the algorithm rather than their usage - because this can make them ambiguous or misleading in meaning:
does 'intUserValue' indicate something entered by the user, some property of the user, the user's value to the organisation etc
Making up variable names can be one of the hardest parts of coding something especially if one coding house uses identical names differently to another. I recently dug myself into a hole migrating a business app from SAGE accounts to XERO, because in SAGE anything (Nominal ledger entries, customers, suppliers etc) can be in an 'account'. In XERO only nominal items go in 'accounts', customers go in 'contacts'. I only discovered this when I tried to post a customer invoice and found that I couldn't assign it to an 'account', only to a 'contact'.
Then there are the times when you use a library function return value in-line, there's a bug, and even your modern sophisticated IDE has no way to inspect the return value without dropping right down to assembler level code inspection - so you put the result into a variable which the compiler then helpfully removes again during optimisation so you still can't debug it easily.
After many years, I have come to the conclusion that KISS applies as much to variable naming as to code itself: Also if you are dyslexic, long variable names can be incredibly difficult to cope with too.
So, as simple as possible, don't bother with describing the type in the name (except possibly in languages that don't have or enforce types, and even then limit yourself to single letters if possible eg iRetVal, not integerRetVal).
Simple variable/function names along with careful, concise comments can make all the difference!
You have heard of comments, haven't you? 8)
|
|
|
|
|
A wonderful response.
Really enjoyed this one especially.
Thanks.
I was aware of most of the history that you mentioned.
The long variable and function name thing made me nearly spit my stout out over the keyboard. I have never seen this before but I have seen similar.
I usually comment on names, especially function names and occasionally with Variables if they may seem obscure.
A comment is sometimes priceless.
"Rock journalism is people who can't write interviewing people who can't talk for people who can't read." Frank Zappa 1980
|
|
|
|
|
I agree with most of this. I've only been coding since the mid 80s but I have worked in software professionally since I was 18, with some breaks here and there for my mental health. So I have some experience, and for me I've found
A) Style isn't as important as consistency of style
B) It's easier to go with the flow. Your job is to make your flow come correct. That takes practice. Make it instinct to do the right thing. With variable names this means foster good habits, but then move to relying on the "muscle memory" of those habits in terms of naming patterns
C) Everyone has opinions. You can't satisfy every developer, so satisfy you and your project lead.
Just my $0.02
Real programmers use butterflies
|
|
|
|
|
I think that the single responsibility principle (from SOLID) is directly linked to names: if you make sure that your function or class or even variable just fulfills a single purpose, then you should also be able to name it appropriately, using that purpose. Or, the other way round: if you find that parts of a name you're looking at describe different purposes, then there is likely a copnflict with the single responsibility principle!
In other words, clean code leads to good, and reasonably short names.
But let's look at your examples:
doubleCalculateOffsetForWaveFunction(intScaleFactorForWaveFunction,floatWaveFunctionSeedValue)
doubleCalculateOffsetForInverseWaveFunction(intScaleFactorForWaveFunction,floatWaveFunctionSeedValue)
In these names, the type information does absolutely nothing to explain the purpose, so these parts must go. Next, the function names describe what the result is used for (the (inverse) wave function). This info should go into the argument list, not the name. That will also make the calculateOffset functionality easier to refactor: if there's anything you need to fix or change in the offset calculation, having just one function to look at is always preferable to having >1 functions!
As for naming style, I consider '_' separators to be more readable than any other style, but TBH I couldn't care less, so let's stick with what you had. With my comments above, you get just one function instead of two:
calculateOffset(scaleFactor, seedValue, functionType)
Since the function type goes into the argument list anyway, I've dropped it from the argument names. I'd also drop the meaningless suffix 'Value', but it's already a lot more readable. And all that without losing any information!
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)
|
|
|
|
|
Indeed so!
For the avoidance of doubt, these were not functions created by me! 8)
I have never understood the need, even in interpreted languages like modern BASICs etc, for 'hungarian' notation - if the language isn't type-safe, then no amount of attaching prefixes etc is going to prevent some library assigning a string to the integer variable you just passed it silently and hence subtly altering the results etc.
Possibly useful as a reminder to you as coder, but cannot be relied on by anyone else reading your code, so better to have meaningful variables and proper tests, exception handling etc so that context reveals what should be going on.
I'm working on a very elderly codebase at the moment where some, but not all, tables are named tbl<name>; some, but not all, forms are frm<name>; some, but not all, reports rpt<name> etc etc. The lack of consistency renders all these prefixes completely useless and just makes typing out code tedious and mistake prone...
As for comments? Ah yes, I did find one, once, somewhere in the 100,000 or so lines of code...
|
|
|
|
|
Mike Winiberg wrote: For the avoidance of doubt, these were not functions created by me! 8)
Thought as much, your post made that pretty obvious.
Mike Winiberg wrote: if the language isn't type-safe , then no amount of attaching prefixes etc is going to prevent some library assigning a string to the integer variable you just passed it silently and hence subtly altering the results etc.
I beg to disagree. Prefixes or suffixes can be rather helpful in spotting semantic errors in places where no amount of type safety can prevent them. Consider this example:
class Box {
public:
double height();
} box;
double size = box.height();
This is perfectly fine with regards to the types being used, and there is no apparent reason to use different types. But what if the box is defined in meters, and the size you need expects millimeters? The code above will not so much as hint at a potential problem!
Now look at this code:
class Box {
public:
double height_m();
} box;
double size_mm = box.height_m();
The use of appropriate suffixes makes the error imediately obvious, without the help of comments.
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)
|
|
|
|
|
I don't disagree with you, or the use of helpful hints like you suggest. But whilst your suggestion (and indeed hungarian notation etc in general) provides useful prompts and hints to the coder it doesn't address type safety and in fact can be counterproductive in non typesafe languages:
I hit this kind of thing a lot in an elderly VBA codebase that I maintain and develop for a client. GUIDs can be represented (validly) as either a string (in 3 different formats FFS!) or as a BYTE array. When reading a GUID from SQL Server into a table and thence into a form and onwards into code you usually get a string, but sometimes (I presume depending on the temperature of Bill Gates' shower at the time the code runs) you get a BYTE ARRAY - all of these can appear in the variable you assign them to if it's a Variant, and you can only find out which one you get by testing the type of the variable after assignment, or when an exception is raised on use! However, if you are attempting to assign the GUID to a string and it arrives as a BYTE array it doesn't cause an exception, instead you silently get a GUID consisting of '??????' 8)
I have spent many many hours tracking down strange bugs caused by this behaviour.
If (as I have discovered in code I inherited) errors have been disabled so that (unless the error is actually fatal) code continues with the statement after the one where an error occurs, you are falling down a rabbit hole with no bottom!
Note that although you may get a BYTE array GUID, this cannot be assigned to a GUID column in a table, so you have to convert it to a suitably formatted string (and the formatting acceptable depends on whether the table is local or on the SQL server).
Working on code like this when it is full of incredibly long-winded, supposedly 'typed' variable and function names is just adding insult to injury! 8)
|
|
|
|
|
I know what you mean. I've seen my share of legacy garbage. And it doesn't stop in front of the big names. I still remember one project where I tried to put a thin layer between our embedded application and embedded Windows (back then still called CE), in an attempt to port it to another embedded OS. I stopped when I realized just how full the Windows APIs were with inconsistencies, including a couple of obvious bugs (well they became obvious when I worked on it - they weren't obvious at all when you looked at the individual parts of the API in isolation )
Everybody makes mistakes, and the older the systems are, the more mistakes you'll find. That's just the way things are, and my own code is no exception.
That doesn't invalidate my statement though: if used in the way I presented above, even if used inconsistently, it will increase the likelyhood of discovering semantic errors.
That said, I wouldn't use hungarian notation for any of the examples you brought up: I agree with you that in those cases it served no meaningful purpose.
I've found the article that was at the back of my mind all the time when posting here: Making Wrong Code Look Wrong – Joel on Software[^] I really like how Joel explains the do's and don'ts of hungarian notation, and how to use it correctly.
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)
|
|
|
|
|
Thanks for that link - I've read a few of his articles in the past and found them helpful.
So much to read - so little time!
8)
|
|
|
|
|
And having read the paper - I once again agree with what he says!
I was a fervent adopter of C++ in its early days, but as the language developed and got harder and harder both to use effectively and read I gave up using it. (The fiasco of manipulators between versions 1,2 and 3 didn't help either!) (Neither did a commercially produced database library 'accidentally' passing parameters by value and not by reference - as per the documentation - which caused an amazing array of problems until I tracked down just what was going on! 8) )
Joel's example of what appears to be a simple multiplication is one of my pet peeves about C++ and the fact that in a complex class you can end up with what are effectively class globals that can be accidentally hidden by local variables if you are not very careful is another. Once it became harder to use C++ effectively than it was to solve the programming problems I was using it for, I gave up.
As for exceptions, tracing back through 12 layers of exception handling to find out what is causing it is a nightmare - like he says useful for stuff that isn't mission critical, but a bottomless pit in difficult stuff.
|
|
|
|
|
grralph1 wrote: I love and respect Sander. Love you too man #nohomo #bromance 😘
|
|
|
|
|
Haha
"Rock journalism is people who can't write interviewing people who can't talk for people who can't read." Frank Zappa 1980
|
|
|
|
|
I did respond to the previously mentioned post, as one who does use silly names.
Perhaps a new topic, but I also leave silly (funny?) comments in the code for whomever receives the punishment of having to fix modify my code later.
if (...) {
-
-
} else {
}
Nothing succeeds like a budgie without teeth.
|
|
|
|
|
Yes I do remember your bravery and your pride.
I do like the idea of silly or humorous comments.
You only live once.
And it may cheer up someone who is reworking your work.
Weirdly though I hardly ever do it.
(Probably because no one else usually ever sees my source code.)
For the past 10 years I have been commenting for others. Prior to that it was only ever for me.
Thinking about this whole thing I have discovered that I appear to be most creative (not silly) when making up names for functions.
Less so for subs and variables.
However I recently noticed that in some legacy code that I had a public boolean variable called TheWhiteZone. The comment said "The white zone is for loading and unloading only".
This was exactly what the Var was indicating, loaded or not, and it wasn't aloud to park there. No Way.
"Rock journalism is people who can't write interviewing people who can't talk for people who can't read." Frank Zappa 1980
|
|
|
|
|
Indeed. I still remember that, when thinking how to properly initialize a boolean, rather than deciding whether to initialize it with true or false, I literally did initialize it with true||false
But that's decades ago, and I don't recall having done something silly as that ever since.
Although... I once caught a run time error in my code that I was convinced could never happen. Consequently, the error message stated something along the lines of "this should never happen - please contact {my name}". The client I delivered this to did have a laugh, but I was still happy to hear that it was caught in acceptance test and never went out to the real clients...
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)
|
|
|
|
|
I use "result" or "response" when it is really a throw away variable for debugging purposes. Using "ewww" or "blurpp" is crossing the line. We are working, not joking with friends. Even if it's a personal project, bad habits get carried to other things.
|
|
|
|
|
Agree.
"Rock journalism is people who can't write interviewing people who can't talk for people who can't read." Frank Zappa 1980
|
|
|
|
|
I have used and will continue to use "temp" for a temporary variable that lives for one or two lines of code.
|
|
|
|
|
I always use something meaningful, even if it is a throwaway variable. I work hard to make my code readable and think of whether the name will help or hinder me six months from now. I have worked in way too much legacy code that took forever to figure out and understand maintenance is where the bulk of programming time gets spent. (much to my dismay!)
|
|
|
|
|
I learned from this series of posts to utilize "str" for strings. I never liked using "string" since it conflicts w/ std::string. I always use "using namespace std;"
I favor descriptive names however I would rewrite doubleCalculateOffsetForWaveFunction(intScaleFactorForWaveFunction,floatWaveFunctionSeedValue)
as
Offset_forWaveFunction(scale_factor, seed_value)
I don't believe in Hungarian notation as it is merely another source of error and of course the return value is already documented. "Calculate" is redundant since we know that's what functions do. I find it helpful to distinguish prepositions in the name. "ForWaveFunction" is not needed since the variable is in context. If this method was of a class WaveFunction then all that would be needed would be Offset(scale_factor, seed_value). My local variables are always lower case. Capitals I reserve for global or public objects.
I am fascinated by naming notation conventions. I like the notation to say something about the method and variable e.g. to distinguish public methods from private e.g. camel for public and snake for private though I am conflicted as I like snake as it is easy on the eyes with no capital letters shouting at me though I am currently utilizing all capitals for statics and terminate all lambdas with "_LAMBDA". I am eager to learn of other's techniques and preferences. - Cheerio
modified 23-Apr-21 11:16am.
|
|
|
|
|
Thanks for that it is very interesting.
Quote: doubleCalculateOffsetForWaveFunction(intScaleFactorForWaveFunction,floatWaveFunctionSeedValue)
Gee.
I can read your rewrite easily.
The original is like a the name for a Welsh town and the only person who could read that would be the OriginalGriff.
I have never used ALLCAPS for anything. No reason, just never even thought about it. Therefore no titleCASE case either.
I usually use camelCase now but used to use CamelCase. I sometimes but rarely use snake_case or a cross between it and one of the camel styles just for some emphasis.
For Public variables I always distinguish these with a g prefix. Like gWaveVal. The g indicates Global.
It is fascinating to hear what other peoples preferences are and also the reasons for their preference.
Thx
"Rock journalism is people who can't write interviewing people who can't talk for people who can't read." Frank Zappa 1980
|
|
|
|
|
I once came across a function whose purpose was to send a message to the Sales And Marketing application. The developer had amusingly but appropriately named the function TelegramSAM. Unfortunately, they had then got a little carried away:
The author was listed as M. Bolan
The variables were named "jungle", "faced", "jake", "make", "no" and "mistake".
|
|
|
|
|
This made me laugh.
What a great name for the function.
Almost the perfect name but in retro case.
It may fly completely over the head of younger developers though.
I like the idea of having a theme though.
However easy to get carried away.
"Rock journalism is people who can't write interviewing people who can't talk for people who can't read." Frank Zappa 1980
|
|
|
|
|
Hands down the 3 hardest problems in programming:
-naming stuff
-off-by-1-errors
For throwaways, I usually pick my repertoire of Result (for holding something that'll get returned) and Scrap (generic temporary).
For stuff like responses from dialog boxes, I either take my old-and-tried Scrap, or give it some meaningful name like "SerialNo" when the user is prompted for a serial.
|
|
|
|
|