Created by Maximilian Schwarzmüller
    Last Updated on December 18, 2019

    # What’s the Problem?

    When it comes to writing good code, you can dive into highly philosophical discussions about what exactly good code looks like and which programming paradigm you should follow.

    This article (and video, see above) will not join into those discussions though - instead, we’ll dive into three very important ways of writing code and compare them.

    • Procedural Programming
    • Object-oriented Programming
    • Functional Programming

    These three approaches will be shown at the example of JavaScript but they apply for most programming languages (some languages push you towards a certain paradigm though - JavaScript doesn’t).

    You find a detailed comparison of the three aproaches in the video on top of this page! There, we build a simple dummy website three times - once with each approach.

    In addition, you can also check out my JavaScript - The Complete Guide course where you learn JavaScript from scratch and in great detail (>45h of content!).

    # Procedural Programming

    Procedural programming is all about writing “procedures”. You could kind of translate this with: “Write down the steps your program should execute in order”.

    Here’s a brief example (dummy code):

    const button = document.querySelector('button');
    
    const doSomething = () => {
      // do something...
    }
    
    button.addEventListener('click', doSomething);

    In this snippet, we have four steps:

    1. Get access to the first <button> element and store it in a constant (button)
    2. Define a function doSomething
    3. Add an event listener to the button and run doSomething upon a click event
    4. Execute any code inside of doSomething

    This code snippet doesn’t look to spectacular - and it isn’t. It’s pretty straightforward vanilla JavaScript code. Indeed, when you’re learning JS, you’ll probably write code like this relativley early.

    It could be called “procedural” because we have multiple steps we execute after each other. That’s of course the case for all programs but we don’t group any logic in any special way - besides the doSomething function which we use to have some “on-demand” code for our click event.

    # Object-oriented Programming

    If we would follow an object-oriented style, we could re-write (and arguably over-engineer this simple example) in the following way:

    class InputArea {
      constructor() {
        this.button = document.querySelector('button');
        this.button.addEventListener('click', doSomething);
      }
    
      doSomething() {
        // do something
      }
    }
    
    new InputArea();

    As mentioned: This is definitely over-engineered. But it’s just an example - in bigger apps, structuring your code by grouping it into classes and objects can make your code easier to read and manage. The video on top of the page already shows a bit of a better example (i.e. a bit of a more complex project) already.

    The idea behind object-oriented programming (OOP) is that you organize your code in classes/ objects (objects are based on classes).

    Your data is stored in properties, your logic in methods. And properties and methods that work closely together live in the same class.

    An advantage of OOP is that your code resembles real-world examples (we think about objects all the time in the real world) and that code that belongs together is automatically grouped together.

    As a downside, you have the overhead of writing and using classes as well as maybe some issues with the this keyword in some cases. It is JavaScript after all.

    # Functional Programming

    So what’s functional programming then? The best approach?

    No - it’s simply another way of structuring and organizing your code.

    Here’s the same example one more time - again over-engineered.

    function findElementOnPage(elementTag) {
      return document.querySelector(elementTag);
    }
    
    function doSomething() {
      // do something
    }
    
    function connectInput() {
      const btn = findElementOnPage('button');
      btn.addEventListener('click', doSomething);
    }
    
    connectInput();

    You could write this differently, you could add more (or less) functions.

    The idea behind functional programming is that you organize your code into multiple functions where each function works on its own.

    That last part is important: Functions should be stateless and pure, they also shouldn’t cause side-effects (e.g. manipulate the DOM).

    Sometimes, side-effects can’t be avoided (and this is okay) but you should aim for functions that take some input (=> parameters) and produce/ return a reliable output.

    Like findElementOnPage. Of course this is a bit of a redundant function but you could do more in there than just select an element. You could add an if check to verify whether an element was found (and throw an error otherwise) for example.

    findElementOnPage is a pure function - for the same input it will always produce the same output. At least as long as an element is found on the page - hence you could argue that it actually has a side-effect (it doesn’t manipulate the DOM but it reaches out to it).

    The advantage of the functional approach is that you have a bunch of highly re-usable (and managable) functions which have little to no extra dependencies. This makes your code very easy to maintain and understand.

    Just like the OOP approach, this approach can be an overkill for very simply use-cases (like the example above) but it can really shine in more complex applications.

    # Which approach is best?

    So which approach is best, which approach should you use?

    There is no winner here - all three approaches are viable and fine to use. It’s up to you which approach you prefer.

    And the more experience you gain, the more you’ll be able to identify which code style might best suite a specific project you’re working on.

    Often you’ll end up with the OOP or functional style because the procedural style can reach its limits in bigger applications - you want to split and organize your code there typically.

    Of course there also are mixed approaches - you can build an app where you use some classes and some functions (outside of classes). This might be hard for some religious fanatics out there but if it works for you (and your team), you can of course go with such a hybrid style as well.

    This hopefully clarifies these three approaches a bit and helps you in your future projects. As always, share any feedback you have! :-)