Reisebericht Türkei 2012

Als Frühlingsauftaktreise kam Alex spontan auf die Idee, einen Billigflug nach Analya in der Südtürkei zu starten. Prompt meldete ich mich für diese hervorragende Idee mit an.

Nach butterweichem Hinflug und einem ausserordentlich freundlichen Empfang landeten wir dann bei
einem Couchsurfing-Host, der uns direkt mit - für die Türkei üblich - grottenschlechtem Gras begegnete.

Da pures liegen auf der faulen Haut uns also nicht glücklich machte, fuhren wir mit dem Bus in den 60 Kilometer weiter südlich gelegenen Ort Oliympos.

Fast alle folgenden Fotos sind leider Schwarz-Weiss, da die Kamera wohl einen geringen Energiestand hatte...

Bei immerhin schon 20 °C Aussentemperatur wanderten wir dort durch das Gebirge:



Und schauten uns antike Festungen, Tore und Amphitheatren an:


Immerhin waren die natürlichen, niemals versiegenden Flammen des Ortes Çıralı, die wir, nachdem wir uns um den Mann, der den Eintritt verlangte, herumgeschlichen hatten, erleben durften, relativ spannend - dank dem Mangel der Farben auf diesem Bild allerdings kaum zu erkennen:


Es wurde spät und dunkel - so entschlossen wir, doch erstmal am Strand zu schlafen. Dort traf ich dann einen Recklinghäuser mit seinem Wohnmobil - ein Zufall, der seinesgleichen sucht.

Nach einem halben Strandtag, bei dem man sogar im Wasser schwimmen und sich komplett Nackt sonnen konnte, wanderten wir weiter - stets bergauf natürlich:



Hier ein Eindruck, wie mollig warm der Strand war, aufgenommen von ein paar antiken Ruinen auf einem Berg herab:



Schon weit oben auf dem Berg angekommen, erschraken wir vor dem monumentalen Anblick des noch weitaus höheren Berges Tahtalı - etwa 2400 Meter hoch:





Hier Alex beim überqueren eines Flusses:



Und ich später beim gleichen Vorhaben - allerdings etwas bequemer:



Einen Tag später zurück in Antalya gab es dann noch ein paar Sehenswürdigkeiten zu sehen:


human readable difference between two timestamps in php

I recently encountered a common problem in computer engineering:
Displaying the difference between two timestamps in a human
readable fashion. For example, between the second day of may
2012, 12 o' clock and the fourth day of may 2012, 14 o'clock are
50 hours difference, which renders into 2 days and 2 hours.

To achieve this in php, i have written the following function:

function dateDiff($date1, $date2) {
$seconds = abs($date1 - $date2);

$delay = array();
foreach( array( 86400, 3600, 60) as $increment) {
$difference = abs(floor($seconds / $increment));
$seconds %= $increment;
$delay[] = $difference;
}

return strtr('{days} D, {hours} H, {minutes} M', array(
'{days}' => $delay[0],
'{hours}' => $delay[1],
'{minutes}' => $delay[2]));
}


At first, we get the difference between the timestamp in
seconds. We remove the sign of that value with abs().
Then we splice the seconds through 86400, 3600 and 60, which
represents the seconds of one day, a hour and a minute, each.
At last we display the calculated values to the User.

A quick, handy solution in just a few lines. Enjoy !

Ankündigung zur sportlichen Kurzreise

Morgen früh starte ich auf eine spätsommerliche, spontane Kurzreise mit dem Fahrrad von Leipzig nach Recklinghausen. Das Ziel ist es, die Strecke von insgesamt etwa 500 kilometern trotz kaum getätigter konditioneller Vorbereitung in drei Tagen, also 72 Stunden zu schaffen.

Das ganze geschieht immer noch auf dem gleichem Fahrrad, mit dem ich das vorletzte Jahr meine Reise nach Paris angetreten bin. Erstaunlicherweise habe ich, trotz täglicher Nutzung, an dem Rad nichts ausser den Bremsbelägen ausgewechelt. Somit wird das ganze Unterfangen eine Belastung für Mensch und Maschine.

Geschlafen wird natürlich unter freien Himmel im Schlafsack. Ich denke, die spätsommerlichen Temperaturen sollten es gerade noch ermöglichen, komfortabel frei zu rasten.

