Skip to content

Der neue Blinker (Lauflicht) von Audi, oder die Verletzung des Entwurfsmusters KISS

Als Informatiker kennt man das Entwurfsmuster "KISS" und ist sich der Wichtigkeit dieses Musters bewusst. Mit den Worten "Wende das Muster immer an, sonst wird es kacke" - kann man dies zusammenfassen. Im Kern geht es darum, dass man auf unnötige Informationen und Doppeldeutigkeit verzichtet, da beides nur verwirrt.
Genau dieses Prinzip verletzt Audi jedoch mit seinem Lauflichtblinker!

Warum und wieso ist dies schlimm?

Das Warum ist relativ einfach erklärt, wenn man sich der "Doppeldeutigkeit" des Lauflichtes bewusst wird.
Seitdem es Signallichter an Fahrzeugen gibt, gilt ein eine Regel. "An die Seite, auf der das optische Zeichen gesetzt wird, wird sich das Fahrzeugt ausrichten". Kurzum, blinkt es links, fährt das Fahrzeug nach Links. Blinkt es rechts, fährt das Fahrzeug nach rechts.
Nun ist Audi auf die Idee gekommen diese simple Regel mit einer etwaigen zweiten Interpretationsmöglichkeit (Information) zu überlagern. Audi hat ein Lauflicht eingeführt, dass auf der linken Seite von Rechts nach Links "läuft". Wenn es in dieser Richtung aufleuchten kann, besteht die Möglichkeit, dass es in die entgegengesetzte Richtung aufleuchten könnte. So verwirren es sich liest, so verwirrend ist es auch wenn man das einfache und eineindeutige System des Blinkers kennt und gegen das neue System vergleicht. Beim normalen Blinklicht geht nur "an" oder "aus", mehr nicht - "stupid simple" eben.
Das "wieso ist das schlimm" erschließt sich hoffentlich sehr schnell.
Das mehr an Information muss, bei jedem Aufblinken des Signalgebers, verarbeitet werden - der Informatiker sagt "geparst". "Bei jedem Aufblinken" aus dem Grund, da es wegen der Doppeldeutigkeit immer in den aktuellen Kontext gesetzt werden muss.
Dies führt dazu, dass dem Verarbeiten des Signalgebers mehr Kapazität und Zeit zugeführt werden muss. Zeit, die dann für andere Bereiche des Straßenverkehrs fehlen.

Die Quintessenz daraus lautet für mich. Hier wurde auf Kosten der Verkehrsicherheit ein System eingeführt, um sich von den restlichen Marktmitbewerbern zu unterscheiden. Und all dies von einer Marke, die mit "Vorsprung durch Technik" wirbt - sehr schade.

some thoughts about AwareInterfaces and InjectorInterfaces

With the newest version of some fancy php frameworks, i got in touch with the terms of dependency injection and service locator. While the ideas behind the to terms a quick clear so far, i wanted to know how dependency injection is implemented. Because of that, i took a look into some implementations and i'm still in the process of getting a feeling of the terms and process for dependency injection.

Nevertheless, i had to use and implement some AwareInterfaces and here are my thoughts about the.

A AwareInterface should have three methods:

  • getObject()
  • hasObject()
  • setObject(\My\Object $object)

If a class is not useable without the object, it should either throw an runtime exception or implement the InjectInterface.

A InjectInterface should only have one method:

  • injectObject()

Currently, i prefer to define InjectInterfaces if they are needed to use a object. The AwareInterface is used as an addition / nice to have object, for example if you want to inject a logger. This leads to situations that a class only implements a "FooInjectInterface" or a "FooAwareInterface".

Lets see where the journey goes. Hopefully i don't have to overturn the position from above.

Update: 2013-10-02
A teammate made the suggestion to rename the "InjectInterface" to "DependentInterface" to keep the naming in sync with the "AwareInterface".

web - Zend Framework 2 ServiceManager

english I found a great summary about available service manager features.

Invokables An invokable is simply a fully qualified class name, provided to the SM as a string. When requested, it will simply be instantiated with new $invokableClass();. [...] Factories A factory is either a PHP callable, an object, or the fully qualified class name of a class implementing Zend\ServiceManager\FactoryInterface. Factories are used to perform any setup or dependency injection required for the object being requested. [...] Aliases An alias simply points one service name to another and they can be recursive. This may seem pointless at first, but aliases actually play a very important role in a modular environment. [...] Initializers An initializer is either a closure, an object, or the fully qualified class name of a class implementing Zend\ServiceManager\InitilizerInterface. Any object pulled from a service manager is ran through the registered initializers which can perform additional initialization tasks. [...] Configuration Classes A configuration class that implements Zend\ServiceManager\ConfigInterface. Config classes simply know how to configure an instance of the SM, potentially setting several factories, invokables, initializers, etc. [...] Shared Services Anything placed in the SM can be either shared or not shared. If shared, the SM will create an instance of the requested service object the first time it is requested, and on subsequent requests, return that same exact instance. If shared is set to false for a service, the service manager will create a new service. By default, all services are set to shared. [...] Abstract Factories If a SM is asked for a service which it cannot locate, it will then query the registered abstract factories to see if any of them are able to create the requested object. An abstract factory is either a fully qualified class name as a string or instance of an object that implements Zend\ServiceManager\AbstractFactoryInterface. [...] Peering Service Managers The service manger introduces a concept of peering. Each service manager can have “peers”, or rather, a stack of one or more other service managers which can also be used when a service is pulled from the SM. [...]
source Quick start service managers in your application Great survey, isn't it?

