Study Notes: Computer Science (9645) - Software and Systems Fundamentals

Hello! Welcome to the foundation of Computer Science: Software. In this chapter, we move beyond the physical components (hardware) and dive into the instructions and logic that bring a computer to life. Understanding software—how it's designed, built, and executed—is crucial, whether you are coding your first program or understanding why your operating system works the way it does. We will cover everything from the basic data types you use in programming to the complex processes that manage the computer's memory and run your applications. Let’s get started!

1. The Relationship Between Hardware and Software (3.6.1)

A computer system relies entirely on the interplay between its physical parts and its instructions.

  • Hardware: The physical, electronic components of a computer system (e.g., CPU, RAM, hard drive).
  • Software: The sequences of instructions that are executed using the hardware. Without software, hardware is just a box of circuits!

1.1 Classification of Software (3.6.2)

Software is broadly divided into two main categories:

System Software

This software manages and controls the computer hardware, allowing application software to run. It acts as a middleman between the user/application and the physical machine.

The most important system software is the Operating System (OS).

  • Hiding Complexity: A core role of the OS is to hide the tricky details of the hardware from the user and other software.
  • Utility Programs: These add extra functionality to assist in system management. (Examples: Virus checker, compression software, disk defragmenters).
  • Libraries: Collections of pre-written functions or subroutines that can be used by other programs.
  • Translators: Programs (like compilers or interpreters) that convert source code into machine code (which the processor can execute).

Key Functions of an Operating System:

  1. Scheduling: Deciding which tasks or processes should run next and for how long, managing the CPU efficiently.
  2. Memory Allocation: Managing main memory (RAM), ensuring different programs have the space they need without interfering with each other.
  3. I/O Device Management: Handling input and output devices (like printers, keyboards, monitors).
  4. Interrupt Handling: Responding to signals (interrupts) from hardware or software that require immediate attention.
Application Software

This is software designed to perform specific tasks for the user. (Examples: Word processors, web browsers, games, spreadsheets.)

Quick Takeaway: System software manages the computer; application software performs tasks for the user.

2. Programming Fundamentals: Data and Instructions (3.1.1, 3.1.2)

When we write software, we are manipulating data using instructions. Before manipulating data, we must define what type of data it is.

2.1 Data Types (3.1.1)

A data type tells the computer how much memory to allocate for a piece of data and what kind of operations can be performed on it.

  • Integer: Whole numbers (positive, negative, or zero). (Example: 5, -100)
  • Real / Float: Numbers with a fractional part (decimal points). (Example: 3.14, 0.5)
  • Boolean: A logical value that can only be True or False.
  • Character: A single letter, digit, punctuation mark, or symbol. (Example: 'A', '5', '?')
  • String: A sequence of characters. (Example: "Hello World")
  • Date/Time: Values representing a specific date and/or time.

Memory Aid: Think of data types as containers. You wouldn't store water in a sack (a String container), you'd need a jug (like a Float container)!

2.2 Variables and Identifiers (3.1.2)

  • Variable Declaration: Setting aside memory space and giving it a name (identifier).
  • Assignment: Putting a value into that variable.
  • Meaningful Identifier Names: It is extremely important to use names that clearly indicate the variable's purpose. This makes code easier to read and maintain. (e.g., use TotalScore instead of x).

2.3 Input, Output, and Comments (3.1.2)

Programs must be able to interact with the user (Input) and show results (Output).

  • Input: Obtaining data from the user (e.g., asking for their age).
  • Output: Displaying results (e.g., printing "Your final score is 95").
  • Comments: Explanatory notes added to the code. These are ignored by the translator but are vital for human programmers to understand how the code works and why certain decisions were made.

Quick Takeaway: Data types define data; variables store it; identifiers make it readable; I/O handles user interaction.

3. Control Flow: Logic and Operations (3.1.2.1-3.1.2.3)

Control flow statements determine the order in which instructions are executed.

3.1 Arithmetic Operations (3.1.2.1)

These are standard mathematical operations:

  • Addition (+), Subtraction (-), Multiplication (*).
  • Real/Float Division: Standard division resulting in a float (e.g., 7 / 2 = 3.5).
  • Integer Division (DIV): Division resulting only in the whole number part (quotient). (Example: 7 DIV 2 = 3).
  • Remainder (MOD): Returns the remainder after integer division. (Example: 7 MOD 2 = 1).
  • Exponentiation (Power): Raising a number to a power.

We also have functions to adjust numerical results:

  • Rounding: Adjusting a number up or down to the nearest whole number (or specified decimal place).
  • Truncation: Simply chopping off the fractional part of a number (always moves towards zero).

