exercises and solutions

OOP exercises

OOP exercises should focus on responsibilities rather than syntax inventory. Ask what data an object owns, which operations it exposes, and which invalid states it prevents.

Practical Example

PHP example
<?php

declare(strict_types=1);

final class Basket
{
    public function __construct(private array $items) {}

    public function total(): int
    {
        return array_sum(array_column($this->items, 'price'));
    }
}

$basket = new Basket([['price' => 500], ['price' => 750]]);

echo $basket->total() . PHP_EOL;

// Prints:
// 1250

OOP exercises should focus on responsibilities: what data the object owns, what behaviour it exposes, and what it hides from the caller.

Useful extensions include introducing a value object, replacing a broad array with a typed model, or adding an interface where callers genuinely need interchangeable implementations.

Practice

Model A Basket
Show solution

Validate each quantity when constructing or adding an item, then sum price_pence * quantity inside total(). Keep the items private so callers cannot bypass the invariant.

The object earns its place by owning a rule and a useful operation, not merely by wrapping an array.

Model A Money Value
Show solution

Keep the pence value private and validate it in the constructor. add() should return new Money($this->pence + $other->pence). A formatter can return number_format($this->pence / 100, 2).

Returning a new value keeps the object easy to reason about and prevents callers from changing an existing total accidentally.