Da ich nicht davon ausgehe, dass ich unterwegs zwischenberichte schreiben kann, gibt es den nächsten Bericht bei der Ankunft in Recklinghausen oder auch erst bei der Wiederankunft in Leipzig. Den Rückweg plane ich auch mit dem Fahrrad zu absolvieren.

Backside 180 Kickflip

im Skatepark im Nova Eventis Park bei 35° Aussentemperatur:

meine Gentoo success story

Nach geschätzten 20 Stunden kompilierzeit ist mein hoch optimiertes Gentoo-System nun auf dem Asus Eeepc 1201N lauffähig. Ich habe den Weg zum Erfolg dokumentiert.

mkfs.ext4 /dev/sda5
mount /dev/sda5 /mnt/
cd /mnt

# Download Stage 3 and Portage
wget ftp://ftp.wh2.tu-dresden.de/pub/mirrors/gentoo/releases/amd64/autobuilds/20100514/stage3-amd64-20100514.tar.bz2
wget ftp://ftp.wh2.tu-dresden.de/pub/mirrors/gentoo/snapshots/portage-20100605.tar.bz2

# Check for integrity
md5sum stage3-amd64-20100514.tar.bz2
md5sum portage-20100605.tar.bz2

# Unpack system
tar xvjpf stage3-amd64-20100514.tar.bz2
tar xvjf portage-20100605.tar.bz2 -C usr/

# chroot into our new system
mount -o bind /dev /mnt/dev/
mount -t proc none /mnt/proc
chroot . /bin/bash

vi etc/resolv.conf # set nameserver
env-update
emerge --sync
eselect profile list
eselect profile set 2 # Desktop System without GNOME/KDE

# We want to compile with gcc4.5 to optimize for -mtune=atom, so we need to
# install layman to add the toolchain overlay
emerge subversion
emerge layman
echo "source /usr/local/portage/layman/make.conf" >> /etc/make.conf
echo "PORTDIR_OVERLAY=\"/usr/local/portage\"" >> /usr/local/portage/layman/make.conf
layman -a toolchain
nano /etc/make.conf
add ACCEPT_KEYWORDS="~amd64" to make.conf to allow development version of gcc
mkdir /etc/portage

# Unmask gcc 4.5.0
echo "=sys-devel/gcc-4.5.0 **" >> /etc/portage/package.keywords
echo "=sys-devel/gcc-4.5.0" >> /etc/portage/packages.unmask
emerge gcc
gcc-config x86_64-pc-linux-gnu-4.5.0
env-update
source /etc/profile
emerge binutils
emerge libtool

nano /etc/make.conf
# CFLAGS="-march=native -mtune=atom -msse3 -O2 -pipe"
# CXXFLAGS="${CFLAGS}"
# MAKEOPTS="-j5"

emerge -eav system
emerge -eav world

emerge vim # i don't like nano
vi etc/locale.gen # set your locale
locale-gen

cd usr/src/
wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.34.tar.bz2
tar xvf linux-2.6.34.tar.bz2
ln -s linux-2.6.34 linux
cd linux/
# configure your kernel or copy existing .config here
make; make modules; make modules_install
cp arch/x86_64/boot/bzImage /boot/linux-2.6.34
vi /etc/fstab
# configure your fstab here

# configure your bootloader. when using ubuntu 10.04 see this
# http://ubuntuforums.org/showthread.php?t=1195275

emerge dhcpcd

# We now need to boot our system to have our kernel running

# The Asus Eeepc1201N has an Nvidia Ion (Geforce 9400M) chipset, so we need
# to install the nvidia-drivers. Portage will automatically emerge the
# x.org environment for us.

emerge nvidia-drivers
emerge xf86-input-evdev # important because X.org will freeze without evdev
nvidia-xconfig

# Now install the other system essentials

# the dual-core atom isn't the fastest processor around, so we should try to
# reduce compile time as much as possible using ccache
emerge ccache

# emerge other system essentials
emerge xterm fluxbox irssi hnb alpine screen xdm xfe

# make sure that hald is running
/etc/init.d/hald start

startx

# enjoy your new optimized gentoo System

Hier meine make.conf (work in progress):
ACCEPT_KEYWORDS="~amd64"
CFLAGS="-march=native -mtune=atom -msse3 -O2 -pipe"
CXXFLAGS="${CFLAGS}"
CHOST="x86_64-pc-linux-gnu"
USE="mmx sse sse2 gtk -qt4 -qt3 -qt3-support -xulrunner -kde xvmc threads"
MAKEOPTS="-j5"
INPUT_DEVICES="keyboard mouse evdev"
VIDEO_CARDS="nvidia"

