Jeg tenkte vi skulle se på komposisjon. Komposisjon er, sammen med forståelse, en sentralt komponent i det å programmere systemer. Komposisjon er den mekaniske delen av programmeringen, det å sette sammen abstrakte enheter til en mer kompleks abstrakt enhet. På den andre siden så er forståelse den biten som handler om å finne mening eller definere semantikken bak de abstrakte enhetene.
Komposisjon er å sette sammen løsninger på enklere delproblemer for å løse et mer komplekst problem.
For å konkretisere det litt før vi går videre så kan vi si at komposisjon er det å sette sammen løsninger på enklere delproblemer for å løse et mer komplekst problem. Innen programmering er komposisjon noe ganske velkjent...
De fleste kjenner komposisjon fra objekt orientering:
class Animal { //... } class Dog extends Animal { //... } class Owner { private Dog bjarne = new Dog(); //... }
...eller fra funksjonell programmering
function compose(f, g) { return function(x) { f(g(x)); } } function mapWith(a, f) { return a.map(el => f(el)); }
Det som er viktig med komposisjon er at det ikke kommer i veien for forståelse. Derfor er det en viktig egenskap ved komposisjonsmekanismer at effekten av komposisjonen er lokalisert og at resultatet er forutsigbart. Hvis komposisjonen av to enheter fører til at enhetene selv endrer funksjonalitet vil det gjøre det veldig mye vanskeligere å forstå helheten. La oss ta en titt på hvordan dette fungerer i CSS.
.btn { color: red; background: silver; display: inline-block; } .sidebar .btn { color: black; background: red; }HTML:
<div class="sidebar"> <button class="btn">Press</button> </div> <!-- color: black; background: red; display: inline-block; -->
Her har vi laget oss en generell stil for alle elementer med klassen .btn. Så lager vi oss en spesialisering av .btn som gjelder for .btns i sidebar. Resultatet er en button som har rød bakgrunn og svart tekst. Det er slik mye CSS skrives i dag. Vi arver noen av stilene og så overskriver vi noen attributter for å spesialisere dem.
Noen har kanskje lagt merke til noen problemer allerede. CSS mangler de egenskapene som gjør at komposisjon fungerer. Vi tar et eksempel til for å illustrere.
.sidebar .header { font-weight: 700; text-decoration: underline; } .news-item h2 { color: blue; }HTML:
<div class="sidebar"> <h1 class="header">Sidebar</h1> <div class="news-item"> <h2 class="header">News</h2> <p>There were news.</p> </div> </div> <!-- font-weight: 700; text-decoration: underline; color: blue; -->
Dette er ikke et helt uvanlig problem i CSS. Et sub-tre gir match på to ulike regler og vi får en uønsket effekt ved at stilene fra begge regler blir satt på header elementet i sidebar. Hvis vi tenker oss at de to reglene befinner seg i helt ulike ender av stilarket som blir brukt så kan man fort forestille seg at det er en umulig oppgave å forutse effekten på header-elementet.
Effekten av en CSS-regel er potensielt avhengig av alle andre CSS-regler i stilarket.
Problemet med CSS er at effekten av en CSS-regel vil kunne påvirkes av all annen aktiv CSS. Vi har ingen måte å forutse effekten av en CSS-regel på et html-element uten å kjenne til all annen CSS som også påvirker elementet.
1) Skriv om den uønskede regelen til å matche smalere.
2) Overskrive uønskede attributter og øke spesifisitet.
Det er vanligvis to ulike måter å motvirke denne typen problemer.Den første løsningen går ut på å skrive om den første regelen til å matche smalere. Dette kan potensielt føre til ringvirkninger i markup hvor man fort må gå over og legge til klasser på alle h2-elementer. Den andre løsningen går ut på å overskrive de uønskede attributtene med resets eller andre verdier, for å til det må spesififiseteten til regelen økes.
Ønsket om å kunne gjenbruke regler i så stor grad som mulig forsterker problemene.
La oss prate om gjenbruk. Når vi skriver CSS regler forsøker vi ofte å lage regler som er generelle, slik at vi kan gjenbruke dem i flere situasjoner. Dette får oss til å lage regler som matcher veldig bredt og på den måten bidrar til å forsterke den typen problemer vi har sett med komposisjon i CSS. Og her er kjernen til mye av problemene med vedlikeholdbar CSS.
Måten vi ønsker å gjenbruke CSS overser helt de svakhetene som er iboende i måten CSS komponerer på. Bred gjenbruk basert på overfladisk likhet fungerer ikke.
Begrense ansvaret til CSS-regler ved å snevre inn påvirkningen til så få elementer som mulig.
Begrense gjenbruk av stiler til ting som er faktisk like, og ikke bare overfladisk like.
Finnes det løsninger? Kanskje ikke perfekte, men iallefall et par grep som vil minske effekten av de iboende svakhetene til CSS. Vi kan begrense ansvaret til CSS-regler. Isteden for å starte med noe generelt lager vi heller regler som er veldig spissa, så kan vi heller skille ut ting i mer generelle regler etterhvert som behovene viser seg. For å sørge for at behovene som melder seg er faktiske behov for generalisering så begrenser vi gjenbruk av stiler til ting som er faktisk like og ikke bare overfladisk like.
Stian Veum Møllersen / @mollerse
BEKK