Benutzer:Tril/Zukunftsvision

Aus Contao Community Documentation

Anmerkung.png Anmerkung: Diesen Artikel habe ich am 12. April '12 im Wiki der Contao Community Alliance gepostet, welches mittlerweile abgeschaltet wurde. Um meine Gedanken zu "retten", setze ich diesen Artikel nochmal hier ein.


Zukunftsvision

In diesem Artikel geht es um Ideen, Vorstellungen, Wünsche, Träume, was ein modernes CMS heute können sollte. Diese Informationen spiegeln die Meinungen der Community wieder und nicht der des Contao Projektes!

Light or light?

Ich habe einige Diskussionen mit Leo Feyer und langjährigen Mitgliedern aus der Contao Community geführt, über die ursprüngliche Bedeutung des Wortes Light im alten Namen TYPOLight.

Dabei kam es zu ganz unterschiedlichen Aussagen:
- Das System ist einfach/leicht zu bedienen.
- Das System ist einfach/leicht zu verändern.
- Der Einstieg in das System ist einfach/leicht.
- Das Framework ist einfach/leicht zu verstehen.
- Die Entwicklung für das System ist einfach/leicht.
- Das System ist ein leichtgewichtiges/lightweight System.
- Das System kann nur das nötigste.
- Das System ist nicht überladen.
- Man muss nichts lernen um mit dem System umgehen zu können.
- Man muss wenig lernen um mit dem System umgehen zu können.
- Es reicht PHP zu können, um einfachste Anpassungen machen zu können.
- Das System verbraucht so wenig Speicherplatz wie möglich.
(für alle Aussagen die ich vergessen habe: mea culpa)

In meinen Augen beißen sich die Aussagen ein wenig, es geht nur um einfach, leicht, wenig lernen müssen. Eine Einstellung die ich persönlich zwar nachvollziehen kann, aber nur bedingt gut heißen kann. Im Umkehrschluss bedeutet es nämlich, wir beschäftigen uns heute mit Technologien und Prinzipien, die man vor 5 Jahren das letzte mal eingesetzt hat und ignoriert Weiterentwicklungen die uns weiterbringen würden.

Ich bin der persönlichen Ansicht, das ein Umdenken stattfinden sollte. Viele Community Mitglieder scheinen sich förmlich vor neuen Technologien und neuen Softwareprinzipien zu sträuben. Andere hingegen wollen mit Kanonen auf Spatzen schießen. Der Mittelweg, ein einfaches Grundsystem, welches das nötigste für Web-Worker bietet, aber flexibel genug ist auch großen Ansprüchen gerecht zu werden.
Einige behaupten Contao wäre das heute schon, für einen FE-Entwickler mag das vielleicht noch gerade so zutreffen, für Extension-Entwickler aber keinesfalls. Das System ist in sich eng verkapselt, stark verkoppelt und bietet kaum Möglichkeiten um einzelne Komponenten austauschen zu können.

Bestes Beispiel für die "eingefahrenheit" der Community war eine Diskussion auf dem Contao Camp bezüglich ORM.
Das erste Argument der Community: Es ist viel zu kompliziert!
Meine Antwort: ORM ist einfacher als SQL, das kann ich auch beweisen. 2 Entwickler, beide können lediglich PHP und OOP (beides Voraussetzungen für Contao), aber kein SQL oder Datenbanksysteme. Dem 1. Entwickler erklärt man den Umgang mit ORM. Dem 2. Entwickler erklärt man den Umgang mit SQL. Der 1. Entwickler wird innerhalb weniger Minuten mit Datenbankobjekten umgehen können, er brauch sich nicht um Datenbankspezifikas zu kümmern, weil das ORM System das für ihn macht. Der 2. Entwickler hingegen wird mehrere Tage benötigen, weil er sich ein viel größeres Grundlagenwissen aneignen muss.

Nächstes Argument der Community: ORM ist einfach langsam!
Meine Antwort: Natürlich ist der Grad zwischen einem möglichst stark flexiblen und gleichzeitig möglichst schnellem System sehr schmal. Aber wenn man mal genau hinschaut stellt man fest, dass ein ORM System nur unter bestimmten Bedingungen "deutlich" langsamer ist (Source). Aber in manchen Bedingungen kann ORM sogar schneller als raw php sein und das ohne das ich als Entwickler noch eigene Optimierungen durchführen muss! (Source).