FEATURES="ccache"
CCACHE_SIZE="2G"

source /usr/local/portage/layman/make.conf


One-foot Ollie

Ein Trick, den ich in dieser Höhe erst seit wenigen Tagen beherrsche.




Dieses Foto kam diesen Frühling etwas später, da das Wetter es erst jetzt zuliess. Der See im Hintergrund ist der Markkleeberger See.
Ohne die stets dagewesene, sich nun aber deutlich zeigende Fügung der modernen Sozialisten in klassisch/konservative Machtverhältnisstrukturen gutheißen zu wollen, möchte ich darauf hinweisen, wie deutlich es sich nunmehr zeigt, mit welch selbstverständliche falscher Miene hier die Gunst der besitzlosen Masse zu erhaschen versucht wird. Aus intellektueller Sicht das Prinzip linker Ideologie ad Absurdum geführt, wenn sie auf solch unredliche, ja fast religiöse Weise das Glück der Massen verspricht, sollte sich das Volk ihrer Macht nur fügen.

Solche politischen Szenarien gab es in der Geschichte öfter, und ich würde nur auf die Weisheit konservativer Politik wetten bzw. hoffen, die ein wiederholen der Geschichte in der Moderne nicht erneut möglich macht. Ferner wünsche ich, dass die politische Unqualifiziertheit und der Kurzblick der jetzigen Liberalen in dieser noch langen Legislaturperiode nicht auf die konservative Stabilität auswirkt.

Herbst 2009

An einer geheimen Brücke am Elsterflussbett wurde vor einigen Jahren eine Quarter in den Beton gebaut. Jeder mit großen Rollen kann an diesem echten Untergrund-Spot Spaß haben. Genau so wie ich hier, während der Produktion meines Herbst-Nackt Skatefoto 2009, das mittlerweile vierte Foto der Serie, die zwei mal im Jahr fortgeführt wird - das erste mal auch als Sequenz.

OpenGeoDb Umkreissuche optimieren und in Yii implementieren

In diesem Kurzartikel geht es darum, wie die aktuelle OpenGeoDb-Geolokalisationsdatenbank durch ein PHP-Skript so umbauen, dass eine Umkreissuche möglich ist. Es gibt bereits zwei Tutorials zu diesem Thema, nämlich hier und hier, dessen Resultate in meinen Augen aber ineffizient sind. Trotzdem danke ich diesen Autoren, dass sie mir die Arbeit leichter gemacht haben. Besonderen Dank möchte ich an den Autor dieses Tutorials ausrichten, da er den mathematischen Hintergrund der Umkreissuche sehr einleuchtend vermittelt.

Mein Skript benutzt das Yii-Framework, speziell die PDO-Klasse, um die Datenbankverbindung aufzubauen.

1.) Vorbereitung:

Die eleganteste Datenquelle für unsere Umkreissuche wäre eine Tabelle aller deutschen Städte und Ortschaften, mit einmaliger Postleitzahl, Ortsbezeichnung, Breitengrad und Längengrad. Wir bereiten eine SQL-Tabelle dementsprechend vor:

CREATE TABLE IF NOT EXISTS `Stadt` (
`Plz` INT(11) UNSIGNED NOT NULL ,
`Ort` VARCHAR(80) NOT NULL ,
`Latitude` DOUBLE NULL ,
`Longitude` DOUBLE NULL ,
PRIMARY KEY (`Plz`) )
ENGINE = InnoDB;


2.) Extrahieren der Geo-Daten

Als erstes werden wir aber nur dazu kommen, die Spalten Plz und Ort zu füllen, da die Extraktion der Breiten,- und Längengrade komplizierter ist. Dies bewerkstelligen wir, wie an dieser Stelle im OpenGeoDb-Handbuch beschrieben, folgendermaßen:

SELECT code.text_val as "Plz", name.text_val as "Ort"
FROM geodb_textdata code, geodb_textdata name
WHERE name.loc_id=code.loc_id AND
code.text_type=500300000 /* AREA_CODE */ AND
name.text_type=500100000 /* NAME */
ORDER by 2;

Wir lesen diese Daten in unsere Tabelle ein.

