TutorChase logo
Login
AQA A-Level Computer Science

1.1.2 Programming constructs and control flow

Understanding programming constructs and control flow is essential for developing logical, efficient, and maintainable software. This section explores key components such as variables, constants, assignments, control flow through selection and iteration, and best practices in naming identifiers. These concepts serve as the building blocks of any algorithm or software system.

Variables and constant declarations

Variables

A variable is a symbolic name for a memory location in a computer that holds data which can change during the execution of a program. Variables are used to store, retrieve, and manipulate data. Each variable typically includes three essential components:

  • Name: A descriptive identifier used to reference the data.

  • Type: The classification of the data it holds, such as integer, Boolean, string, float, etc.

  • Value: The actual content stored at that point in time.

The value of a variable can be reassigned multiple times throughout a program. However, some programming languages may impose constraints on reassignment in certain contexts, such as immutability in functional programming or the use of final in Java to prevent modification.

Python example:

python

age = 17

Java example:

java

int age = 17;

Some languages support implicit typing, like Python, where the type is inferred from the assigned value. Others, like Java or C++, use explicit typing, where the type must be declared.

Well-named variables improve code readability and make it easier to debug and maintain. They should always represent the data they hold accurately and reflect the variable’s purpose.

Constants

Constants represent values that should not change during the execution of a program. Once a constant is assigned, it remains fixed. Constants are typically used for:

  • Mathematical constants (e.g., pi)

  • Configuration values

  • Thresholds and limits

Using constants increases the clarity and maintainability of the code, and they help safeguard against accidental modifications.

Python example (by convention):

python

PI = 3.14159

Java example:

java

final double PI = 3.14159;

Advantages of constants:

  • Clarity: Seeing PI is clearer and more meaningful than seeing 3.14159 throughout the code.

  • Maintainability: If a constant's value ever needs to change, it only has to be updated in one place.

  • Safety: Prevents unintentional updates to values that should remain fixed.

Constants are integral to robust programming and should be used whenever a value is intended to stay the same across the lifetime of a program.

Assignment

The assignment operator

Assignment is the act of storing a value in a variable. Most programming languages use the = symbol to denote assignment. It is important to understand that assignment is not the same as comparison, which typically uses ==.

The general syntax of an assignment is:

plaintext

variable = expression

The expression on the right-hand side is evaluated first, and the resulting value is stored in the variable on the left-hand side.

Examples:

python

counter = 10
counter = counter + 1  # counter now holds 11

Many languages provide compound assignment operators as shortcuts for performing an operation and assignment in one step:

  • counter += 5 (adds 5 to the current value of counter)

  • counter -= 3 (subtracts 3 from the current value)

  • counter *= 2 (multiplies the current value by 2)

  • counter /= 4 (divides the current value by 4)

Beginners often confuse = (assignment) with == (equality check). This misunderstanding can lead to logical errors and should be corrected early in programming practice.

Control flow: selection

If statements

Control flow structures like selection allow a program to make decisions. The most basic selection structure is the if statement. It evaluates a condition and executes a block of code only if the condition is true.

Python example:

python

if temperature > 30:
    print("It's hot outside.")

If-else statements

The if-else construct allows for two alternative paths: one if the condition is true, and another if it is false.

python

if temperature > 30:
    print("It's hot.")
else:
    print("It's not hot.")

Elif / else if

In cases where multiple conditions need to be checked, elif (Python) or else if (Java, C++) can be used.

python

if temperature > 30:
    print("Hot")
elif temperature > 20:
    print("Warm")
else:
    print("Cold")

This structure allows a chain of conditions to be evaluated in order.

Switch/case statements

Some programming languages, such as Java and C++, offer a switch statement. This is often used when checking a variable against a list of possible values. It can be more efficient and readable than a series of if-else statements.

Java example:

java

switch(day) {
    case 1: System.out.println("Monday"); break;
    case 2: System.out.println("Tuesday"); break;
    default: System.out.println("Invalid day");
}

Benefits of switch statements:

  • Clear structure for many discrete options

  • Often more efficient at runtime

  • Reduces complexity compared to deeply nested if-else statements

Control flow: iteration

Definite iteration

Definite iteration, or count-controlled loops, are used when the number of repetitions is known ahead of time. These are ideal for situations like processing items in a list or performing a task a set number of times.

Python example:

python

for i in range(5):
    print(i)

