Så er vi nået til vejs ende for denne gang. Ugens konkurrence tog lidt længere tid for mig at komme igennem, da jeg jo ikke bare kunne nøjes med at tælle anslag. Jeg har læst kode, kørt test, debugget en smule og har tilmed været en tur i Reflector.
Ni bidrag blev det til denne gang, og det var interessant at se de meget forskellige løsninger. Jeg har lavet en zip-fil med alle bidragene, så I selv kan studere dem, men for at give et lille indtryk, kommer her et par kommentarer om hvert bidrag (i vilkårlig rækkefølge).
Hvis der er noget, jeg har overset i de enkelte bidrag eller har taget fejl omkring et eller andet, må I endelig sige til.
Anders Uhl Pedersen
Løsningen følger en indlysende struktur, og de hjælpemetoder, der er, giver ligeledes god mening. Koden checker ikke for null password, og der er desværre også sneget sig en utilsigtet fejl ind, der gør, at vi skal helt op på fire gentagede tegn, før et password erklæres ugyldigt. Det ændrer dog ikke ved, at den subtile fejl er ganske fin. Opgaven definerede ikke, hvad bogstaver dækker over, og Anders’ kode regner derfor danske bogstaver som specielle tegn, hvilket naturligvis ændrer optællingen en smule. Det ugyldige password, der godkendes, er således:
kunmedsmå0gtal
Claus Christiansen
Nogenlunde ligetil struktur i IsPasswordValid, men noget mere ugennemskuelig kode i hjælpemetoden checkIndividualCharacters(). Koden checker ikke for null password. Fejlen er en klassiker: Off by one. Nærmere bestemt: En off by one i løkken gør, at member variable aldrig opdateres med den korrekte længde, hvis gentagelse er i enden af password. Det ugyldige password er:
___SubstringAtStartIsAccepted
Morten Gejl
Koden er pæn og ligetil, og der bliver checket for null password. Det er også den eneste løsning, der indeholder exception håndtering. Det havde jeg bestemt ikke regnet med at se i kode til check af et password, så her slog mine code review-alarmer til, og eftersom fejlen ganske rigtig var relateret til håndtering af exceptions, synes jeg ikke, at den er subtil nok. Når det er sagt, er jeg dog glad for Mortens bidrag, for det belyser et område, hvor der meget let kan snige sig fejl ind. Det ugyldige password udnytter et overflow i en byte counter og er således længere, end jeg vil vise det her, men se i koden for det fulde eksempel.
Martin Faartoft
Koden er meget let at sætte sig ind i, og der bliver også checket for null password. Fejlen er dejlig subtil; to tegn, der er byttet om i et regulært udtryk. Jeg må indrømme, at jeg dog opdagede den ret hurtig – måske fordi jeg har lavet en del af den slags i min tid. Det ændrer dog ikke ved, at den type fejl kan tage lang tid at finde, så jeg vil ikke lade mit held spille ind i bedømmelsen. Martins forslag var min favorit langt hen ad vejen. Det ugyldige password:
abcdABCD
Dennis Riis
Dennis’ forslag adskiller sig meget fra de andre. Han har implementeret alle reglerne som delegates (og tilmed husket at checke for null password ikke mindre end to gange), som han efterfølgende afvikler af via All() og Count() på IEnumerable. Fejlen er også ret god: Koden opsætter et fornuftig LINQ-udtryk, men glemmer at udføre det. Det ugyldige password:
aBBB.01to
Brian Holmgård Kristensen
Koden i dette forslag er lige en smule mere kompliceret, end godt er, synes jeg. Der bliver sammenlignet på magic numbers og en negering af en bool er med til at mudre billedet. Der er desværre også en utilsigtet fejl, idet metoden kræver passwords på mere end 8 tegn. På den positive side bliver der checket for null password, og fejlen er også en klassiker: Endnu en off by one. Det ugyldige password er:
AAAe3Bc5Cy7$d$$
“ToyPanther”
Koden er forholdsvis omfattende og en smule kompleks. Der er dog også en masse kommentarer, der i denne sammenhæng kan bruges til at forvirre læseren. Implementeringen checker ikke for null password, men fejlen er god. En simpel “slåfejl” gør, at en tællevariabel initialiseres til to forskellige værdier afhængig af omstændighederne. En gang refactoring ville dog nok komme denne fejl til livs (uanset om man var opmærksom på den eller ej). Det ugyldige password er:
aaaSh0uldFa1l
Mads Mau Pedersen
Mads’ implementering er også meget anderledes end de resterende bidrag. Implementeringen er meget objektorienteret forstået på den måde, at alle valideringerne er implementeret af dedikerede typer. På trods af den store mænge kode er det desværre ikke blevet til null check, og jeg har det personlig svært med kode, der checker en bool for at returnere en bool. Men det er altså detaljer, for fejlen i koden er virkelig god. Jeg har gengivet de nødvendige linjer nedenfor, så brug lige et par minutter og se om du kan spotte, hvad der går galt her.
private CaseValidator(bool isupper) { CheckForUpperCase = isupper; }
private CaseValidator() { }
public static CaseValidator HasUpperCase = new CaseValidator();
public static CaseValidator HasLowerCase = new CaseValidator(false);
private static bool DefaultValue = true;
private bool CheckForUpperCase = DefaultValue;
Jeg skulle tænke en del her, og det var først, da jeg tog Reflector til hjælp, at brikkerne faldt på plads. Mads udnytter, at statics afvikles i den rækkefølge, de erklæres i kildeteksten, så når CaseValidator() oprettes, er DefaultValue ikke blevet initialiseret til true, og derfor har den sin oprindelige default værdi, false. Det er en god fejl!
Det ugyldige password:
mu11pssed
Christian Bjerre Nielsen
Koden i IsPasswordValid() følger en indlysende struktur, men de underliggende metoder er unødig komplekse, synes jeg. Dertil kommer manglende null check, og en lidt ineffektiv løkke, der bliver ved at undersøge for gentagelser efter at det er blevet konstateret, at der ikke er en gentagelse. Optællingen er også lidt spøjs, idet den sammenligner hvert tegn med sig selv og tæller op på grund af gentagelse. Fejlen er dog fin. Passwordet deles op i to i forbindelse med check for gentagelser, men grundet lidt forkerte udregninger af grænseværdier, vil gentagelser i enden af passwordet ikke blive opdaget. Det ugyldige password er således:
1SimCorpppp
Og vinderen er …
Som det sikkert kan læses ud af ovenstående, er jeg mest begejstret for Mads’ bidrag, så et stk. MSDN snowboard går til ham. Andenpladsen var svær, og valget stod mellem Dennis og Martin. Begge fejl er ret gode, synes jeg, og det er svært at fremhæve den ene over den anden. I mangel på bedre har jeg simpelthen trukket lod, så vinderen af et par biografbilletter er: Martin. Stort tillykke til vinderne og mange tak til jer alle for bidragene.