Fælles kodestandard - vejen til smuk kode eller ... krig (del 1/2)

Som programmør har man altid sin egen stil, men når kode-projekter vokser bliver det det relevant at diskutere fælles kode-stil. Det er en af vejene til at håndtere store kodebaser, men samtidig også vejen til ballade og frustration :-) I dette blogindlæg sætter jeg fokus på C/C++ kode-stil, og et værktøj til at lave fælles kodestil kommer i næste blogindlæg.

Valget om fælles kodestil

Det første vigtige valg i et firma eller projekt er om man skal indføre fælles kodestil. Det er nok her man virkelig kan dumme sig. Hvis nogen i projektet indfører en kode-stil og retter andres kode op, uden at have fået accept af dette, så ligger vejen til kriser lige for.

At rette kode-stil op samtidig med at andre laver almindelige kodeændringer giver typisk problemer med at merge/flette kode ind i et fælles versions-kontrolsystem.

Derfor vil jeg klart anbefale at man vælger at rette kodestilen op på et tidspunkt, hvor der ikke er andre parallelle del-projekter i gang. Det er vigtigt at det er meldt ud at det sker på det valgte tidspunkt. Hvis der er grund til at diskutere valget om fælles kodestil, så tag diskussionen FØR der rettes kode.

Valget af en fælles C/C++ kodestandard

Det er i praksis umuligt at blive enige om hvilket af de to følgende kode-stiler, som er "bedst". Begge kodeblokke laver det samme, men brugen af mellemrum og indrykning i koden er lavet forskelligt. Begge stilarter er rimelig konsistente, og den enkelte udvikler kan sikkert forklare hvorfor netop den stil er den bedste....

Eksempel 1

/* 
 Eksempel 1 
*/
for (i=0;i<10;i++) {
 ar[i]=7;
 ar2[i]=i+9;
}

Eksempel 2

for (i = 0; i < 10; i++) /* Eksempel 2 */
{
    ar[i]  = 7;
    ar2[i] = i+9;
}

Meget apropos valget af kodestandard så rammer XKCD den diskussion lige på kornet:

Foto: https://xkcd.com/927/

Alternativt se hvad Clint Eastwood mener om det - nå nej...

Vil man have en fælles kodestandard for C/C++ kode, så vælg en kodestandard som allerede findes. Værdien af at lave en ny egen standard er nok meget begrænset. I sagens natur er vil andres kodestandard aldrig være 100% det man selv ville vælge, men jeg mener at værdien af en kodestandard især ligger i to faktorer:

  • Hvor præcis standarden er
  • Hvordan standarden er understøttet i udviklernes værktøjer.

Den anden del om kobling til værktøjer ser jeg mere på i næste blogindlæg.

Hvad findes allerede af C/C++ kodestandarder

En af de bedste kodestandarder jeg har set er Googles C++ kodestandard: https://google.github.io/styleguide/cppguide.html fordi den er meget klar og snildt kan anvendes for C-kode.

En anden standard, som er meget relevant er LLVM: http://llvm.org/docs/CodingStandards.html

Fra Linux-verdenen findes naturligvis også Linux kernel-code style: https://www.kernel.org/doc/Documentation/CodingStyle

BSD-vennerne har tilsvarende https://www.freebsd.org/cgi/man.cgi?query=style&sektion=9

Søger man på nettet dukker der regler for kode-stil for hver af det store Open Source projekter.

I næste blogindlæg ser jeg på koblingen mellem kodestandard og udviklingsværktøjer.

Relateret indhold

Peter Tofts billede
Peter Toft er algoritme-designer hos Fingerprints Cards. Han har blogget om open source og Linux siden Version2's begyndelse. Blogger også jævnligt om andre sjove teknologi-områder.

Kommentarer (65)

Kommentarer (65)
Ivan Skytte Jørgensen

Gennem årene har jeg observeret at min personlige kodestil i hobbyprojekter har ændret sig langsomt. Hvis jeg havde valgt en stil for 25 år siden og pedantisk holdt fast i den, så ville jeg nok være mindre produktiv i dag.
Den stil som person A betragter som optimal / "perfekt" i miljø X kan være væsentlig forskellig fra hvad person B foretrækker i miljø Y. Miljøerne og sprogene udvikler sig, og udviklere som holder fast i den stil, som var god dengang far var dreng, modarbejder produktivitet.

F.eks. hvis man ved at det miljø som man vil bruge fremover indeholder avancerede IDEs (kdevelop/netbeans/visual-studio), hvorfor så holde fast i stilen med "return-type on separate line"? Der er jo ingen som vil bruge 'ctags'. Eller hvis man ved at man vil være tvunget til at rette kode i en 80x24 terminal med vi (ja vi, ikke vim), så er kodestandarden om 200+ blanke linier før for-løkker måske ikke optimal. Omvendt, hvis man ved at folk vil redigere kode i grafiske miljøer, hvorfor så forsøge at holde koden på under 80 tegns bredde? Ville 120 ikke være mere fornuftigt?

Den eneste regel, som jeg altid (næsten) overholder, er at den stil, som der er i en enkelt kildekodefil, skal være konsistent.

Det skal siges at jeg har en høj tolerance for, skal vi sige, "alternative stile". I mit første job brugte hovedudvikleren en indrykning på 0 for det meste. Og tit en global variabel 'i'.

"Consistency is contrary to nature, contrary to life. The only completely consistent people are the dead." - Aldous Huxley

Lars Skovlund

Glæder mig til næste indlæg i serien. Jeg har ikke noget problem med kodestandarder som sådan, men det er ofte et problem at man udstikker en sådan uden at der følger kode/config med til at opsætte den i mindst en editor. Jeg ville nok være mere tilbøjelig til at følge dem hvis det var tilfældet.

Kim Brouer

...den rigtige (din egen) og den forkerte (alle der ikke ligner din).

Eksempel 2 mangler lige et mellemrum på hver side af plusset i "i+9", så er det til gengæld også The One True Style™. ;-)

Jacob Larsen

Hvis man roder med Android, så kan man godt forberede sig på at det meste allerede har en defineret kodestil, bare ikke den samme over det hele. Der er Linux kernen selv, som selvfølgelig har Linux kernel style, som man bliver nødt til at følge, siden koden sandsynligvis skal forbi Hr. Torvalds på et tidspunkt. Der er også Android userspace, som fra Googles side følger en stil der passer meget med eksempel 2 ovenfor. Men derudover inkluderer Android jo et par hundrede forskellige open source projekter (dem under "external" i source træet), som har hver deres kodestil.

Palle Simonsen

I hobbyprojekter har jeg bemærket, at jeg næsten altid bruger samme kodestandard til sprog med 'C' lignende syntax. Indryknings reglerne overlader jeg til sublime text. Så jeg er nok mere til konsistens end inkonsistens:

    function outer(c, d) {  
        var e = c * d;  
   
        function inner(a, b) {  
            return (e * a) + b;  
        }  
   
        return inner(0, 1);  
    }

Når man ikke koder mere i det daglige virke og man lige pludselig skal ha' fat i noget gammel kode i git(hub) er det vigtigt at læsevenligheden er i top og man har husket kommentarer på de svære dele, hvis der er sådan noget og også en lille documentation-block på de fleste funktioner / klasser / structs o.lign. Alt sammen noget man bliver glad for en aften hvor man skal bugfixe efter +10 timer på daytime job.

Morten Wegelbye Nissen

Jeg har selv været udsat for mere eller mindre hårde konventioner, og selv været tilhænger før.
Men med tiden er det gået op for mig at de ikke hjælper på korrekthed eller kvalitet. Det eneste man har er nogle leads der mere eller mindre nydende udøver deres magt.

Jeg er selv nået dertil:
Hvis det ikke kan understøttes af et percommit hook er det ligegyldigt.
Kodestil skal aldrig refactores, det eneste man får ud af det er tabt historik.