Anschliessend erzeugen wir uns eine Hilfstabelle z.B. tmp_stadt, die genau so aussieht, wie unsere Tabelle Stadt.
Mithilfe meines Skriptes werden nun für jeden einzelnen Ort die Koordinaten ausgelesen:

active = True; // Verbindung aktivieren

// Optional: group by Ort; dann wird jeder Ort nur einmalig mit seiner Haupt-PLZ aufgeführt.
$command = $connection->createCommand("select * from Stadt group by Ort");

$data = $command->queryAll();

foreach($data as $object) {
$query = "SELECT zc_id, zc_location_name, zc_lat, zc_lon FROM zip_coordinates WHERE zc_zip = '";
// Da Integer keine führenden Nullen haben, müssen wir hier unter Umständen eine einfügen
if (strlen($object['Plz']) == 4) $query .= "0";

$query .= $object['Plz'] . "'; ";

$reader = $connection->createCommand($query)->query();
$result = $reader->read();

// Sollten die Geodaten einmal fehlen, müssen sie mit 0 hineingeschrieben werden, da das Skript sonst abbricht:
if($result['zc_lat'] == '') $result['zc_lat'] = 0;
if($result['zc_lon'] == '') $result['zc_lon'] = 0;

$query = "insert into tmp_stadt (Plz, Ort, Latitude, Longitude) values ('" . $object['Plz']."','" . $object['Ort'] . "', " . $result['zc_lat'] . ", " . $result['zc_lon'] . ")";

// Wenn gewünscht, zeige an, was du tust:
if($verbose) {
$i++;
echo $i . ": " . $query . "";
}

if(!$connection->createCommand($query)->execute()) {
echo $query;
die("something went wrong!");
}
}
?>


Da in der OpenGeoDb leider nicht alle Stadtteile eingepflegt sind, beschränkt sich mein Skript darauf, für Ballungsgebiete wie z.B. Hamburg oder Berlin die Position der ersten gefundenen, also kleinsten Postleitzahl zu verwenden. Soll aber trotzdem jede Postleitzahl auftauchen, kann man das Group by Ort durch Group by Plz ersetzen. Da aber nach dem SQL-Feld Ort gruppiert wird, kann man das Skript auf eventuell später nachgepflegte Datenbestände anwenden, und es würde dann den Bestand präzisieren.

Nach dem hoffentlich erfolgreichen durchlaufen, was je nach Rechenleistung einige Sekunden oder Minuten dauern wird, finden wir unser Ergebnis in tmp_stadt wieder. Wir löschen Stadt, benennen tmp_stadt in Stadt um und geniessen unseren Datenbestand.

Dieser hat aber leider selten vereinzelt einige Lücken, siehe z.B. hier:

mysql> select * from tmp_stadt where Ort = 'Leipzig';
+------+---------+----------+-----------+
| Plz | Ort | Latitude | Longitude |
+------+---------+----------+-----------+
| 4318 | Leipzig | 51.3667 | 12.3833 |
| 4328 | Leipzig | 0 | 0 |
| 4329 | Leipzig | 51.3667 | 12.3833 |


Diese Lücken sind aber selten, und ich denke, man kann damit erstmal leben.

3.) Umkreissuche

Für die Realisierung der Umkreissuche bedient man sich einfach diesem recht guten Algorithmus, hier auch ein mal in Yii implementiert:

$query = "SELECT Plz, Ort, Latitude, Longitude FROM Stadt WHERE Plz = '";

if (strlen($plz) == 4) $query .= "0"; // wieder auf führende Nullen achten

$query .= $plz . "'; ";

$reader = Yii::app()->db->createCommand($query)->query();
$result = $reader->readAll();

$latitude = $result[0]['Latitude'] / 180 * M_PI;
$longitude = $result[0]['Longitude'] / 180 * M_PI;

$query = "SELECT Plz, Ort, (
6368 * SQRT(2*(1-cos(RADIANS(Latitude)) *
cos(".$latitude.") * (sin(RADIANS(Longitude)) *
sin(".$longitude.") + cos(RADIANS(Longitude)) *
cos(".$longitude.")) - sin(RADIANS(Latitude)) * sin(".$latitude.")))) AS Distance
FROM Stadt WHERE
6368 * SQRT(2*(1-cos(RADIANS(Latitude)) *
cos(".$latitude.") * (sin(RADIANS(Longitude)) *
sin(".$longitude.") + cos(RADIANS(Longitude)) *
cos(".$longitude.")) - sin(RADIANS(Latitude)) * sin(".$latitude."))) <= ".$radius." ORDER BY Distance "; $reader = Yii::app()->db->createCommand($query)->query();
$result = $reader->readAll();