deutsch Auf der Suche nach einer Erklärung über das Wort "invokable" fand ich einen Eintrag, der eine Übersicht über vorhandene Service Manager Funktionen gab. Um das Wissen auch in meiner Muttersprache weiter zugeben, folgt anschließend die Übersetzung der weitern oben zitierten, englischen Zeilen.

Invokables Ein "invokable" ist ein vollqualifizierter Klassenname, welcher dem ServiceManager als Zeichenkette zur Verfügung bereitgestellt wird. Falls verlangt, wird eine neue Instanz dieser Klasse mit Hilfe von "new $invokableClass();" erzeugt. [...] Factories Eine "factory" (Fabrik) kann eine PHP abrufbare, ein Object, oder ein vollqualifizierter Klassenname einer Klasse sein, welche die Schnittstelle "Zend\ServiceManager\FactoryInterface" implementiert. Fabriken werden genutzt um jegliche Einrichtung (Setup) oder Abhängigkeitsinjektion (dependency injection) für die Instanziierung einer Klasse zu realisieren und zentralisieren. [...] Aliases Eine "alias" (alternative Bezeichnung) zeigt einfach auf einen anderen Dienst und kann rekursiv sein. Wirken Aliases am Anfang als unnütz, können sie bei einer modularen Umgebung eine große Rolle spielen. [...] Initializers Ein "initializer" (Initialisierungsprogramm) ist entweder ein Closure, ein Object oder ein vollqualifizierter Klassenname einer Klasse, welche die Schnitstelle "Zend\ServiceManager\InitilizerInterface" implementiert. Ein Objekt, welches vom ServiceManager kommt, durchläuft die registrierten Initialisierungsprogramme, welche weitere Initialisierungsaufgaben vornehmen können. [...] Configuration Classes Eine "configuration class" (Einstellungsklasse) implementiert die Schnittstelle "Zend\ServiceManager\ConfigInterface". Einstellungsklassen wissen, wie sie den ServiceManager konfigurieren, setzen etwaig Fabriken, "invokables", Initialisierungsprogramme usw. [...] Shared Services Alles, was in den ServiceManager vorhanden ist, kann geteilt werden. Wenn ein Dienst geteilt ist, wir der ServiceManager eine Instanz des gewünschten Objects erstellen und zurückgeben. Wurde bereits eine Instanz erstellt, gibt der ServiceManager diese Instanz bei einer enreuten Anfrage wiederrum zurück. Falls ein Dienst nicht geteilt werden darf, erstellt der ServiceManager bei jeder Nachfrage eine neue Instanz der Klasse. Von Haus aus sind Dienste geteilt. [...] Abstract Factories Falls ein ServiceManager nach einem Dienst gefragt wird, den er nicht finden kann, wird er alle vorhandenen, abstrakten Fabriken anfragen um das gewünschte Objekt zu erstellen. Eine abstrakte Fabrik ist entweder ein vollqualifizierter Klassenname oder eine Instanz eines Objekts, welches die Schnittstelle "Zend\ServiceManager\AbstractFactoryInterface" implementiert. [...] Peering Service Managers Der ServiceManager hat das Konzept des "peering" (Späherei/Umherschauens/Gleichrangigkeit) eingeführt. Jeder ServiceManager kann einen, oder eine Sammlung von, "Gleichgestellten"/"Spähern" ServiceManagern besitzen, welche ebenfalls genutzt werden können, wenn ein Dienst vom ServiceManager angefordert wird. [...]
Quelle Schnellstart Service Managers in deiner Anwendung Übersetzungsfehler korrigiere ich gern.

Constructor in Interfaces? Again no

Its a rainy day outside so i clicked (if it is clicking when you use CTRL+F ;-)) through the word wide web and found an entry by Ralph Schindler about PHP Constructor - Best Practise. Ralph explained why

Strict standards: Declaration of Bar::somemethod() should be compatible with that of Foo::somemethod()
wont raise an error when you define another constructor signature in an extended class like
class \Foo { public function __construct(array $bar) { //put code in here } } class \Bar extends \Foo { public function __construct(array $options, \foo $foo { //put code in herer } }
If you want to know why, click on the link and read the article :-). What i liked most in his article was his consolidation of my one coding style by writing:
Moreover, constructors should not appear in interfaces.
as i asserted in an older entry. But you really should read the whole article while he is talking about the prototype pattern. Also the comments can help you to forget the rain outside ;-).