En ting jeg dog til stadighed kan undre mig over er den generelle kvalitet af de kommentar der bliver skrevet. Folk har en tendens til at kommentere hvad de gør istedet for hvorfor de gør det.

Ivan Skytte Jørgensen

Men med tiden er det gået op for mig at de ikke hjælper på korrekthed eller kvalitet. Det eneste man har er nogle leads der mere eller mindre nydende udøver deres magt.


Kodestandarder er særdeles nyttige. De er nemlig gode at bruge til at dunke folk i hovedet med.
De er ikke synderlig nyttige til at sikre fungerende og vedligeholdelsesvenligt software.

Kodestil skal aldrig refactores, det eneste man får ud af det er tabt historik.

Enig. Historikken er normalt vigtigere end det psykiske ubehag som en udvikler måtte få ved at se på "forkert formateret" kode.Hvis en udvikler omformaterer koden velvidende at historikken går tabt, så bør man begynde at kigge efter en ny udvikler.

Kim Jensen

Hov-hov, du antager jo at maskinen bruger to-komplement. Det er jo ikke portabelt.

Faktisk så bruger eksemplet 1s-komplement "~" som er helt portabelt og følger ANSI C standarden. Normalt bliver alle heltal i C dog compileret til 2s-komplement, men selv hvis de på nogle (meget gamle) maskiner ikke gør det, så skal 1s-komplement aritmetik virke alligevel.

Ivan Skytte Jørgensen

Normalt bliver alle heltal i C dog compileret til 2s-komplement, men selv hvis de på nogle (meget gamle) maskiner ikke gør det, så skal 1s-komplement aritmetik virke alligevel.

Plus og minus er aritmetiske operationer, mens ~ er en bit-operation. På en 1-complement maskine så er ~-2 == 5

På 2-komplement maskine: (jeg bruger blot 4-bit registre som eksempel)
2: 0010
-2: 1110
~-2: 0001
= 1

På 1-komplement maskine:
2: 0010
-2: 1010
~-2: 0101
= 5

Vi må straks få indført en regel i Kodestandarden som forbyder ~operatoren af portabilitetshensyn. Den regel kan kun fraviges efter en Fagin-inspektion og skriftlig accept fra diktatoren^H^H^H^H^H^H^Hprogramming lead samt styrekomiteen.

Men vi kan så måske blive enige om følgende standard uden 1s-komplement:

for(i=5<<!0;i+1;--i)ar2[i]=(10&(2|1))+(ar[i]=4^3)+i;

Se, det er straks mere acceptabelt :-)

Kim Jensen

Plus og minus er aritmetiske operationer, mens ~ er en bit-operation.


Bit-operationer kan også kaldes aritmetiske operationer da de udfører en operation der kan beskrives med plus og minus. F.eks. er ~-2 = 1 (på en 2s komplement maskine) og generelt så er ~x = -(x+1). Aritmetik er defineret som alle propertioner der kan skabes med plus, minus, gange, og division.

På en 1-complement maskine så er ~-2 == 5

På 2-komplement maskine: (jeg bruger blot 4-bit registre som eksempel)
2: 0010
-2: 1110
~-2: 0001
= 1

På 1-komplement maskine:
2: 0010
-2: 1010
~-2: 0101
= 5

Vi må straks få indført en regel i Kodestandarden som forbyder ~operatoren af portabilitetshensyn.


Nu skrev jeg at programmet er skrevet til at virke til ANSI C, og da ANSI C kom i første version i 1989 (C89), så må de antages at alle maskiner hvor man kompilerer ANSI C til er af nyere data. Så vidt jeg ved så skal vi tilbage til 60'erne og de tidlige 70̈́'ere for at finde maskiner som ikke bruger 2s komplement ! Men det kan selvfølgelig være en god idé at indføre i standarden at den ikke skal bruges til museums genstande. Og du kan så få æren for at have påpeget dette :-)

Casper Bang

...er naturligvis at vi skal til at gemme kode som AST, og gerne et generic standardiseret et af slagsen. Det vil løse mange issues, f.eks.:

  • Tabs. vs. Spaces.
  • Linielængde
  • Indentation længde
  • Optional single-line brackets
  • Bracket-style
  • Line ending (LF, CR, CRLF)

...dertil kommer mere avancerede sprog-specifikke ting som f.eks.:

  • Optional modifiers/arguments
  • Valg af sprog version (syntax sukker)
  • Valg af sprog

Jeg er klar over det har været forsøgt før i bl.a. Lips og diverse IDE'er som f.eks. JetBrains MPS med begrænset success - men jeg tror nu stadig på det på sigt. Mange IDE'er er generelt begyndt at vise/integrere tæt med AST'et og mange compilere er ligeledes begyndt at eksponere hooks direkte ind fra toolingen (MS' Roslin og Java's Compiler API).

Når først man er enige om et caninical AST format vil diff værktøj mf. bare fungere ud fra hvilken kode-standard (eller rettere, den rendering) den pågældende udvikler foretrækker med alle de andre fordele der følger med (f.eks. undlade at vise kommentarer).

Men disse ting vil nok nå de højere sprog først, C/C++ vil nok forblive legacy sprog med begrænset tooling sådan som det har været de sidste maaaaange år.

Kim Jensen

Vi må straks få indført en regel i Kodestandarden som forbyder ~operatoren af portabilitetshensyn. Den regel kan kun fraviges efter en Fagin-inspektion og skriftlig accept fra diktatoren^H^H^H^H^H^H^Hprogramming lead samt styrekomiteen.


Jeg vil mene at C kode standarden vil blive endnu bedre ved at forbyde direkte brug af arrays og så istedet kun bruge pointere, medmindre arrays bruges uden for deres normale indekserings område til at tilgå anden data. Det bør så betragtes som god stil altid at tilgå data ved med pointer eller arrays at tilgå data med andet navn end det som kan ses direkte i kildekoden (dog har tilgået data et navn i kildekoden, men et andet sted end det navn som bruges til at tilgå dataen).

David Kjær

Kodeformatering er efter min mening det mindst væsentlige emne vi kæmper med i "branchen".

Dårlig kode vil stadig være dårligt selv hvis det er pænt formateret. Læsbarhed sikres gennem sigende og konsistent navngivning, korte og veldefinerede klasser, metoder og funktioner samt et løst koblet og intuitivt design.

Det er muligt at voldformatere god kode så det bliver ulæseligt - men det skal næsten foregå med forsæt :)

Hvis man endelig skal bekymre sig om formatering (og det skal man jo lidt) så er Clang Format et godt bud: http://clang.llvm.org/docs/ClangFormatStyleOptions.html.

Baldur Norddahl

I mit første job brugte hovedudvikleren en indrykning på 0 for det meste.

Det er min erfaring at dette altid er et udtryk for en udvikler der ikke selv kan overskue koden. Jeg var engang instruktør på et kursus i Java programmering, og denne uvane var det første vi bankede ud af folk.

Jeg kan godkende opgaver med næsten en vilkårlig kodestil, så længe der er en stil, og det kan man ikke sige der er i kode uden indrykning. Det var desuden også min erfaring at jeg ofte blot behøvede udtale "tryk lige ctrl-shift-f", som er keybinding for at autoformatere programmet i Eclipse. Herefter kan den studerende ofte godt selv se fejlen.

Troels Henriksen

Det er min erfaring at dette altid er et udtryk for en udvikler der ikke selv kan overskue koden. Jeg var engang instruktør på et kursus i Java programmering, og denne uvane var det første vi bankede ud af folk.

Det er et meget godt argument for sprog med semantisk betydende indrykning, som Python eller (til dels) Haskell. Mennesker har alligevel en tendens til at læse indrykningen som betydende, så man kan lige så godt få oversætteren til at gøre det samme.

