Universally Bad Programming Practises (and their alternatives) pt.1
Tags: webdev, programming, productivity, php
Published: 2023-01-26 19:47:30


The focus of this post is to highlight **bad programming practises that can occur on any modern programming language or framework**. We are going to try and identify bad practises that are unquestionably wrong and should be avoided.

To try and analyse these bad practises, undestand why they are happening and how they can be solved we will need a programming language to show some concrete examples. **We will use PHP** for this as i am most familiar with it.

<hr>

So one of the unquestionable bad practises used is...

#**Uncontrolled usage of global variables** 🤪

![A line that goes from complex to straight](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bxskf7w59cbh72j79ayj.png)
_(in reverse)_

Our usual suspects are **Global Mutatable States**

**[Global](https://www.javatpoint.com/what-is-global-variable)** means that it can be **accessed from every point of our code**. A usual example for this is the $_POST, $_GET or $_SESSION parameter in PHP. 

**[Mutatable](https://developer.mozilla.org/en-US/docs/Glossary/Mutable)** means that it **can change its value from everywhere**. $_SESSION parameter is an example of a parameter that is going to be used throughout our application and can change its state.

**[State](https://academind.com/tutorials/what-is-state)** is the current situation. For example a switch of a light has two states. Being on or off. Based on its history it can only go from one state to another. If it is On the only state it can go into is being off.

One clear example of widespread use of Global mutatable states is the **$_SESSION variable in PHP**.

<hr>

## An example of uncontrolled usage of a global variable🔧

Let's suppose that you are saving in a session the information of a cart in an e-shop. $_SESSION['cart']. Your use of the session variable is justified as the user will need access to the cart information througout his visit. Let's look at an example of a function that takes a decision based on the cart length

```php
function sendNotificationEmailBasedOnCartLength() {
    if (sizeof($_SESSION['cart']) > 4 && $_SESSION['cart']['hasSentEmail'] == 0) {
        sendSomeEmail();
    }

    $_SESSION['cart']['hasSentEmail'] = 1;
}
```
<hr>
### Unessesary global injection ❌

Issues that injection presents:

1. **Maintainabillity:**
In this example we can see that there is an **unecessary injection of the global variable $_SESSION['cart']** inside function. This function is at this point **dependant** on the $_SESSION variable to function. Even if we decide later that we have found a better way to store and retrieve cart information we will have to **identify every point that $_SESSION** is used and change the usage. 

2. **Readabillity:**
One more problem that arises from injecting these global variables is that whoever is reading the function doesn't know that these variables exist in the first place. It is not obvious as they are not stated as parameters. This degrades the readabillity of the code.

This is an **error-prone** approach. If your project does not have test suites you will have to debug this slowly and a lot of mistakes will eventually land on production.

### Uncontrolled change of global state

Here we are changing the hasSentEmail value of cart to 1 to inform the application that we have already sent an email to this cart and to not do it again.

**Where else does this value change? We have absolutely no clue** The hasSentEmail value from $_SESSION variable could change at any point in our application from any function if we do not have any controlled way of using this session. If we are doing a session_start() and opening the session gate in every file there could be a session mutation in any file. **This creates unpredictabillity and destabilizes our program**. 

<hr>

## Solutions! 🤔

### Limit the globallity of the $_SESSION

```php
function sendNotificationEmailBasedOnCartLength(int $cartSize, int $hasEmailBeenSentForCart = 0) {
    if ($cartSize > 4 && $hasEmailBeenSentForCart == 0) {
        sendSomeEmail();
    }
}
```

First you would need to decouple the function and the session. Pass any information you need about the session inside the parameters of the function. This limits the global variable to a local variable.

### Better control of $_SESSION by limiting it's usage

Second, you should not access the $_SESSION['cart'] variable directly in any file. Choose a file and create a class that is responsible for creating the session, retrieving it and changing it. By having a single class that is responsible for these actions you can be assured that the global variable will not have an unexpected state somewhere down the road. 

```php
session_start();

class Cart {
    private $products;

    public function __constructor() {
        if (!$_SESSION['cart']) {
            $_SESSION['cart'] = ['products' => [], "emailIsSent" => 0];
        }
    }

    public function initializeCart() {
        $_SESSION['cart'] = ['products' => [], "emailIsSent" => 0];
    }

    public function addProduct(Product $product) {
        $_SESSION['cart']['products'][] = $product;
    }

    public function setEmailIsSent() {
        $_SESSION['cart']['emailIsSent'] = 1;
    }

    public function getCart() {
        return $_SESSION['cart'];
    }
}
```

Here can see a simple example of creating a class that is in **the only mutator and retriever $_SESSION['cart']**. If you decide in the future to retrieve information for the cart or creating a new cart you are **not dependable on the $_SESSION['cart']** variable as you can swap the functionallity of these functions anyhow you like and the your app would work the same. 

Additionally we can decide that only _these_ classes will have the abillity to interact with sessions and remove all session_start() instances from anywhere else making sure that this **global variable will only change its state in this controlled enviroment**.

The session['cart'] variable can only hold the values specified by this class. 

<hr>

## In conclusion

We did show why having a global variable mutate uncontrollably in our application is bad as it creates:

1. Unpredictabillity
2. Maintainabillity issues
3. Unredabillity

and we demonstrated with the use of classes that control the mutations and retrieval of these variables how we can make our application cleaner and easier to adapt to change

Sources:
- [Global mutatable states](https://ericnormand.me/article/global-mutable-state)