14.092012

CSS - Einführung in objektorientiertes css (OOCSS)

Hallo Freunde der gepflegten Webentwicklung. Nachdem wir euch schon die Vorteile von CSS Preprozessoren wie LESS und SASS vorgestellt haben, soll es heute um objektorientiertes CSS gehen. Auch als Frontend Developer ist es heute üblich nach Prinzipien der Softwareentwicklung zu coden. Eines der gängigen Prinzipien ist die objektorientierte Programmierung. Objektorientierte Programmierung kam in den 90ern ganz stark auf. Programmier wussten oder wussten scheinbar, wie man Programme nun richtig schreibt. Sprachen wie Java verinnerlichten die neuen Vorgehensweisen. Doch schnell zurück zum eigentlichen Thema dieses Beitrags. Im Folgenden stelle ich euch die Leitlinien objektorientierter Programmierung vor und wie man diese in CSS verwenden kann.

Single Responsibility Principle (Prinzip der einzigen Verantwortung)

Die Objekte oder Software-Einheiten in einer Software, die zu Modulen zusammengefasst werden und mit anderen Modulen interagieren können, stehen genau für eine einzige Verantwortung. Ein Wetter-Widget wäre so ein Modul. Oder kleiner gedacht ein Stylesheet, welches ein Grid-Layout zur Verfügung stellt. Auf CSS angewendet sagt uns das Prinzip, dass wir "Skinning" und "Structure" getrennt handhaben sollten. Macht eine Deklaration beides sollten wir die Abhängigkeit lösen. Andernfalls haben wir Elemente, die eben nicht dem Prinzip der einzigen Verantowrtung folgen, sondern Aussehen und Struktur einer Seite beeinflussen.
Es ist also keine schöne Art und Weise, wenn wir Text-Styles, Rahmen und Schriftfarben mit Positionierung und Floats mischen. Die Struktur von Elementen sollte z. B. durch ein Grid oder ein Elternelement definiert werden. Dadurch kann am Skinning etwas geändert werden, ohne dass es die Struktur einer Seite verändert.

Open/Closed Principle (Offen für Erweiterung, geschlossen für Änderung)

Ein gutes Modul muss (und soll) nicht verändert werden, um erweiterbar zu sein. Wir sollen nicht den Kern eines Moduls ändern, sondern Erweiterungspunkte (z. B. durch Vererbung) geben. In CSS bedeutet das, dass wir an den Basis-Klassen nichts verändern, sondern in den von diesen erbenden Elementen Änderungen vornehmen. Eine Deklaration im Reset ändern wäre so ein Fall. Oder ihr habt eine globale Button-Klasse die alle Buttons einer Site beschreibt. Änderungen wirken sich in diesem Falle auf alle Buttons aus. Ist das Projekt bereits in einer stabilen Version online, sind solche Änderungen nur noch beim Fixen von Fehlern ratsam. Das Anlegen einer weiteren Sub-Class um die erforderlichen Modifikationen vorzunehmen ist die bessere Wahl. Um dieses Prinzip zu verinnerlichen, muss jedoch überhaupt erst einmal klar sein, welche Styles global sein sollen. In der Entwicklungsphase kann sich noch so manche Änderung einschleichen. Evtl. hat man dann globale Elemente, die gar keine mehr sind und schafft damit mehr unsauberen Code (siehe Interface Segregation Principle). Das sind Dinge, die im Team geklärt werden müssen. Klar ist, dass je mehr globale Styles ein Projekt hat, desto eher kann diese Regel verletzt werden.

Liskov Substitution Principle (Ersetzbarkeitsprinzip)

Objekte in einem Programm sollen durch eine Instanz austauschbar sein, ohne das Elternobjekt oder die Anwendung in seinem Gerüst zu verändern. Um das obige Beispiel mit den Buttons noch einmal aufzugreifen: Ein Standard-Button X hat eine feste Größe. Ein von diesem Button erbender, sollte nun in seiner Höhe nicht verändert werden. Dafür wäre eine andere "Vererbungslinie" zuständig. Das Gleiche gilt für Positionierung und Ausrichtung. Das Einhalten des Prinzips führt zur besseren Wiederverwendbarkeit des Codes. Die Anwendung wird flexibler. Es kann zwischen Parent- und Childclass problemlos hin und her gewechselt werden, ohne das wir dadurch das Layout verändern würden.

Interface Segregation Principle (Module entkoppeln)

Viele kleinere Module sind besser als ein allgemein bestimmendes Modul. Oder Clients sollten nicht dazu gezwungen werden von Modulen abzuhängen, die sich nicht verwenden. Das heißt, es ist besser verschiedene, spezifische Module vorzuhalten als ein einzelnes, welches Abhängigkeiten maximiert. Müssen viele Module für die Erfüllung einer Aufgabe herangezogen werden, sind diese voneinander abhängig. Ziel sollte es aber sein, diese Abhängigkeiten zu lösen. Z. B. durch neue Module, die die Abhängigkeiten regeln. Häufig sind diese Abhängigkeiten gut gemeint entstanden: Globale Definitionen, die wiederverwendbar sind mehrere Probleme auf einen Schlag lösen. Doch manchmal schaffen wir damit Abhängigkeiten, die gar nicht gewollt waren und Änderungen erschweren. Ändere ich z. B. die margins um einen Blog-Artikel auf meine Homepage ändere ich sie damit auch auf anderen Detailseiten. Das greift auch das Prinzip "Offen für Erweiterung, geschlossen für Änderung" auf. Hier gilt, lieber eine Sub-Class definieren die ein individuelles Problem löst, als Module zu koppeln, auch wenn es nur die beste Absicht war. Das kann dann nämlich ungewollte Nachwirkungen haben, wie zerschossene Seiten in den Tiefen einer Website.

Dependency Inversion Principle (Umkehr der Abhängigkeiten)

Auch hier sei das Prinzip erst einmal wissenschaftlich formuliert: Module sollen nicht untereinander abhängig oder gekoppelt sein, sondern durch Abstraktionen (Schnittstellen). Dabei gilt, dass Module höherer Ordnung nicht von Modulen niederer Ordnung abhängen sollten.
Module sollten sich nicht auf Spezialisierungen (Details), sondern auf Abstraktion stützen.
Auf CSS angewendet besagt diese Regel, dass ein Container-Element keine Abhängigkeiten zu seinen Kind-Elementen haben darf. Die Existenz oder optische Beschaffenheit kann ihm völlig egal sein. In einem Blog kann ein Titel völlig unabhängig zum Artikel stehen. Es sei denn, es beeinflusst seine Positionierung. Kind-Elemente sollten von ihren eigenen Modulen und CSS-Deklarationen beschaffen und änderbar sein, ohne Eltern-Elemente zu berühren. Das ist eine der Kernaussagen von OOCSS.

Im nächsten Artikel beleuchten wir die Prinzipien mit einigen Code-Beispielen und zeigen weitere sogenannte "Real-World-Examples", also Beispiele aus dem echten Leben eines Frontend Developers.