I need to reduce the cyclomatic complexity of my input tests. I have no control over the inputs, so I have to go through all of these checks.
if(y1 < 2000 || y2 < 2000 ||
!(m1 >= 1 && m1 <= 12) ||
!(m2 >= 1 && m2 <= 12) ||
!(d1 >= 1 && d1 <= DaysInMonth(m1)) ||
!(d2 >= 1 && d2 <= DaysInMonth(m2)) ||
(m1 == 2 && IsLeap(y1) && !(d1 >= 1 && d1 <= DaysInMonth(m1) + 1)) ||
(m2 == 2 && IsLeap(y2) && !(d2 >= 1 && d2 <= DaysInMonth(m2) + 1)))
{
return 0;
}
Is there any way, to make it less complex. Should I approach this in different way?
EDIT
Thanks everybody. I managed to lower the complexity. Basically the main issue was with the function DaysInMonth, as it wasn't handling leap years. It was just a small helper function at first and I didn't need to manage leap years. But that changed in the end, so I plastered the leap year logic outside of it wherever I needed it.
I tweaked DaysInMonth a bit with the help of your examples and cyclomatic complexity went down.
I also made a function for the invalid date checking and switched to disjunctions.
So this is my result.
int IsInvalidDate(int year, int month, int day) {
return year < 2000 ||
month < 1 || month > 12 ||
day < 1 || day > DaysInMonth(year, month);
}
...
if(IsInvalidDate(y1, m1, d1) || IsInvalidDate(y2, m2, d2)) {
return 0;
}
IsValidMonth
,IsValidYear
,IsValidDay
,ValidateLeapYear
etc. Would also remove some of the copy/paste and make your intent clearer.validDate(d,m,y)
operation.DaysInMonth
so that it takes in the year and handles leap years internally. Then you would not need the separate leap year check.