An Improved Median Function
After my test script found errors with my previous median function, I’ve gone ahead and made some improvements. Again, the goal here isn’t to be thorough but is to demonstrate a boundary-testing technique that is easy to conceive, implement, and build-upon. Like I mentioned in my previous post, this single test script can be the foundation for a testing class. I would also go further by wrapping all of this into a table-driven engine, which would call the function, define its parameters, and identify its expected return value. With VFP9, structured error handling will also help.
I imagine that a revisit of this topic at some point will be in order. Until then, enjoy the much improved get_median function:
*--The following code is an improved get_median FUNCTION get_median_clean LPARAMETERS tnType, teName, teColDel *-- boundary testing IF !BETWEEN(tnType,1,3) RETURN 0 ENDIF DO CASE CASE tnType = 1 .and. VARTYPE(teName)<>"C" RETURN 0 CASE tnType = 1 .and. (!ISDIGIT(teName) .or.; VARTYPE(teColDel)<>"C") RETURN 0 CASE INLIST(tnType,2,3) .and. TYPE(teColDel)<>"N" RETURN 0 CASE tnType = 2 .and. (!USED(teName) .or. ; EMPTY(FIELD(teColDel,teName))) RETURN 0 CASE tnType = 2 .and. ; VARTYPE(EVALUATE(FIELD(teColDel,teName))) <> "N" RETURN 0 CASE tnType = 3 .and. ; VARTYPE(EVALUATE(teColDel[1,teColDel])) <> "N" RETURN 0 ENDCASE *-- local declerations LOCAL lcSelCol AS String LOCAL lnItems, lnHalf, lnInc AS Integer LOCAL lnMedian AS Number *-- create the aMedian Array DO CASE CASE tnType = 1 && use a delimted string lnItems = ALINES( aMedian , STRTRAN(teName ,teColDel,CHR(13)) ) FOR lnInc = 1 TO lnItems aMedian[lnInc] = VAL(aMedian[lnInc]) NEXT CASE tnType = 2 && calculate using an alias lcSelCol = FIELD(teColDel,teName) lcSQL = "SELECT " + lcSelCol + " FROM " + teName + ; " ORDER BY " + lcSelCol + " INTO ARRAY aMedian" &lcSQL lnItems= _TALLY CASE tnType = 3 && calculate using an array lnItems= ALEN(&teName,1) DIMENSION aMedian[lnItems] FOR lnInc = 1 TO lnItems aMedian[lnInc] = &teName.[lnInc,teColDel] NEXT ENDCASE *-- find the median ASORT(aMedian) lnHalf = CEILING( lnItems / 2) IF MOD(lnHalf,2) = 0 lnMedian = ( aMedian[lnHalf] + aMedian[lnHalf+1] ) / 2 ELSE lnMedian = aMedian[lnHalf] ENDIF RETURN lnMedian ENDFUNC
Data Warehousing and Business Intelligence consultant, with expertise in business analysis, data modeling, and data integration. Extensive experience developing vertical and integrated desktop and Internet applications spanning municipal, clinical, and financial industries.
June 29th, 2007 at 10:16 pm
[…] and related topics ← Boundary Testing — CASE: Get Median function An Improved Median Function […]
June 29th, 2007 at 10:23 pm
[…] following program works, but has several flaws. Next week I will present an improved get_median function that addresses these flaws. I’ll expose some of them using boundary testing […]