Principles of Programming

AS Level — Unit 1: Fundamentals of Computer Science

Programming Paradigms

A programming paradigm is a fundamental style or approach to programming that defines how we structure and organise code to solve problems.

There are several major paradigms, and many modern languages support more than one (these are called multi-paradigm languages). The WJEC AS specification requires knowledge of four paradigms: procedural, event-driven, visual and mark-up languages.

Procedural Programming

Procedural programming organises code as a sequence of instructions (statements) that are executed in order. The program is broken down into procedures (also called subroutines, functions, or methods) that perform specific tasks.

Key features:

  • Programs follow a top-down design – the problem is broken into smaller sub-problems, each solved by a procedure.
  • Data and procedures are separate – data is passed to procedures via parameters or accessed through global variables.
  • Uses sequence, selection (if/else), and iteration (loops) as control structures.
  • Variables have defined scope (local or global).
# Procedural example: calculating average of a list
def calculate_total(numbers):
    total = 0
    for num in numbers:
        total += num
    return total

def calculate_average(numbers):
    total = calculate_total(numbers)
    return total / len(numbers)

marks = [72, 85, 64, 91, 78]
avg = calculate_average(marks)
print(f"Average: {avg}")
' Procedural example: calculating average of a list
Function CalculateTotal(numbers() As Double) As Double
    Dim total As Double = 0
    For Each num As Double In numbers
        total += num
    Next
    Return total
End Function

Function CalculateAverage(numbers() As Double) As Double
    Dim total As Double = CalculateTotal(numbers)
    Return total / numbers.Length
End Function

Dim marks() As Double = {72, 85, 64, 91, 78}
Dim avg As Double = CalculateAverage(marks)
Console.WriteLine("Average: " & avg)

Examples of procedural languages: C, Pascal, BASIC, COBOL.

Event-Driven Programming

In event-driven programming, the flow of the program is determined by events — user actions or system-generated signals — rather than a fixed sequential order. The program waits for events to occur and responds to them by running the appropriate event handler (a subroutine triggered by a specific event).

Key features:

  • The program runs an event loop that continuously listens for events.
  • Code is organised into event handlers attached to specific controls or triggers.
  • The order of execution depends on what the user does, not on the programmer’s predetermined sequence.
  • Well suited to graphical user interfaces (GUIs) where user interaction drives the program.
# Event-driven example using tkinter (Python GUI library)
import tkinter as tk

def on_button_click():
    label.config(text="Button was clicked!")

def on_key_press(event):
    label.config(text=f"Key pressed: {event.char}")

window = tk.Tk()
window.title("Event-Driven Example")

button = tk.Button(window, text="Click Me", command=on_button_click)
button.pack()

label = tk.Label(window, text="Waiting for event...")
label.pack()

window.bind("<Key>", on_key_press)
window.mainloop()  # Event loop — waits for events

Examples: Visual Basic .NET (Windows Forms), JavaScript (web browsers), Python tkinter.

Visual Programming

Visual programming environments allow programmers to create programs by manipulating graphical elements (blocks, icons, flowchart symbols) rather than writing text-based code. The visual representation directly reflects the program’s structure.

Key features:

  • Programs are built by dragging and connecting visual blocks or components.
  • Reduces the risk of syntax errors since the environment enforces valid connections.
  • Makes programming more accessible to beginners and non-programmers.
  • Particularly useful for education, simple automation, and rapid prototyping.

Examples: Scratch (block-based, education), MIT App Inventor (mobile apps), LabVIEW (scientific instrumentation), Blockly (Google’s visual programming library).

Mark-Up Languages

A mark-up language uses tags embedded in text to define the structure, formatting, or meaning of content. It is not a programming language in the traditional sense — it does not contain logic, loops, or variables — but it instructs how content should be displayed or structured.

Key features:

  • Tags surround content to describe what it is (e.g. <h1> for a top-level heading).
  • The tags themselves are not displayed — they are interpreted by a browser or processor.
  • Separates content from presentation.
  • Used for web pages, document formatting, and data exchange.
<!-- HTML — HyperText Markup Language -->
<!DOCTYPE html>
<html>
  <head>
    <title>My Page</title>
  </head>
  <body>
    <h1>Welcome</h1>
    <p>This is a <strong>paragraph</strong> with bold text.</p>
    <ul>
      <li>Item one</li>
      <li>Item two</li>
    </ul>
  </body>
</html>

Examples: HTML (web pages), XML (data exchange), Markdown (documentation), CSS (styling — technically a style sheet language but works with mark-up).

Paradigm Comparison Table

Feature Procedural Event-Driven Visual Mark-Up
Core idea Sequence of instructions Respond to events Graphical blocks Tags describe content
Control flow Top-down, sequential Determined by events Visual connections N/A (not executable logic)
Typical use General computation GUIs, user interaction Education, rapid dev Web pages, data
Examples C, Pascal, BASIC VB.NET, JavaScript Scratch, App Inventor HTML, XML

For the exam, be able to describe each paradigm, identify examples of each, and explain the differences between them. A key distinction: procedural programs follow a fixed sequence; event-driven programs respond to unpredictable user actions. Visual languages use graphical blocks instead of text. Mark-up languages describe structure, not logic.


Object-Oriented Programming: Objects, Classes and Methods

Classes and Objects

A class is a blueprint or template that defines the attributes (data) and methods (behaviour) that objects of that type will have. An object is a specific instance of a class, with its own set of attribute values.

