Structured Programming
Assembly language has a famously problematic feature called goto, where control can be transferred from any point in the program to any other point in the program. This makes software fabulously hard to maintain. It's tricky to debug a piece of code, or figure out what it's going to do, if you can't figure out what the state of the computer is when the code starts up. That state depends on where the computer was just prior to entering that code. With goto, that could be any place in the program at all. Computer language designers wanted a way to limit the ways that code could be run.
They found that most gotos were used in particular ways. Sometimes they're used in a loop: Do a set of instructions, and then do them again. Sometimes they're used to do one of two options, or as a contingent loop (do all of the code in the loop until some bit becomes zero). This is an early instance of discovering a design pattern. More importantly, they managed to prove that you could do everything using only these few structures: the generic goto wasn't needed at all.
So they invented structured programming. C is an example of a structured programming language, although it wasn't the first. The basic unit (granularity) of a C program is an expression or statement, each of which translates into a series of assembly language instructions. Like assembly language instructions, statements also have contracts. For example, the contract of
while(expression) { statement1 statement2 ... }
is to evaluate the expression, and then do statements 1 and 2 (and so on), and repeat that as long as the expression is true. This is a contract in the sense that the computer will always do this. All the statements will be done, in the same order, every single time, always (and only) until the expression becomes false.
Removing goto from the programming language and replacing it with structures like for, while, and if is called structured programming. The for, while, and if structures represent the next level of abstraction up from assembly programming.
Notice that the contract here is a lot more complicated than the contract of the LD assembly language mnemonic. The higher the level of abstraction, the more complex the contracts are. This allows you to say a lot with a little bit of programming. Substituting multi-letter mnemonics for single-byte instructions may have been the only time in programming history when abstractions made the program lengthier than the resulting object code. Even that's a bit misleading; LD (BC),A has only as many letters as 00000010 has bits.
An important feature of the while loop is that you can't jump into the middle of it: You enter it only at the top. That makes it easy to figure out what's going on in the program leading up to the while loop. If you want to figure out what the loop does, you only have to look at the code leading up to it.
There are those who say that, in addition to entering the loop only at the top, you should exit it only at the bottom, as with a break or continue statement. That would certainly make life easier on the maintenance programmer, since it would mean that the next statement after the while loop would always be executed after the while loop, and only when the expression became false. You wouldn't have to worry about return statements in the middle of the loop preventing the statement from being executed. You'd also be sure that the expression was false, since that would be the only way out of the loop.
There are others who say you should just be grateful that the "spaghetti" structure of the loops has been eliminated by the introduction of structured programming, and that continue, break, and early return statements often simplify the code. Personally, I try to avoid jumping out of loops as often as I can, but I'm not willing to make the code completely unclear just to avoid them. Your style will be your own, but I've found that very often, effort saved is often spent later when I go back to extend the code.