Switch statement decreases adaptability of a function Below you can see a class and a function. The class is just an dummy entity. The functon has a switch statement. That switch statement calculates the tax by to a predefined hardcoded string, and I don't like that. What's next, this switch statement violates the Open/Closed principle.
The class entity:
class Product {
    private int $id;
    private string $name;
    private int $price;
    private string $category;
    
    public function __construct(int $id, string $name, int $price, string $category) {
        $this-&gt;id = $id;
        $this-&gt;name = $name;
        $this-&gt;price = $price;
        $this-&gt;category = $category;
    }
    public function getId(): int
    {
        return $this-&gt;id;
    }
    public function getName(): string
    {
        return $this-&gt;name;
    }
    public function getPrice(): int
    {
        return $this-&gt;price;
    }
    public function getCategory(): string
    {
        return $this-&gt;category;
    }
}

The client code:
//$product = new Product(200, 'Bread', 200, 'Food'); // A different product category
$product = new Product(100, 'Chair', 5000, 'Furniture');

$taxForChair = calculateTax($product);
var_dump($taxForChair); // float 1050
exit;

function calculateTax(Product $product): float {
    // The switch statement below decreases adaptablity.
    // The function also violates the Open/Closed principle.
    // At this point, it has 2 cases. 
    // When the Business Rule change by create a new product category, then this function needs to change too.
    switch($product-&gt;getCategory()) {
        case 'Furniture':
            $tax = $product-&gt;getPrice() / 100 * 21; 
            break;
        case 'Food':
            $tax = $product-&gt;getPrice() / 100 * 9; 
            break;
        default:
            $tax = 0;
            break;
    }
    
    return (float)$tax;
}

Would you be so kind and write a better calculateTax function?
I fixed it by myself by introducing abstract classes, see below:
class Product {
    private int $id;
    private string $name;
    private int $price;
    private Category $category;
    
    public function __construct(int $id, string $name, int $price, Category $category) {
        $this-&gt;id = $id;
        $this-&gt;name = $name;
        $this-&gt;price = $price;
        $this-&gt;category = $category;
    }
    public function getId(): int
    {
        return $this-&gt;id;
    }
    public function getName(): string
    {
        return $this-&gt;name;
    }
    public function getPrice(): int
    {
        return $this-&gt;price;
    }
    public function getCategory(): Category
    {
        return $this-&gt;category;
    }
}

here it goes
abstract class Category { 
    abstract public function calculateTax(int $price): float;
}
class CategoryFurniture extends Category {
    public function calculateTax(int $price): float {
        return (float)($price / 100 * 21);
    }
}
class CategoryFood extends Category {
    public function calculateTax(int $price): float {
        return (float)($price / 100 * 9);
    }
}

//$product = new Product(200, 'Bread', 200, new CategoryFood); 
$product = new Product(100, 'Chair', 5000, new CategoryFurniture);

$taxForChair = calculateTax($product);
var_dump($taxForChair); // float 1050
exit;

function calculateTax(Product $product): float {
    
    $price = $product-&gt;getPrice();
    
    $category = $product-&gt;getCategory();
    return $category-&gt;calculateTax($price);
}