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
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.