Lange Methoden kürzen
Stellen wir uns ein Objekt vor, das eine Zeichenkette repräsentiert, die eine bestimmte Länge haben muss. Konkret fordern wir, dass der String mindestens fünf, aber höchstens zehn Zeichen lang sein darf:
<?php declare(strict_types=1);
namespace spriebsch\tfd\cleanCode\singleLevelOfAbstraction\checks;
use RuntimeException;
class SomeObject
{
private string $string;
public function __construct(string $string)
{
if (mb_strlen($string, 'UTF-8') <= 5) {
throw new RuntimeException('Too short');
}
if (mb_strlen($string, 'UTF-8') >= 10) {
throw new RuntimeException('Too long');
}
$this->string = $string;
}
}
Wir verwenden mb_strlen()
anstelle von strlen()
, damit wir auch mit Umlauten und anderen Gemeinheiten, die nicht als genau ein Byte kodiert werden, richtig umgehen können. Ein Unicode-Zeichen entspricht schließlich nicht immer einem Byte.
Ein zu kurzer String führt also zu einer Exception:
<?php declare(strict_types=1);
namespace spriebsch\tfd\cleanCode\singleLevelOfAbstraction\checks;
require __DIR__ . '/autoload.php';
$object = new SomeObject('short');
var_dump($object);
PHP Fatal error: Uncaught RuntimeException: Too short in SomeObject.php:14 Stack trace: #0 short-will-fail.php(7): spriebsch\tfd\cleanCode\singleLevelOfAbstraction\checks\SomeObject->__construct() #1 {main} thrown in SomeObject.php on line 14
Ebenso führt ein zu langer String zu einer Exception:
<?php declare(strict_types=1);
namespace spriebsch\tfd\cleanCode\singleLevelOfAbstraction\checks;
require __DIR__ . '/autoload.php';
$object = new SomeObject('this is far too long');
var_dump($object);
PHP Fatal error: Uncaught RuntimeException: Too long in SomeObject.php:18 Stack trace: #0 long-will-fail.php(7): spriebsch\tfd\cleanCode\singleLevelOfAbstraction\checks\SomeObject->__construct() #1 {main} thrown in SomeObject.php on line 18
Aber wenn wir uns anstrengen, können wir es unserem Objekt sogar auch recht machen:
<?php declare(strict_types=1);
namespace spriebsch\tfd\cleanCode\singleLevelOfAbstraction\checks;
require __DIR__ . '/autoload.php';
$object = new SomeObject('a-string');
var_dump($object);
example.php:8: class spriebsch\tfd\cleanCode\singleLevelOfAbstraction\checks\SomeObject#2 (1) { private string $string => string(8) "a-string" }
Ah. Eine Zeichenkette, in einem Objekt gekapselt. Wir wissen nun von dieser Zeichenkette, dass sie nicht zu lang und nicht zu kurz ist. Aber wo bleibt jetzt unsere Pyramide? Oder anders gefragt: Welche Abstraktionsebenen hat unser Konstruktor?
Das, was ich gerne "frickeln auf Daten(strukturen)" nenne, in unserem Beispiel die Aufrufe der Funktion mb_strlen()
, die ja zum Beispiel sämtliche Besonderheiten von Unicode-Encoding vor uns verbirgt, ist auf jeden Fall eine technischere Abstraktionsebene als das fachliche "prüfe die Länge der Eingabe".
Wir könnten vermutlich sogar argumentieren, dass mb_strlen()
eine andere Abstraktionsebene als strlen()
ist, weil die eine Funktion Unicode verstehen kann, während die andere nur Bytes zählt.
Wenn ich das hier so schreibe, dann bin ich ehrlich gesagt hin- und hergerissen zwischen der Frage, ob diese Überlegungen für Dich Leser jetzt total klar und verständlich sind, oder ob Du Dich gerade fragst, ob dieses Nitpicking hier nicht einfach nur Zeitverschwendung ist.
Lass uns mal den "langen" Konstruktor kürzen. Ich weiß, dass er nicht wirklich lang ist, daher möglicherweise das "Nitpicking". Aber ein Beispiel muss halt immer auch halbwegs kurz und übersichtlich sein, deshalb wird hier vielleicht nicht so sehr deutlich, worum es uns eigentlich geht.
Stell Dir einfach vor, der Konstruktor einer realen Klasse wäre deutlich länger als dieser hier. Dann würde uns "Single Level of Abstraction" einen guten Impuls geben, wie wir diesen langen Codeblock kürzen können.