Nächstes Argument der Community: Mit ORM kann man viel falsch machen!
Meine Antwort: Mit plain-SQL mindestens genau so viel, wahrscheinlich sogar mehr als mit ORM!

Nächstes Argument der Community: Ein ORM wie Doctrine bläht das System nur unnötig auf.
Meine Antwort: Nein es bläht es nicht auf, es fügt nur einen großen Haufen an Funktionalität hinzu, die man bei Bedarf nutzen kann.

Nächstes Argument der Community: Ein Web-Entwickler brauch die ganzen Funktionen nicht! Die verwirren nur!
Meine Antwort: 1. arbeiten nicht nur Web-Entwickler, sondern auch Software-Entwickler mit Contao, die diese Funktionen sehr zu schätzen wissen und 2. ist ORM immer noch einfacher zu verstehen als SQL.

Mein Fazit: Viele scheinheilige Argumente, die bei genaueren hinhören eher den Eindruck vermitteln ich will nix neues lernen, lass mir mein PHP und SQL dann bin ich glücklich. Ok, ich lass dir dein PHP und plain-SQL, aber dann sei bitte nicht verwundert das ich irgendwann mir ein System suche, das meinen Ansprüchen gerecht wird. Ob es Contao Reloaded sein wird, weiß ich noch nicht und das es immer einen gewissen Kompromiss geben wird ist mir auch klar. Die Frage ist letztlich nur, wie groß ist der Kompromiss, den ich mit Contao Reloaded eingehen muss? - (Tristan Lins)

Fazit: Der Begriff light hat keine objektive Bedeutung mehr, er wird eigentlich mehr als Kampfbegriff eingesetzt und man sollte sich von diesem Begriff lösen.

Zielgruppen

Um die Frage nach dem "Funktionsumfang" klären zu können, muss klar gestellt werden, wer mit dem System arbeitet und wie tief diese Zielgruppe in das System rein geht.

  • Der Redakteur benutzt das System lediglich um Inhalte zu verwalten. Technische Feinheiten sind für ihn uninteressant, für ihn kommt es auf gute Usability des Backends an.
  • Der Web-Designer setzt ein Layout mit HTML, CSS und JavaScript um, für Ihn ist es wichtig, Templates auf einfache Weise verändern zu können und CSS/JavaScripts einfach in die Seite einbauen zu können.
  • Der Web-Entwickler kommt erstmals mit dem eigentlichem "Kern-System" in Verbindung. Er muss Datentypen verändern können, Default Werte setzen und bei Bedarf kleine Micro-Extensions bis hin zu Mittelgroßen-Extensions entwickeln können. Die Komplexität ist aber meist gering, d.h. er muss nicht sehr tief in das System einsteigen und profitiert von viel Automatismus und der Unterstützung durch das System.
  • Der Software-Entwickler arbeitet auf dem gesamten Spektrum des Systems. Für Ihn sind selbst komplexe Sachverhalte täglich Brot. Daher muss er sich nicht nur mit der oberen Ebene des Frameworks auseinander setzen, sondern bei Bedarf auch explizit in das Framework eingreifen können.

Anforderungen

Welche Entwurfsmuster und Programmierprinzipien sollte ein modernes CMS verfolgen?

Entwickler sollen sich auf das wesentliche Konzentrieren können.

Damit ist vor allem gemeint, dass ein Entwickler sich auf den Algorithmus konzentrieren können soll und diesen möglichst einfach umsetzen kann ohne sich um bestimmte Spezifika kümmern zu müssen. Dabei sollte er von der IDE unterstützt werden und nicht jedes einzelne Feld auswendig kennen müssen. Aktuell muss man sich als Entwickler um viel zu viele Grundfunktionen, die sich eigentlich automatisieren ließen Gedanken machen, was Zeit kostet und die Qualität der Arbeit deutlich reduziert.

Magic is out

