Under mit spike (Scrumm’s term for research) på et event DSL, løb jeg ind i et behov for at angive et ugedagsfilter. Altså en måde at angive dage i en ugentlig gentagelse. Det skal være muligt at filtrere f.eks. mandage, tirsdage og fredage. Mit første take på opgaven var at bruge en ‘bitmaske’ – altsås: søndag: 0x01, mandag: 0x02, , , lørdag: 0x40. Man vil så kunne bestemme om en given dato overholder filtret ved at lave en logisk ‘og’:
public class DayOfWeekFilter1
{
public DayOfWeekFilter1(bool su, bool mo, bool tu, bool we, bool th, bool fr, bool sa)
{
if (su) filter |= 0x01;
if (mo) filter |= 0x02;
if (tu) filter |= 0x04;
if (we) filter |= 0x08;
if (th) filter |= 0x10;
if (fr) filter |= 0x20;
if (sa) filter |= 0x40;
}
int filter;
public bool IsMatch(DateTime input)
{
int d = (int)input.DayOfWeek + 1;
return (d & filter) == d;
}
}
Jeg synes løsningen er simpel og logisk, men en bekendt påpegede over for mig, at koden var svær at gennemskue, og at hun til hver en tid ville foretrække et filter af følgende form:
public class DayOfWeekFilter2
{
public DayOfWeekFilter2(bool su, bool mo, bool tu, bool we, bool th, bool fr, bool sa)
{
this.mo = mo;
this.tu = tu;
this.we = we;
this.th = th;
this.fr = fr;
this.sa = sa;
this.su = su;
}
bool mo, tu, we, th, fr, sa, su;
public bool IsMatch(DateTime input)
{
if (su && input.DayOfWeek == DayOfWeek.Sunday)
return true;
if (mo && input.DayOfWeek == DayOfWeek.Monday)
return true;
if (tu && input.DayOfWeek == DayOfWeek.Tuesday)
return true;
if (we && input.DayOfWeek == DayOfWeek.Wednesday)
return true;
if (th && input.DayOfWeek == DayOfWeek.Thursday)
return true;
if (fr && input.DayOfWeek == DayOfWeek.Friday)
return true;
if (sa && input.DayOfWeek == DayOfWeek.Saturday)
return true;
return false;
}
}
Jeg har selvfølgelig svært ved at argumenterer mod at koden er kompleks (det kommer jo an på øjnene der ser), men jeg vil gerne kunne sige at ‘min’ måde er mere effektiv (hurtigere), da den er mere simpel (IL-koden fylder 1/5).
Jeg satte en lille test op, hvor jeg testede 1 million datoer. Forskellen var meget begrænset under 100 ms med et filter der tog mandage. Hvis filtret tog alle dage undtagen mandage, var forskellen ca 600 ms. Det skyldes selvfølgelig at filtret får en ekstra kondition at checke for hver dag der tilføjes filtret.
Effektiviteten er ikke signifikant bedre, så man kan vel sige at Signes argument om uigennemskuelig kode er valid…men jeg holder mig nu til min første indskydelse :-)
Code on…