Programming Paradigms and Styles

One school task, several ways to organize it

A school needs to add a student’s maths and science marks. We already know the calculation: 40 + 35 = 75. Now the question is how to organize the instructions so that someone can understand and change the program.

A programming paradigm is a way of organizing computation. Procedural programming emphasizes steps and reusable routines. Object-oriented programming groups related data and operations. Functional programming emphasizes calculating results with functions and controlling changes to data. These ideas can overlap within one program.

You do not need to master functions or classes before starting. Each example explains its new syntax. Our aim is to compare the ideas; later lessons develop the tools in detail.

  1. Recognize the emphasis

    Explain what procedural, object-oriented and functional styles make central in the same school task.

  2. Trace equivalent results

    Follow each complete JavaScript example and explain how it produces 75.

  3. Choose with a reason

    Select a reasonable style for a small calculation or a growing school record system, including its cost.

Three views of the same marks total

  1. Procedural

    Describe the sequence inside a reusable routine.

    0 → 40 → 75
  2. Object-oriented

    Keep a student’s marks with an operation that calculates their total.

    student.total() → 75
  3. Functional

    Pass marks to a calculation that returns a result.

    calculateTotal(40, 35) → 75
These are different emphases, not mutually exclusive boxes. Each example below prints 75.

A style is not a programming language

In the previous lesson, we compared ways to carry out source code. Here we compare how to structure that source. Execution strategy and programming style answer different questions.

All three main examples use JavaScript, so a different language is not responsible for their different organization. Many languages allow multiple styles, while their features make some approaches easier than others.

The first lesson’s student marks calculation is the prerequisite. Remember that named values hold marks, + adds them, and a display instruction produces output. We will keep the same marks in each example so you can focus on the structure.

Procedural: spell out the steps in a routine

A procedure is a reusable routine that performs a task. In this JavaScript example, function defines a routine named printStudentTotal. The names inside its parentheses are inputs, called parameters. Calling it with 40, 35 supplies the two marks.

Inside the braces, let gives us a total we can update. Follow its values: start at 0, add maths to get 40, add science to get 75, then display 75. Defining the routine does not perform the calculation; the call at the bottom starts it.

This style is useful when the task is naturally a sequence, such as reading marks, checking them and printing a report. The important idea is the ordered work, not the presence of a particular keyword.

JavaScript · local teaching example

function printStudentTotal(maths, science) {
  let total = 0;
  total = total + maths;
  total = total + science;
  console.log(total);
}

printStudentTotal(40, 35);

Expected output

75

What changes when a routine also prints?

JavaScript · a routine that calculates and prints

function printStudentTotal(maths, science) {
  let total = 0;
  total = total + maths;
  total = total + science;
  console.log(total);
}

printStudentTotal(40, 35);

Expected output

75

This routine calculates and displays the total in one place. That is convenient for a small console report. It also means every call produces output, even if another part of the program only needs the total for a different calculation.

Such an observable action is called a side effect. Printing is a side effect because it changes what appears outside the calculation. Side effects are necessary in useful programs, but deciding where they happen helps you reuse and test the calculation.

You can use procedures without sharing uncontrolled global data. Keeping inputs explicit is helpful in any style. Later, functions and reusable routines and variable scope explain these boundaries.

Object-oriented: put marks and behavior together

An object groups related data and operations. A class describes how to create such objects. In this JavaScript example, StudentMarks describes an object containing maths and science marks.

new StudentMarks(40, 35) creates an object and calls its constructor to store the marks. this refers to that object. The function-like operation total(), called a method, reads its marks and returns their sum. The final line displays that returned value.

Follow the data: the object stores 40 and 35; calling its method reads those values; addition produces 75. Creating the object by itself does not print anything. See JavaScript’s class documentation for these language-specific rules.

JavaScript · local teaching example

class StudentMarks {
  constructor(maths, science) {
    this.maths = maths;
    this.science = science;
  }

  total() {
    return this.maths + this.science;
  }
}

const student = new StudentMarks(40, 35);
console.log(student.total());

Expected output

75

When an object helps—and when it adds work

JavaScript · a student’s marks and total method

class StudentMarks {
  constructor(maths, science) {
    this.maths = maths;
    this.science = science;
  }

  total() {
    return this.maths + this.science;
  }
}

const student = new StudentMarks(40, 35);
console.log(student.total());

Expected output

75

A growing school system may manage many student records, each with its own marks and operations. Grouping the data and operations can help readers locate what belongs to each record. Calling a method on one student uses that object’s marks.

For a one-off sum, a class adds more structure than the calculation requires. It is reasonable to choose a simpler function. Naming a class after a real-world noun does not automatically make the design clear; the object still needs a focused responsibility.

This example’s fields can be changed from outside the object. Grouping data alone does not guarantee controlled access or valid marks. Later, classes and objects and encapsulation explain how to design and protect that boundary.

Functional: calculate a result from explicit inputs

A function can receive values and return a result. In this JavaScript example, calculateTotal takes two marks and returns their sum. The caller stores the returned value as total, then displays it separately.

This calculation is a pure function: the same inputs give the same result, and it does not change outside state or perform output. Calling it with 40 and 35 returns 75 without modifying any student record. The later console.log performs the necessary side effect.

