Let's consider a standard situation.
You completed a code, and you are ready to debug it.
And now you are reviewing each line of your code.
Suppose that you see this line,
p is set to q by 60 plus r. Any ideas what is meant here?
Perhaps you guessed that the code computes
time in minutes from midnight to the current time.
Q stores the current hour,
r stores the current minute,
and p stores the total time in minutes.
Note, that even in this case,
it is not so obvious.
Even if you guessed right,
maybe you've spent some time on it.
There could be surrounding lines that could help you to understand this code.
For example, you could look at input output formats,
and somehow realize the purpose of these variables.
But the point is that if these variables were given suitable names right away,
you would understand the meaning of this line faster.
Giving meaningful names to variables will not
only help your teammates to understand your codes,
it will also help you to understand it.
Have you ever found yourself in a situation that it is difficult
to get the main idea of your own code that your wrote,
say a year ago?
If yes, they probably know already that it
makes perfect sense to keep your code understandable.
At the same time, don't take it too seriously.
Of course, in some small tasks like short local loops,
single letter variables are more convenient.
A few words about code style.
Even if you don't work in team,
following some reasonable rules during coding also makes your code more clear.
That's why it's recommended to use indent,
spaces, and so on.
Consider the problem of computing the sum of
all integers closed cubes alpha one to 5,000.
The upper bound is not exclusive.
It is possible to find a formula that gives that answer,
but it is absolutely normal to write a simple loop for this task.
But what loop type to use?
There are basically two types of loops: loop with a pre-condition,
and a loop with a post-condition and there is a big difference between them.
Consider two examples.
Here we see an example of loop with a pre-condition.
The pre-condition here is i cubed is less than 5,000,
and it defines what must be true before anything in the loop.
In particular, if the condition is not satisfied from the very beginning,
the loop will not execute at all.
Here is an example of loop with a post-condition.
The post-condition here is also i cubed is less than 5,000,
and it says what must be true before continuing the loop.
It means that this loop always performs at least one iteration
because it just doesn't check the condition before the execution of the first iteration.
Both types of loops work fine,
but what if we change 5,000 to one?
There are no integers that are at most one and less than one simultaneously.
That's why the correct answer is zero.
And it is easy to see that a conditional loop remains correct.
But we can no longer use both conditions
here because a loop will perform the first iteration,
and it wants total sum.
We failed in the second case because loop invariant wasn't preserved.
Loop invariant is an assertion that must be true every time within a loop.
It is associated with a specific position in the loop.
In our task, we can come up with two examples of invariants.
First, i cubed is not greater than the one,
and is integer less than 5,000.
Second, sum equals sum of all i's seen so far.
Think which invariants are preserved in each case if we change 5,000 to one.
In the first version of task with upper bound of 5,000,
both types of loops preserve these invariants.
But when change 5,000 to one,
in the post-conditional loop first invariant fails.
Doing in the first iteration i equals one,
so i cubed is no less than the one because of
this sum is calculated incorrectly though the second invariant is preserved.
These situation tells us that we should be very careful with invariants.
Sometimes conditions in loops are more complicated than i cubed is less than 5,000,
and you need to be precise to write a loop correctly.
In other words, you should always convince
yourself that the code of your loop matches your logic.
Also be careful with common cases with empty sets.
For example, let's remember that task about the list of people.
If there are zero people in the list,
sum of age of all people is defined and equals zero.
So, we should also consider this case.
By the way our solution still works.
To summarize this lesson,
we can consider several ways to make our codes
more structured, understandable,and debuggable.
On several examples we've seen that this is a really
important and shortens the time of getting a written code.