Fælles kodestandard - værktøj til at hjælpe (del 2/2)

I forrige blog-indlæg diskuterede jeg valg af C/C++ kodestandard. I dette blogindlæg ser jeg nærmere på et værktøj til at rette kode op i forhold til en kode-standard.

clang-format

Et godt alternativ til GCC compileren er CLANG/LLVM. Fra dette projekt er der lavet et godt side-projekt "clang-format".

Med clang-format kan man nemt opdatere en (eller flere) C/C++ kode-filer i forhold til Googles, LLVMs, eller andre kode-stilarter.

På en Linux-maskine skal man installere f.eks. clang-format-3.6 (eller en nyere version). Pudsigt nok, så er indeholder clang-format kommandoen versions-nummeret. Har man installeret clang-format-3.8, så er det den som anvendes.

Vi kan f.eks. tage en stump C-kode (eksempel1.c) , som følger BSD-standarden med 8 mellemrum.

/* eksempel1.c */
for (; cnt   < 15; cnt++) {
        stmt1;
        stmt2;
}

Vi kan nu prøve at lave koden lavet om til Googles stil, som anvender indrykning med to mellemrum.

$ clang-format-3.6 -i eksempel1.c

På en Linux-maskine kan alle filer i et katalog og nedefter reformatteres med

$ find . -name "*.cpp" -exec clang-format-3.6 -i {} \;

Super stærk :-)

Argumentet "-i" til clang-format laver "inline replacement", dvs. ændrer filen. Vil man bare se hvad der vil blive ændret så udelad "-i", og dermed kommer den ændrede kode ud på stdout, dvs. i konsollen.

Emacs-, vi- og visual-studio-brugere kan med fordel læse http://clang.llvm.org/docs/ClangFormat.html, hvor der er mere information om integration i disse værktøjer.

Jeg anvender oftest Emacs, og har derfor tiføjet følgende til min .emacs

(load "/usr/share/emacs/site-lisp/clang-format-3.6/clang-format.el")
(global-set-key [C-M-tab] 'clang-format-region)

Med dette kan jeg vælge en region og med Ctrl-Alt-Tab reformattere koden fra

/* eksempel1.c */
for (; cnt   < 15; cnt++) {
        stmt1;
        stmt2;
}

til

/* eksempel1.c */
for (; cnt < 15; cnt++) {
  stmt1;
  stmt2;
}

Jeg kan også i Emacs reformattere hele filen med "Alt-x clang-format-buffer".

Jeg har ikke fået clang-format til løbende at vise kode-fejl i Emacs (svarende til hvad jeg tidligere beskrev for Python kode). Hvis du ved mere, så kommenter gerne nedenfor. Alternativt er "flymake" interessant. Det kan lave lignende tricks som jeg tidligere har beskrevet for Python-kode. Flymake er dog mere fokuseret på syntax-fejl end kode-stil fejl.

MEN

Det er vigtigt at huske på at nok er "clang-format" et fedt værktøj, men det friholder ikke mig selv som programmør. Det retter sjuskefejl for mig - fint nok, men det retter ikke inkonsistens i variabel-navngivning såsom dette:

/* eksempel2.c */
int etIteratorIndex;
int et_andet_iterator_index;

og clang-format er kun et hjælpe-værktøj til at lave ensartet kode-stil - men skriver man klyt-kode og sender det igennem "clang-format" så er det stadig klyt-kode man får ud ... bare lidt pænere på overfladen:-)

/pto

Kommentarer (6)
Ivan Skytte Jørgensen

Overvejet Git pre-commit hook til clang? ...eller er det lidt for nazi?

Det er lidt risikabelt, men afhængig af kodebasen så kan det fungere. På mit tidligere job var jeg svn-administrator og kodebasen var 14 år gammel. Folk havde været forholdsvis flinke til at skive fornuftige commit-beskeder. Der havde været ret stor personaleudskiftning. Så historikken var vigtig og omformatering af udelukket. Så der var kun få commit-checks, som følge af konkrete problemer vi havde oplevet:
- Kun UTF8 i koden og commit-besked.
- Kun NL var tilladt. CR+NL var forbudt.
- *.depend, *.bak, *.o, osv. kunne ikke lægges i repository.
- trailing spaces var forbudt.
- *.sh skulle have x-bit sat, men *.cc ikke måtte have det.

Og selv med de få rimelige regler måtte nogle af dem slås fra på visse subtræer. Det eneste eksempel jeg kan huske var at nogle filer fra arvet fra en anden afdeling var rå HTTP-beskeder med CR+NL brugt til unittest. At ændre det ville have krævet en større omskrivning af test-suiten, og det kunne ikke forsvares.

Inden man lægger commit-checks ind, skal man huske på at den ene gang ud af 1000, hvor man har brug for at bryde reglerne, typisk sker klokken 03 om natten når man skal have en kundes produktionssystem til at køre igen. Man kan så overveje at tillade brud på reglerne ved at inkludere specielle tags i commit-beskeden, eller istedet for commit-check, så lav post-commit kørsel af checks + email af resultatet til udviklergruppen. Hvad der er bedst og detaljerne afhænger helt af ens miljø.

Så vidt jeg ved så fulgte java-udviklerne slavisk Suns coding guidelines. Jeg spurgte om de ønskede et commit-check af det. De takkede nej.

Log ind eller Opret konto for at kommentere