if(0 == very_long_function_name_here(param1, param2)) {
Tells me a lot after I've read a little of the line, whereas: if(very_long_function_name_here(param1, param2) == 0) {
Makes the == 0 part easy to miss, and buried behind a lot of clutter. if(0 == very_long_function_name_here(param1, param2)) {
Tells me a lot after I've read a little of the line, whereas: if(very_long_function_name_here(param1, param2) == 0) {
Makes the == 0 part easy to miss, and buried behind a lot of clutter. if (VERY_LONG_AND_SPECIFIC_ENUM_NAME_HERE == func(param1)) {
}
Makes the function called easy to miss and buried behind a lot of clutter ;)Also, there are many more ways of dealing with readability: try different formatting and indentation rules, wrap lines manually where you think it makes sense and so on. As for your example, even the lowly C let's you do something like this:
int (*short_name)(int) = &veeeeery_long_and_ugly_and_unnecessary_function;
if(short_name(1) == 2) {
printf("\n\nYay, it worked!");
}
which completely solves the problem, no matter the order of compared objects. I'm not sure, but I suspect things like this are being optimized away by the compiler anyway, which would mean that you can use it anywhere you want without worrying about costs of indirection.In higher level, modern languages you have even more, much more sophisticated tools for doing this kind of things.
How long identifiers are acceptable depends on a language. With languages without namespacing or modules you obviously have to use some naming convention so that there are no name conflicts and this makes your names longer. I'd say 5 words is ok in this case.
But I'm not arguing against long names of things: on the contrary, I like having names as descriptive as possible. OTOH, too long names are also bad, because they make the code less readable and harder to work with. Like almost always it's a matter of balance: you need to know when to stop adding words to a name. I think that "name is too long when it starts making other names in the same line much harder to spot" is a good heuristic for this.
Not to mention it becomes more verbose once you make that alias a const ptr (which we do on all of our local variables).
You'd be confused once or twice, then you'd learn the technique and you'd stop being confused. Every code pattern was unfamiliar to you at first. And confusing, until you internalized it. It's unrealistic to assume that you can ever stop learning new patterns - try switching to another language and you immediately have dozens of unfamiliar, confusing patterns to learn. (it gets better after a certain amount of languages known (like https://klibert.pl/articles/programming_langs.html) because you start noticing meta-patterns)
My C is rather rusty nowadays and using function pointer here may not be the best option, but as someone else said, there are other language tools for doing this kind of aliasing, like #define. I'd go for function pointer probably, because it reveals not only a name, but also a type of function and it's guaranteed not to escape the current scope (unless explicitly returned) while #define has no knowledge of scopes at all. In languages which support real macros, and preferably lexically scoped macros (like Racket) I'd use those. In languages with closures and first-class functions I'd probably do it in yet another way. But in general, if I find myself working with a name so long that it makes it hard to spot other names on the same line I will alias it locally.
Have you read http://shop.oreilly.com/product/9780596802301.do ? It's a good, short book on the topic and it discusses exactly this issue at length in one of the chapters.
Sometimes you might not have a say in how the function was named... having some practices to deal with the unruly code that hasn't been graced by one's own perfect sense of style isn't terrible! ;)
try different formatting and indentation rules, wrap lines manually where you think it makes sense and so on.
All fine ideas, but I wouldn't discount yoda-conditions as not being in the same category.
Some languages are more opinionated than others, but one positive thing about "superstitious" programming is that code is often more consistent because of it ('pythonic' PEP 8, code patterns, skeletons/boilerplate, ...). Many times you'll end up seeing the same patterns elsewhere, for example adherence to Google C++ style guidelines on projects completely unrelated to Google -- simply because they are both practical and familiar.
In a similar vein, I'd probably religiously opt for a #define ... #undef pattern for your given example, because I've seen it more often than using a separate function pointer variable. There isn't really a technical advantage, but mostly one of familiarity.
If your code has a lot of clutter it's usually telling you something about your design.
For readability a better way of handling it might be for the function could return a boolean instead of an int:
if (is_valid(param1, param2)) {
self documenting code and all that.
if (0 == number_of_students(context, classroom))