Besserer Code durch ordentliche Kontrollstrukturen

In diesem Artikel schreibe ich mal ein wenig über Kontrollstrukturen. Genauer gesagt Verzweigungen in Programmen, vielleicht auch besser bekannt als ‘if’ oder ‘switch’.

Warum denn das? Die Praxis zeigt, dass obwohl es sich dabei um absolute Grundlagen handelt, viele Programmierer unnötigen und dadurch oft unübersichtlichen Code schreiben.

Es lohnt sich auf jeden Fall mal einen Blick darauf zu werfen.

Ich gehe einfach mal davon aus, dass die Strukturen von ‘if’ und ‘switch’ grundsätzlich vertraut sind und gehe nicht weiter darauf ein.

Beim Programmieren geht es in erster Linie darum, die gewünschten Vorgaben, und seien es auch nur die eigenen Ideen, möglichst schnell umzusetzen. Also wird mal hier, mal da schnell was gebastelt und schon ist das Programm fertig und alle sind glücklich – vorerst.

Nun entwickelt sich die aber Anwendung weiter, weil weitere Anforderungen hinzu kommen. In der Zwischenzeit arbeitet auch schon die Xte Generation Entwickler daran und weil es immer schnell gehen soll, wurden viele Ausnahmen und Sonderfälle implementiert (natürlich nicht kommentiert!) und nun haben wir ein ‘historisch gewachsenes’ Gebilde.

Das Problem wächst an dieser Stelle mit, da jede weitere Änderung in diesem unübersichtlichen Code mehr Zeit beanspruchen wird und die Arbeit dadurch teurer wird.

Wie halten wir unsere Anwendung also nun möglichst sauber und verständlich? Zum Einen hilft sicher Rücksicht gegenüber Anderen, die wahrscheinlich irgendwann an unserem Code mit- oder weiterarbeiten müssen und natürlich ein gewisses Maß an Erfahrung.

So, genug geredet. Was wären denn nun typische Fälle? Hier eine kleine Auswahl:

<?php
/**
 * @return bool
 */
function hasParent()
{
  if(null !== $this->_parent) {
    return true;
  } else {
    return false;
  }
}

In diesem Fall ist das If-Konstrukt absolut überflüssig, da die Bedingung ja an sich schon einen Wahrheitswert ergibt und auch direkt zurückgegeben werden kann.

<?php
/**
 * @return bool
 */
function hasParent()
{
  return null !== $this->_parent;
}

Ähnlich können wir auch vorgehen, wenn wir einen booleschen Wert auf das jeweilige Gegenteil ändern wollen.

<?php
if(true == $flag) {
  $flag = false;
} else {
  $flag = true;
}

Dieses unhandliche Konstrukt können wir auch kürzer schreiben.

<?php
$flag = !$flag;

Wenn wir Variablen mit einem booleschen Wert prüfen, dann können wir auch auf den Vergleichsoperator verzichten. Ansonsten ist es ratsam, den konstanten Wert links und die Variable rechts vom Operator zu schreiben, weil dadurch Vertipper, wie ‘=’ statt ‘==’ schneller gefunden werden können.

<?php
if($flag) {
  // mach was
}

Eine weitere Möglichkeit, den Code übersichtlicher zu machen, ist der Verzicht auf unnötige Verschachtelung von Bedingungen.

Halte den Code links!

Was ist damit gemeint? Zuerst wieder ein Beispiel, wie es nicht aussehen sollte:

<?php
function machWas()
{
  if(true == $value1) {
    if(5 == $value2) {
      return false;
    } else {
      return true;
    }
  } else {
    return false;
  }
}

Diese Verschachtelung macht den Code unübersichtlich und schlecht lesbar. Ich habe auch schon Code gesehen, den ich horizontal scrollen musste, weil zuviele Bedingungen ineinander verschachtelt waren.

Ein wenig umformuliert und schon ist unser Codeblock kürzer und übersichtlicher. Wir verwenden quasi Wächter, die uns aus der Funktion leiten.

<?php
/**
 * @return bool
 */
function machWas()
{
  if(true != $value1) {
    return false;
  }
  return 5 != $value2;
}

Neben den typischen If-Konstrukten können wir in manchen Situationen auf Kurzschreibweisen zurückgreifen. Zum Beispiel, wenn wir das Ergebnis für eine Zuweisung oder Ausgabe weiterverwenden wollen.

<?php
$variable = bedingung ? 'ist wahr' : 'ist nicht wahr';

Wenn das immer noch zu lang ist, dann geht es sogar noch kürzer. Allerdings ist hier immer der jeweilige Kontext zu beachten.

<?php
defined('APPLICATION_ENV') || define('APPLICATION_ENV', 'development');

Wer mit dem Zend Framework arbeitet, dem wird dieser Ausdruck bekannt sein. Am Anfang steht die Bedingung und hinter dem OR-Operator (‘||’) die alternative Aktion. In diesem Fall wird geprüft, ob die Konstante APPLICATION_ENV bereits definiert ist oder noch gesetzt werden muss.

So können wir mehrere Aufrufe hintereinander notieren und die Abarbeitung stoppt, sobald eine Bedingung wahr (true) ist.