Jeg koder ikke selv i Go, men jeg er stor tilhænger af gofmt - et standardprogram der automatisk omformatterer Go-kode med den officielle standard-kodestil[0]. Det er måske ikke den farve jeg selv foretrækker til cykelskuret, men når det kommer til overfladiske æstetiske valg, så er det nok nemmest slet ikke at have brug for at snakke om det.

[0]: I grunden stikker kodestil jo dybere end semantisk ligegyldige valg angående indentering og blanktegn. Hvad med såsom omkring hardcoding versus parametriseret kode, hvornår kode udtrækkes til hjælpefunktioner, punktfri kode i funktionssprog, immutérbar versus mutérbar data, osv? Disse er også et spørgsmål om "stil", idet ethvert problem kan løses på begge måder.

Carsten Hansen

Jeg har arbejdet meget med et standardsystem, hvor mit job var at lave tilretninger. Disse tilretninger skulle senere implementeres igen og igen i opdaterede versioner af standardsystemet. Derfor tillod jeg mig at afvige fra gængs navngivning mht. f.eks. feltnavne, variabelnavne og funktionsnavne, da der ikke var mulighed for ekstra lag eller namespace.

Når jeg fulgte "standarden", så kunne jeg være sikker på, at der opstod mystiske komplikationer, når der skulle opdateres.

Kim Jensen

Jeg glemte at komme med et eksempel på lov om ny C kodningsstil standard:

Forudsat at de to arrays deklareres og defineres som følger:

int ar[5<<(3^2)], ar2[5<<!0];

Så bør følgende kode bruges:

for (i=5<<!0;i+1;--i)ar[i+(5<<(3^2))]=(10&(2|1))+(ar2[i-(5<<!0)]=4^3)+i;

Christian Nobel

.. må være at kode er overskuelig, så også andre (rimelig nemt) kan få overblikket og er i stand til at gennemskue hvad man har lavet - uden at skulle prøve at rekonstruere et helt loopforløb i hovedet.

Imo er "one liners" en no go, og linieskift er gratis.

Men i stort omfang er det vel ligesom helt almindelig tekst - man kan godt skrive det hele i en køre uden linieskift og uden at lave nye afsnit, men læsbarheden bliver også derefter.

Lakmustesten er at prøve at tage noget kode frem man ikke har rørt i et år, og hvis man skal bruge urimelig lang tid på at gennemskue hvad det egentlig er man har lavet, ja så må man vel sige at have fejlet.

Thomas Søndergaard

Men disse ting vil nok nå de højere sprog først, C/C++ vil nok forblive legacy sprog med begrænset tooling sådan som det har været de sidste maaaaange år.

Det er en forældet opfattelse. C++ udvikler sig skam stadig. C++11 er en kæmpe fornyelse af sproget og yderligere forbedringer kom til i C++14. C++17 (forventet) vil bringe yderligere forbedringer. På tooling området har Clang - tak Apple! - sørget for at der er kommet skærpet konkurrence på compiler-fronten, så gcc, MSVC har måttet oppe sig for at følge med. Clang har også vist vejen med stærkt forbedret tooling generelt.

På IDE fronten er der også sket en del. Qt Creator er efter min mening et langt bedre IDE end gamle bedagede Visual Studio, og Jet Brains CLion skulle også være et stærkt bud.

Torben Mogensen Blogger

Det er et meget godt argument for sprog med semantisk betydende indrykning, som Python eller (til dels) Haskell. Mennesker har alligevel en tendens til at læse indrykningen som betydende, så man kan lige så godt få oversætteren til at gøre det samme.

Jeg er til gengæld ikke tilhænger af betydende indrykning. Jeg har programmeret i to lignende sprog: Standard ML (indrykning uden betydning) og F# (indrykning har betydning), og selv om man sparer et par nøgleord i F#, finder jeg det frustrerende med den betydende indrykning. Specielt betyder manglen på den redundans, som eksplicit afslutning af blokker er, at fejl ofte bliver indikeret længe efter den faktisk position, og generelt giver fejlagtig indrykning ofte svært forståelige fejlmeddelelser. Selv om F#-oversætteren gør sit bedste for at foreslå, at en fejl kan skyldes forkert indrykning, tager den ofte fejl. Det er specielt et problem for nybegyndere (vi er skiftet fra SML til F# som første programmeringssprog).

Endvidere gør indrykningsfølsom syntaks det vanskeligere at specificere syntaksen -- uanset om det er gennem formelle grammatikker eller uformelle beskrivelser, og det er vanskeligere at lave programmer, der genererer programkode.

Redundans er godt i kode, der skal læses af mennesker, og redundans gør det nemmere for oversættere og fortolkere at opdage og lokalisere fejl. Ja, det gør kildeteksten marginalt større, og det tager lidt ekstra tid at skrive, men det opvejes efter min mening af fordelene. Ikke dermed sagt, at redundans ikke kan overdrives.

Kim Jensen

Din holdning er fuldstændigt imod god kodningsstil IMO. Det vigtigste er at man indgående kender til det sprog man programmerer i, og man bør aldrig arbejde sammen med mennesker som ikke f.eks. kan udføre bit-operationer i hovedet eller udregne f.eks. hvilke hukommelses pladser pointere til pointere til pointere påvirker. Og man bør undgå ethvert programmeringssprog som ikke muliggør kreativ kompakt brug af sproget, og her kan især Assembler, C og Javascript anbefales (sprog som Java bør derfor altid undgås). Intet er gratis og derfor er linjeskift heller ikke gratis, og det er anstrengende for øjnene og kræver også for også mange tastebevægelser ikke at have sin kode samlet så kompakt som muligt (folk der bruger musebaserede editorer bør man under ingen omstændigheder arbejde sammen med da kun VI lignende editorer kan anerkendes, da andre typer editorer medfører sløvsind og langsomlighed). Desuden bør der aldrig stå noget i koden som ikke er nødvendigt for compileren eller fortolkeren. En god programmør tænker og regner som en compiler eller fortolker, og hvis den kode man laver ikke konstant kræver en aktiv regneindsats, så bliver man ramt af sløvsind og på sigt hjernedød hvis man ikke er det i forvejen. Den bedste måde at sikre at sin kode kan forstås efter flere år er derfor at skrive den således at den kun kan forstås ved at gennemregne kodens funktionalitet, da man således hukommelsesmæssigt genaktiverer de udregninger som man gjorde ved udarbejdelsen af koden, og det gør at man så straks forstår koden igen (og hvis ikke så er det et tegn på at man er blevet for svag og man bør derfor straks påbegynde intensiv hjernegymnastik).

Christian Nobel

En god programmør tænker og regner som en compiler eller fortolker,

Gud fader bevares - enten mangler du et <irony>, eller også har du meget store tanker om dig selv.

Kodning er bare en lille del af en opgaveløsning, og hvis denne opgave løsning inkluderer mange mennesker, som måske skal arbejde sammen, så er der stor risiko for at der går CSC i løsningen hvis de alle sammen tror de er guds gave til menneskeheden, og så ellers kan sidde i hver sin lille osteklokke og lave 17 leftshifts i hovedet.

Troels Henriksen
Morten W. Jørgensen

Det var det første fornuftige jeg har set i den her tråd!

Cadeux til dig for det!

Selv Googles retningslinjer for C++ er rent kosmetisk og nævner, så vidt jeg kan se, ikke noget om at have const expressions på venstre side af sammenligninger for at undgå utilsigtede assignments når nogen glemmer et = og skidtet kompilerer alligevel.
Det kan selvfølgelig være jeg har overset det så ret mig endelig hvis I kan se det i google retningslinjer.

Bikeshedding to the max, nemlig.

Troels Henriksen