Magische Methoden und Eigenschaften, darauf bauen viele dynamische Systeme und nicht zuletzt das heutige Contao sehr stark auf. Aber eigentlich steht das in totalem Widerspruch zu der Idee eines leichten Systems. Magische Methoden und Eigenschaften muss man sich merken. Nicht mal die IDE kann den Entwickler dabei unterstützen.

Ein kurzes Beispiel zeigt den Unterschied:

class MagicModel
{
    protected $arrData = array();
 
    public function __set($k, $v)
    {
        $this->arrData[$k] = $v;
    }
 
    public function __get($k)
    {
        return $this->arrData[$k];
    }
 
    public function store()
    {
        // keine IDE Unterstützung verfügbar
    }
}
 
$object = new MagicModel(); // IDE Unterstützung verfügbar
$object->firstname = 'Martin'; // keine IDE Unterstützung verfügbar
$object->lastname  = 'Mustermann'; // keine IDE Unterstützung verfügbar
$object->email     = 'martin@mustermann.de'; // keine IDE Unterstützung verfügbar
$object->store(); // IDE Unterstützung verfügbar


class RealModel
{
    /**
     * @var string
     */
    protected $firstname;
 
    /**
     * @var string
     */
    protected $lastname;
 
    /**
     * @var string
     */
    protected $email;
 
    /**
     * @param $firstname string
     * @param $lastname string
     * @return RealModel
     */
    public function setName($firstname, $lastname)
    {
        $this->firstname = $firstname;
        $this->lastname  = $lastname;
        return $this;
    }
 
    /**
     * @return string
     */
    public function getName()
    {
        return $this->firstname . ' ' . $this->lastname;
    }
 
    /**
     * @param $firstname string
     * @return RealModel
     */
    public function setFirstname($firstname)
    {
        $this->firstname = $firstname;
        return $this;
    }
 
    /**
     * @return string
     */
    public function getFirstname()
    {
        return $this->firstname;
    }
 
    /**
     * @param $lastname string
     * @return RealModel
     */
    public function setLastname($lastname)
    {
        $this->lastname  = $lastname;
        return $this;
    }
 
    /**
     * @return string
     */
    public function getLastname()
    {
        return $this->lastname;
    }
 
    /**
     * @param $email string
     * @return RealModel
     */
    public function setEmail($email)
    {
        $this->email = $email;
        return $this;
    }
 
    /**
     * @return string
     */
    public function getEmail()
    {
        return $this->email;
    }
 
    public function store()
    {
        // IDE Unterstützung zu allen Eigenschaften ist verfügbar
    }
}
 
$object = new RealModel(); // IDE Unterstützung verfügbar
$object->setFirstname('Martin'); // IDE Unterstützung verfügbar
$object->setLastname('Mustermann'); // IDE Unterstützung verfügbar
$object->setEmail('martin@mustermann.de'); // IDE Unterstützung verfügbar
$object->store(); // IDE Unterstützung verfügbar
 
// Alternativ
 
new RealModel() // IDE Unterstützung verfügbar
  ->setFirstname('Martin') // IDE Unterstützung verfügbar
  ->setLastname('Mustermann') // IDE Unterstützung verfügbar
  ->setEmail('martin@mustermann.de') // IDE Unterstützung verfügbar
  ->store(); // IDE Unterstützung verfügbar

Aber das ist doch viel zu viel Aufwand und geht doch gar nicht mit dynamischen Models! - Doch es funktioniert und ist sogar ohne großen Aufwand zu realisieren. Dafür müssen die Models einfach aus einer Tabellenbeschreibung (DCA oder etwas ähnliches) generiert werden. Die Generierten Klassen können dann mit der IDE eingelesen werden und man hat die entsprechende Unterstützung. Und zu guter letzt hat das sogar noch einen Performance Vorteil, echte Model Klassen ohne Magie sind immer schneller als dynamische Magische Models.

BTW: Doctrine besitzt einen Entity Generator.

Dependency Injection

