In imperative programming, writing a computer program means to define a sequence of steps that need to be taken to achieve a goal. In that sequence, states are defined together with state transitions — how to get from A to B, what A and B are precisely, and when getting from A to B is even an option. That’s what people mean when they say imperative programming is all about state.
Theoretically, a sequential program could be written line by line, the execution running from top to bottom and ending there. In reality, of course, even on the CPU level there are tools to make programming a bit more efficient, and programming languages have functions and methods and other blocks that can be used to add levels of abstraction. The basic function of such blocks in imperative programming is to remove code duplication and to break code into functional blocks that are easy to manage. One of the major issues in imperative programming has always been that code blocks tend to grow larger over time, and this is still apparent in many code bases.
Because of the focus on execution sequence, functions and methods in imperative programming tend to be referentially opaque. This means that even if they are called with the same (or no) input parameters, they are not guaranteed to return the same result every time. Implementations of the functions often use variables in a larger scope (class level fields for instance), which is generally referred to as global state. Just like ...