Lite om god OOP design

Sven-Olof Nyström
OOP med Java våren -25
Informationsteknologi
Uppsala Universitet

Lite om god OOP-design. Det mesta är en repetition av vad som sagts tidigare.

Lämpliga klasser

Utgå från vad klasserna representerar. En klass representerar ofta något konkret och fysiskt. Exempel: Klasserna Person, Employee, Furnace från avsnitt 1.

I Javas standardbibliotek hittar vi till exempel Map (en slags tabell), List (en lista), JFrame (ett fönster på skärmen).

I samtliga fall kan man (med lite vilja) tänka sig att klasserna svarar mot nåt konkret och fysiskt.

Undvik att definiera klasser som bara samlar ihop diverse relevanta attribut.

Klasser som beskriver handlingar är sällan bra.

Ge klasser namn

Namngivning är viktigt. Namnet på klasser ska förstås beskriva vad en instans av klassen representerar. Använd alltid ental—en klass som beskriver personer ska heta Person, inte Persons.

Vad återstår när man har valt klassnamn? Det roliga! Du måste hitta en representation. Välj vilka attribut (instansvariabler) som är relevanta för klassen och programmet. Definiera operationer på klassen (metoder).

Arv

Som jag skrev tidigare (i avsnittet om klasser) bör arv endast användas när klasserna är konceptuellt relaterade. Man kan till exempel tänka sig att en Employee är en slags Person. Därför kan det vara rimligt att låta klassen Employee vara en subklass till klassen Person.

Man vill också att det ska fungera implementationsmässigt att låta en klass ärva av en annan. Exempel: en kvadrat är en slags rektangel. Ändå blir det konstigt att låta klassen kvadrat vara en subklass till klassen rektangel; en kvadrat har ju bara en instansvariabel (längden på en sida) men en rektangel har längd och bredd. Om kvadrat ärver av rektangel får ju kvadrat en 'onödig' instansvariabel. Här passar det bättre att definiera en ny superklass som har de egenskaper som rektanglar och kvadrater (och andra figurer) har gemenamt. Vad borde den nya superlassen heta?

Namn på variabler och metoder

För variabler och metoder är namngivning också viktig. Vad beskrier variabeln? Vad beskriver metoden?

För en klass Person kan vi ha instansvariabler age och name. age är förstås personen ålder och name personens namn. I båda fallen beskriver instansvariabeln nånting om personen. (En instansvariabel age är kanske inte superbra—personer blir ju äldre ibland och då måste man uppdatera objektet. Vad skulle man kunna göra istället?)

Metoder bör beskriva handlingar. Vanligtvis är metoder kopplade till något objekt i en klass (när jag vill vara tydlig om att det är såna metoder jag talar om kallar jag dem instansmetoder). Här har varje metodanrop en mottagare, och det följer omedelbart att metoden är en operation på det objektet.

Några metoder i Javas standardbibliotek: toString() tar fram en strängrepresentation av objektet. Notera att metoden inte tar några parametrar; all information man behöver finns ju i objektet. size() ger antalet element i en lista. add(Object x) används för att addera nåt till en lista. (Det finns flera metoder add() i Javas standardbibliotek. Du kan också definiera egna metoder add för de klasser du definierar.)

Get- och set-metoder

Om en klass har en instansvariabel (till exempel name) brukar man ofta definiera metoder för att kunna ta fram värdet på variabeln (getName()) och uppdatera variabeln (setName(String newName). Försök att följa denna form om du definierar metoder för att ta reda på eller ändra värdet av en instansvariabel. Omvänt, om en metod heter nånting med get eller set väntar sig nog en läsare att den fungerar som i exemplet. Om du vill implementera ett annat beteende, välj ett annat namn på metoden.

Konstruktorer

Konstruktorer är avsedda att användas för konstruktion och initiering av objekt. Undvik att använda konstruktorerna till annat. En konstruktor bör inte innehålla kod som inte handlar om konstruktion och initiering.

Privata instansvariabler

Instansvariabler för en klass bör inte användas av kod i andra klasser. För att försäkra dig om att det inte sker av misstag kan du deklarera variabeln private. (Detta begrepp beskrivs i avsnitt 4.)

Lagom stora klasser och metoder

Klasser och metoder bör inte vara för stora och komplicerade. Om en klass blir stor bör du överväga att dela upp den i mindre klasser. (Hur skulle det gå till?)

På samma sätt bör en metod inte bli för stor. Även här brukar det vara ganska lätt att hitta naturliga sätt att dela upp metoden i mindre metoder.