3.2 Control Structures: Selection and Iteration (3.1.2)

Selection (Decision Making): This allows the program to choose different paths based on conditions (e.g., IF, ELIF, ELSE, CASE statements).

Iteration (Looping): Repeating a block of code.

  • Definite Iteration: Loops that run a fixed, predetermined number of times (e.g., FOR loops).
  • Indefinite Iteration: Loops that run until a certain condition is met (e.g., WHILE or REPEAT UNTIL loops).
  • Nested Structures: Placing one selection or iteration structure entirely inside another. This is common when processing 2D data, like rows and columns in a grid.

3.3 Relational and Boolean Operations (3.1.2.2, 3.1.2.3)

Relational Operations compare two values and result in a Boolean (True/False) value:

  • Equal to (= or ==)
  • Not equal to (\( \neq \) or !=)
  • Less than (<), Greater than (>)
  • Less than or equal to (\( \le \)), Greater than or equal to (\( \ge \))

Boolean Operations (Logical Operators) combine Boolean values:

  • NOT: Reverses the truth value (True becomes False).
  • AND: True only if BOTH conditions are True.
  • OR: True if AT LEAST ONE condition is True.
  • XOR (Exclusive OR): True if ONLY ONE condition is True (but not both).

Order of Precedence: When a statement has multiple Boolean operators, they are evaluated in a specific order:

NOT (Highest) > AND > OR (Lowest). (Brackets always override this order).

Quick Takeaway: Programs use operations and control structures (selection/iteration) to decide what steps to take next.

4. Modularity and Procedures (Subroutines) (3.1.2.7)

A large program is too complex to write all at once. We break it down into smaller, manageable chunks called subroutines (sometimes called functions or procedures).

4.1 Subroutines and Parameters

  • Definition: A subroutine is a named, 'out of line' block of code that performs a specific task.
  • Calling/Execution: It is executed (called) simply by writing its name in a program statement.
  • Advantages:
    • Modularity: Breaking the problem down (Decomposition).
    • Reusability: The code block can be used multiple times throughout the program without rewriting it.
    • Easier Debugging: Smaller chunks are easier to test and fix.
  • Return Values: Subroutines can calculate a result and return that value back to the main routine that called it.
  • Parameters: Data passed into the subroutine when it is called, allowing it to work on specific values.

4.2 Variable Scope (Local vs. Global)

The scope of a variable defines the parts of the program where that variable is accessible.

  • Global Variables: Variables accessible throughout the entire program.
  • Local Variables: Variables declared inside a subroutine.
    • They only exist while the subroutine is executing.
    • They are only accessible within that subroutine.

Good Practice: It is always best practice to limit the scope of variables (use local over global) where possible, as this prevents accidental modification of important data by other parts of the program.

4.3 The Stack Frame

When a subroutine is called, the computer needs a way to save its place and manage the data for that call. It uses a region of memory called the Stack. A stack frame is created for each subroutine call to store:

  • Return Address: The memory location of the instruction to go back to once the subroutine is finished.
  • Parameters: The values passed into the subroutine.
  • Local Variables: The variables declared inside the subroutine.

Quick Takeaway: Subroutines improve code quality and manage data access using local/global scope, with the stack frame handling the memory during execution.

5. Data Structures (3.2, 3.2.1-3.2.4)

A data structure is a way of organising and storing data in a computer so that it can be accessed and modified efficiently.

5.1 Static vs. Dynamic Structures

  • Static Data Structure: The size is fixed and decided when the program is compiled or first run. (Example: Arrays)
    • Advantage: Faster access; Memory allocation is simpler.
    • Disadvantage: Wasted space if not full; Cannot grow if more space is needed.
  • Dynamic Data Structure: The size can change while the program is running (can grow or shrink). (Example: Lists, Queues, Stacks when implemented using linked lists)
    • Advantage: Efficient use of memory; Can handle unpredictable amounts of data.
    • Disadvantage: More complex memory management; Slower access times sometimes.

5.2 Arrays, Lists, and Records (3.2.1, 3.2.2)

  • Arrays/Lists: A collection of items of the same data type stored under a single identifier. We can use two-dimensional arrays (arrays of arrays, like a grid) to store complex data like a chessboard or a spreadsheet.
  • Records: A collection of related data values (known as fields) which may be of different data types, grouped and manipulated as a single entity.

    Example: A 'Student Record' might contain the fields: Name (String), ID (Integer), Grade (Character).

