Advertisement

How many of you write self-documenting code?

Started by July 09, 2015 12:54 PM
63 comments, last by SimonForsman 9 years, 3 months ago


Because this is premature optimisation leading to bad code

Bad code? Quite overwhelming statement about less compressed "readable" code, while it is not true either, becouse a local variable of native type like int -is more understandable when used than a some-function invoking. One is supposed to navigate to the invoked strangness all-over the place instead of being stacked int, to find out wheather it is intentional or "throw me optimize, readibility altar" case

Yes the whole of the snippet is bad code in my book, if i see code and i don't immediately understand what it does, it's bad code in my book, and the author of the code himself says he can't so yes, that's bad and one of the reason is micro optimisations. Good code reads like you read English, because when writing good code it will actually pretty closely ressemble the way you'd state the logic of it in English, if it's a mess instead then as i said, it doesn't need to get commented but rewritten.

What does the variable type have to do with the code being understandable? You don't need to navigate to anything, the intent is clear. You see a container, it's getting Size called, if you need to navigate to the definition of size to figure out what it is, then you're a begginer in that language, and that is fixed by you learning the language, not by other people writing code specifically for your own shortcomings.

Good code doesn't need to be clear "to anyone", it just needs to immediately be clear to anyone proficient in the language and APIs you're using.

The compiler would actually be forbidden from optimizing it in many cases, as C functions are not guaranteed to be pure. Only if the function is visible and can be inlined and it can be proven there is no aliasing there is a reasonable chance for it to be optimized.

Exactly. While this is Java, I prefer to be explicit with my intentions instead of hoping the JIT will do The Right Thing™. I got enough indirection as it is, and this tiny bit of code is literally the step before issuing all the draw calls. It shouldn't waste time.

Why do you have a local variable named queue (and nothing else), hungarian notation is bad, yet it gives you the type and intent, the type is too much but here you have "only" the type, and you even have the wrong one as it's an array and not a queue, i can't think of any worse variable name.

Whoa man, relax for a bit. "Queue" isn't the type. As you see its a plain array, so the name tells you how it should be treated, processed from 0 to (size-1), like a queue. That's why named it queue instead of, say, bananas. I'll give you that, 'tasks' can be a better name. That bit is a leftover from the previous iteration on the drawing method, they were "RenderInstances" instead of RenderTasks and "instances" sounded silly (like calling an object 'object').

The issue in that piece of code aren't the variable names. They're literally defined 5 lines above, you can't miss them. They follow a very simple pattern, array declaration then size declaration, repeat for everything that will be iterated on. Then there is 'mbs' just so the VM doesn't dares to fetch the value from main memory again. They're all single purpose, limited only to that method.

Problem here is the horrible nested loop logic that depends on like 4 different conditions. That's why the rest of the variables have more complete names (maxInstance, lastItem, completedLastTask, etc) and why you have comments in that section, because that is the complex part, not the damn for-loop declaration. There are no variable naming scheme in the world that will save you from trying to debug that mess.

If you want to bike-shed the variable names that's fine but its definitively not the time I end up spending on when I try to understand these kind of things. Specially if all the variables being used are orderly declared at the beginning of the method, as I said, very hard to miss. Its an idiom that some languages even support directly by disallowing variable declarations in the middle of the block.

the rest of the code is also pretty bad as it seems you're trying to use the arrays as queues, why aren't you simply actually using a queue then instead of all the cryptic special case looping code?

Bag is a list with a simple array as backing storage. The reason behind using the backing arrays directly is that they're easier to "understand" by the JIT, there are no class hierarchies to check nor methods to try to inline, just direct array access.

Since Bag can be used like anything, "queue" communicates how it should be treated. Why I don't use a Queue class or something? Because I already got Bag, and it works. Bag is made to be used as you see fit. In this case its essentially used simply to dynamically resize the backing array as needed, since all I use is the bag.add(item) and bag.clear() methods.

Why I don't use standard Java collections? Because they don't allow you to grab the backing array for fast iteration, and they don't contain "unsafe" methods that don't do internal size checks, unlike Bag.

Cryptic "special case looping" has nothing to do with queue and all to do with all the things its tracking. Current task, current instance of the task, tasks left, instances left from the previous task, current index to start from in the draw call, etc. Everything has to be accounted for or you end up without nice efficient batching. Its shit, but its doing good and important stuff well.

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

Advertisement

Is that guaranteed to be optimized by the compiler…

Any modern, optimizing compiler will replace repeated calls to a function whose return value remains constant over the loop span into a cached value lookup, yes.

…but more importantly is that style actually safe to use in a modern multi-threaded environment?

Depends: is modifying the sequence object thread safe? Have we generally established concurrent execution paths that might simultaneously modify the sequence object?

Concurrency imposes additional constraints on code design, particularly in a language without a native threading model, and thus should not be considered an intrinsic when authoring readable code, IMO. Very often you have to sacrifice some readability in the pursuit of thread safety.

Yes the whole of the snippet is bad code in my book, if i see code and i don't immediately understand what it does, it's bad code in my book

Oh- code roman cannot understand-burn it!

If you aproach and criticize machine code EDIT[from this particular point of fact], wheather a library performant or a educational tutorial..... you are so screwed sad.png((


Yes the whole of the snippet is bad code in my book, if i see code and i don't immediately understand what it does, it's bad code in my book

Oh- code roman cannot understand-burn it!

If you aproach and criticize machine code EDIT[from this particular point of fact], wheather a library performant or a educational tutorial..... you are so screwed sad.png((

I maintain what i said, i can understand it just fine, it just actually takes effort to read through,; good code should read like you'd explain it in English.

The compiler would actually be forbidden from optimizing it in many cases, as C functions are not guaranteed to be pure. Only if the function is visible and can be inlined and it can be proven there is no aliasing there is a reasonable chance for it to be optimized.

Quite a few C and C++ compilers these days have extensions that let you explicitly mark functions as pure,, with gcc you can for example use __attribute__ ((pure))

[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!

This topic is closed to new replies.

Advertisement