In $result habe ich nun ein Array aller Städte im Umkreis von $radius km der Stadt mit der Plz $plz. Ausserdem gehe ich in diesem Beispiel davon aus, dass ich die Datenbankverbindung in meiner Yii-Applikation in Yii::app()->db konfiguriert habe.

Ich benutze für diese Beispiele die Version opengeodb-0.2.5a-UTF8-sql.gz. Nach diesem Durchlauf hatte ich
6358 Städte in meiner Datenbank, wenn jede Stadt nur ihre Haupt-Postleitzahl benutzt, und 8270 Städte, wenn alle Städte mit ihren Stadtteilen aufgeführt werden (Group by PLZ vs. Group by Ort).

bash & vim & screen als IDE

Da ich in Zukunft wieder in die Programmierung zurückkehre, habe ich mich auf der Suche nach komfortablen und mächtigen IDE's gemacht. Bisher habe ich immer auf der Console gearbeitet. Nachdem ich mich nun mal mehrere Tage gezwungen habe, mit NetBeans zu arbeiten, bin ich wieder zu meiner bash, meinem screen und dem vim zurück gekehrt. Einige Funktion habe ich in Netbeans aber zu schätzen gelernt, und möchte zeigen, wie diese alle in vim genutzt werden können:

Die Exuberant CTags bringen Tagging-Funktionen für 34 Programmiersprachen mit. Ein einfaches "ctags -R" taggt alle Dateien rekursiv vom aktuellen Ordner in die Datei "tags"; ein Aufruf von "vim -t tags" lässt vim die Tags einlesen und öffnet, sofern vorhanden, eine als Tag markierte Datei. Mithilfe eines einfach ":ca " kann ich nun blitzschnell zwischen den gewünschten Positionen pendeln, tab-completion ist auch integriert.

Folding ist seit Vim7 problemlos möglich: Im Visual-Modes (v) den Bereich markieren, und mit zf einklappen.

Aus der globalem /etc/vim/vimrc sollten mindestens folgende Optionen in die eigene .vimrc übernommen werden:

set showcmd " Show (partial) command in status line.
set showmatch " Show matching brackets.
set ignorecase " Do case insensitive matching
set smartcase " Do smart case matching
set incsearch " Incremental search
set autowrite " Automatically save before commands like :next and :make
set hidden " Hide buffers when they are abandoned
set mouse=a " Enable mouse usage (all modes)
syntax on



der Untergang des rheinländischen Kapitalismus durch die Finanzkriseninszenierung

Ergänzend zu meiner Kurztabelle über die Unterschiede zwischen dem Angelsächsischem und dem Kontinentaleuropäischen Kapitalismus findet sich in Richard Sennetts der flexible Mensch eine ähnliche Perspektive. Im Kapitel "Flexibility" beschreibt er*1, wie es ein angloamerikanisches und ein rheinisches Modell gibt. Das rheinische Modell sei das klassischerweise durch Holland, Deutschland und Frankreich*2 praktizierte, in dem die Gewerkschaft und das Konzernmanagement die finanzielle Macht teilen, während der Wohlfahrts/Sozial-Staat ein enges Netz von Rentenverfügbarkeit, Bildung, Gesundheitsversorgung, Versicherung, usw. produziert.

Das anglo-amerikanische Modell sei der Inbegriff des ungeregelten Marktes, die völlig ungezügelte Form der freien Marktwirtschaft. Soziale Verpflichtungen werden im rheinischen Modell zur Aufgabe des Staates, der Kommune und des Gemeinwesens, während diese Ziele im angloamerikansichen Modell der Wirtschaft untergeordnet sind.

Die Staaten des Rheinmodells bremsen im allgemeinem Veränderungen, bei denen ihre schwächeren Bürger Nachteile erleiden, während das angloamerikanische Modell sämtlichen wirtschaftlichen Organisationen freie Fahrt erteilt.

Es ist diese dem rheinländischem Modell anliegende Bremse, welche verhindert, daß gesellschaftliche Zustände wie in Amerika hier zu lande herrschen. Der Import des durchwegs neoliberalen Gesellschaftskonzeptes wird zwar schrittweise durchgeführt, ich nenne die ständigen Privatisierungswellen, die Riesterrente und die Hochschulreform als Beispiel; das traditionelle soziale Netz der strengeuropäischen Staaten hinderten diese Importe in den letzten Jahren aber immer wieder, aufzublühen.