Java example:

java

for(int i = 0; i < 5; i++) {
    System.out.println(i);
}

These loops automatically update the loop variable and stop after the specified number of iterations.

Indefinite iteration

Indefinite iteration, or condition-controlled loops, are used when the number of repetitions is not known in advance. The loop continues until a condition becomes false.

Python example:

python

while user_input != "exit":
    user_input = input("Enter a command: ")

These loops are useful for user input, real-time processing, or waiting for a particular condition to be met.

Pre-condition vs. post-condition loops

  • Pre-condition loops check the condition before executing the body. If the condition is false at the start, the loop body may never run.

  • Post-condition loops execute the loop body at least once before checking the condition.

Java example of a post-condition loop:

java

do {
    System.out.println("Enter a number:");
    num = scanner.nextInt();
} while(num != 0);

This loop is guaranteed to run at least once, which is useful when a user must perform an action before evaluation, such as entering input.

Combining principles: sequence, selection, iteration

Every program is structured using three basic programming constructs:

Sequence

This is the default flow of control where instructions are executed one after another in the order in which they appear.

Example:

python

print("Welcome")
name = input("Enter your name: ")
print("Hello", name)

Each line is executed sequentially from top to bottom.

Selection

Selection introduces branching in the program. It allows the program to make decisions and follow different paths based on conditions.

Includes:

  • if, if-else, elif

  • switch statements

Iteration

Iteration allows a section of code to run repeatedly based on a condition or count.

Includes:

  • for loops

  • while loops

  • do-while loops

By combining sequence, selection, and iteration, any complex algorithm or logic can be implemented effectively.

Nested selection and iteration

Nested selection

When decision-making needs to consider multiple levels or criteria, if or if-else statements can be nested within each other.

Example:

python

if grade >= 60:
    if grade >= 90:
        print("Distinction")
    else:
        print("Pass")
else:
    print("Fail")

This nested structure is useful for scenarios where one decision depends on the result of another.

Nested iteration

A loop inside another loop is known as a nested loop. This is especially helpful when working with two-dimensional data structures like matrices or grids.

Example:

python

for row in range(3):
    for col in range(3):
        print(f"Cell at {row}, {col}")

Nested loops allow for operations such as printing tables, processing image pixels, or navigating through grids.

When to use nested structures

Use nested selection or iteration when:

  • Decisions rely on multiple criteria

  • Working with multi-dimensional data like 2D arrays or nested lists

  • Handling complex workflows like menu systems or form validation

However, deep nesting can make code hard to read and maintain. If you find yourself nesting more than 2–3 levels deep, consider refactoring your code into functions or subroutines.

Meaningful identifier names

What are identifiers?

Identifiers are names used to label variables, functions, classes, methods, and other elements in a program. A good identifier conveys its purpose clearly and concisely.

Examples of poor identifiers:

  • x

  • temp

  • data1

Examples of good identifiers:

  • user_score

  • total_price

  • is_valid_input

Importance of meaningful names

  • Improves readability: Code is easier to understand and follow.

  • Reduces errors: Clear names help avoid using variables incorrectly.

  • Aids debugging: Makes it easier to trace logic and find bugs.

  • Supports collaboration: Other programmers can understand your code more easily.

Best practices

  • Use camelCase for Java, JavaScript, and other C-style languages.

  • Use snake_case for Python and some other scripting languages.

  • Use verbs for functions or methods (e.g., calculateTotal, getInput).

  • Use nouns for variables (e.g., total, priceList).

  • Prefix Boolean variables with is, has, or can (e.g., isLoggedIn, hasPassed, canVote).

  • Avoid non-standard abbreviations (e.g., usrSc instead of user_score).

  • Be consistent in style and naming conventions across the codebase.

Good identifiers serve as implicit documentation. They reduce the need for excessive comments and make the program easier to maintain and scale over time.

FAQ

Indentation is crucial in control structures because it defines the structure and scope of blocks of code, making the flow of logic clearer and preventing errors. In Python, indentation is syntactically enforced—incorrect indentation will raise an error and prevent the program from running. Each indented block must be consistently aligned under its control statement, such as if, for, or while. For instance, all statements under an if condition must be indented equally to indicate they belong to the same block. In contrast, languages like Java or C++ use braces {} to explicitly mark code blocks, and indentation is not required for execution, but is still considered best practice for readability. Poor indentation can lead to misunderstood logic, especially in complex nested structures. Therefore, maintaining consistent indentation—using either spaces or tabs, but not both—is essential for producing reliable, readable, and maintainable code across all programming languages, regardless of whether the syntax enforces it.