<?php
tuDies() || tuDas() || machWasAnderes();

Vielleicht sind die Aufgaben aber auch voneinander abhängig, so dass die dritte nur ausgeführt werden soll, wenn die erste und zweite erfolgreich waren.

Dann könnten wir das so schreiben:

<?php
tuDies() && tuDas() && machWasAnderes();

Soviel zu den If-Bedingungen, aber wir haben ja auch noch unser ‘switch’.

Mit switch können wir übersichtlichen, aber dennoch komplexeren Code schreiben.

<?php
switch($errorLevel)
{
  case NOHOPE:
    echo 'Das wars, super schwerer Fehler!';
    break;
  case CRITICAL:
    echo 'schwerer Fehler!';
    break;
  case ERROR:
    echo 'Fehler!';
    break;
  default:
    echo 'keine Ahnung was los ist!';
    break;
}

Hier könnten wir auch auf zwei breaks verzichten und einfach mehrere Stufen mitnehmen.

<?php
switch($errorLevel)
{
  case NOHOPE:
    echo 'Das wars, super ';
  case CRITICAL:
    echo 'schwerer ';
  case ERROR:
    echo 'Fehler!';
    break;
  default:
    echo 'keine Ahnung was los ist!';
    break;
}

PHP erlaubt uns im switch-Konstrukt sogar noch mehr; wir können die Bedingung auch hinter das case hängen und haben dadurch noch etwas mehr Möglichkeiten.

<?php
switch(true)
{
  case tuDies():
    echo 'tuDies() gab true zurück';
    break;
  case tuDas():
    echo 'tuDas() gab true zurück';
    break;
  case machWasAnderes():
    echo 'machWasAnderes() gab true zurück';
    break;
  case ($a <= $b):
    echo '$a <= $b';
    break;
  default:
    echo 'keine Ahnung was los ist!';
    break;
}

Zusammenfassend lässt sich sicher sagen, dass sich der Programmablauf auf viele Arten beeinflussen lässt. Richtig oder falsch gibt es an dieser Stelle nicht. Als Entwickler sollte man selber entscheiden, was im jeweiligen Kontext lesbarer ist.

Entgegen dem Satz ‘Wenn dein einziges Werkzeug ein Hammer ist, dann sieht jedes Problem wie ein Nagel aus’, müssen wir nun nicht mehr stumpf auf alles draufhauen, sondern können qualifiziert unterscheiden und saubere Arbeit abliefern, denn wir haben eine bessere Auswahl an Werkzeugen!

Schlagwörter: Adapter, Amazon, Animation, Annotations, Anonyme Klasse, Ant, Apache, API, Array, ArrayAccess, Attachment, AutoLoader, Bedienung, Bedingung, Benchmark, Bildbearbeitung, BOM, Bootstrap, Bot, Byte Order Mark, Callback, CamelCase, Canvas, Captcha, Cheatsheet, CLI, Closure, Cloud, CodeSniffer, Community, Comparator, Contest, Controller, Converter, CouchDB, Countable, Cronjob, CSV, CustomLibrary, Custom_Model, Data Mapper, Datei, Datenbank, Datenstruktur, Datentypen, Dating, Decorator, Dekorierer, Design Patterns, Dump, Duplikat, each, Eclipse, Entwicklung, Entwurfsmuster, Enum, Erweiterung, Eventhandling, Exception-Handling, Extension, Factory, Fehler, Flash, Foreach, Formatierung, Formular, Funktion, Futon, Header, HTML5, HTTP, IDE, If, Implementierung, InnoDB, Interceptor, Interface, isset, Iterator, Java, JavaScript, jQuery, Konfiguration, Konsole, Kontrollstruktur, kopieren, Late Static Binding, Layout, Linux, Listeners, Logging, Löschen, Magento, Magic Methods, Marketing, Methode, Model, MVC, MySQL, NetBeans, Objekt, Observable, Observer, OOP, Operator, Parameter, Partnersuche, Performance, PHP, phpMyAdmin, PHPUnit, Plugin, Proxy, Qualitätssicherung, Query, Reflection, Request, Response, Rest-API, Rockstar, Routing, S3, Samba, Scheifen, Schleife, Schutz, Secure Shell, Selbstreferenz, Shop, Sicherheit, Sicherung, Singleton Pattern, SOAP, Sortierung, Sourcecode, Spam, Speicherproblem, Spickzettel, SPL, SSH, Statement, Stellvertreter, Strategy Pattern, Stream, String, Sun VirtualBox, Support, Switch, Symfony, Symfony2, Symfony Live, Tag, Template, Template Method, Ternär Operator, Testing, Thumbnail, Tool, Tour, Twig, Type-Cast, Umwandlung, Underscore, unset, Vererbung, Verzweigung, Video, Videospiel, Virtualisierung, Visitor Pattern, Vorschaubild, walk, Webserver, Webservice, Weiterleitung, Wrapper, Youtube, Zeitsteuerung, Zend Framework, Zend_Cloud, Zend_CodeGenerator, Zend_Http_Client, Zend_Service, Zugriffsmethode