Think of a class as a cookie cutter and objects as the individual cookies made from it. The class defines the shape; each object is a distinct cookie.

class Dog:
    def __init__(self, name, breed, age):
        self.name = name        # Attribute
        self.breed = breed      # Attribute
        self.age = age          # Attribute

    def bark(self):             # Method
        return f"{self.name} says Woof!"

    def get_info(self):         # Method
        return f"{self.name} is a {self.age}-year-old {self.breed}"

# Creating objects (instances)
dog1 = Dog("Rex", "German Shepherd", 5)
dog2 = Dog("Bella", "Labrador", 3)

print(dog1.bark())       # Output: Rex says Woof!
print(dog2.get_info())   # Output: Bella is a 3-year-old Labrador
Class Dog
    Public Property Name As String
    Public Property Breed As String
    Public Property Age As Integer

    Sub New(name As String, breed As String, age As Integer)
        Me.Name = name
        Me.Breed = breed
        Me.Age = age
    End Sub

    Function Bark() As String
        Return Name & " says Woof!"
    End Function

    Function GetInfo() As String
        Return Name & " is a " & Age & "-year-old " & Breed
    End Function
End Class

Dim dog1 As New Dog("Rex", "German Shepherd", 5)
Dim dog2 As New Dog("Bella", "Labrador", 3)

Console.WriteLine(dog1.Bark())       ' Output: Rex says Woof!
Console.WriteLine(dog2.GetInfo())    ' Output: Bella is a 3-year-old Labrador

Summary of OOP Concepts

Concept Description Benefit
Class Blueprint for creating objects Defines structure and behaviour
Object An instance of a class Represents a specific entity
Method A subroutine defined inside a class Describes what objects of that class can do
Attribute A data item held by an object Holds the state of that particular object

The spec requires you to describe the relationship between object, class and method. In an exam: a class is the template; an object is a specific instance of that class; a method is a subroutine defined within the class that describes the behaviour of objects of that class.


Low-Level vs High-Level Languages

Low-Level Languages

Low-level languages have little or no abstraction from the hardware. They deal directly with memory addresses, registers, and machine instructions.

Machine code:

  • Binary instructions (1s and 0s) the CPU executes directly.
  • Completely hardware-specific — machine code for one CPU will not run on another.
  • Extremely difficult for humans to read or write.

Assembly language:

  • Uses human-readable mnemonics (e.g. MOV, ADD, JMP) to represent machine code instructions.
  • Near one-to-one mapping to machine code — each mnemonic maps to one instruction.
  • Hardware-specific — requires an assembler to translate to machine code.
MOV AX, 5      ; Load 5 into register AX
MOV BX, 3      ; Load 3 into register BX
ADD AX, BX     ; Add BX to AX (result: 8 in AX)

High-Level Languages

High-level languages provide a high level of abstraction from the hardware.

  • Use English-like keywords and mathematical notation.
  • One statement may translate to many machine code instructions.
  • Portable — the same source code can run on different hardware platforms.
  • Easier to read, write, debug, and maintain.
  • Examples: Python, VB.NET, Java, C#.

When to Use Each

Situation Language Level Reason
Writing an operating system kernel Low-level Needs direct hardware control
Programming an embedded microcontroller Low-level Limited memory; speed-critical
Writing a device driver Low-level Must interact directly with hardware
Developing a business application High-level Productivity and maintainability matter
Writing a web application High-level Portability and rapid development needed
Performance-critical inner loop Low-level Maximum execution speed required

Comparison Table

Feature Low-Level High-Level
Abstraction Little or none High
Readability Difficult Easy
Portability Hardware-specific Mostly portable
Execution speed Very fast Slower (needs translation)
Memory control Direct Managed automatically
Development time Slow Fast

The key trade-off is control and speed (low-level) vs productivity and portability (high-level). Be ready to justify which is most suitable for a given scenario — always relate your answer to the specific requirements described.


Translators

Source code must be translated into machine code before the CPU can execute it. There are three types of translator: assemblers, compilers, and interpreters.

Assembler

  • Translates assembly language into machine code.
  • Near one-to-one translation — each mnemonic maps to one machine code instruction.
  • Output is a machine code file ready for execution.

Compiler

  • Translates the entire high-level source program into machine code all at once, before the program runs.
  • Produces a standalone executable file — the source code is not needed to run it.
  • Compilation can be slow, but the compiled program runs fast.
  • All errors are reported after the full program is analysed.

Interpreter

  • Translates and executes high-level source code one statement at a time.
  • No executable file is produced — the interpreter must be present every time the program runs.
  • Stops at the first error encountered, reporting the exact line.
  • Slower execution than compiled code, but easier to debug during development.

Comparison

Feature Assembler Compiler Interpreter
Input Assembly language High-level source High-level source
Output Machine code Executable file None (executes directly)
Translation One-to-one Whole program at once One line at a time
Execution speed Fast Fast Slow
Error reporting After assembly After full compilation At the first error line
Source needed at runtime No No Yes

Choosing the Right Translator

  • Use an interpreter during development — it stops at each error, making debugging easier.
  • Use a compiler for distribution — the compiled program runs faster and the source code is protected.
  • Use an assembler when writing low-level code for hardware control or performance-critical routines.

Be able to justify the choice of translator for a given situation. A developer might use an interpreter while writing and testing code (immediate error feedback) then compile the final product for release (faster execution, no source code exposed to end users).