Object-oriented programming might be a very strong & powerful way of writing code for software development, but many errors may arise when used improperly. OOP can provide you with a variety of features that can let you handle a lot of common programming issues, but when you exploit the usage of these features, you might end up developing spaghetti code.

Spaghetti Code

So, you might wonder what spaghetti code looks like. Is it yellow and stringy? Well, spaghetti code is a term used in programming to denote that your code is tangled in itself where the source code accesses everything it needs randomly from anywhere without following a certain protocol or style – and therefore resembles a plate of spaghetti. Code like this can be hard to maintain & visualize for long-term purposes.

Don't Be Like Him

Loose Coupling and Tight Coupling

So, what exactly is the Law of Demeter? The Law of Demeter is a principle or a guideline that is used in object-oriented software development, which is based on the idea of Loose Coupling.

Loose Coupling vs Tight Coupling

Loose Coupling is a design concept that encourages the reduction of one class's dependencies on another and ensures that those classes don't break due to changes in each other. On the other hand, Tight Coupling means that the components or objects are heavily dependent upon other classes' components and objects.

The Law of Demeter

The Law of Demeter is also known as the dots rule/multiple dots rule. Demeter Law is therefore based upon the idea of Loose Coupling, which can be summarized in the following ways:

  • Each unit should have limited knowledge about other units: only units "closely" related to the current unit.
  • Each unit should only talk to its friends; don't talk to strangers.
  • Only talk to your immediate friends.

This law creates minimal privileges for classes to contact or make changes to each other. It lets a single module only access the information and resources that are strictly necessary for the module's functionality.

Example 1

Here's an example code that violates the Law of Demeter:

Player.GetNearestObject().GetStatsComponent().UpdateUI();

Let's diagnose the code above.

We can see we first get access to our player class and then get the nearest object from it. However, when we try to get the stats component of the nearest target, we don't know what type of class we are going to get from the GetNearestObject. This is the first bad dependency we get. Similarly, when we try to update the UI, it creates another dependency.

The problem with the code is that the code chain has too many link dependencies, and if we proceed to do a single change to the part of the chain, everything needs to change according to their dependencies. This is not a suitable way to implement such a functionality.

So, to solve the problem with the above code, you will have to write something like:

Player.UpdateNearestObjectStatsUI();

This way, you will have a loosely coupled code where the player class will contain more code, but the chain link will be eliminated, making the code much safer. All the checks for objects with Stats can be checked inside the player class. Also, any changes to StatsComponent will be easier to find now.

Example 2

Here's another use case for the Law of Demeter:

public class Player:MonoBehaviour{
	public PlayerPower powerUp;
    [SerializeField] PlayerUI playerUI;
    public void OnPowerUp()
    {
    	playerUI.UpdatePowerUI();
    }
}

public class PlayerUI:MonoBehaviour{
	public void UpdatePowerUI()
    {
    	Player player = 		 Gameobject.FindObjectWithName("Player").GetComponent<Player>();
        if(player.powerup.teleport.maxPowerLimit < 0){
        //Update UI here
        }
    }
}

public class PlayerPower(){
	public TeleportPowerUp teleport;
}

public class TeleportPowerUp{
	public int maxPowerLimit;
}
Code Violating the Law of Demeter

The above code is another example of a violation of the Law of Demeter.

In the PlayerUI class, the if statement checks through a chain of links just to find the maxPowerLimit of a powerup. Let's take an instance here: if there are some changes to the PlayerPower class that lets it hold more powerups, we will have to create more dependency chains for PlayerUI, which will make the code harder to manage and retain editability.

To fix the above code according to the Law of Demeter, we can:

public class Player:MonoBehaviour{
	public PlayerPower powerUp;
    [SerializeField] PlayerUI playerUI;
    public void OnPowerUp()
    {
    	playerUI.UpdatePowerUI(powerUp);
    }
}

public class PlayerUI:MonoBehaviour{
	public void UpdatePowerUI(PlayerPower pow)
    {
    	Player player = 		 Gameobject.FindObjectWithName("Player").GetComponent<Player>();
        if(pow.GetMaxPowerLimit() < 0){
        //Update UI here
        }
    }
}

public class PlayerPower{
	public PowerUp currentPowerUp;
    
    public int GetMaxPowerLimit()
    {
    	return currentPowerUp.maxPowerLimit;
    }
}

public class TeleportPowerUp:PowerUp{
	public int maxPowerLimit;
}

public class PowerUp{
	string powerUpName;
    float powerUpLevel;
}
Code Following the Rule of Demeter

Here, we now make sure that our PlayerUI class gets limited information from the PlayerPower class. We have also decoupled the chain by passing in our PlayerPower object as a parameter for the UI update, and we have added a line of code in the PlayerPower class that lets us get the read-only maxPowerLimit through a function.

I have also separated the TeleportPowerUp by making it inherit another parent class called PowerUp that makes sure that the PlayerPower class only handles the current powerup – making the code reusable for every other powerup as well.

Conclusion

The Law of Demeter reduces long dependencies among classes and their objects, ensuring the code isn't spaghetti. You can also use actions, delegates, and properties to solve these huge code dependencies. Following the Law of Demeter also lets you create more robust and reusable code as most of your code becomes more suitable for later use because of its independence.

Loose Coupling FTW
Thank you for reading and learning with me. Please leave comments if you have any regarding this article.