Göm meny

Riktlinjer och praxis för att skriva kod

Att programmera innebär i de flesta fall att en programmerare skriver källkod i en eller flera textfiler. Hur denna kod ser ut och är strukturerad varierar mellan olika programmeringsspråk, men i de allra flesta fall vill vi som programmerare skriva kod som vi själva och andra programmera kan läsa, förstå och underhålla.

På denna sida hittar du några allmänna riktlinjer och praxis för att skriva kod som vi tillämpar i denna kurs.

Krav eller inte?

I början av kursen kommer vi inte ställa några krav på att ni ska följa några riktlinjer alls, men allt eftersom kursen fortskrider, så kommer det att ställas fler krav på er kod.

Är denna lista över riktlinjer komplett?

Detta dokument är inte fullständigt eller uttömmande. Vissa av riktlinjerna som tillämpas på kursen finns med just för att detta är en grundkurs i programmering, snarare än att de är någon form av allmän praxis eller standard.

Kompletteringar på grund av kodstil m.m.

Även om det inte är krav på att varje riktlinje ska följas i alla tillfällen, så betyder det inte att det är OK att bryta mot riktlinjerna i vilken utsträckning som helst.

Detta betyder är det möjligt att den assistent som rättar er kod ber er komplettera er kod med avseende någon aspekt som gör er kod onödigt oläsbar, onödigt komplicerad, eller onödigt innefektiv trots att den fungerar när man kör den.

Pythons officiella stilguider

När det kommer till riktlinjer för programmeringsspråket Python, så finns det vissa officiella riktlinjer som vi kommer att tillämpa i större om fattning ju längre vi kommer i kursen. Dessa finns definierade i PEP-dokument (Python Enhancement Proposals), och det är framförallt PEP8 - Style Guide for Python Code och PEP257 - Docstring Conventions som är aktuella för denna kurs.

The Zen of Python

En hel del designbeslut kring designen av programmeringsspråket Python har sin grund i läsbarhet som är en av de principerna som vi hittar i PEP20 - The Zen of Python:

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Globala variabler

Vid användning av globala variabler som konstanter ska variabelnamnet bestå av enbart versaler (stora bokstäver). Användning av globala variabler för andra syften ska endast göras om det finns mycket goda skäl till att göra det.

Att det enbart skulle vara “smidigare” eller att det blir “mindre kod” är inte ett tillräckligt gott skäl.

Om en global variabel används, ska detta deklareras i början av funktionen så att det är tydligt för andra som läser koden.

Exempel

def draw():
    global state
    ...

Läsbarhet

Majoriteten av riktlinjerna här är framtagna för att förbättra läsbarheten hos koden vi skriver. Du kommer läsa din kod flera gånger än du skriver den, och många gånger kommer kod läsas av andra som inte varit med och skrivit den.

En generella princip för att få läsbar kod är att koden ska vara vägledande vid läsning snarare än vilseledande. Denna princip kan vi utveckla till

  • namn ska vara beskrivande vid läsning snarare än intetsägande
  • formatteringen och disposition av koden ska vara förutsägbar snarare än överraskande

Namngivning

  • använd substantivliknande namn för variabler
  • använd substantivliknande namn i plural för variabler som refererar listor eller dictionaries
  • använd verbliknande namn för funktioner och metoder
  • använd beskrivande prefix vid namngivning

Undvik namn på endast en bokstav om det inte är absolut, absolut uppenbart vad variabeln används till. Exempel på fall där variabelnamn på en bokstav är rimliga:

  • i för index
  • x för x-koordinat
  • y för y-koordinat

Formattering av namn

PEP8: Naming Conventions innehåller också namngivningskonventioner.

  • Använd
    • snake_case för funktions- och variabelnamn
    • CamelCase för klassnamn
    • UPPERCASE_WITH_UNDERSCORES för konstanter

Använd inte ovanstående till något annat, t.ex. använd inte CamelCase för att namnge funktioner eller metoder.

  • Använd inte
    • mixedCase
    • Capitalized_Words_With_Underscores

Radlängd

PEP8: Maximum Line Length har riktlinjer för radlängd.

  • Begränsa radlängden till 79 tecken för vanlig kod.
  • Begränsa radlängden till 72 tecken för docstrings m.m. som använder fler än en rad.