A functional style builds work from calculations like this and manages changes deliberately. One pure function illustrates the idea; it does not make every part of a whole application pure.

JavaScript · local teaching example

function calculateTotal(maths, science) {
  return maths + science;
}

const total = calculateTotal(40, 35);
console.log(total);

Expected output

75

Keep calculation separate from actions

JavaScript · calculation first, output at the boundary

function calculateTotal(maths, science) {
  return maths + science;
}

const total = calculateTotal(40, 35);
console.log(total);

Expected output

75

Separating the calculation from printing lets another caller use the same result in a report, a comparison or a test. You can check calculateTotal(40, 35) without capturing console output.

A useful school application must still read input, store records and display results. Functional programming does not remove those actions; it encourages keeping their effects clear. For complex data, returning new data instead of changing existing data can improve predictability, but it can also require extra copying or a different data structure.

The procedural example also used a function. That is not a contradiction: styles overlap. The distinction here is the emphasis on a returned calculation with explicit inputs and no side effects. Continue later with parameters and returned values and pure functions and immutability.

Another distinction: describe steps or describe a result

Imperative code specifies operations to carry out. The running total in our procedural example is imperative: initialize it, add maths, add science. Declarative code emphasizes the desired result and leaves more of the procedure to another tool.

For example, this SQL query requests the marks total for student record 7 from a database table named student_marks. Assume that row stores maths 40 and science 35.

SELECT maths + science AS total
FROM student_marks
WHERE student_id = 7;

Expected result: one row with total 75. You specify which data and result you want, while the database chooses how to find the row. AS total names the result column. SELECT requests a value, FROM names the table and WHERE limits the rows. This is a database example, not JavaScript to paste into the lesson player.

Declarative and functional are related ideas in some designs, but they are not synonyms. The imperative/declarative distinction describes how much of the procedure you spell out.

A school interface can combine several styles

JavaScript · a calculation an event response could call

function calculateTotal(maths, science) {
  return maths + science;
}

const total = calculateTotal(40, 35);
console.log(total);

In an event-driven program, an event—such as a teacher selecting “Save marks”—triggers a registered response. The event decides when work begins. The code inside that response can use objects, procedures and pure calculations.

For example, the save response can read values from a form, call calculateTotal, update a student record and display a confirmation. A pure function can calculate the total, while the response handles the actions that affect the interface and stored data.

This is a design description rather than a browser event simulation. We have not implemented form validation, database saving or network failures here. Later, callbacks and asynchronous responses explains how programs arrange work that happens after a triggering event.

Add English marks without losing the idea

JavaScript · extend this two-subject calculation

function calculateTotal(maths, science) {
  return maths + science;
}

const total = calculateTotal(40, 35);
console.log(total);

The complete functional example is shown here. A third subject, English, has a mark of 25. Change the function and its call so the result includes all three marks. Predict the output before reading the worked answer.

Worked answer

Add an english parameter, include it in the returned sum, and supply 25 when calling the function. The calculation now returns 40 + 35 + 25 = 100. It still leaves output to the caller.

function calculateTotal(maths, science, english) {
  return maths + science + english;
}

const total = calculateTotal(40, 35, 25);
console.log(total);

Expected output: 100. Changing only the call would not include the third mark: the original function never used a third input. A function’s instructions must match the values you want it to process.

Choose a structure for the requirement, not a winner

A small report with a clear sequence: a procedure is a reasonable starting point. Its ordered steps are easy to follow. Keep calculations separate when you need to reuse them without repeating output.

Many records with related operations: objects can help organize each record’s data and behavior. They add structure and require careful decisions about valid state and who may change it.

Calculations reused in reports and tests: pure functions make inputs and results explicit. Keep input, storage and display effects at clear boundaries. Do not assume every external action can be replaced with a pure calculation.

These are choices, not performance guarantees. Classes do not automatically make a program easier to maintain, and a function is not pure just because it uses the function keyword. Start with the clearest structure for the task and revise it as requirements grow.

Check: identify the functional emphasis

JavaScript · calculation and output for this question

function calculateTotal(maths, science) {
  return maths + science;
}

const total = calculateTotal(40, 35);
console.log(total);

Expected output

75
Why does this version separate console.log from calculateTotal?
Choose one answer. You can try again.

Answer and explanation

It lets the calculation return a reusable result without performing output itself.

Yes. The caller can use the returned total in different ways. Printing remains an explicit action outside this pure calculation.

Check: can styles work together?

A Save marks response uses a student object and calls a pure calculation before displaying the total. Which statement fits?
Choose one answer. You can try again.

Answer and explanation

The design can combine event-driven, object-oriented and functional ideas.

Yes. The event triggers the work, the object organizes data, and the pure function calculates a result.

Explain each style using the same marks

Procedural code emphasizes ordered work in routines. Object-oriented code groups related state and behavior. Functional code emphasizes result-producing functions and deliberate handling of change. All three examples calculated the same marks total, 75.

Imperative code spells out operations; declarative code describes a desired result. Events can trigger workflows that combine several styles. These distinctions are tools for reasoning, not exclusive labels or rankings.

Before moving on, explain where the marks live, when addition happens and which instruction displays the total in each example. Then begin variables and stored values. Return to functions and classes and objects when you are ready to build these structures yourself.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Variables and Values: Store and Update Data →