2010-03-07

Objekt och abstrakta datatyper

Jag har funderat lite mer på det här med objekt-orienterad programmering. När jag lärde mig att programmera på riktigt så tog det ganska lång tid innan jag såg fördelarna med objekt-orientering, trots att folk försökte övertyga mig. När jag läste eller skrev objekt-orienterad kod så kände jag att den blev krånglig och svår att följa.

Men eftersom det är allmänt erkänt att objekt-orientering är bra, och att det faktiskt är ett enkelt sätt att strukturera kod man skriver på, så lät jag mig övertygas. Att abstrakta datatyper är vettigt kan alla vara överens om, och det är lätt att tro att objekt-orientering i första hand handlar om att strukturera sin data i abstrakta datatyper. Men en abstrakt datatyp ska inte vara mer än inkapslad data. I typisk objekt-orienterad programmering blir datatyperna mycket fetare än vad de borde vara, eftersom man måste klämma in all funktionalitet i dem, även om den inte hör hemma där.

De största problemen jag ser med typisk objekt-orienterad design är:

1. Kontrollflödet blir svårt att följa, eftersom det sprids ut över en massa klasser. Algoritmer passar inte in i objekt-orienterad programmering.

2. Det är lätt att hemfalla åt bristfälliga vanor, där medlemsvariabler används istället för metodparametrar. Att använda medlemsvariabler på det här sätter är i stort sett lika illa som att använda globala variabler: metoder tenderar att ha sidoeffekter i onödan.

Den gemensamma roten till båda de här problemen är att objekt-orienterad programmering prioriterar data över algoritmer på ett sätt som gör att man måste använda skohorn för att få in algoritmerna i objekten. Algoritmer hör typiskt inte till ett visst objekt, utan sprids ut på ett mer eller mindre godtyckligt sätt mellan olika klasser. En viss bit funktionalitet hamnar i en viss klass för att den verkar höra hemma där mer än i någon annan klass, även om den inte egentligen hör hemma där.

Klasser blir typiskt mycket tyngre än de hade varit om metoder bara hade använts till vad de är menade att göra: att manipulera lokal data i det objekt de tillhör. Men algoritmerna måste in i något objekt, även om de egentligen inte hör hemma i något objekt, vilket gör att en klass som kanske egentligen skulle ha haft 10 vettiga metoder, kommer bestå av 10 vettiga metoder och 40 ovettiga.

Jag tror att det i de flesta fall är mer vettigt att dela upp sin kod i abstrakta datatyper, som man kan kalla för klasser om man vill, och gammal god strukturerad imperativ kod, som inte tillhör en viss klass. Då får man klasser som är enkla att förstå, eftersom de inte gör mer än vad de borde göra, och kontrollflöden som är enkla att förstå, eftersom de inte är utspridda över 10 olika klasser.

Enligt det här resonemanget så är språk som Objective C, Python och C++ mer vettiga än t.ex. Java, där allt är objekt. För allt är inte ett objekt. Sen finns det givetvis problem där objekt-orientering kan hjälpa, typiskt för att arv är bra i vissa situationer.

Bygger man stora system ska man titta närmare på t.ex. Component Oriented Programming, som ser ut att vara ett sätt att avhjälpa ovan nämnda problem, på ett sätt som känns överdrivet i små eller medelstora program.

Vill man läsa mycket text om det här och andra relaterade problem så finns det en hel del schyssta rants på den här sidan. Geocities, yo! Jag gillar t.ex. avsnitten under rubrikerna Granularity Problem och Do the Noun Shuffle. Kommunist-analogin är väldigt söt också.

3 kommentarer:

TLDR sa...

hjon

Bittergrass sa...

hjon och TLDR: Jag tycker ni är ganska konstiga och undrar vad ni vill? Tacksam för svar.

ni sa...

Vem undrar vad vi vill?