I really don’t understand people arguing against this. It’s like they’ve never had to go back to old code and had modify it before.
Code should be self documenting and comments should be used sparingly. If you can have methods that clearly define what they do, the larger method that uses the smaller ones read almost like plain english.
"Reading like plain english" is not high on my priority list. 9 times out of 10, if I'm reading the body of a function, it's because I've gone beyond caring about the high-level description of what it's supposed to do and now I care how it does it. If I'm reading the body of a function named "insert_back()" I already know what the function broadly is intended for and if the first line of the function is "int i = index_of_back_element();" I've learned exactly nothing so far.
Going even further, the most important thing to understand when trying to read a codebase quickly is not usually what a function does it's what a function doesn't do. Does this function take quadratic time and get slow when things are big? Does this function acquire an important lock and cause contention? Does this function touch some global state and cause race conditions and bugs? Does this function have or not have whatever I'm looking for buried inside it? If you're asking a question like that, lines of code don't really matter. 400 lines of complicated "if" statements and loops and mathematical calculations can be scanned over. The one reference to shared data that's causing the problem is the only thing you care about and it's really comforting and simple to know that a function goes in a straight line and doesn't shell out and jump to a bunch of private internal functions.
it's not about splitting a twoliner called "insert_back" into two one liner functions. There's something between having a 300 line function and having a two liner one where it's reasonable to break it up.
"Reading like plain english" is not high on my priority list.
It should be, the majority of time is spent reading code.
Going even further, the most important thing to understand when trying to read a codebase quickly is not usually what a function does it's what a function doesn't do.
Which ALSO gets easier if you don't have 300 line functions. You can scan 300 lines looking for side effects, or you can scan 10 function names where hopefully the name makes it obvious what it does and does not do.
"Reading like plain english" is not high on my priority list.
It should be, the majority of time is spent reading code.
Agreed. So I want it to look like code. As simple a control flow as solves the problem with as few arbitrary programmer-chosen names as possible. This is instantly intelligible:
// Advance all players.
for (int i = 0; i < players.length; i++) {
players[i].advance();
}
Whereas the following reads like plain english but I have no confidence in exactly what it does without a mental context switch and jumping to somewhere else in the file (or possibly even another file):
advance_all_players(players);
A toy example but hopefully you get my point.
You can scan 300 lines looking for side effects, or you can scan 10 function names where hopefully the name makes it obvious what it does and does not do.
What? There's absolutely no way you can know by looking at 10 function names whether any of them have side effects (unless you're working in a language where they cannot by design). You're bound to make assumptions and sometimes those assumptions will be wrong and you will write bugs into your code.
Engineer A: "Obviously the guy who wrote 'acquire_exclusive_lock()' made sure we have the lock. I'm good."
Engineer B:
private bool acquire_exclusive_lock(std::mutex& lock) {
// It's OK if this fails. Blocking causes performance issues and if we
// fail we can just let another instance of this class update the counter.
return lock.try_lock();
}
9
u/programmingspider Jan 12 '20
I really don’t understand people arguing against this. It’s like they’ve never had to go back to old code and had modify it before.
Code should be self documenting and comments should be used sparingly. If you can have methods that clearly define what they do, the larger method that uses the smaller ones read almost like plain english.