Kürzer als Kurz: Der Ternär Operator für Geizige

Anfang diesen Jahres habe ich ja schonmal einen Artikel über Kontrollstrukturen geschrieben und bin dabei eigentlich nur nebenbei auf die Kurzschreibweise des IF-Konstruktes, den Ternär-Operator, eingegangen. Nun reiche ich einfach noch ein paar Beispiele nach und zeige, dass es noch kürzer als kurz geht.

Die gewohnte, und sicher aus jedem Informatikuntericht bekannte Form des If/If-Else kann ja bekanntlich beliebig viele Bedingungen abdecken und ist für Kontrollstrukturen auch sehr gut geeignet.

<?php
if ($bedingung1) {
  // mach was
} else if ($bedingung2) {
  // mach was anderes
} else {
  // mach was ganz anderes
}

Die geschweiften Klammern sind zwar bei nur einer folgenden Anweisung optional, aber sollten dennoch immer geschrieben werden, denn spätestens mit der nächsten Änderung und einer weiteren Anweisung werden sie gebraucht.

Für einfache Überprüfungen z.B. ob eine Variable gesetzt ist oder nicht, ist dieses Konstrukt dann aber doch etwas unhandlich.

<?php
if ('ja' == $wert) {
  $variable = 1;
} else {
  $variable = 0;
}

Nun gut, der Code ist nicht besonders sinnvoll, aber es geht ja auch nur um ein Beipiel. In der Kurzschreibweise sieht die selbe Logik dann so aus:

<?php
$variable = 'ja' == $wert ? 1 : 0;

Es müssen aber auch nicht immer Zuweisungen von Variablen sein, auch einfache Verzweigungen sind damit möglich. Ob man das im Code haben mag oder nicht sollte dann jeder für sich entscheiden.

<php
function peng() { echo __FUNCTION__; }
function puff() { echo __FUNCTION__; }

$flag = true;
$flag ? peng() : puff();

// Ausgabe: peng

Noch kürzer geht es, wenn wir auf Objektinstanzen prüfen wollen und gegebenenfalls eine Instanz erzeugen müssen.

<?php
class Obst {
  private $_name;
  public function __construct($name) { $this->_name = $name; }
  public function __toString() { return $this->_name; }
}

$test = new Obst('Apfel');

echo $test ?: new Obst('Birne');

// Ausgabe: Apfel

In diesem Fall wird nur dann eine neu Instanz von Obst erzeugt, wenn $test null ist. Dementsprechend wäre dann die Ausgabe Birne.