Dependency Injection besagt, dass das System Abhängigkeiten in ein Objekt injiziert, anstatt das sich das Objekt die Abhängigkeiten holen muss. Dependency Injection erlaubt lose Kopplungen, wodurch Komponenten unabhängig vom System werden. Lose Kopplungen sind vor allem dann Sinnvoll, wenn man test driven development betreiben will. Für UnitTests sind lose Kopplungen ein großer Vorteil, weil man die abhängigen Komponenten durch Test-Komponenten ersetzen kann, was bei festen Kopplungen unmöglich ist.

Data Models und ORM

Models finden bereits in Contao 3 Einzug, allerdings ist diese Implementierung eher ein Tropfen auf den heißen Stein, der viel zu spät kommt. Data Models und viel mehr noch ORM vereinfachen den Umgang mit der Datenbank erheblich. Für den Entwickler ist der Aufbau und Umgang der Datenbank kein zentrales Thema mehr. Und wenn es für Sonderfälle doch notwendig ist, direkt unten auf der Datenbank zu Arbeiten, dann kann man sich immer noch auf die DBAL Ebene unterhalb des ORM begeben. Aber im allgemeinen Umgang mit Contao wäre ORM kein Sonderfall, sondern eine Automatisierung von aktuell immer wiederkehrenden Aufgaben.

Content Provider

Ein Content Provider liefert Daten zu einem bestimmten Content. Content Provider sind eng verwand mit Entity Managern und werden oft als solche implementiert. Allerdings sind Content Provider vom Grundsatz her austauschbar, kombinierbar oder stapelbar. Ein Beispiel: Die Benutzerdaten für die Systemanmeldung werden von einem Content Provider geliefert. Diese können je nach Bedarf ausgetauscht, kombiniert oder gestapelt werden.

Abfragen aller Benutzer:

Users::getAll() {
    call CmsUsersProvider::getAll() // CMS integrierte Benutzerverwaltung
    call LdapUsersProvider::getAll() // Benutzer aus einem angebundenen LDAP
    call CrmUsersProvider::getAll() // Benutzer aus einem angebundenen CRM
}

Speichern eines Benutzers:

User user = CmsUsersProvider::get(ID) // einen Benutzer von einem Content Provider holen
// Den Benutzer verändern
user.save() // den Benutzer speichern

Authorisieren eines Benutzer:

User user = Users::auth(username, password) {
    return CrmUsersProvider::auth(username, password) if success // Benutzer aus dem Crm haben die höchste Priorität, also werden Sie als erste versucht zu authentifizieren
    return LdapUsersProvider::auth(username, password) if success // Benutzer aus dem Ldap haben eine niedrigere Priorität
    return CmsUserProvider::auth(username, password) if success // Benutzer aus dem CMS haben die niedrigste Priorität
}

Ob man es nun Content Provider oder Austauschbare Komponente oder anders nennt, sei mal dahin gestellt. Wichtig ist das es möglich sein sollte, Komponenten zu kombinieren oder zu ersetzen. Dadurch erreichen wir eine große Flexibilität, ohne das das System wirklich verkompliziert wird. Über entsprechende Interfaces kann der Zugriff vereinheitlicht werden und um den Rest kümmert sich dann das System. Factories sind ein schönes Standardmittel um derartig austauschbare Komponenten zu erstellen.

Template Engine

Template Engines werden oft als Verschlimbesserung gesehen, man sollte sie aber eher als Sicherheitsmedium sehen. Abgesehen davon, dass Template Engines umfangreiche Funktionen liefern, die PHP selbst nicht liefern kann, schützen Template Engines auch vor Gefährlichem Code. In einer Template Engine sind nur jene Funktionen verfügbar, die man verfügbar macht, aber nicht das vollständige Spektrum von PHP.

Befürworter

Ansichten
Meine Werkzeuge

Contao Community Documentation

<user> Composer meckert bei Isotope, dass er mit tablelookupwizard 3.1 nicht zurecht kommt - korrekt?
<Toflar> keine Ahnung, sowas weiss ich doch nicht auswendig :D
<user> wer dann ;)
<Toflar> na niemand, deswegen schreibt man's ja in die composer.json

Navigation
Verstehen
Verwenden
Entwickeln
Verschiedenes
Werkzeuge