5.3 Stacks (LIFO) (3.2.4)

A Stack is a dynamic data structure where the last item added is the first one to be removed. This is called Last-In, First-Out (LIFO).

Analogy: A stack of plates—you always take the top (most recent) one.

Stack Operations:

  • Push: Adding an item to the top of the stack.
  • Pop: Removing and returning the top item.
  • Peek (or Top): Returning the value of the top item without removing it.

Stacks are essential for managing subroutine calls (the stack frame discussed earlier) and checking the balance of brackets in expressions.

Implementation: A stack is often implemented using a one-dimensional array, requiring checks for whether the stack is Empty or Full.

5.4 Queues (FIFO) (3.2.3)

A Queue is a dynamic data structure where the first item added is the first one to be removed. This is called First-In, First-Out (FIFO).

Analogy: People waiting in line at a shop—the person who arrived first is served first.

Queue Operations:

  • Enqueue: Adding an item to the rear of the queue.
  • Dequeue: Removing and returning the item from the front of the queue.

Queues are used in operating systems for tasks like print spooling and handling data buffers.

Implementation:

  • Linear Queue: Simple implementation using an array. Problem: Once items are dequeued, the 'front' moves forward, leaving unused empty spaces at the beginning of the array.
  • Circular Queue: Solves the linear queue problem by wrapping the queue indices around the array. This allows the efficient reuse of space once items have been dequeued.

Quick Takeaway: Stacks are LIFO (Last-In, First-Out), and Queues are FIFO (First-In, First-Out).

6. Software Design and Development (3.3)

Software development follows a logical structure to ensure the final product meets requirements and is maintainable.

6.1 Structured Approach to Programming (3.3.1)

The structured approach focuses on clarity, quality, and control. Key features include:

  • Modularised Programming: Breaking the program into independent subroutines/modules (as seen in Section 4).
  • Use of Parameters and Return Values: Clearly defined inputs and outputs for modules.
  • Use of Local Variables: Limiting scope to prevent unintended side effects.

Design tools like Hierarchy Charts (showing overall program structure) and Structure Charts (showing modules, parameters, and data flow) are used.

6.2 Abstraction and Decomposition (3.3.2)

  • Decomposition: Breaking down a large, complex problem into smaller, identifiable sub-problems. This is often achieved using subroutines.
  • Abstraction: Removing unnecessary details from a problem to focus on the essential features needed to solve it. (Example: When designing a simulation of a car race, you abstract away the specific engine bolt sizes and only focus on speed, fuel, and location.)

6.3 The Software Development Cycle (3.3.4)

Software is typically created through several stages. This may be an iterative (repeating) process, often using prototyping or an agile approach.

Stage 1: Analysis

Define the problem clearly. Establish the requirements of the system by interacting with intended users. This creates a functional specification and a data model.

Stage 2: Design

Plan the solution before writing any code. This includes:

  • Designing data structures (like arrays and records).
  • Designing algorithms (using pseudocode or flowcharts).
  • Designing the modular structure (subroutines).
  • Designing the Human User Interface (HUI).

The focus may start on the critical path—the part of the solution everything else depends upon.

Stage 3: Implementation

Translating the models and algorithms into code (instructions) that the computer can process.

Stage 4: Testing

Checking the implementation for errors. You must use selected test data:

  • Normal Data (Typical): Valid data expected under usual conditions.
  • Boundary Data: Valid data right at the limits of acceptable input (e.g., 1 or 100 if the range is 1 to 100).
  • Erroneous Data: Invalid data that should be rejected by the system (e.g., a letter when a number is expected).

Stage 5: Evaluation

Judging the finished system against predefined criteria:

  • Correctness: Does the system meet the requirements? (Did it solve the problem?)
  • Efficiency: How quickly does it run (time) and how much memory does it use (space)?
  • Maintainability: How easy is it for a programmer to fix, update, or modify the code later?

Quick Takeaway: Good software is built using structured methods, focusing on decomposition and following the Analysis, Design, Implementation, Testing, Evaluation cycle.

7. Programming Languages and Translation (3.6.3)

The computer only understands machine code (binary), but humans write software in higher-level languages. Translators bridge this gap.

7.1 Low-Level Languages

These languages are very close to the hardware and are specific to the processor's instruction set.

  • Machine Code: Binary instructions (0s and 1s) directly executable by the CPU. This is the only language the computer truly understands.
  • Assembly Language: Uses mnemonics (short, readable abbreviations like ADD, LOAD) to represent machine code instructions.

