On 12/12/2022 16:59, Juha Nieminen wrote:
> David Brown <
david...@hesbynett.no> wrote:
>>>> This is especially true given that
>>>> full types in C++ can regularly take more than a single line to write out.
>>>
>>> There we go again with the brevity argument.
>>
>> If you can't see the wood for the trees, the code is unhelpfully
>> long-winded.
>
> I don't think you understand.
>
> The driving principle in writing code should be "this makes it easier to
> understand", not "this makes it shorter".
>
Of course I understand, and agree with that principle. The sticking
point seems to be that you apparently have difficulty understanding that
short code can be easy to understand - easier than long versions.
Sometimes it is simply the fact that the code is shorter that makes it
easier to understand - people generally write "long" instead of "signed
long int" precisely because it is shorter and requires less cognitive
effort to understand.
"auto", used appropriately, can do the same thing.
> It's not about making the names longer for the sake of making them longer.
> It's about making them easier to understand. If that means writing longer
> names, then so be it. There's zero reason to avoid longer names, if that
> makes the code clearer for the reader who is reading the code for the
> first time. (Conversely, if a name is so long that it makes it harder to
> understand, then express it more concisely and clearly.)
>
> The problem is that the majority of programmers do not choose names based
> on how easy it makes the code to understand for third-parties. They choose
> the names based on personal preference, which in the vast, vast majority
> of cases means overtly short names. Most programmers prefer writing "ret"
> instead of "returnValue", "err" instead of "errorCode", "genRandVal"
> instead of "generateRandomValue". They do not think if that makes the
> code harder for someone else to read. (And in the majority of cases if
> you point this out, they will ferociously defend their practice, against
> all logic.)
Of course they write "ret" instead of "returnValue" - it makes the code
easier to understand!
Choosing and using good names is an art. There are guidelines, but no
fixed rules. Like many stylistic aspects of programming, it can depend
significantly on the size of the project, the size of the development
group, the lifetime of the code, the type of code, and many other factors.
One common rule, however, is that the bigger the scope of an identifier,
the longer and more explicit it must be. Inside a short loop, you use
an index variable "i" because it is short and /clear/. Calling it
"loop_index_counter" makes the code harder to read and understand -
longer and more explicit is directly counter-productive. A function
that could be called from anywhere in a million-line program, on the
other hand, needs a very good and clear name - though that is almost
certainly best done via appropriate uses of namespaces (or other
structured naming) rather than a long identifier. (C++ is not C.)
Compare:
int calculate_average_of_vector_of_ints(std::vector<int>
vector_of_ints_to_average)
{
int sum_so_far = 0;
for (this_int : vector_of_ints_to_average) {
sum_so_far += this_int;
}
int the_size_of_the_vector_of_ints_to_average =
vector_of_ints_to_average.size();
int return_value = sum_so_far /
the_size_of_the_vector_of_ints_to_average;
return return_value;
}
with :
int average(std::vector<int> xs) {
{
int sum = 0;
for (x : xs) {
sum += x;
}
return sum / xs.size();
}
Are you seriously suggesting that the first version is "clearer" or
easier to understand, because it has long, explicit names?
If I see someone use a variable called "returnValue" in something
presented for code review, I'd reject it. It's a name that means
nothing (what information does it give you in "return returnValue;" ?)
The only conceivable reason to have it is that the function is so long
the it is unclear what it is returning - and /that/ is the problem to fix.
The same goes for "errorCode". If it is not clear from the code that
"err" is an error code, /that/ is the problem - not the name of the
variable.
If we are talking about functions accessible from far off in the code,
then longer names are needed. But not local names.
>
> If 'std::map<std::string, std::string>' makes the code easier to understand
> than 'auto', then write the former. There's no need to save disk space.
> Shorter is not always better.
I fully agree - no one has argued any differently.
What people (generalising wildly from myself) are reacting against is
your idea that shorter /cannot/ be better, or that longer is /always/
better.
When used correctly, shorter most certainly can be better precisely
because it is clearer and easier to understand - and it is clearer and
easier to understand precisely because it is better.
That only applies when it is clear what the identifier means, of course.
And that will vary enormously according to the rest of the code.
>
>>> Length does not matter. Clarity does.
>>
>> If you think clarity increases with length, you haven't read enough
>> code. Tens of thousands of lines is not a lot.
>
> I have read enough code to know that brevity does not increase clarity,
> but the opposite.
>
>> Let's take a different case. If I want an integer to store numbers in
>> the range of 15 decimal digits, I'll write :
>>
>> int64_t x;
>>
>> I won't write :
>>
>> signed long long int x;
>>
>> even though the later is more portable, more explicit, and avoids an
>> unnecessary non-portable requirement of the implementation having a type
>> of exactly 64 bits.
>
> You are now trying to argue from redundancy. 'signed' and 'int' are
> redundant there. They don't add information. There's no need to say the
> same thing multiple times.
You are being inconsistent. Writing "signed" makes it clear and
explicit that we are dealing with signed types - no one has to read
"int" or "int64_t" and remember that by default integers are signed in
C++. Or are you happy that /sometimes/ it's okay to write short code
whose meaning is clear to everyone reading it, and you don't have to
write out /everything/ in the longest, most explicit manner?
I think it turns out that you too understand that "a happy medium" is
the ideal - not too long, not too short, not too explicit, not too
implicit. You might have a personal preference towards slightly longer
than the preferences of the "average" programmer, but that's detail
rather than principle.
>
> Also, those two lines are not equivalent. It's not *merely* about naming
> conventions in this example. There's a functional difference.
>
There is - and I know the difference, and stated it. But I actively
choose the version that is marginally subpar in the technicalities of
what the code means, precisely because the "int64_t" version is clearer
and easier to understand, primarily because it is shorter.
>>> Keep your code smart, not stupid.
>>
>> KISS means "Keep it simple, stupid" - not "Keep it stupid".
>
> I suppose you choose to insult your readers then, rather than the second S
> referring to the code itself.
>
"KISS" is a well-known acronym and guiding principle throughout
engineering (not just programming). The "stupid" is not an insult as
such, and is targeted at the developer not the reader - it means it is a
stupid idea to make things more complicated than necessary.
If you prefer Einstein's version, "make things as simple as possible,
but no simpler".
> Either way, I'd rather code be readable and understandable than simple.
I'd rather it be /both/ - because they are strongly correlated. Simple
code is easier to read and understand.