Some Thoughts about Different Programming Paradigms

Sunny Pun
6 min readMar 13, 2019

Object Oriented Programming. Functional Programming. Reactive Programming…

Buzzwords?

Hypes?

Those are paradigms.

If you search on Wikipedia, you’ll see a big list (nested list indeed) that shows a lot of different paradigms.

Programming is a lifelong journey. Paradigms, like tools, are made to address different issues. Not only should we learn about how to use them, but also when to use them. We should internalize the concepts and use them, which empower us to be language and framework agnostic.

Programming is a lifelong journey. Paradigms, like tools, are made to address different issues. Not only should we learn about how to use them, but also when to use them. We should internalize the concepts and use them, which empower us to be language and framework agnostic.

As time passes, there are different trends. Like drinks — every one of them exists for a purpose. Every one has different preferences and tastes.

Source: Unsplash

So here I would like to go through some paradigms that I have learnt, in chronological order, and to suggest that the name isn’t what the concept is about.

This must be controversial. Shouldn’t we make it conversational? Feel free to leave me comments whether you agree or not!

Imperative Programming isn’t about Imperative

Imperative Programming is what is like for the first few lessons of Programming 101. “Imperative” means to give commands in an authoritative manner.

During those lessons, we were told how to use computers’ language. To command computers to compute for us. We learnt about syntax. We learnt about how code is executed, line by line.

However, the most important take-away is about our mindsets. We have to keep learning how to break a problem into steps that we know how to implement. It’s about building using building blocks we have. It’s about how to express our thoughts clearly and precisely.

Source: http://www.commitstrip.com/en/2016/08/25/a-very-comprehensive-and-precise-spec/

Procedural Programming isn’t about Procedures

After we have acquired knowledge about how to do basic variable assignments and manipulation, with some conditionals, looping control structure, we were taught that we can group several lines of code together and put them somewhere else. Those are procedures, or sometimes called subroutines, functions, methods…

Yup. One of the reasons is that we can achieve code reuse.

It’s about the big picture. Sometimes we can exchange the order of a few lines to group similar lines together. Sometimes we group not the similar lines, but the related, relevant lines.

It’s about “divide and conquer” and design upfront. We have a flow about how to approach the problem and write the procedures to solve each “milestones” in each stages of the flow. Code reuse will come as a by-product when each stages are decoupled.

And we get less if we are from pulling lines out of a few hundred lines just to make the main procedure look shorter and bugs buried deeper.

Object Oriented Programming isn’t about Objects

OOP gives us a lot of good things: Encapsulation, Polymorphism, Inheritance… And we have SOLID principles.

We like the extensibility. We like interfaces more than inheritance someday. We have public, private, and sometimes protected and even more. We put almost everything in classes and instantiate them as objects to call their methods.

I’d say it’s about state management. What changes the internal state of a class should only happen in its methods. When the program grows bigger, this “guarantee” helps a lot by having much less lines to read for debugging.

While all these can be said with one word “encapsulation”, I do want to put more focus on “changes to internal state are internal”, instead of “being a black box”.

Illustration: Pseudocode for Checkout, with Objects

Lemme illustrate the point with an example of doing a checkout, which we have products in the cart and we want to have the final sum. We’ll call the payment API with that sum to charge the customer.

So here we have 3 products and the cart: (pseudocode)

Product product1, product2, product3; Cart cart;

Everything is an object. What if we do this to call the API with the sum:

// ...
cart.sum = product1.price + product2.price + product3.price;
// ...
callAPI(cart.sum);

Though everything is an object of some classes, if in the end we called the API with a wrong sum, we have to look into what happened before and after the line for assigning the sum. This way, we can still say we are doing OOP (we have objects!), but we are not harnessing what is good about OOP.

Getters and Setters

Let’s make the sum private. Let’s see what can happen:

sum = product1.getPrice() + product2.getPrice() + product3.getPrice();
cart.setSum(sum);
// ...
callAPI(cart.getSum());

It even does what I have mentioned: changing the sum only happens in setSum. However, maybe you could sense it — after we know we are calling the API with the wrong sum, we know it is happening in setSum, but then we have to trace back to the “bigger” scope which is about how we calculated the sum and pass it to setSum.

The problem (of poor structure) may even happen in a “form” that, we are now allowing one more products to be added to the cart. A random developer just set the correct sum before calling the API, leaving all previous calls untouched.

What should it Look Like?

cart.addProduct(product1);
cart.addProduct(product2);
cart.addProduct(product3);
// ...
callAPI(cart.getSum());

(If we want the cart to be responsible for the calculation, ) the calculation should go into the cart. Discounts, freebies, etc. should go with it. When we have to debug, we’ll go inside the cart, and see how it is applying all the business logic, without going back to outer layers.

One thing that I’d look for when doing Code Reviews is how “localized” is a piece of code. addProduct and getSum are of the “same abstraction level”. However plain old number addition is more “profound” than setSum and getSum. That somehow helps ensuring we are (at least trying to) properly name the procedures to get the code itself as a documentation.

Let that sink in if that sounds unfamiliar.

We feel a little bit left behind if we have not memorized a few design patterns. Such patterns are good ways to decouple object relationships. Even it may be hard to recite them, try to understand what problem the pattern is trying to solve, and that will help even when we are not doing OOP.

Functional Programming isn’t about Functions

When learning Functional Programming, it was really eye-opening to see that we don’t have if and for. And the idea that “everything has to return something” (so we use cond and map instead).

And then we may come across Maybe, Optional types and learn about wrappers. As how scary “design patterns” are to OOP, Monads, Functors, Reducers, Transducers came into the picture of FP.

With all the goodies (currying, ease in defining new types) that come with FP, the core concepts are immutability and avoid side-effects as much as possible.

When we refrain from doing assignments (not the course assignments, I mean variable re-assignments here), we have confidence about where the input values are from. The idea of having functions returning a value which only depends on the inputs (without concerning about global state, other instance statuses if those are not the inputs) increased testability a lot.

As the returned value is only depending on the inputs, it helps polymorphism in the sense that we have “pattern matching” for arguments which runs different lines of code while calling the same function (like doing a recursive call).

By the way, there is a design pattern named as “decorator” which is often used in the functional programming paradigm. A function which wraps another function to add more functions to the function.

Reactive Programming isn’t about React

Okay this title is a joke. But I do think Reacting Programming isn’t about how to make things reactive.

We do have to learn a ton about how observers observe observables, subscribers subscribe subjects.

It’s more about hooks (or streams which have many hooks). It’s about how to do the pub-sub (publisher-subscriber) structure to make interdependent (conceptual) components to be updated more automagically according to underlying changes.

This piece of knowledge helps a lot when we are using various third party libraries, about event handlers. This makes us aware of providing “anchors” that others can rely on to build on things that we have built.

Again, tell me what you think and correct me if I missed some key points! Thanks for reading.

--

--

Sunny Pun

Amateur Writer about Programming, and Cantonese Lyrics Enthusiast esp. Church Choral Music