Advantages of Low-Level Languages (L-L-L):

  • The programmer has precise control over the hardware and memory.
  • Produces very fast and efficient code.

Disadvantages of L-L-L:

  • Difficult and time-consuming to write.
  • Non-portable (code written for one type of CPU won't work on another).

7.2 High-Level Languages (HLL)

These languages are closer to human language and easier to use.

  • Imperative HLL: A language where the commands explicitly describe the *process* (sequence of steps) that should be followed to carry out a task. (Most common languages like Python, Java, C++ are imperative.)

Advantages of HLL:

  • Easier to read, write, and debug.
  • Portable across different hardware platforms.

7.3 Types of Program Translator (3.6.3.2)

Translators convert source code (human-readable) into object code (machine code/executable).

Translator Role & Process When to use
Assembler Converts assembly language into machine code. When needing control over specific hardware components.
Compiler Translates the entire source code into machine code before execution. Creates an executable file. When the final, fast, and secure product is needed (e.g., commercial software).
Interpreter Translates and executes the code line by line during run time. No separate executable file is created. During development and testing, or when running on systems where portability/quick changes are key.

Intermediate Languages (like Bytecode): Some compilers produce an intermediate language instead of direct machine code.

  • Why use them? They are more portable than machine code and allow security checks before execution.
  • How are they used? They are run by a virtual machine (which interprets the intermediate code) or a Just-In-Time (JIT) compiler (which converts it to machine code right before execution).

Quick Takeaway: Programmers use HLLs for ease and portability, relying on Compilers (for speed) and Interpreters (for flexibility) to generate the final Machine Code.

8. Object-Oriented and Functional Paradigms

While most AS programming focuses on the imperative/procedural approach, modern software uses different approaches called paradigms.

8.1 Object-Oriented Programming (OOP) (3.9)

OOP is used because it models real-world entities better, promoting reusability and security.

Core OOP Concepts:

  • Class: A blueprint or template that defines the common characteristics (properties/attributes) and behaviours (methods) of objects. (e.g., A "Car" class.)
  • Object: An instance of a class. Objects are created via instantiation using a constructor (which initialises the object's state). (e.g., "MyToyota" is an object of the "Car" class.)
  • Encapsulation: Hiding the internal ways in which a class operates and represents data from other classes. This protects the integrity of the data. Access is often controlled using getter and setter methods.
  • Inheritance: A relationship where a new class (subclass or derived class) is a more specialised version of an existing class (base class or parent class). (e.g., A "Truck" subclass inherits properties from the "Vehicle" base class.)
  • Overriding: When a method inherited from the base class is redefined in the subclass to make the subclass behave differently.
  • Association: A weaker relationship between two objects where one object simply uses another. (e.g., A "Team" object uses "Player" objects.)

8.2 Functional Programming (FP) (3.12)

FP focuses on computing results using mathematical functions, treating them as first-class objects (meaning they can be passed as arguments or returned from other functions).

  • Function Application: Giving specific inputs (arguments) to a function to get a result.
  • Composition of Functions: Combining two functions to get a new function. (If function f runs, and then function g runs on the result of f, that is g of f.)
  • Higher-Order Functions: Functions that take another function as an argument, or return a function as a result, or both.
    • Map: Applies a function to every element in a list, returning a new list of results.
    • Filter: Processes a list to produce a new list containing only the elements that match a given condition.
    • Fold (Reduce): Reduces a list of values to a single value by repeatedly applying a combining function. (Note: foldl works forward (left to right), foldr works backward (right to left)).

Quick Takeaway: OOP models real-world objects using Classes and Objects; FP treats functions as data and uses higher-order functions to manipulate lists efficiently.

9. Additional Programming Utilities

9.1 String Handling and Conversion (3.1.2.4)

Strings are sequences of characters, and various operations allow us to manipulate them:

  • Length: Finding the number of characters.
  • Position: Finding where a character or substring starts.
  • Substring: Extracting a part of a string.
  • Concatenation: Joining two strings together.
  • Conversion: Moving between data types (e.g., String to Integer, or Character to its numerical code).

9.2 Exception Handling (3.1.2.6)

This is a programming technique to manage unexpected events (exceptions) that occur during program execution, such as trying to divide by zero or trying to open a file that doesn't exist.

Don't worry if this seems tricky at first! Exception handling is simply planning for when things go wrong and making sure your program doesn't crash.

Quick Review: Software is the instructions executed by hardware. It's built using modular structures (subroutines), defined data types, and logical control flow (selection and iteration). The design process ensures correctness, efficiency, and maintainability.