För att bryta en rad, dvs berätta för pythontolken att nästa rad i koden egentligen är en fortsättning av föregående rad, kan vi använda tecknet \:

if long_function_name(argument1, argument2) == 42 and some_value > 0 \
        and another_value < 0:
    code_in_if_block()

I detta fall är det en rad som påbörjar ett block som bryts. I detta exempel följer vi även rekommendationen att bryta en rad innan användning av en binär operator istället för efter operatorn (Se PEP 8#linebreak-binary-operator).

Notera att den brutna raden är överindenterad så att man inte råkar läsa another_value < 0 som en del av själva blocket. Se PEP 8#indentation för fler exempel på indentering vid bruten rad.

Om möjligt är det bättre att använda parenteser om det finns ett behov av att bryta rad; vi kan bryta en rad inuti parenteser utan att använda \:

if (long_function_name(argument1, argument2) == 42 and some_value > 0 and
        another_value < 0):
    code_in_if_block()

Indentering

PEP8: Indentation anger att 4 mellanslag ska användas för att indentera kod (använd INTE tab-tecken, däremot är tab-tangenten inställd för att ge 4 mellanslag istället för tab-tecken i utvecklingsmiljöer anpassade för Python). Det finns även riktlinjer och exempel för indentering när man bryter en rad.

Whitespace (blankrader och mellanslag)

PEP 8: Blank Lines anger att funktioner på toppnivå i en fil ska omges av två blankrader (dvs två tomma rader före och två tomma rader efter).

I klassdefinitioner används dock bara en tom rad mellan metoder.

Se även PEP 8: Whitespace in Expressions and Statements för riktlinjer för var vi lägger till mellanslag i uttryck och satser.

Disposition i pythonfiler

Det är viktigt att kunna orientera sig och hitta i sin kod. En vanlig ordning är följande:

  1. importer
  2. globala konstanter
  3. funktionsdefinitioner
  4. klassdefinitioner
  5. övrig kod, t.ex. anrop till en main()-funktion

Kommentarer

Många gånger kan vi dela in kommentarer i kod i två kategorier. Kommentarer som ska läsas av de som använder vår kod, och kommentarer som ska läsas av de som utvecklar koden.

  • inline-kommentarer: Börjar med ett #-tecken och kan stå på en egen rad eller i slutet av en rad. Dessa är kommentarer till utvecklarna av koden
  • docstrings: Börjar med """ och slutar med """ och läggs i början av en modul, funktion, klass och metod. Kommentaren är till för användarna av modulen, funktionen, klassen eller metoden och de beskriver syftet hos det som dokumenteras; svar på frågan “Till vad/varför ska jag använda detta?”. Notera att “syftet” inte är samma sak som svaret på frågan “Hur har detta implementerats?”.

Docsträngar

  • Första raden ska alltid vara en komplett sammanfattande mening.
  • Om ytterligare rader behövs, ska en tom rad finnas mellan den första raden och de efterföljande raderna.
  • Om docsträngen är för en funktion eller metod ska parametrarna dokumenteras.

Kommentarer till satser längre än en rad

I denna kurs har vi för många av de senare laborationerna även krav på att satser som sträcker sig över mer än en rad ska kommenteras. Detta är inte nödvändigtvis något som följs i “verkliga livet”, men vi har med det för att ni ska öva er på att växla mellan abstraktionsnivåer; att kunna beskriva vad koden gör utan att upprepa koden.

Kommentarer ska bidra med något

När ni skriver kommentarer ska de bidra med något, t.ex. förklara koden, göra det lättare att använda koden, eller göra det lättare att läsa/navigera koden.

Kommentarer som bara är “innantilläsningar” av kod tar bara plats och bidrar inte till något av ovanstående. Se även PEP 8: Inline Comments.

Dåligt

# lägg till padding till x_start
x = x_start + padding

Bättre

# padding fungerar som en  inre marginal och ger lite luft från fönstrets
# vänsterkant
x = x_start + padding

(Ovanstående är endast ett exempel, om vi lyckas skriver kod som kan tala för sig själv behöver vi inte kommentera den)


Sidansvarig: Johan Falkenjack
Senast uppdaterad: 2023-12-04