Jeg er til gengæld ikke tilhænger af betydende indrykning. Jeg har programmeret i to lignende sprog: Standard ML (indrykning uden betydning) og F# (indrykning har betydning), og selv om man sparer et par nøgleord i F#, finder jeg det frustrerende med den betydende indrykning. Specielt betyder manglen på den redundans, som eksplicit afslutning af blokker er, at fejl ofte bliver indikeret længe efter den faktisk position, og generelt giver fejlagtig indrykning ofte svært forståelige fejlmeddelelser.

Nu ved jeg tilfældigvis at du også har langt mere erfaring med Standard ML end F#! Jeg selv har meget ringe erfaring med F# og dens oversætter, men min Haskell og Python-erfaring fortæller mig, at der ikke er noget til hinder for letforståelige syntaks-fejlbeskeder i sprog med betydende indrykning. Selvfølgelig kan en given parser gøre det dårligt, men samme problem kan jo opstå i klassiske sprog hvis man glemmer at lukke en tekstkonstant eller en parentes. Hvis man kvajer sig med indrykning i et indrykningsfølsomt sprog, så vil fejlen typisk være ret tydelig, da indrykning er nemt at scanne visuelt.

Endvidere gør indrykningsfølsom syntaks det vanskeligere at specificere syntaksen -- uanset om det er gennem formelle grammatikker eller uformelle beskrivelser, og det er vanskeligere at lave programmer, der genererer programkode.

En god løsning på dette problem, som er valgt i Haskell, er at definere sproget med tuborgklammer og semikoloner, og definere den indrykningsfølsomme syntaks som et sæt regler for hvornår disse indsættes automatisk i den leksikale fase. Det gør sproget venligt over for både mennesker og maskiner.

Det løser dog ikke det for mig største problem ved indrykningsfølsom syntaks: Nemlig at det er sværere at flytte/kopiere kode uden hjælp fra tekstredigeringsværktøjet, da det sted man tager koden fra kan have et andet indrykningsniveau end der hvor man kopierer den hen. I et sprog som C kan det godt ende med at se herrens ud til at starte med, men Emacs kan automatisk gen-indentere i den nye kontekst. Det kan ikke lade sig gøre hvis indenteringen er syntaktisk betydende.

Kim Jensen

Kodning er bare en lille del af en opgaveløsning, og hvis denne opgave løsning inkluderer mange mennesker, som måske skal arbejde sammen, så er der stor risiko for at der går CSC i løsningen hvis de alle sammen tror de er guds gave til menneskeheden, og så ellers kan sidde i hver sin lille osteklokke og lave 17 leftshifts i hovedet.


Du har fuldstændig misforstået pointen. Formålet med nævnte kodningsstil er dels at ekskludere wannabe typer som ikke kan tænke selv og som ikke forstår sproget der programmeres i og kodens reelle funktionalitet, og dels at sikre at stil og kommentarer ikke kommer til at skabe illusioner om at koden gør noget som den muligvis ikke gør alligevel. Hvis andre skal deltage i kodningen så er der helt essentielt at de således tvinges til at forholde sig til den aktuelle kode og dens funktionalitet, og ikke påstået funktionalitet (og indryknings og mellemrums stil kan nemt forstås som udtryk for funktionalitet, ligesom kommentarer ikke nødvendigvis er sande ligemeget hvor pæne det er eller hvor mange standarder de følger, undtaget dog hvis man opfinder en kode til normal læsesprog kommentar cross compiler). Det mest ideelle vil være at kode i maskinkode med en hex editor da man således bliver tvunget til at forholde sig til hvad koden gør uden yderligere abstraktionslag som muliggør misforståelser (desværre er koden så ikke særlig portabel, men metoden kan anbefales til f.eks. MCU programmering). Men hvis man skal programmere i højere abstraktionsniveau end maskinkode, så bør koden skrives uden kommentarer, mellemrum, og indrykninger. Dog kan man evt. lave et linjeskift imellem funktioner/metoder, da dette ikke ødelægger meningen med kodningsstilen og gør det nemt at finde ønskede funktioner/metoder, men bortset fra dette bør editorens søge og markerings funtion bruges. Hvis man så sørger for at den editor man bruger ikke har for meget bredde, så kan man nemt overskue koden indenfor et begrænset synsfelt hvilket er afslappende og roligt for øjnene og gør at man så hurtigt kan komme rundt i koden.

Flemming Poulsen

og det er den, der gør at man kan rette en andens kode kl. 5 den 1/1 !

Det kan godt være det tager lidt mere tid at skrive, men tænk på at det måske er en kollega der kl. meget sent om natten bliver ringet op og skal fejl søge.
Ligegyldigt hvilket sprog - skriv det simpelt og overskueligt - hellere 10 linier der kan læses end 2 der er uoverskuelige.
mvh Flemming - programmør siden 1977

Hans Schou

Hvis man endelig skal bekymre sig om formatering (og det skal man jo lidt) så er Clang Format et godt bud:


Eller Artistic Style. Hvis så man i gruppen ikke er enige, så man blive det, og kode det ind i astyle, og så omformatere al koden. Hvis din beautifier ikke gør det rigtige, så fix beautifieren. Ingen undtagelser.

Bruger man VCS, så sørg for beautifier automatisk køres inden der committes.

Bent Jensen

Bare koden er godt kommenteret.
Som definition af funktionskald, hvad det skal ind, og hvad det returnere. Og hvad der sker med data i denne.

Koder ikke længere, men gode kommentare hjælper, så behøves man ikke at læse eller forstå selv koden, hvis man hurtigt skimter,

Kim Bøndergaard

Har nu været gennem det oprindelige indlæg plus alle mulige relevante og irrelvante (selvom det er lidt nørdet-sjovt at lave det mest ulæselig kode) kommentarer til indlægget, og har kun fundet et indlæg (af Morten W. Jørgensen ) som ganske kort berører formålet med en kodestandard, nemlig at forbedre kode. Det kan være at gøre koden mere sikker nu og her og det kan være at gøre koden mere vedligholdelsesvenlig.
Der er nok ingen tvivl om at hvis alle overholdt 'min standard' omkring formatering og indrykning mv. ville det være meget lettere at forstå noget nyt kode første gang man bliver præsentereret for det. Ofte er de projekter vi stifter bekendtskab med i dag dog baseret på integration af en masse forskellige andre projekter, ofte skrevet på hver sin måde. Så enten må vi vænne os til at ikke alle skriver ens eller også må vi bruge nogle tools til at formatere til det format vi hver især kan lide. Men som en skrev i et indlæg: Vær konsistent med den fil du retter i.

Et langt større og vigtigere formål med en kodestandard er at gøre koden mere 'sikker'.

Et par typisk eksempler:
'{' ved if() i C/C++: Hvis man kræver '{' selv ved oneliners mindskes risikoen for at der fejlagtigt indsættes et ekstra statement som fejlagtigt ikke omfavnes af if() conditionen. (Iøvrigt vil Linux kerne communitiet ikke have '{' ved oneliners)

Eller hvis man sørger for at have constanter på venstre side i conditions mindskes risikoen for fejlagtigt at skrive en assingment (= i stedet for ==) i conditionen.

Disse par eksempler er dem jeg typisk har set i de lokalt genererede kodestandarder som jeg i mit professionelle virke er stødt på.
Men det kan gøres meget bedre.