15 Kommentare

  1. Der Mensch ist von Natur aus faul. Das ist wahr. Aber wenn die Faulheit in nicht sofort lesbaren Code endet, ist die Grenze des erträglichen überschritten.
    Diese Schreibweise finde ich persönlich grauenvoll, da sie nicht sofort erfassbar ist. Wenn man nur für sich herum werkelt, mag dass noch gehen. Wenn man aber im Team arbeitet, muss man dafür sorgen, dass alle den Quellcode so schnell wie möglich erfassen können, um z. B. Fehler zu beheben, oder neue Sachen hinzu zu fügen.

  2. Kurzer Code = Schlechter Code

    ist eine einfache Regel. Code soll wartbar und lesbar sein.

    $variable = ‘ja’ == $wert ? 1 : 0;

    Ist das sicher nicht, da muss man schon genau schauen um zu sehen was gemeint ist. Bedenke: Eine Zeile Code wird nur einmal geschrieben aber zig mal gelesen.

    (und ja, unnoetig komplexer Code ist auch nicht gut)

  3. Hi,
    im letzten Beispiel wird allerdings ne Notice geworfen, weil $test nicht deklariert ist =)

    Außerdem gibts die ?: Extremkurzvariante erst seit php 5.3.

  4. @MaikL & Johannes: Wenn es um Zuweisungen geht, ist diese Schreibweise für mich übersichtlicher, weil alles in einer Zeile steht. Würdet ihr statt dessen eher die lange Form vorziehen?

    @Michael: Du hast recht, das habe ich vergessen dazu zu schreiben. Vielen Dank!

  5. Man kann den Operator ja durchaus für Zuweisungen benutzen aber dann sollte zumindest nicht mit Formatierung gespart werden. Ich schreibe ja auch nicht ein ganzes Skript in eine Zeile nur weil ich es kann und es dann kürzer aussieht ;-)


    $variable = ('ja' == $wert)
    ? 1
    : 0;

    so finde ich persönlich es durchaus lesbar (Einrückung bitte dazu denken falls das Blog sie nicht anzeigt)

  6. Ich schließe mich meinen Vorredner an – man spart sich vielleicht die Tipp-Arbeit beim eingeben, aber ist es wert dafür eine endlose Anzahl an Schlägen von seinen Mitarbeitern einzustecken, die den Mist dann warten müssen?

    Einer meiner Co-Programmierer hat sogar Ternär Operatoren in Ternär Operatoren gepackt (ja, das geht). Er kann heute noch nur flüssige Nahrung zu sich nehmen…

  7. Wenn man vernünftige Variablen Namen benutzt verschlechtert sich dadurch nicht die Lesbarkeit.
    Klar, wenn ich $var = $x == ‘j’ ? 1 : 0; schreibe kommt man ins Stolpern. Aber bei $accepted = $answer == ‘j’ ? true : false; kommt man gut damit klar.
    Manchmal benutze ich ihn aber auch bei Ausgaben, aber nur manchmal.

    @Fabian: Nimm es mir nicht übel, aber das sieht ja schlimm aus… :)

  8. Mache ich genauso wie Fabian. In diesem speziellen Fall würde ich allerdings $variable = (int) ‘ja’ == $wert; vorziehen.

    Darauf, einen _Zuweisungs_operator als If-Statement zu mißbrauchen (Bsp 4) reagiere ich allerdings allergisch. SOwas muß nun wirklich nicht sein. Der nächste ersetzt noch ein einfaches IF mit der neuen ?: Syntax, weil es ein μ kürzer ist.

  9. @Patrick: Das ist wohl Geschmackssache, allerdings ist das Beispiel auch etwas unglücklich, für 0 und 1 würde ich eigentlich auch keine neuen Zeilen anfangen, das sollte sich anders lösen lassen. Aber hier mal ein konkreter Fall aus meinem aktuellen Code (übrigens inspiriert vom Java Interfaces Artikel in diesem Blog :) )

    $comparator = $this->reverse
    ? new ReverseComparator($this->getComparator()) // decorate
    : $this->getComparator();

    @nik: Das ist wohl eine PHP-Krankheit, ich sage nur “or die()”. Verlockend ist es aber schon manchmal :D

  10. Fabian muss ich solange recht geben solange es in einer Methode gekapselt ist:

    public function GetComparator()
    {
    return $this->comparator ? new ReverseComparator($this->getComparator()) : $this->getComparator();
    }

    macht schon Sinn, wobei jedoch ein Backstore mit:

    public function GetComparator()
    {
    if($this->comparator === null)
    $this->comparator = new ReverseComparator($this->getComparator());
    return $this->comparator;
    }

    auch lesbar ist. man sollte ja die Object-Erzeugung von Objekt-Gebrauch entkapseln.
    Somit ist der Ternäre Operator in 99.9% der fällen ein klarer WFT.

    Hilfreich ist er in Helper methoden, oder in vielen fällen von Optionalen Object Parametern.

    public function __construct(MyObject $obj = null)
    {
    $this->myObj = $obj :? new MyObject();
    }

    hierbei muss man jedoch 2 sachen beachten:
    1: ClassHint sollte gegen InterfaceHint getauscht werden
    2: Objekte soll man nicht im Ctor erzeugen.
    (3: Man sollte sowieso nichts im Ctor machen/erzeugen/…, außer übergabeparameter zu speichern, und gegen invalid arguments prüfen)

    so genug senf ;p

  11. @Fabian: Bin ja auch Stamm-PHPler. Mag aber trotzdem sprechenden Code.

  12. Ich finde es immer sehr interessant, wenn viele verschiedene Meinungen aufeinander treffen. Jeder hat andere Erfahrungen und eine andere Vorstellung von gutem Code.

  13. Moin,

    ich bin mittlerweile ein Fan dieser Kurzschreibweise, insbesondere wenn es um Variablenprüfung geht:

    $var = empty (‘var’, $_POST) ? true : false;

    Oder

    empty (‘var’, $_POST) ? $var = $_POST['var'] : “”;

    Rein inhaltlich geht es hier für mich nicht um Fallunterscheidungen sondern um eine Prüfung und da ist der kurze Code schön übersichtlich…

  14. Moin,

    diese Schreibweise bringt durchaus Vorteile und kann bei mehreren Zuweisungen nacheinander die Übersichtlichkeit durchaus erhöhen. Man muss zuvor natürlich verstehen wie es funktioniert sonst bleibt es unübersichtlich.

    Der Aussage das kurzer code gleich schlecher code ist würde ich mich pauschal nicht anschließen.

    Gruß
    Andreas

  15. nun ja… schlecht lesbar ist der Code wohl nur, wenn die Schreibweise (a<4)?true:false; oder ähnlich nicht bekannt sind. Bei vermehrter Verwendung, lernt man dies aber schnell und wird dies dann auch immer problemlos verstehen.

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