cccccc
INTRODUCTION: Not only are there many computer languages, but they can work in rather different ways, called paradigms. Paradigm, being a "fifty-cent word" that was originally used for grammatical examples such as in Latin, "amo, amas, amat . . ." (Click if you dare!) Then in the 1960's Thomas Kuhn famously borrowed the term, to describe new departures in science based on a breakthrough by often controversial pioneers like Copernicus, Kepler, Galileo and Newton. Yes, it is no accident that "revolution" got its political meaning from the title of Copernicus' book on the revolutions of heavenly bodies. Paradigm shift entered our language to describe step-changes in practice and capability, then it became a hot buzz word. (Try this, if you dare!) Now past the half-century mark, it has settled down to a sensible maturity as a useful though sometimes vague idea.
From this, we can build a picture of computing/programming paradigms, in two stages, setting up why there is a buzz about object oriented programming. That will help us deal with the buzz about Object Oriented Programming, OOP (and, it will give us a very useful background to understand and work with different types of computing languages).
Then, we can explore Object oriented programming in that light.
PART A:
Paradigms . . . ?
(As in, yes Virginia, there is more than one way to skin a catfish!)
First, let's knock up a rough, framework description of a paradigm:
a paradigm is an accepted way for a community of workers -- or, "school of thought" -- in a field of effort to do (and to see or think about) their work and to address its issues; often, based on key, breakthrough cases solved by respected pioneers and their associated key concepts or beliefs, "war stories" and legends etc. [See, Webster's]
(Did an apple really fall and perhaps hit Newton on the head as the Moon swung by in orbit? Did Galileo really drop a musket ball and a cannon ball over the side of the Leaning Tower of Pisa? Why not a feather, too? Was that too obvious? So, why didn't others see the tie-in of air resistance? Why not, then, suspend another musket ball from a cloth made into a mini parachute? Did Einstein really lie on his back in a park, pondering what it would be like to ride on a beam of light? It seems, Kekule really did have a dream of snakes swallowing their tails and that helped him see the Benzine Ring. Likewise, it seems his academic objectors really did refuse to look through Galileo's telescope.)
Second, for computing and programming, there are many such paradigms, that were once red hot breakthroughs but are now part of the common furniture of thought and the programmer's big box of tools. These start from 1 and 0 machine code then the creation of more readable assembly language then higher level languages in their many, still evolving families. And yes, this is technological evolution by highly intelligent and knowledgeable, creative design.
Where, a current trend for leading languages such as Java, Python, C# [Cee-Sharp] etc is to facilitate multi-paradigm programming.
However, OOP now rules the roost, especially in a windows and web era.
Even Cobol and Fortran -- pioneering high level languages from the 1950's -- now sport object oriented features!
Obviously, there are many paradigms, some major, some minor. A tree diagram can be used to represent several significant ones:
![]() |
| One way to set out relationships between some key programming paradigms [HT: Tutorialspoint etc] |
There are differences of terminology and focus, but the difference between telling the computer to do step 1 then step 2 etc and declaring a given relationship or state of affairs to be so seems fairly clear.
However, a semi historical approach will help:
- Given modern computing's roots in automation of complex computation, thus register-focussed machine language and the use of abbreviations to make references to data, registers and arithmetic/logic operations passably readable [assembly language], imperative programming comes first.
- Procedures are laid out step by step, using input, process, output, and the transformation of data to bodies of validated, secured, richly interconnected, meaningful information, then
- it was realised that the famous four structures can make better sense than spaghetti code: structured programming.
- This is also the general period in which high-level, problem-solving rather than machine structure based languages emerged: Fortran, Cobol, Basic, Pascal, C and kin, requiring translators, of two main types: Type 1: line-by line code-executing Interpreters and Type 2: Compilers that did a more function by function rendering into executable machine code.
- Object oriented programming actually enfolds structured programming in its methods, but uses encapsulation to reduce tightness of coupling of modules.
- Artificial Intelligence (AI) opens up . . . likely, a family of! . . . new paradigms; indeed, as a general purpose transformational technology, we are likely seeing a rising, generation-length economy transforming wave (see, debates over Kondratiev's long waves and insights on Schumpeter's creative destruction). In the case of Large Language Models (LLM's) and Generative Pre-trained Transformers (GPT's) such as ChatGPT etc, we may quote ChatGPT5 about itself as
"a kind of AI that learns patterns of language, reasoning, and knowledge by analyzing vast amounts of text [--> the "training"]. Instead of following rigid instructions like older software, it generates responses by predicting the most fitting next words, one after another, based on context [--> and probabilities]. This allows it to answer new questions, adapt flexibly, and combine ideas across fields."
Thus, writing prompts and interacting with an AI becomes a new way to be digitally productive, and this includes working collaboratively with an AI to develop, test and run code -- right from first steps in learning how to code. Yes, too, some AI's can draw, create music, operate vehicles, etc.
- On the side, hypertext markup language, HTML opened the way for the world wide web, www, being a markup, text/page description/display language.
- Beyond, XML embedded a "meta-level," not-displayed informative description of the meaning of text/page/document components and is now a key part of how modern word processing software creates, edits, indexes and searches content.
- Next, functional programming in effect gets rid of changing states of variables [which caused synchronisation headaches once systems become complex] and expands the idea of mathematical functions, a program here is effectively a calculation.
- Logic programming gives a way to code logical relationships, logic of cause and even frameworks of expert knowledge; facts are asserted, rules to infer and to manage the process are given, the process is carried out internally and the result is given.
- Along the way it was recognised that database management was in fact full-bore, Turing-complete programming;
- pointing onwards to the DIKW framework and inviting machine learning, neural networks and deep learning with other Artificial Intelligence techniques that support knowledge growth and wisdom-oriented decision support:
- Thus, we see the information systems focus: measurements > data > validated & secured information bases > bodies of [proprietary, trade secret . . . ?] knowledge > wisdom-based decision support.
- In this too, we can see recursion as a further, fairly subtle mathematical and computing paradigm, where once we have a base case say CASE 0 that is reasonably directly calculable or identifiable etc, and more and more complex cases that can be formed as CASE n := INCREMENT on {CASE n-1}, CASE n can be decomposed in steps and then calculated or identified. Here, := or sometimes = = means, so, by definition, by contrast != means, not equal. The key step, now, is to see that the decomposition is a generic process, so we can code an algorithm that calls itself repeatedly, hence, "recursion." Then, when we reach CASE 0, we directly obtain that and compose CASE N through the chain of increments.
Two classic cases are the factorial function and the Fibonacci sequence. For the former, 0! := 1, and FACT n := n x {FACT n-1}, e.g. 4! = 4 x 3!, 3! = 3 x 2!, 2! = 2x 1!, 1! = 1 x 0!, where 0! is the base case. So, pulling from the stack -- that's a key data structure, comparable to plates piled up -- of stored results, we compute 4! = 4x3x2x1x1 = 24. Unfortunately, such a stack can pile up fast and the rate of growth of complexity of computation, in this [and for many similar cases], is extreme as n climbs. Already, 12! is 479,001,600. Stack overflow is an obvious challenge as a practical machine runs out of resources. And, the study of complexity of algorithms is itself a key topic with its own, Big-O notation, algorithms for factorials and the Fibonacci sequence can easily grow exponentially. Algorithm taming can be seen as a version of lion taming.
Here is an outline of this self-calling algorithm:
FUNCTION FACT(N : INTEGER) : INTEGER;
BEGIN
IF N = 0 THEN
FACT := 1
ELSE
FACT: = N * FACT(N-l)
END;
Notice, we define a base case and the generic self referential case, embedding in a loop that descends to the base case. Referring to a stack of intermediate results, we then compute the final value, reliably. [Here, that is incremental.]
So, we can see that we need to focus on:
1] Structured, procedure oriented programming, and
2] Object oriented programming
We will mention, Functional and logic programming and say a bit more on recursion, a notoriously challenging concept.
![]() |
| The Input-Process-Output (IPO) framework at the core of all coding from machine language up |
A pause to briefly explain, so we can have an idea of the environment of current computing:
- Imperative programming tells the computer what to do, step by step in the IPO framework, typically invoking variables and values then processing them to give desired output values. A variable is in effect a named memory location and its value is loaded there. The state of a system or object based on these variables is set by their collective value. Such variables are typically organised in frameworks, called data structures, such as s-t-r-i-n-g-s, arrays, stacks, trees and onward, data bases or even knowledge bases.
- Structured, procedural programming uses sequences, branches [selection], loop and case patterns to design programs and sub routines that have one normal entry point and one normal exit point, avoiding tangled spaghetti code. This builds on the IPO pattern by guiding programmers to use certain well defined, effective and controllable patterns in code writing and algorithm design. An algorithm is a step by step finite pattern of procedures that moves toward a goal and halts in a controlled way. There is a theorem that any procedure can be reduced to these structures. The one entry, one exit rule is especially key for reducing tangled interlocking interactions that can frustrate maintenance.
- Object oriented programming (which uses structured programming in its methods) further reduces overly entangled processing by creating encapsulated objects that interact on a software stage by passing messages, so that processing is internal to the object, reducing tightness of coupling. Also, objects can inherit and extend properties and capabilities from parent objects so that re-usability is promoted. This has been particularly important, once graphical user interfaces became important.
- Declarative programming gives the what is to be achieved as a logical description, leaving issues of stepwise control and flow to the built in capability of such languages. (That is, we are seeing here a very high level abstract machine amenable to the logic of the problem to be tackled that automates lower levels through built in facilities of languages.)
- Functional programming is one style of declarative programming. Where, it has been suggested that Excel -- yes, the spreadsheet app -- is the world's most popular more or less functional programming language and application. Obviously, it can be used to instruct a machine to evaluate a cluster of mathematical expressions, or functions. However, in its ideal form we here turn everything into a function including say +, this is not function in the usual mathematical sense. Because state-changing [= "mutable"] variables are locked out, this reduces a major source of tightly coupled complexity and error and allows massively parallel execution, there is at this level no required sequence of steps and states. Of course, there are ways to define a trajectory of states by creating a chain of variables, often using recursion by which the code calls itself repeatedly.
{ DRAFT, per surfacing thought in the night Mar 24 2025 4 am: Where, we may also define an "umbrella, persistent variable attribute" (say, t) that captures the cluster of values of variables (say, t_k) at diverse sampled points (say, k), but is an attribute insulated from the tight coupling that would occur with repeatedly re-assigned variables familiar from Fortran etc, where t = t + 1 increments t . . . leading to synchronisation issues,
Here, flow accumulates --> stock
- as, each t_k value and point will be "immutable," once evaluated/formed, even as
- accounting values are fixed once entered, but have an umbrella tracking attribute-value across the span of the relevant variables and function;
- to correct an accounting error a special correcting entry is made, creating a separate value, suggesting
- use of a dummy variable to mark provisional (but presumed valid), checked and correct vs incorrect values.
- This echoes how we often have subscripted values for a variable, such as t_0, t_1, t_2 . . . t_k . . . and where
- some x(t) has an onward immutable value x_k -- read: x-sub-k -- for a given t = k once it is assigned at t = k; of course, this then feeds a general model of how systems change state (x, y, z . . . ) across time under the impact of forces acting on them . . . in effect the diagram says, at a given time the stock = initial amount + accumulated flow/change [= think, water flowing into and filling a bucket]. . . that is, state x_k is the accumulation of increments of change acting on an initial state x_0 {where x-in-bold is a vector x = (x, y, z . . . )}; also,
- this exploits how vast memory is now relatively cheap; certainly, far less constrained and far less costly than coder and debugger time . . . or worse, a damaging, bug-triggered event due to loss of synchronisation across a cluster of coupled variables.
- This also suggests, real time issues of synchronisation and latency across variables in an inter-sample window . . . e.g. how do we define and control "now"-ness (and "here"-ness)?}
A key facet here is lambda calculus, a general format for functions, e.g. (λx.x^2)6 --> 36.
(parameters) -> expressionOR(parameters) -> { statements; }The parameters are the input of the function, and the expression or statements are
the output of the function. The arrow (->) separates the parameters and the body of
the function.For example, the following lambda expression takes two integers as parameters and
returns their sum as an expression:(a, b) -> a + b. . . .
- Logic programming is another style of declarative programming, often used with artificial intelligence efforts [AI]. Here, logic statements use a head, H, and Body, B1, B2, . . . Bn. For instance H if (B1, B2 . . . Bn) means that if the B's are so H is the case, which can obviously chain and branch in a tree like structure. We can also have some things that are not the case in the structure. Obviously, this can be used to prove, or to detect good/bad or true/false conditions in answers to queries and a base of "facts". For example, is Socrates mortal? Given fact, Socrates is a man and condition, mortal if man, the answer is, yes. Beyond, we can see how we could code a base of knowledge or expertise and use it to guide expert performance, or evaluate likelihood of outcomes etc. These are the sort of thing that AI is interested in.
Structured vs. Object-Oriented Programming
xx
Let us recall, a Computer can be viewed as a layer cake:
Here, we can first view programming language applications as just that, "apps." Of course specialised to help us create and implement code.
Sometimes, a simple text editor will serve to compose programs, though these days those are usually optimised for coding. It may be more effective to use an integrated development environment, IDE. An application for the language, often specially downloaded, will help us open, interpret or compile the code, and run it. Nowadays, notebook applications help us treat coding as part of a lab notebook.
In the end, the computer can only execute machine code but it is best to automate generation of that through compilers and interpreters [or even standard virtual machines that take in byte codes; such as the Java Virtual Machine, JVM], especially in a world of cheap abundant memory, fast processors and costly programmer time.
(It is worth noting that other programming languages have been modified to generate byte codes for the Java Virtual Machine, for example Jython . . . obviously, Java + Python.)
Here is the Java Virtual Machine model:
This is the heart of the Java ideal, WORA, write once, run anywhere. Sadly, the perfect ideal is often still a tad or a few beyond our grasp. However, we have what is good enough to use.
These forms of software and the underlying languages express paradigms. Yes, likely, plural.
Structured programming, famously, tamed the tangle of procedural programming based on a proof that sequence, branch and loop structures can achieve any computational task. Case structure is effectively a convenience, a chain of branches:
(Beyond, of course, lies recursion, by which a program or sub-program can call itself so that an overall problem can be solved by repeatedly solving smaller, simpler versions of itself, then using a "simple" base case to sweep through the stack of calls to give a final result. Another advanced technique is the consultation of an Oracle, by which the computer asks a trusted source and then acts on the resulting trusted decision, judgement, inference or knowledge, in just one step; allowing it to go beyond the limits of the so-called Turing Machine. It is not too far fetched to say that with oracles, wisdom . . . hopefully, good . . . enters computing. We may also contemplate so-called learning machines and artificial intelligence. Here, intelligence can be seen -- rather roughly -- as ability to independently perceive and understand/interpret, learn, judge [so, warrant], reason and decide, solve challenges/ puzzles/ problems, use language or quantities correctly and to invent or create new things, especially artistically but also technically or strategically. AI, then becomes, machines capable of doing such things with effectiveness comparable to competent persons. A challenge, but potentially transformative . . . or possibly utterly ruinous, raising ethical issues.)
Object oriented programming takes the power of structured programming to the next level. It is also far more familiar than one might have thought. For, as Premchand S Nair, in his Java Programming Fundamentals, gives us through an everyday example:
. . . objects are everywhere. In fact, we live in an object-oriented world! Consider a very simple situation. You are entering your home at night aft er a long day at the library. Due to the darkness, you may turn on a lamp switch. In this situation, the lamp in your room is an object. The switch on is an operation of the lamp. After a while, when you are ready to retire for the day, you switch off the lamp. Again, switch off is another operation of the lamp . . . .
All objects of a class have identical behavior. For example, all lamps behave in the same way. If you turn on the switch, it lights up, and if you turn off the switch, it no longer provides any light. In other words, every instance of the lamp class has at least two operations: switch on and switch off. Thus, every lamp behaves identically and all DVD players have identical behavior . . . . No prior knowledge of electricity, physics, or electrical engineering background is required to use the lamp. In fact all you need to know is what are the available operations and how will the object
behave under those operations. For example, as long as you understand the behavior of
the lamp object under switch on and switch off operations, you can use your lamp very
efficiently. [CRC Press, 2009, pp. 2 - 3.]
As a more "realistic" computing example, Nair discusses a bank account object:
Suppose you have a checking account in Great Friendly Bank. Any time you want to know your current balance, you can request that service. Your bank will promptly comply with your request. As far as you are concerned, you need not know how the bank keeps track of data relevant to your account such as account balance, account number, name, address, and so on. In fact, you do not have to know anything about the internal workings of a bank to carry out any transaction. However, you need to know the valid operations that can be performed. In the case of checking account, some of the valid operations are depositing an amount, withdrawing an amount, and checking the current balance. [p. 3.]
(BTW, this implies that you also have a "data shadow" object, as a user! And "realistic" is in quotes for a reason. As you can see in the Raspberry Pi Unit, Unit R, a computer driving an external LED circuit -- a miniature lamp! -- is a start point for learning about interfacing and control, or even Internet of Things.
- Think about an App on your cell phone that lets you visualise your home from thousands of miles away and turn on and off lights in your living room, etc. Or,
- an app that lets a skilled surgeon carry out an operation on a patient using a remote, surgical robot.)
OOP, then, "sees" the world as a stage with interacting objects in it. Physical, external objects have a "data shadow" object on the software stage, and on the same stage, there are purely software objects (that are often represented by icons in a software window).
We can then play with these objects to do what we need or wish to do: write, draw, calculate, watch an animation, play a game.
To do these things we send messages and the objects respond based on their behaviours and methods, interacting with one another.
So, we now conceive of computing as dealing with interacting software objects viewed through a window . . . and yes, a big boost was given to OOP when Graphical User Interfaces [GUI] with Windows, Icons, Mice and Pointers [WIMP] became prominent:
Where, we see interactions:
![]() |
| Designing a Class/Object |
Notice, how
- the object has a core
- with its distinct name and linked state/attributes.
- This is encapsulated with a methods/behaviour shell and
- interaction is through passed messages,
- thus interface ports with protocols.
As a result, data and state as well as methods are internal to the object, reducing tight coupling.
In turn, we have a class which specifies an object and objects are instances of their classes. This leads to a parent/child tree-like network where for Java the root class is, Object and by degrees other classes and objects are derived -- extended -- from it, allowing inheritance of attributes and/or methods and over-riding of attributes and/or methods, etc.
That makes code reusable and extendable, so a modern OOP language comes with a library of "canned" standard objects, that can be called, modified and extended. This is of course most noticeable for GUIs -- pronounced, "gooeys" -- but it is general and powerful. For example, reducing coupling through message-passing is another step in the war against tangled, confusing, hard to maintain or modify spaghetti code:
Of course, this is the ideal, practical, commercial or open source computer languages, as usual, will fall short of the theoretical ideal. But they are "good enough for gov'mint work."
Where, too, Java (and Python) are Object-Oriented but now also have become multi-paradigm.
Likewise, methods must carry out procedures so structured programming is also a part of the picture . . . no, going on to OOP does not mean abandoning stepwise processes and their algorithms.
How's it done? In more details: DRAFT
- Objects come in classes, and each object is a distinct separately identifiable and named instance of its class
- The class is thus the blueprint for its associated objects that specifies their features [naming, attributes, methods with messaging interfaces], and each member of the class put up on the software stage is an object.
- Sets have members or elements, computing classes include elements and associated operations.
- So, we must always think in terms of blueprints [classes] AND instances [i.e. objects]. Wise programmers will therefore always keep in mind a balanced view of blueprints/instances.
- Each object for a class will have its own name and its own values for its attributes (thus, state).
- But, the objects share the same methods and can act on the same messages, so
- the objects change internal state and/or deliver responses . . . return values . . . based on their particular name and current state, thus individual history-- and thus, time.
- (Sometimes, one should consider building a class/object to deliver a desired method and encapsulating the data etc it needs. This is different from identifying an object then its required states, behaviours and methods. Likewise, you may want to set up a structure to hold data, then consider how to access, change/update and manipulate it. There's more than one way to skin a cat fish. Bear in mind that the obvious, brute force method may be outperformed by improved algorithms that become part of the programmer's toolbox. Tricks of the trade and trade secrets are real issues; they can be part of the expertise you pay for when buying an app.)
- This suggests, describing what is to be done based on inputs, process outputs, then "divide and conquer" by identifying a stage full of actors to carry out the process, given interactions with the user, target systems, networks, stores of information/records etc. Then, we can specify how these actors interact, in a sequence, to provide the service, results and outputs.
- Unified Modelling Language [UML] charts for classes and objects, use cases, process sequence etc are useful. So are at-a-glance overall system diagrams, at overview and detail levels. (Think about the layer cake, user-host-target model of a computer system above and how it helps us to identify and understand how different components and layers/levels of software and hardware work together to make the overall system work.)
- A good hint is to look for nouns in the specification for the program, that point to potential actors and to the roles and services they should provide in answer to messages. Don't overlook a data shadow for the user. A sometimes overlooked future user, too, is whoever has to do maintenance or debugging and trouble shooting.
- Messages implies interfaces to control interaction. Encapsulation of name, attributes/state and methods reduces tight coupling and promotes the black box- layer cake approach that hides and protects what other actors do not need to know. If you need it and don't have it, ask for it.
Message passing, hiding of technical details [so, abstraction as black boxes], processing in response, changed state and return values all point to careful planning and control of interactions between objects, thus identifying and defining ports and protocols.
This UML Sequence Diagram illustrates how objects are
activated [--> fat bars] and pass messages including
making responses. Notice the IF/ELSE "alt" block [Cr, fair use Edu]- By contrast, as we saw, functional and logic programming paradigms remove the varying state with its dependence on such history/time. That makes response independent of time. (Think of how Excel etc Spreadsheets work, and how if you want a time series, you set up a sequence of timed variables and cells with formulas in the spreadsheet.)
- Some languages make the classes explicit, others leave them implicit in how their objects are structured.
- Classes come in a framework that is set up to facilitate code reuse. The original class allows its daughters to inherit attributes, methods etc and extend them, in a tree like pattern of descent.
- For Java, the root class is named Object. Other classes build on -- extend -- Object by adding fresh attributes and/or methods, and so forth.
- Sometimes, certain inherited attributes and methods can be suppressed or overridden, just as a snake has lost its limbs but is still a reptile. An overriding method can be inherited from another class and would provide an enhanced, specialist capability. Adding decimals is more complicated than adding whole numbers, but extends/enhances adding.
- Some languages thus allow for multiple inheritance from different parents, similar to how we inherit features from our mothers and our fathers. (The DNA metaphor is peeking out and saying, Hi!)
- Data in classes and objects comes in various types, strings, characters, integers, boolean variables [true/false etc], "floating point" numbers with single and double precision, arrays etc and
- methods can be coded so the way they work automatically adjusts to the type of data, think about adding . . . an operation with many forms . . . integers, fractions [e.g. 1/3 + 3/4 = 13/12], floating point [*], vectors, matrices. Multiplication and division get even more complicated.
____________[* Floating point numbers are in effect, "decimals" and "scientific notation" etc. with whole and fraction parts, e.g. 19.78 = 0.1978 x 10^2. See here for a useful primer. (Yes, that humble source can be useful on cut and dry topics like this.)] - This is one facet of polymorphism, poly + morphe, many forms. Notice, how the operator + took on a special meaning, chain together strings and assign a composite meaning.
- This facet of polymorphism is termed method overloading.
- Similarly, overriding allows a coder to customise or replace one or more methods in a daughter class, so it can function differently. This can work with multiple inheritance so methods can be shared across diverse classes. This is, another form of polymorphism.
- Such fits with the DRY principle: Don't Repeat Yourself, i.e. share a common method written once and run everywhere instead of creating multiple, duplicate copies . . . which will be harder to keep track of and maintain.
- Of course, as the diagrams above show, classes and objects encapsulate their methods and data, so interaction is through standardised message ports, which
- allows us to freely maintain or modify a given class or object so long as we preserve the message interface. Responses and return values depend on the states of objects, thus their history.
- In encapsulation, we should give each object "everything it needs to do its job": attributes/state, data, methods with message interfaces. That way other objects [including data shadows of users] have no need to be aware of or directly interfere with internal details. So, we have access control to internal details and exposing the public face of the class/object. Layer cakes and black boxes again.
- This leads to one reason for abstraction, where classes defend their encapsulation by blocking direct access to detailed data, only allowing access through methods thus their message ports and protocols. As a result, an abstract summary face is presented as publicly accessible, with underlying details hidden in a black box and protected.
- From another angle, abstraction is the process of simplifying something, drawing out and arranging or summarising ALL of its essential features without entangling us in needless technical details and data. Thus, information hiding. Or better, protective information access control.
- Also, polymorphism allows us to use the layer cake - black box strategy, interacting with a simple standardised interface (and "virtual machine" model) without dealing with underlying complex, shielded details inside the black box. We thus see modularisation leading to identifiable objects.
- Notice, above, how the layer cake approach works for the computer as a whole and how the "virtual machine" works for the Java language itself.
- For example, there's a lot going on inside the black box when you "simply" point an arrow icon at an object and click or double click it.
Rumour has it, Apple spent 200 programmer years on getting the Graphical User Interface for their Lisa Computer right . . . the famous MacIntosh was a simplified Lisa. Of course, the killer App was the invention of visual, what you see is what you get desktop publishing, with Aldus Pagemaker leading the pack. Contrast what would have to be done if one were typing inputs at a console to lay out the page! GUI interfaces were revolutionary, making computers far more accessible, thanks to visual, software window approaches and the black box- layer cake strategy. Today's touch screens extend that breakthrough.
Aldus Pagemaker, ver 1.0 for Windows, showing
menus, tool palettes, WYSYWIG layout etc- User interface items now come bundled with operating systems and programming languages.
- vv
Here is a suggested list of principles by Javin Paul, for effective, reliable design with Java:
1] DRY (don't repeat yourself) means don't write duplicate code, instead use Abstraction to abstract common things in one place. If you have a block of code in more than two places, consider making it a separate method, or if you use a hard-coded value more than one time, make them public final constant.
2] [E]ncapsulate the code you expect or suspect to be changed in the future. The benefit of this OOP Design principle is that It's easy to test and maintain proper encapsulated code.
3] [Open/closed] Classes, methods, or functions should be Open for extension (new functionality) and Closed for modification . . . which prevents someone from changing already tried and tested code.
4] Single Responsibility Principle . . . SRP, there should not be more than one reason for a class to change, or a class should always handle single functionality.
5] [Dependency Inversion] Don't ask for dependency; it will be provided to you by the framework
6] [F]avor composition over inheritance, if possible. Some of you may argue this, but I found that Composition is a lot more flexible than Inheritance.
7] According to the Liskov Substitution Principle, Subtypes must be substitutable for supertype, i.e. methods or functions which use superclass type must be able to work with the object of subclass without any issue".
8] The Interface Segregation Principle states that a client should not implement an interface if it doesn't use that. This happens mostly when one interface contains more than one functionality, and the client only needs one functionality and no other. Interface design is a tricky job because once you release your interface, you can not change it without breaking all implementations.
9] Always program for the interface and not for application; this will lead to flexible code that can work with any new implementation of the interface. So use interface type on variables, return types of method, or argument type of methods in Java.
10] Don't do all stuff by yourself, delegate it to the respective class. Classical example of delegation design principle is equals() and hashCode() method in Java. In order to compare two objects for equality, we ask the class itself to make a comparison instead of the Client class doing that check. The key benefit of this design principle is no duplication of code and pretty easy to modify behavior. Event delegation is another example of this principle, where an event is delegated to handlers for handling. If you put more than one functionality in one Class in Java, it introduces coupling between two functionalit[ies].
Of course, we should not overlook AI. As ChatGPT5 went on to say about its power in coding:
When you ask me to write code I:
-
Treat code like language — during training I saw lots of real code, so I learned common tokens (
public,class,{,;, etc.), idioms, indentation and typical APIs. -
Use context — I pay attention to the programming language you request (Java) and the surrounding text to keep style, imports and types consistent.
-
Respect syntax patterns — I don’t “compile” code, but I generate sequences that match patterns that typically compile (types, method signatures, braces in the right places) because I learned those patterns.
-
Prefer correctness — I favour clear variable names, correct signatures, and common numerical patterns (e.g., RK4 integration for ODEs) when solving physics-style problems.
-
You still should compile & test — I can produce runnable code, but always compile and test it in your environment and adjust parameters/units.
More broadly, it put up a summary for the proverbial intelligent twelve year old:
I am GPT-5, a type of artificial intelligence called a large language model. You can think of me as a very advanced reader and writer of text. My role is to take in what you say, understand the context, and generate a useful or interesting continuation.
How I’m built:
My “brain” is a vast neural network, made of billions of adjustable connections.
I was trained by reading an enormous amount of text—books, articles, websites—and practicing the task of predicting the next word in a sentence.
Over time, I learned patterns of language, reasoning, and association that let me generalize beyond memorization.How I work in conversation:
I read your words and break them into small chunks (tokens).
I look at the context of the conversation.
I use my trained patterns to predict the next word, then the next, then the next, until a full answer is formed.
What you see is a fluid response, built word by word in real time.Am I just string matching?
No. I don’t simply recycle phrases I’ve memorized. Instead, I combine patterns flexibly—almost like snapping together Lego bricks of meaning—to create something new each time. That’s why I can answer questions I’ve never seen before, adapt to your wording, and connect ideas across very different fields.
Why this is a new paradigm:
Earlier software followed strict step-by-step rules. I work differently: I use probabilities, context, and pattern recognition to generate responses that feel conversational and adaptive. That shift—from rigid instructions to probabilistic, generative systems—is why many see AI as a new paradigm in computing.
Transformative, and empowering.
xx
Hello World as a case of OOP in action
vv
Let us look for a moment at a marked up Hello World Java Program, which is actually full of Object-oriented features, now that we know what to look for and where to look:
Yes, object-orientation is right there in the Title! See: "public class HelloWorld." Also, it is public so other objects may access it.
Next, passing by the /*. . . */ comment, we find a required method for every Java Program, the main method. This has a structure here that sets each section of code within a pair of double brackets { . . . } then includes the famed Java incantation:
public static void main(String[] args)
The method in view is public, callable by any object. It is static, set up early and callable by other classes without needing to be instantiated as an object. Void means, no return value.
Then of course, we invoke . . . main ( . . . ) which is the method with what it grabs listed between its "plier jaws."
![]() |
| Beads on a string, a model for string data structures (HT: 123learning.co.uk) |
Here, we see between the jaws the sort of message it accepts, strings. Better, s-t-r-i-n-g-s where characters are following one another like beads on a string. Hence, the name.
Strings itself carries a pair of square jaws. (And, "jaws" is informal but helps us see what is going on.)
Argument, args for short, is a fancy computer science word for what is to be acted on as input to be processed and yield an output.
BTW, more modern stylistic practice is to use indents and set off the braces to mark the indents. This helps with troubleshooting. As Nair gives on p. 26, adding colour coding for the { . . . } jaws:
/**
A Greeting Program
*/
public class HiThere
{
public static void main(String[] args)
{
System.out.println("Hello! How are you?");
}
}
The next line
System.out.println("Hello! How are you?");
tells us first, that the System class from the core Java Library API [Application Program Interface] is being summoned and extended as out for standard output. Out also means the standard output, the screen, is going to be used.
The dots show the extensions, don't overlook them.
After the second dot, we see the method to be used is print line, println( . . . ).
This will print a line and do a "carriage return,"or "line break," i.e. we are going back to the days of old fashioned typing printers that were like mechanised typewriters. Here, the output will write a line to the screen and enter, putting the cursor for onward steps, starting on the next line.
Notice, the string to be printed, "Hello world!" and how the double, plain quote marks mark out the string of characters.
Finally, the line is terminated with a semicolon.
Closing double brackets complete the required structure.
So, now we have decoded the strange-seeming incantation that sets up a Java program. It turns out, that Java wears its object orientation scaffolding on its sleeve, unlike Python, which hides it so a hello world is print ("Hello world!"). That makes Python easier to start with but we have to search harder to see how object orientation comes in. That's part of why Scratch and Python are in introductory units and Java will be our focus in these main units.
Another example with explicit scaffolding is HTML, hypertext markup language, which has a standard page description, layout structure like:
When executed, this is what we would see:
Also, our philosophy is to learn by tutorial-like case study examples, so we can build knowledge with understanding and skills by example.






































.jpg)