Short-circuit evaluation impacts control flow by potentially bypassing the evaluation of certain conditions in logical expressions. In if statements that use logical operators such as and or or, short-circuiting means the second condition is only evaluated if necessary. For example, in an expression like if user_logged_in and user_has_permission, if user_logged_in is false, the second condition is never checked because the overall result cannot possibly be true. This not only improves performance by avoiding unnecessary checks but also prevents errors when the second condition relies on the first. For instance, if user and user.is_active avoids an error if user is None, because user.is_active is only evaluated if user is truthy. In selection structures, this means the control flow can skip sections of code or conditions based on earlier evaluations. Understanding this behaviour is essential for writing safe and efficient compound conditionals, especially in languages like Python, Java, and JavaScript.

Using global variables can disrupt the predictability and integrity of sequence and control flow in a program. Global variables are accessible from any part of the code, which means they can be modified by any function or block, often without clear visibility. This breaks the principle of encapsulation and can lead to unintended side effects where one part of the program changes a global variable, affecting other parts unpredictably. In control structures like loops and conditional statements, global variables may introduce bugs if their values are changed elsewhere, making the flow of logic harder to trace. For example, if a loop condition depends on a global variable that is altered in another function, the loop may terminate unexpectedly or run indefinitely. Additionally, global variables hinder reusability and testing because functions relying on them are tightly coupled to external state. Limiting their use and preferring local variables or passing arguments helps maintain modular, predictable, and manageable code.

A do-while loop is preferable when the block of code must execute at least once regardless of the condition, which is especially useful in user interaction scenarios such as input validation or menu-driven programs. Unlike a while loop, which checks the condition before executing, a do-while loop checks the condition after running the loop body. For example, in a menu system where a user is prompted to choose an option, the menu should be displayed at least once even if the exit condition is already met. Similarly, if asking the user to enter a password or confirm an action, the prompt should appear initially before checking the input. This ensures the program behaves intuitively and avoids skipping essential steps in the user experience. Using a do-while loop in these situations improves program logic, ensures consistent interaction, and reduces code duplication by avoiding the need to duplicate prompts outside the loop.

Nested control structures, while sometimes necessary, can negatively impact both performance and readability if overused or poorly managed in large programs. Deep nesting of if, else, or loop blocks can make the code difficult to follow, increasing cognitive load for developers trying to understand or maintain it. It also raises the risk of logic errors, such as missing else clauses or incorrectly scoped variables. Performance-wise, heavy nesting can lead to inefficient execution, especially if nested loops perform repetitive or redundant tasks over large data sets. Each additional layer of nesting adds complexity to the control flow, potentially increasing the time complexity of the program. For example, nested loops used to process a 2D array have a time complexity of O(n²), which becomes problematic for large data sizes. Best practices include reducing nesting through guard clauses, modularising code into functions, and using clear, flat structures when possible. This improves maintainability, testability, and efficiency.

Practice Questions

Explain how the use of meaningful identifier names and constants contributes to the readability and maintainability of code.

The use of meaningful identifier names significantly enhances code readability by clearly indicating the purpose of each variable, function, or constant. For example, total_price is far more understandable than tp. This helps both the original developer and others to comprehend and debug the code efficiently. Constants improve maintainability by ensuring fixed values like PI are only defined once, avoiding repetition and minimising errors during updates. If a constant value changes, only one line needs to be modified. Together, these practices make code more understandable, reduce development time, and support collaborative or long-term software projects.

Describe the difference between definite and indefinite iteration, and give a suitable example of when each would be used.

Definite iteration refers to loops that execute a predetermined number of times, such as a for loop that prints numbers 1 to 10. This is useful when the number of repetitions is known in advance, like printing each item in a list. Indefinite iteration uses a condition to determine when to stop, such as a while loop waiting for correct user input. This is more appropriate when the number of repetitions is unpredictable. For example, prompting a user to enter a password repeatedly until it matches the correct one would require indefinite iteration due to the unknown number of attempts.

Hire a tutor

Please fill out the form and we'll find a tutor for you.

1/2
Your details
Alternatively contact us via
WhatsApp, Phone Call, or Email