The different programming paradigms
We utilise a number of different programming languages for the various products that we build here at Double Negative.
In keeping up to date with the development and progression of the various tools, frameworks, and paradigms that we use, I often find myself exposed to various 'buzzwords'.
I often find that these phrases are utilised in a seemingly misunderstood manner. One can not be a 'functional programmer' in that you can't explicitly always write code in a functional manner. Some programming languages are not built in a way conducive to functional programming.
This post serves as a general overview of my understanding of the different programming paradigms. I make no suggestions as to any being 'better' than the others simply because the utility of programming in a certain manner is completely context dependent. Furthermore utilisation of the paradigms below are not mutually exclusive in the same way that a 'project' often utilises multiple languages and tools.
Simply being aware of these paradigms is not enough - it is all in the execution. I could write purely functional PHP but it would be a complex and arduous process not best suited to what I want to achieve.
Functional programming is explained very succinctly by Kris Jenkins in the context of what he terms 'side-causes' and 'side-effects'.
My interpretation of functional programming is programming whereby everything is built up from functions. Functions can take other functions as inputs (first class citizens), and can return functions in a manner such that when pieced together (like lego bricks) you have a complete program. In the context of Kris' explanation, there are no external or independent dependencies for the executing functions - all inputs and outputs are known and discernible from the function signature.
Functional programming does not allow for mutable state, and has no need for loop constructs, instead relying on recursion.
Haskell is one of the commonly referenced Functional programming languages. As outlined on the linked page this means that it is optimised and designed with the intention of being used with functional paradigms. It makes it inherently difficult to program in other ways.
PHP (which I regularly use) is not typically considered a functional language, but given that it is is somewhat unconstrained in its nature, it can be used in a functional manner.
It is like having a toolbox - you can use the tools however you like. That said, people might give you some funny looks if you use a hammer in a manner that is not considered 'normal' or is overkill for the situation/problem. A hammer might get the job done, but that does not mean that using a hammer is an appropriate or reasonable way to do so. This is the reason why PHP is often looked down upon - its flexibility means that is often used poorly.
Object Orientated Programming (OOP)
Object Orientated Programming.. it's in the name. It is premised around Objects.
I feel that this StackOverflow answer explains it fairly well: "Objects are nouns, methods are verbs.".
For example, an item of 'Food' is an object that can be broken down into more specific forms (objects) - 'Cake', 'Steak' etc.
The Food object definition describes the properties of an item of 'Food' and the things that can be done to it. For example
OOP is associated with buzzwords such as:
Inheritance - the process by which 'Cake' inherits the properties and methods of its parent, 'Food'. As 'Cake' IS food, you can
Interfaces - a set of methods which the implementing class must define to conform. The
needsCooinginterface could specify methods that must be implemented by conforming classes to define how one cooks the 'Food'.
Polymorphism - the process by which many different types of object can do the same behaviours. Whilst 'Cake' and 'Steak' are inherently different, both can be eaten. By implementing a specific interface both can have
eatThis()implementations which do different things (stuff into mouth hole vs utilise knife and fork like a civilised human being).
Nate Good provides an easily accessible introduction to prototypical OOP.
Essentially POOP (tehehe) involves no separation between classes and instances. There is no explicitly differentiated blueprint of what 'Food' instances should look (or act) like, and instead everything is an object. An instance object simply delegates calls up its prototype chain as opposed to copying functionality from a blueprint.
Your blueprint IS an object, and your instances are also objects which inherit (or copy) the
prototype of the blueprint object.
I see no need to reinvent the wheel and explain prototypes when Sebastian Porto has done it so clearly already.
Interestingly, whilst Java is not typically considered a prototypical language, it can be utilised in such a manner. This answer gives some extremely interesting insights into the pros of prototypical design. This is also a prime example of paradigms in context. Whilst not the most obvious approach to designing a program in Java, given the context of what the author was trying to achieve, a prototypical approach served him best (for the reasons that he outlines).
Procedural programming is by my definition a situation whereby your code executes as it reads. That is to say, line 1 executes, then line 2, then line 3 etc.
Procedural programming avoids the abstraction inherent in Object Orientated design. As a result procedural programs can easily get out of hand as complexity increases, and can become prone to repetition (going against the Don't Repeat Yourself (DRY) paradigm).
Again, things are not black and white in that within an Objects method definition you could perform a series of procedural steps - do X, then do Y. Different aspects of your program can (and should be) programmed utilising the most appropriate paradigms for the problem.
My view is that a program should not be purely procedural, and when utilised within an OO design it should be utilised appropriately alongside/within the appropriate design patterns so as to make it optimally maintainable and readable.
Modular programming isn't so much a programming style but rather a manner of organisation. It essentially involves separating different 'parts' of your (much larger) program into modules which do specific functionality.
In one of our PHP based projects we have two distinct 'modules' namely 'Admin' and 'Public'. If I am looking to modify some administrative functionality.. guess where I go?
This allows you to decouple your software. You can minimise your file sizes by only including the modules that you require, whilst also making your codebase more manageable.
I am hesitant to use the word 'interface' (given the discussion above), but one can utilise an externally developed module and being aware of the methods that its API exposes write software without an underlying knowledge of its internals. Because the codebase is not tightly coupled the module developer could completely rewrite the module (whilst maintaining the exposed interface) and your code that utilises it would still work as expected.
require('module'). Browserify allows you to bring this functionality to the browser space. This means that 'reinventing the wheel' is no longer excusable. Why bother building something that someone else has already built?
So there you have it. An easily digestible overview of some of the more common programming paradigms.
If there is a particular paradigm that you want me to write about, or you have any questions or comments then do let me know.