Introduction to Programming Paradigms

Software Engineering Series #3
In “Software Engineering Series”, I cover and discuss specific techniques and methods that are commonly used in large code bases. Software is a rapidly evolving field, and new ideas and techniques will always re-emerge over the years. This is by no means an exhaustive discussion. Opinions are welcomed, even more so when accompanied with actual experience.

Sat, Jan 30, 2021

Read in 7 minutes

One common saying is that "good code should read like a story". And just like a story, code can have different type of code structures for readers to make sense of what the code is doing.

Prerequisites

Some basic understanding of primitives and control flow. Familiar with if-else, while, for, etc.

Additional Resources / Reading List

https://hackr.io/blog/programming-paradigms - Good introduction. Can skip the section on logical programming, not very common in modern languages.

https://repl.it/ - Programming sandbox environment. Pick from any language and start playing with language features.

Head First Object-Oriented Analysis and Design: A Brain Friendly Guide to OOA&D by Brett McLaughin - Very fun and approachable book on understanding object oriented programming. Not matter how old, it is still relevant.

What is programming paradigm and why is it important?

Software development and programming is mostly an exercise in thinking and expressing our thoughts into code. One common saying is that “good code should read like a story”. And just like a story, code can have different type of code structure for readers to make sense of what the code is doing. This is especially important for code that is co-developed by a team, where team members need to quickly understand what is going on in order to make changes.

Most programming languages support a mix of programming paradigms.

In the following we will attempt to get the same result using different programming paradigms.

Procedural

As the name suggests, it is written in a way how you want the computer to carry out the procedure. It is code that literally hand-holds the computer through what you want it to do. It is also known as imperative programming.

list = ['apple', 'pear', 'orange']
index = 0

while index < list.length  do
	if list[index] == 'apple'
		put 'found'
	end
end

Core characteristics

Pros

Cons

Use cases

You can’t really escape procedural programming. After all, a computer is supposed to receive a set of instructions to do anything useful. However, the bulk of your thought process should not be thinking in procedures.

Functional

Functional programming has its roots from mathematics and relies heavily on using specific expressions to return values.

list = ['apple', 'pear', 'orange']

# This defines a function that calls itself
def find_apple(array)
	if array.empty?
		false
	elsif array[0] == 'apple'
		puts 'found'	
	else
		find_apple(list[1..array.length])
	end
end
# call the function
find_apple(list)

# this is another way, using 'reduce'
list.reduce(false) { |item| 
	if item == 'apple'
		puts 'found'
	else
		false
	end
}

Core characteristics

Pros

Cons

Usage

Simple functional programming principles can help you express your intent clearer and reduce surprises in your code. For example, when writing functions, separate the pure effects from impure effects. Example:

# --------------
# Impure example
def upcase_and_print(string)
	string.upcase!  # the ! changes the original 
	puts string   # < writing to terminal is a side-effect
end
text = "hello"
upcase_and_print(text) # ==> "HELLO"
puts text # ==> "HELLO"  -> this changed text by surprise

# ------------------------
# Separate pure and impure
def upcase(string)
	return string.upcase  # this doens't change the original 
end
def print(string)
	puts string
end
text = "hello"
new_text = upcase(text)
print(new_text) # ==> "HELLO"
puts text # ==> "hello"  --> this doesn't change original by surprise

Object Oriented Programming

As the name suggests, object oriented programming (OOP) is built around modelling things in the real world. Modelling software against real world objects is a natural (and correct) thing to do, and most people are able to pick up the basics quickly. It is also a fact that the invention of OOP paved the way for large and complex software to be built for the modern world.

class Fruit
	attr_reader :name # this line makes name publicly accessible

	def initialize(name)
# the '@' makes the variable specific to only this instance
# You can have many instances of Fruit, and this allows each to have
# different names that they maintain internally
		@name = name 
	end
end

class Basket
	def initialize(items)
		@items = items
	end
	
	def find_item(name) # this is known as a 'method'
		if @items.find { |item| item.name == name }
			puts 'found'
		end
	end
end

list = [Fruit.new('apple'), Fruit.new('pear'), Fruit.new('orange')]
basket = Basket.new(list)
basket.find_fruit('apple')  # ==> 'found'

Core characteristics

Pros

Cons

Usage

OOP should be the first thing that all new engineers learn. It is a common skill among engineers and most projects use OOP, so it is easy to slip into a project if needed. It also helps to promote critical thinking around where’s the best places to keep data and separate responsibility between classes.

Conclusion

There is more than 1 way to get the same result. What you choose depends on who and what you are working with. There are even more paradigms that are not discussed here like declarative (SQL), logical (Prolog) and more. Feel free to go down the rabbit hole at your own time.

Where to go from here?

I highly recommend trying out writing a couple of lines of code in OOP to get a feel of how it works. A basic exercise:

Foreign purchases

Create a class called Money that holds information about amount and currency.

Create a class called LineItem that holds information about transaction name and spending.

Spending should be an instance of Money.

Line item should have a method called print that outputs the value in a specific format.

spending = Money.new(100.00, 'SGD')
line_item = LineItem.new('clothes', spending)
line_item.print # You should see 'clothes SGD 100.00'

Find similarities and differences

Fire up your web browser and search for object oriented programming for some programming languages you have heard of (e.g. search object oriented programming python)

Look for similarities and differences in the way how each language

Popular languages are more similar than different. This exercise helps you to gain confidence that programming structure is more important than language specific syntax.

Learning to write software? Subscribe now to receive tips on software engineering.

Back to home page