Erst unsere neue, seit Ende 2008 in die Öffentlichkeit projizierte langjährige Rezession wird es schaffen, die letzten Hürden des rheinländischen Kapitalismus aufzulösen und echte neoliberale Zustände hinauf zu beschwören.

Erst unter dieser Legitimation kann die gegenseitige Unterstützung der liberalen Wirtschaft und des Staates, in diesem Fall durch die Verstaatlichung insolventer Banken so erfolgreich und protestlos durchgeführt werden.

Zu diesem bewundernswerten stoischen Gleichmut der Bevölkerung hat auch die Gewöhnung an den nächstjährigen Status Quo beigetragen, gar nicht zu sprechen vom nahezu perfekten Medienmonopol.

Zu dieser festgefahrenen gesellschaftlichen Situation gibt es viele Alternativen; doch während diese große gesellschaftliche Umbruchsphase zu ihrem Endspurt kommt sollten diese eigentlich eine Konjunktur haben. Diese Konjunktur bleibt aus, und ich sehe keine andere Möglichkeit, als dass dieser Endspurt so stattfinden wird, wie es die letzte, vergleichbare Rezession geschafft hat.

Sie endete mit dem Beginn des zweiten Weltkrieges.

*1 Dieses Modell nimmt er von Michel Albert, einem französischem Wirtschaftsmodelltheoretiker.
*2 Dieses Modell ist auch in Italien, Japan, Skandinavien und Isreal übernommen worden.
*3 Dieses Monopol wird momentan durch die Internet-Zensur weiter perfektioniert.

Traits vs. Grafts in PHP6

Nach dem heutigen Release von PHP 5.3 möchte ich etwas über zwei potenzielle Implementierungen, die das objektorientierte Paradigma in PHP6 fundamental verändern könnten, berichten.

Den bekannten Problemen (z.B. das "Diamond Problem" & hier) mit der klassischen Mehrfachvererbung (multiple Inheritance) in Programmiersprachen wie C++ 0der auch python halten strengere OOP-Sprachen wie Objective-C und Java Interfaces entgegen. Ausgehend vom Prinzip des Interfaces gibt es zwei Vorschläge, wie PHP6 in Zukunft mit dieser Problematik umgehen wird.

Ein trait, als abstrakte, nicht-instanziierbare Schemaklasse entspricht dabei weitestgehend dem Interface der Java-Welt. Zusätzlich erlauben traits nun auch das einbeziehen vorhergehender traits:

trait A { public function print() { echo 'A &';}}

trait B { public function print() { echo ' B!';}}

trait AandB { use A, B; }

class MyClass { use AandB; }


Ein Graft ist ein, so weit ich weiss, neuartiges Konzept, dass bisher in keiner Programmiersprache implementiert wurde. Ein Graft ist eine Klasse, die innerhalb ihrer Klassendefinition auf mindestens zwei vorherig definierte Klassen zurückgreift, und den Geltungsbereich in der Klassendefinition explizit definiert:

class MyGraft {public function foo() { echo 'foo'; }}
class MyGraftedClass {
use MyGraft { public foo();}
use MyGraft { public bar() from foo(); }
}


Ein Graft zieht sich also aus den vorhandenen, unabhängigen Basisklassen die Methoden, die wiederverwendet werden sollen, heraus, und setzt in der neuen Klasse einen neuen, künstlichen Namensraum, der die Eigenschaften der Ursprungsklassen kopiert. Bei Namensüberschneidungen gilt die Reihenfolge der hineinge-graft-eten Klassen.

Ich denke, dass ein Graft zu einem schlechtem OOP-Design verführt. Es ist ein Kompromiss, der versucht, die Probleme, die die Mehrfachvererbung erzeugen kann, zu dämpfen. Ein Interface resp. Trait ist nach wie vor der Stand der objektorientierten Programmiertechnik, da es Probleme bereits im Design auszuschliessen versucht.

Geistreiche Vorschläge zu diesem spannendem Thema, gibt es hier. Ich hoffe und könnte mir vorstellen, dass des Konzept des Graft aufgrund konzeptioneller Fehler und der immensen Ungewohntheit den Kampf um das zu verwendete Programmierkonzept verliert.