Clean Code PHP – Abstraction and Encapsulation

So Abstraction and Encapsulation. You might have heard this before. We should correctly encapsulate our data and we should abstract our implementation. Both are important concepts in OOP. I will go over the basics of these 2 concepts because it’s important to understand what this actually means.

Object Encapsulation

So what is encapsulation? Well it binds together code and data that it manipulates. It keeps the code and data safe from outside interference and misuse.  We do this by wrapping data and functions together in a class. We then decide what we show to the world. For this we have the public, protected and private keywords.

All your properties and methods should at default be private. This means you can only use them inside your class. They are private to the world. Never make properties  in a class public, don’t allow the outside world to change your data directly. Always use methods to change your data. When functionality changes you don’t have to worry about someone else directly accessing properties. You can easily handle changes in your methods which then manipulates the private data properties.

The public keyword is used when you want to allow a method or property to be used to the public. Changes in public methods are dangerous. You cannot control the code that relies on public method or properties. So you only use public when you need to.

The protected keyword is used to allow child classes to change your data. It has the same dangerous effects as public methods or properties. You also have no control how child classed modifies this data. So this should also be used with caution.

Bad

<?php
class Product 
{
    public $name;
    public $stock;
}

$product = new Product();

// Remove stock
$product->stock -= 1;

Good

class Product 
{
    private $name;
    private $stock;

    public function removeStock($amount)
    {
        if ($amount > $this->stock) {
            throw new \Exception('Amount is greater then available stock!');
        } else {
            $this->stock -= $amount;
        }
    }

    public function addStock($amount)
    {
        $this->stock += $amount;
    }
}

$product = new Product();

// Remove stock
$product->removeStock(1);

By not directly modifying data we can create extra checks in public methods.  You also hide unnecessary data to the world and only expose the relevant data.  By doing this you need to know less about a class to implement it. You don’t need to worry about details.

Data Abstraction

And what is Data abstractions? Well it is a representation of data in which the implementation details are hidden or abstracted.  We reduce something to a set of characteristics. For this we can use interfaces or abstract classes. An interface is the most abstracted concept. You abstract it at the level that you only define the public methods you will need. But that alone don’t make for good abstraction.

Example

You have an Apple and a Pear. The most abstracted definition is a Fruit. Your interface or abstract class in that case is called Fruit.

<?php
interface FruitInterface {
    public function eat();
}

class Apple implements FruitInterface
{
    public function eat()
    {
        // Implementation details for eating Apple
    }
}

class Pear implements FruitInterface
{
    public function eat()
    {
        // Implementation details for eating Apple
    }
}

You can define a method to eat the fruit. You abstracted that you can eat a fruit. How to eat a certain fruit is not important here. That’s implementation.

You always start the design of a class from abstraction. If you want to implement a Product class. You first need to design your Product. You create an interface and you design it, you abstract it. What does it mean to be a Product. What public methods do I need for this product. You create a generalized view of your Product object. When you need to use a Product. You talk with abstractions. You define you need to use a ProductInterface. On a design level you think with abstractions.

Difference between Abstraction and Encapsulation

  • Abstraction solves the problem at the design level.
  • Encapsulation solves the problem at the implementation level
  • Abstraction hides unwanted data and give relevant data
  • Encapsulation means hiding the code and data in a single object to protect it from the outside world
  • Abstraction let you focus on what the object does instead of how it does it
  • Encapsulation means hiding how an object does things

Conclusion

Start with your abstraction. Then implement your abstraction to actual objects. First you design your classes, this is abstraction. You then implement your abstraction and encapsulate your objects correctly.

This means that every implementation always need to start from an abstraction. Think to code!