Hvis man fx baserer sin kodestandard på C-idioms (ex http://www.adamtornhill.com/Idiomatic_expressions_in_C.pdf) så tror jeg på man får bedre kode. Både nu og her og når det har været gennem de næste 3 iterationer.

Martin Kristiansen

Jeg mener det er fuldstændigt forfejlet at have fokus på om tuborg paranteser står på egen linie og om der er mellemrum de rigtige steder. Jeg lader Netbeans (eller IDE du jour håndtere formatering)

Der må være et vist minimum af kompetence hos udvikleren mht. læse kode.

Hvis man insisterer på at:
a = b ? c : (d ? e: f);

skal skrives om til

if(b)  
{  
  a=c;  
}  
else  
{  
  if(d)  
  {  
    a=e;  
  }  
  else{  
    a=f;  
  }  
}

Så skal man finde sig en anden profession

Fatbar navngivning af parametre/variable, metoder/funktioner uden sideeffekter (aka. testbare) og dokumentation af kode er efter min mening meget vigtigere.

Ivan Skytte Jørgensen

Eller hvis man sørger for at have constanter på venstre side i conditions mindskes risikoen for fejlagtigt at skrive en assingment (= i stedet for ==) i conditionen.

Det er faktisk et glimrende eksempel på er verdenen ændrer sig. Der var en gang at det kunne være en rimelig regel, som kunne hjælp med at undgå fejl. Men alle moderne kompilere kan advare imod den konstruktion. Hvis man skal bruge en oldnordisk compiler til target-miljøet så er det på tide at man lærer at udvikle på en anden med bedre værktøjer (valgrind, flexelint, insure++, nyere compiler, syntax-hightligting, ...) og kun lave den endelige oversættelse med den oldnordiske compiler. Og hvis man ikke har slået warnings til i sin compiler, så har man pr. definition fejl i sit program.

Jens Henrik Sandell

Peter,
Supergodt emnevalg. Det ses tydeligt at de fleste kommentatorer er af den rette tro, men især/kun deres egen udgave.

Jeg mener at standarder i udgangspunktet skal hjælpe til at undgå ting som "Apple's SSL brøler", http://www.version2.dk/blog/apples-ssl-broeler-56425

Og jeg er absolut ikke tilhænger af hverken superkomprimeret kode eller formalt ekstrapoleret flueknepperi á la

if(b)    
{    
  a=c;    
}    
else    
{  ...

Check i øvrigt Paul Bourkes hj.side med PovRay Short Code Contest. Der kommer der da i det mindste noget pænt ud af "compileren" (Render maskinen). http://paulbourke.net/exhibition/scc5/final.html

Mogens Hansen

for(i=5<<~-2;i+1;--i)ar2[i]=(ar[i]=~-8)+i+(~-5>>~-2);

For at få samme opførsel som den oprindelige kode antager ovenstående kode at heltals repræsentationen er toer's komplement - som er en af de tilladte repræsentationer.
Hvis heltals repræsentationen er er ener's komplement, som også er tilladt, får man en anden opførsel.

Men god pointe: læsbarhed er meget andet og vigtigere ting end hvor man placerer mellemrum, parenteser og navnekonvention.

Kim Jensen

for(i=5<<~-2;i+1;--i)ar2[i]=(ar[i]=~-8)+i+(~-5>>~-2);

For at få samme opførsel som den oprindelige kode antager ovenstående kode at heltals repræsentationen er toer's komplement - som er en af de tilladte repræsentationer.


Så vidt jeg ved at det kun museums genstande fra 70'erne eller tidligere der bruger 1s complement, men for at gøre at gøre det helt sikkert så kan eksemplet med den indtil videre endelige anbefalede stilart skrives således:

Forudsat at de to arrays deklareres og defineres som følger:

int ar[5<<(3^2)], ar2[5<<!0];

så bør der kodes således:

for(i=(~3==-4?5<<~-2:5<<!0);i+1;--i)ar[i+(~7==-8?5<<(3^2):(5<<(3^2)))]=(~11==-12?!0<<~-2:10&(2|1))+(ar2[i-(~4==-6?5<<!0:5<<!0)]=(~8==-9?~-8:4^3))+i;

Og hvis man ikke gør det så er man en uansvarlig, svag, og dårlig programmør der straks skal sendes på pension uden gyldent håndtryk eller ret til nogensinde at sige noget om noget som helst.

Christian Nobel

Og hvis man ikke gør det så er man en uansvarlig, svag, og dårlig programmør der straks skal sendes på pension uden gyldent håndtryk eller ret til nogensinde at sige noget om noget som helst.

Jeg håber ved gud ikke at det er dig der skal prøve at skaffe børn og unge interesse for at beskæftige sig med programmering og udvikling.

Men udsigten er vel for god oppe på piedestalen til du kan kere dig om det.

Kim Jensen

... tidligere standard ...


VIGTIGT, der nu kommet en opdatering til kodningsstil standard. Husk at alt kode skal harmoniseres øjeblikkeligt af konkurrence og sikkerheds hensyn.

Forudsat at de to arrays deklareres og defineres som følger:

int ar[5<<(3^2)], ar2[5<<!0];

så SKAL der kodes således:

for(i=(~3==-4?5<<~-2:5<<!0);i+1;--i)ar[i+(~7==-8?5<<~-2:5<<(3^2))]=(~11==-12?!0<<~-2:10&(2|1))+(ar2[i-(~4==-6?1/0:5<<!0)]=(~8==-9?~-8:4^3))+i;

Mogens Hansen

Så vidt jeg ved at det kun museums genstande fra 70'erne eller tidligere der bruger 1s complement,

C og C++ er specifikationer som man koder i forhold til, for til gengæld at få veldefineret opførsel på ældre, nuværende og fremtidige implementeringer (hardware, operativ systemer og compilere).

C og C++ har en del muligheder for at lave såvel "unspecified behaviour" som "undefined behaviour". Man gør klogt i at holde sig fra de områder, hvorfor kodestandarder typisk også forbyder kode der falder i de områder.
Det kode du viser har "unspecified behaviour".

Hvis man prøver at snyde sin compiler, skal den nok få sin hævn på et tidspunkt.

Kim Jensen

Det kode du viser har "unspecified behaviour".


Nej, det har det jo så ikke mere i henhold til ny fremlagt kodestil standard, som selv undersøger om systemet er et 2s complement system, og hvis ikke så ikke anvender 1s complement kodning som kræver underlæggende 2s complement system.

Det vil nok være ikke være sandsynligt at computere fremover vil gå tilbage til 1s complement systemer da 2s complement i næsten alle tilfælde giver bedre performance (undtaget f.eks. special purpose netværkudstyr mv.). Så vidt jeg ved findes der ingen moderne CPU'er eller MCU'er der anvender 1s complement, men muligvis man i særlige tilfælde bruger det i ASIC eller FPGA/CPLD systemer.

Kim Jensen

Det kode jeg har kommenteret på har "unspecified behaviour".
Det nye kode er en sjov måde at skrive sin opsigelse.


Da det er en ny kodningsstil standard så bliver man netop opsagt hvis den ikke implementeres helt korrekt. Det er så vigtigt at forstå meningen med standarden. Standarden bygger på nyeste videnskabelige forskning inden for hukommelsesforskning og virker på den måde at den vedligeholder eller forøger den synaptiske elasticitet og øger muligheden for at huske og genkende meningen med kode flere år efter kodningen. Det smarte er at når man udfører diverse udregninger så er det godt for den synaptiske elasticitet, og når hvert statement så har en unik udregnings signatur, så bliver hvert statement lagret i hukommelsen med det tilhørende udregningskompleks og forståelse af koden. Og når udregningerne er konstrueret således at de skaber mange synaptiske hjerne forbindelser, så skabes synaptiske forbindelser som nemt kan genkaldes i hukommelsen, og så kan man hurtigt genskabe forståelsen for hvert statement ved genlæsning, og nye læsere tvinges til at forstå koden på et dybere niveau samtidig med at de også får skabt tilsvarende unikke synaptiske hjerne forbindelser. Hver programmør bør så have tildelt sin egen individuelle beregningspulje, som skal uddeles af og kunne anskaffes fra et central styrings organ, og det vil gøre at hvert statement i hele verden vil blive bundet til et særegent beregningskompleks. Bit operationer er bare en af de beregningsmetoder som kan bruges.

Rune Jensen

Navngivning og konsistens i navngivning er EMM ganske vigtig. Nu opererer jeg mest med HTML/CSS/JS, ikke rigtig med C, omend jeg har leget med VALA for længe længe siden.

Ét af mine spørgsmål gik faktisk på at kunne kende med det samme forskel på globale og lokale variable samt konstanter.

En anden er, om man bør bruge prefixes og supfixes eller ej på vairable. F.eks.

arrFamilyMember

for at antyde, det er array.

Eller om man skal bruge camelCase, om man skal skrive lange betydende variabelnavne eller cutte dem, når de når en vis længde...

Jeg har fundet to forskellige kodestumper, jeg har lavet med to vidt forskellige kodestile, og jeg har forsøgt at omskrive det til én kodestil. Det blev helt umanerligt grimt og ikke letlæseligt.

Det er lidt som om, i visse kodestumper, der virker én kodestil og i andre en anden kodestil. Det var sådan set én af de ting, som fik mig til at interessere mig for en egentlig standard.

For det er jo klart, at kan man gøre det ens overalt, må det også være nemmere at tyde. Hele problemet ligger i hvilken standardiseret kodestil skal jeg så bruge, så den virker overalt i al min kode? (ved samme sprog selvfølgelig).

Jeg er blevet rimeligt god til at standardisere min CSS og min HTML.

Men igen, så halter det ligeså snart det rammer scripting eller egentlig programmering. Så kan jeg ikke finde den mest optimale kodestil ifht. læsbarhed/længde og performance (man kan nogle gange få højere performance af kode ved at lave det mindre læsbart).

Jeg har ledt ganske længe efter egentlige standarder for kodning (særligt javascript) og programmering, skrev faktisk også et par indlæg i nyhedsgrupperne for laaaang tid siden, og fik også en del gode svar, men ikke egentlig enighed om resultatet.

Rune Jensen

Nu er XKCD vel efterhånden lidt en standard indenfor IT-humor. Hvis man er i tvivl, kan man altid henvise til den. Så noget er da opnået.

Jens Henrik Sandell

Jeg kan ikke i min tøreste drøm forstå hvor det ikke er enten compileren eller statisk kodeanalyse der skal til der.

Hej Morten,
Gå lige tilbage og læs på den linkede artikel igen. Dit udsagn tager ikke højde for sourcekodens kompleksitet, analyseværktøjernes ditto, og programmørfolkets vilkår m.h.t. deadlines.

Det vil kun ske hvis alle dimittender kommer ud med den lange skruetrækkereksamen i "formal methods", og samtidig insisterer på kun at tage jobs, hvor de kan anvende disse.

Til sidst vil jeg montere min sølvpapirshat inden jeg svarer i konteksten af konspirationsteorier: Fejlen i Heartbleed (?)blev introduceret(?) så ingen lige umiddelbart ville fatte mistanke, hvis man slog et smut forbi den pågældende fil. Og der var ingen syntaktiske fejl, som compileren kunne flage op.

Morten Wegelbye Nissen

Gå lige tilbage og læs på den linkede artikel igen. Dit udsagn tager ikke højde for sourcekodens kompleksitet, analyseværktøjernes ditto, og programmørfolkets vilkår m.h.t. deadlines.


Mit udsagn var møntet på det ret konkrete eksempel.

Og jeg kan iøvrigt ikke se hvordan bloggens emne hjælper på nogle af de 3 problemer du nævner her.

Og hvis man syntes at det vil være for bøvlet for et analyseværktøj at se at der i det nævnte tilfælde er noget kode der aldrig kan blive ramt - så skal vi nok snakke om hvor gode de værktøjer er.

Og der var ingen syntaktiske fejl, som compileren kunne flage op


Ikke syntax, men der er helt klart noget som kan give en warning. Og jeg forventer at kompetente leverandøre kigge rigtigt godt på warnings i kode der handler om sikkerhed - og jeg syntes ikke det er for meget at forlange.

Kim Jensen

Til sidst vil jeg montere min sølvpapirshat inden jeg svarer i konteksten af konspirationsteorier:


Husk så at for at en sølvpapirshat virker rigtig så skal den kobles som et Faraday bur med jord forbindelse, og hvis det skal gøres helt professionelt så bør jordforbindelsen skabes med jordspyd helst ca. 3 meter ned i jorden. Hvis mobilitet er påkrævet så kan man evt. have en f.eks. 2,5 meter ledning med metalkugle monteret til sølvpapirhatten således at kuglen berører jorden også ved gang. Hvis man mener at hele kroppen skal sikres så kan man påføre sig en trådvest koblet til metal under sålerne. Man kan også isolere f.eks. en hel bygning i et Faraday bur som også har den fordel at det vil beskytte elektronik imod EMP, og så vil selv David Icke føler sig hjemme (sidste dog næppe en fordel).

Mogens Hansen

Ikke syntax, men der er helt klart noget som kan give en warning. Og jeg forventer at kompetente leverandøre kigge rigtigt godt på warnings i kode der handler om sikkerhed - og jeg syntes ikke det er for meget at forlange.

Der var, mig bekendt (og jeg har undersøgt det rimeligt), ikke nogen statiske analysatorer (endsige warnings) der var i stand til at detektere HeartBleed, inden fejlen blev fundet. Efterfølgende er f.eks. Coverity blevet forbedret, så den vil kunne finde HeartBleed og tilsvarende problemer.
Den eneste måde jeg er bekendt med, som kunne have fundet HeartBleed automatisk (og hurtigt) inden problemet blev kendt, er coverage guided fuzzing kombineret med dynamiske analysatorer (f.eks. AddressSanitizer). Det har jeg set demonstreret - og det tog højest et par minutter.
Metoden bruges bl.a. til at teste browsere (WebKit og Chrome), compilere (Clang) og databaser (SQLite) - software som skal kunne modtage vilkårligt underligt data på en robust måde.
Se eventuelt Marshall Clow's fremragende presentation "Hardening your Code" for relateret information på https://www.youtube.com/watch?v=cg7uFBmUh_Q

Kim Jensen

Den eneste måde jeg er bekendt med, som kunne have fundet HeartBleed automatisk (og hurtigt) inden problemet blev kendt,


Interessant hvad du skriver ! Vedr. det med at detektere HeartBleed lignende problemer, så vil det helt sikkert være en god idé i C ikke at bruge usikre libraries som f.eks. gets, sprintf, strcat, strcopy, vsprintf mv., og så kun bruge sikre alternativer som f.eks. fgets istedet for gets osv. Desuden, så er burde det vil ikke være særligt svært til 1s egne programmer at skrive et program der kan detektere buffer overflows og buffer underflows (som blev brugt i HeartBleed), og hvis man samtidig kun bruger sikre systemkald, så er man vel (forhåbentlig) sikker eller hvad (det kan selvfølgelig blive et problem helt sikkert at vide hvilke systemkald der er sikre især på M$, men desværre også på *nix'ere) !!!

Mogens Hansen

Tak for et interessant blog indlæg.
Kodestandarder er altid et emne, der kan starte en god eller i det mindste ophedet diskussion.
Det er interessant at overskriften omtaler ”smuk kode” sammen med ”kodestandard” – er der en sammenhæng ? Måske en simpel sammenhæng ?

Spørgsmålet relaterer sig til hvad er programmering ? Er det en videnskab (som det indikeres i ordene Datalogi eller Computer Science), en kunst eller et håndværk ?
En opfattelse af ”smuk” relaterer sig til programmering som kunst.
Kodestandarder relaterer sig til det håndværksmæssige aspekt af programmering.
Store kunstnere er også ofte dygtige håndværkere, eller får hjælp af dygtige håndværkere. Det gælder f.eks. at den kendte danske skulptør Robert Jacobsen var en dygtig smed, eller fotografen Ansel Adams var dygtig til at fremkalde og kopiere billeder og systematiserede denne viden i hvad han kaldte zone-systemet og beskrevet i bøgerne ”The Camera”, ”The Negative” og ”The Print”.
Programmering har elementer både videnskab, kunst og håndværk.

Man kan spørge: hvorfra kommer smuk kode, hvordan opstår det og kan man lære at lave smuk kode.
Min opfattelse er at smuk kode kommer fra en klar forståelse af det problem der skal løses (problem domænet), kombineret med en klar forståelse af hvordan det kan løses (løsnings domænet – f.eks. programmeringssproget) samt erfaring og god smag.
En måde at komme tættere på at lave smuk kode er at studere kode, som opfattes som smuk. Det er ikke væsentligt anderledes, end at blive bedre til så mange andre ting: studer de store mestres arbejder og lær. Det er ok at prøve at spille guitar som Eric Clapton, selvom man ved man aldrig bliver lige så dygtig, og man bliver givetvis dygtigere.
Der findes en masse kode man kan studere. Der er også skrevet bøger, hvor smuk kode er beskrevet, f.eks. bøgerne
Beautiful Code
Edited by Andy Oram & Greg Wilson
ISBN 0-596-51004-7
eller
Programming Pearls, Second Edition
Jon Bentley
ISBN 0-201-65788-0

Ideen om sammenhæng mellem kodestandarder og smuk kode er nærliggende: hvis vi kan opsætte et relativt simpelt regelsæt, så har vi en mekanisme der kan sikre smuk kode, eller sikre andre egenskaber vi ønsker af vores kode. Den tankegang relaterer sig til Frederick P. Brooks snart 40 år gamle klassiske bog ”The Mythical Man-Month”, som bl.a. behandler den fejlagtige idé at personer og måneder kan udskifte hinanden når et projekt skal laves, og en person frit kan udskifte hinanden. Det er idéen om at man kan lave et system, som eliminerer den usikkerhed som der ligger i at have mennesker involveret, fordi de almindeligvis er uforudsigelige.
Og for god ordens skyld: Brooks promoverer absolut ikke denne idé.

Kodestandarder relaterer sig til det håndværksmæssige aspekt af at programmere. Som sådan kan de potentielt sikre, eller som minimum stimulere, den håndværksmæssige kvalitet af koden. Det kan være egenskaber korrekthed eller læsbarhed.

Inden jeg går videre er en personlig disclaimer på sin plads: jeg er ikke og ønsker ikke at være C ekspert, hvorimod jeg besidder en anseelig mængde C++ ekspertise (velvidende at mange har mere C++ viden). Det betyder også at efterfølgende naturligvis skrives med det udgangspunkt.

I blog indlægget omtales C/C++. Jeg bryder mig ikke om udtrykket, for det er ikke et programmeringssprog. C er ét programmeringssprog og C++ er et andet, som tilsigtet og som på godt og ondt har et stort overlap med C.
Et program kan samtidig være et gyldigt C og C++ program – det kan også nemt ikke være tilfældet.
Se eventuelt http://www.stroustrup.com/bs_faq.html#C-slash for flere overvejelser om denne detalje.

De 2 kode eksempler, der er vist fokuserer på typografiske forskelle: hvor er mellemrum og linieskift placeret. Det er nærliggende at tage ting som linie længde og navngivning med i samme type af anbefalinger.
Sådanne ting påvirker naturligvis læsbarheden. Det er en god idé at være konsistent, og hvis man kan få et tools, som f.eks. clang-format, til at hjælpe sig er det godt. Generelt har jeg stor fidus til Clang tools.
Men langt vigtigere er hvad der rent faktisk står, og hvordan man automatisk eller idiomatisk fremmer at programmer er korrekt, effektive, nemme at vedligeholdet og tilsvarene gode egentskaber.

Hvis man kigger på for-løkken
for (i=0;i<10;i++)
mener jeg at man med fordel idiomatisk kan skrive
for(int i = 0; 10 != i; ++i)
af følgende grunde:
• Begræns scope af ”i” og initialiser den samtidig med den erklæres – hvis det er muligt
• Brug ”forskellig fra” i stedet for ”mindre end”. Det er et mindre krav til en type at kunne afgøre om de er forskellige end om den ene er mindre end den anden. Det spiller ikke nogen rolle for typen ”int”, men for en tilsvarende løkke med std::list<T>::iterator. Ydermere vil en fejl, hvor ”i” utilsigtet bliver tildelt værdi større end 10, sandsynligvis få programmet til at fejle så alvorligt at chancen for at man opdager det er større.
• Hvis muligt skriv en konstant på venstre side af ”forskellig fra”, for så vil en skrivefejl som ”10 = i” være en syntaksfejl, hvorimod ”i=10” er utilsigtet opførsel, som i bedste fald giver en compiler warning.
• Brug prefix ++ i stedet for postfix ++. Det er en idiomatisk performance forbedring. Postfix ++ returnerer den gamle værdi, som ikke skal bruges. Der kræves en ekstra kopi af ”i” for at holde den gamle værdi. Det spiller formodentlig ingen rolle i praksis når ”i” er en ”int”, men hvis det er en std::map<K,V>::iterator gør det formodentlig en forskel.
I C++11 og nyere er range-based for-løkker værd at overveje hvis det er muligt, for de fjerner en del skriveri og nogle muligheder for fejl.
Sådanne overvejelser finder jeg langt mere interessante end hvor mellemrum og linieskift står.

Der findes mange gode anbefalinger til hvordan man håndværksmæssigt forbedrer sin C++ kodestil. Der findes desværre også endnu flere utroligt mange dålige råd og kodestandarder til C++ rundt omkring – og det kan være svært at kende forskel.
Eksempler på generelt gode anbefalinger kan f.eks. findes i bøger af Scott Meyers, Herb Sutter og Andrei Alexandrescu:
Exceptional C++
Herb Sutter
ISBN 0-201-61562-2

More Exceptional C++
Herb Sutter
ISBN 0-201-70434-X

Exceptional C++ Style
Herb Sutter
ISBN 0-201-76042-8

C++ Coding Standards
Herb Sutter, Andrei Alexandrescu
ISBN 0-321-11358-6

Effective C++, Third Edition
Scott Meyers
ISBN 0-321-33487-6

More Effective C++
Scott Meyers
ISBN 0-201-63371-X

Effective STL
Scott Meyers
ISBN 0-201-74962-9

Effective Modern C++
Scott Meyers
ISBN 978-1-401-90399-5

Hvad karakteriserer en god kodestandard ? Jeg mener at de skal være forståelige, troværdige og baseret på viden og holdning som der er bred enighed om. De skal sigte på at gøre det nemmere og hurtigere at skrive korrekte programmer, der er nemme at vedligeholde. Ydermere skal reglerne så vidt som muligt kunne verificeres automatisk med et værktøj.

Der er i blog indlægget nævnt et par kode standarder.
Et gensyn med Google’s indeholder anvisninger, som der er ikke er bred enighed om.
Et eksempel er https://google.github.io/styleguide/cppguide.html#Forward_Declarations som fraråder forward declarations – hvilket jeg mener er et dårligt råd.
Et andet eksempel er https://google.github.io/styleguide/cppguide.html#Exceptions som forbyder brug af exceptions. Det kan være relevant for Google, men det er generelt et rådligt råd.

Anderledes er det for LLVM’s kodestandard. Der afslører et hurtigt kig ikke nogen åbenlyse dårlige råd – men det er også mit indtryk at LLVM/Clang communitiet lægger vægt på at have en høj C++ faglighed.
F.eks. indeholder LLVM kodestandarden den modsatte anbefaling om forward declarations i forhold til Google http://llvm.org/docs/CodingStandards.html#include-as-little-as-possible men forbyder også brugen af exceptions.

Den bedste generelle C++ kodestandard, som jeg kender, er den relativt nye V4 af "High Integrity C++" fra Programming Research. Se http://www.programmingresearch.com/high-integrity-cpp/ og http://www.codingstandard.com/ for detaljer. Den er i stor udstrækning inspireret af nogle af de ovennævnte bøger, og kan i høj grad verificeres af et værktøj (som Programming Research laver og sælger).

En anden god, men mere specialiseret og konkret produktspecifik, C++ kodestandard er den Lockheed Martin skrev i forbindelse med udvikling af Joint Strike Fighter. Se http://www.stroustrup.com/JSF-AV-rules.pdf for detaljer. Den er særligt relevant for kritiske, hard real-time, embedded systemer.
Som man siger om den type software: ”Hvis den ikke virker så risikerer man at nogen dør. Hvis den virker så risikerer man at … - ok, men det er så de andre”.

Jeg bør nok slutte med endnu en disclaimer: jeg kender personligt de væsentlige bidragsydere til ovennævnte 2 kodestandarder. Det er personer som jeg har haft meget god snak med, og hvis holdninger til C++ programmering jeg i stor udstrækning deler – så naturligvis syntes jeg de er anbefalelsesværdige.

Kim Jensen

Hvis en eller anden skulle være kommet til at undre sig over om jeg egentlig har en pointe med mine kodestils standard indlæg, eller var de bare resultatet af akut galskab !

Så er min pointe at vi alle sammen helt sikkert ikke vil kunne blive enige om nogen standard, medmindre en diktator overtager styringen og tvinger os alle til en standard. Om en diktator teknisk set vil være en bedre løsning, så er det muligt, men menneskeligt vil de fleste kunne blive enige at en diktator ikke er ønskelig. Når Peter Toft siger så har vi allerede x antal diktator forsøg og behøves måske ikke lige x+1, så kan jeg godt forstå det på en måde, men min egen oplevelse er at alle de standarder jeg har set ikke lige passer til hvad synes er overskueligt og ser godt ud, så derfor går jeg (og mange andre) i gang med x+1 standard som alle de andre så skal plages med ! Har jeg så en løsning på det ? Jeg kan da godt forstå argumentet om at det er smart hvis alle bruger samme standard især i open source og/eller gruppe projekter, men samtidig vil jeg helt sikkert hade at skulle kode i standarden hvis den ikke lige ligner min, og sådan er vi sikkert mange der har det. Så altså ingen løsning herfra (men kommer i følgende dog med en alligevel >*<), men bare periodisk sort humør, som dog har den pointe at det måske vil være bedre at bruge sine kræfter på at forstå det sprog man koder i istedet for ligegyldig æstetik der alligevel helt sikkert er subjektiv alligevel. F.eks. så vil jeg nok aldrig blive enig med Morgens Hansen om hvorvidt 10 != i er flot æstetik da jeg helt sikkert vil 'sværge til' i != 10 eller i < 10. Og hvis vi nu skulle kode sammen hvilken stil skal så følges ? Jeg vil foreslå at hvis begge har forstand på sproget så kan vi vel godt forstå hinandens stil og tager vel ikke skade af lidt hjernegymnastik. Og endvidere så tror jeg at for meget vane tænkning vedr. stilart kan medføre at man kan komme til at overse problemer i koden, da man måske nemt bare vil konstatere at koden passer ind i vedtaget stilart uden så at tænke den rigtigt igennem igen (og igen og ...). Og derfor kan min foreslået stilart i et eller andet omfang måske give mening, om ellers give mening som et udtryk for at jeg hvis jeg skal læse syge diktator nr. x + z, så vil jeg selv være mere syg med diktator nr. x + z + !0 om ikke andet så for at vise hvor syg jeg synes diktator x + z er ligesom forgængeren x - 1 + z og alle x - ... + z'zzzz er ! Så måske løsningen er psykologisk, nemlig bare at være fleksibel med andres stilarter og betragte det som udfordrerne 'krydderi' !!!

Mogens Hansen

F.eks. så vil jeg nok aldrig blive enig med Morgens Hansen om hvorvidt 10 != i er flot æstetik da jeg helt sikkert vil 'sværge til' i != 10 eller i < 10.

Jeg tror godt vi kan blive enige (uden at det er et mål i sig selv) - jeg ikke syntes det er specielt pænt at skrive 10 != i
Jeg har bare oplevet det som konkret nyttigt. Jeg har ikke problemer med at læse og forstå kode der er skrevet som du sværger til.
I første omgang er det interessant sommetider at overveje hvorfor man skriver på en bestemt måde - som du også siger i forhold til for meget vanetænkning. En måde at overveje hvordan man skriver kode, er at lytte til eller læse om hvilke tanker andre gør sig.

Kim Jensen

jeg ikke syntes det er specielt pænt at skrive 10 != i
Jeg har bare oplevet det som konkret nyttigt


Jeg tænker bare at hvis man kommer til at skrive i = 10 istedet for i != 10, så får man med meget stor sandsynlighed (undtaget hvis der er breaks eller kastes fejl inden i loopet) et uendeligt loop da 10 ikke er 0 og dermed sandt i bl.a. C. Man skal da være meget sjusket hvis sådan kode kommer igennem udvikling og test til produktions/release stadiet !

Ivan Skytte Jørgensen

Med kodestandarder bliver folk typisk uenige om de rent kosmetiske ting, og den diskussion skygger for de mere essentielle og funktionelle ting. Og i mange tilfælde dækker det over tankegangen "hvis bare alle var som jeg..."

Så lad os tage nogle analogier fra andre fag. Nej, ikke den berygtede bil-analogi :-)

1: Der findes lokalplaner som specificerer tagtype+farve, murstenstype+farve+mønster, at der skal være bøgehæk, at gruset i indkørslen skal være type X, farven på vindueskarme, typen af udendørsbelysning, varmetype (med forbud mod andre typer), at græsset skal være slået, at der ikke må være frugttræer i forhaven, at havelågen skal være galvaniseret stål, taghældning på 38%, osv.
Der er folk som kan lide sådanne meget detaljerede regler. Jeg tilhører ikke den gruppe. Jeg vil mene at det vigtige er kravet om BR2015, tilslutning til fjernvarme, samt krav om grundejerforening (som kan vedligeholde fællesarealer). Resten er kosmetisk. Så hvis mit hus har tegltag og nabohuset har eternittag: fred med det!

Derimod, hvis nabohuset har eternittag på det meste, men et par hjørner med tegl, og der er et hul som i 4 år blot har været dækket af en presenning, døren er malet i to nuancer af rødt, samt der holder et bilvrag i forhaven, tja... så ved man nok godt at det hus ikke er meget værd og vil kræve renovering.

2: Jeg formoder at tømrere og snedkere har en uskreven regel om at man aldrig må bruge stemmejern ind imod sig selv. Men hvis en erfaren tømrer gør det (når han ikke er under tidspres), så vil jeg forvente at han ved hvad han gør, vurderet andre muligheder, og vurderet risikoen.

Indenfor programmering vil den første ovenstående analogi svare til en detaljeret kodestandard dikteret af ledelsen (som aldrig vil skulle røre koden).
Den anden analogi ville svare til at man har et stor og velstruktureret program med en konsistent stil, med en enkelt goto i.

Min holdning er ikke perfekt. Uerfarne programmører er en udfordring, bl.a. fordi de ikke har erfaring nok til at indse når de laver noget klamp. Erfarne programmører er også en udfordring fordi nogle af deres vaner ikke længere giver mening, såsom bunden af denne kommentar som er vigtig fordi man jo altid udskriver ting og det er vigtigt at vide at man har fået hele udskriften ud på linjeskriveren.

Så mine råd til kodestandarder:
1: Fokuser på det vigtige og ikke det kosmetiske
2: Indse at forskellige moduler kan have forskellig stil
3: Opdater for at rydde ud i forældede regler, og tilpasse til nye værktøjer/miljøer
4: Indse at andre firmaers/gruppers standarder passer til deres miljøer
5: Hjælp uerfarne programmører.
6: goto 1

//
// EOF
//

Log ind eller opret en konto for at skrive kommentarer