Jeg tror, de fleste har prøvet det: Man sidder og roder i SQL Server Management Studio med 200 forskellige queries på forskellige databaser, og pludselig er man kommet til at køre en DROP eller DELETE statement i den forkerte database.

Der findes en option i SSMS, der kan hjælpe til med at mindske risikoen for at lave den type bommerter: Man kan farvekode sine queries alt efter, hvilken server man er forbundet til.  F.eks. kan man give alle queries, der er forbundet til ens produktionsserver, en rød farve, mens queries mod testserveren er grønne (den farvekombination virker selvfølgelig kun, hvis man ikke er rød/grøn farveblind).  Det ser ud som vist herunder.

image

Farven sættes i “Connect to Database Engine” skærmbilledet.  Tryk “Options >>” og vælg fanen “Connection Properties”.  Sæt et hak i “Use Custom Color” og vælg den ønskede farve.  SSMS husker den valgte farve pr. server.  Nogle gange er det nødvendigt at genstarte SSMS for at ændringen får effekt på nye queries.

image

Normalt forventer man, at hvis a + b giver c, så vil a + b altid give c.  I programmering skal man have en vis tolerance mht. præcision, når man bruger doubles og floats, men hvis a + b giver c i et program, forventer man samme resultat, uanset hvornår man laver beregningen indenfor samme proces.

Sådan troede jeg det var indtil fornylig, hvor én af vores unit tests fejlede – tilsyneladende lidt tilfældigt.  For kørte jeg den pågældende unit test alene, var der ingen fejl.  Kørte jeg den sammen med de andre unit tests i projektet, fejlede den.  Jeg fik ret hurtigt identificeret, hvilke andre unit tests, der drillede, og den fejlende unit test havde absolut intet med de andre unit tests at gøre.  Der var ingen fælles kode.

For nemheds skyld vil jeg kalde den fejlende unit test for A, og kalde de andre unit tests, som forårsagede fejlen i A for B. 

Test A tester kode indeholdende komplekse beregninger (Nelder-Mead), og fejlen gjorde, at det endelige resultat endte med en difference på 0.5!  Det er meget i min verden.

Test B er lidt speciel.  Den tester funktionalitet til at indlæse data fra et regneark.  Dvs. koden, som B tester, benytter Microsoft’s ACE driver. Efter en del test af denne driver, og noget der ligner to dages riven i mit eget hår, var jeg i stand til at genskabe problematikken med et simpelt eksempel, hvor resultat af et gangestykke med doubles gave forskellige resultater før og efter kald til ACE driveren.

Et spørgsmål på StackOverflow affødte en forklaring: “… unmanaged code may be tinkering with the FPU control word and change the way it calculates”.  Der blev også foreslået en løsning, nemlig et kald til _fpreset, som “resets the floating point package”.

Den foreslåede løsning virker, men jeg føler mig ikke overbevist om, at jeg egentlig har lyst til at bruge ACE driveren direkte i vores produktionskode.  En rådslagning med Daniel (også kendt er på sitet som ne0san) førte frem til en anden løsning, nemlig at spawn en ny process, som indlæser data fra regnearket, og kommunikerer data tilbage til hovedprocessen vha. named pipes (måske et emne for en kommende dotninjas blog).  Det virker.  Om det er en bedre løsning end _fpreset er svært at sige.