High-Quality Routines
Chapter 5-6
2
Review Class Quality Checklist
3
4
5
Outline What is a Routine? Valid Reasons to Create a Routine Design at the Routine Level Good Routine Names How Long Can a Routine Be? How to Use Routine Parameters?
6
What Is a Routine? An individual method or procedure invokcable
for a single purpose Function in C, macros in C/C++ Method in Java
What is a high/low-quality routine?
7
How Many Problems Can You Find?
8
Problems Bad routine name – it tells you nothing No documentation Bad layout InputRec is changed
if it is input, its value should not be modified (const), o.w. it should not be called inputRec
Read/write global variables Read from corpExpense Write to profit
9
Problems - cont Non-single purpose No defense against bad data – crntQtr =0? Use of magic numbers - 100, 4.0, 12, 2, 3 Unused routine parameters: screenX, screenY Two many parameters Poorly ordered, undocumented parameters
10
Another Exampleif ( ( (‘a’<=inputChar) && (inputChar <=‘z’)) || ( (‘A’<=inputChar) && (inputChar <=‘Z’))) {
charType = CharacterType.Letter;}else if ( (inputChar==‘ ‘) ||(inputChar == ‘,’) ||
(inputChar==‘.‘) || (inputChar==‘!‘) || (inputChar==‘(‘) ||(inputChar==‘)‘) || (inputChar==‘:‘) || (inputChar==‘;‘) ||(inputChar==‘?‘) || (inputChar==‘-‘)) {charType = CharacterType.Punctuation;
} else if ((‘0’<=inputChar) && (inputChar <=‘9’)) {charType = CharacterType.Digit; }
11
Valid Reasons to Create a Routine Reduce complexity Introduce an intermediate, understandable
abstraction Putting a section of code into a well-named routine is
one of the best way to document its purpose if (node<>null) then
while (node.next<>null) donode=node.nextleafName = node.name
end whileelse leafName = “”end if
leafName = GetLeafName(node)
12
Valid Reasons to Create a Routine - cont
Avoid duplicate code Creation of similar code in two routines implies an
error in decomposition Support subclassing
Need less new code to override a short, well-factored routine than a long, poorly factored routine
Reduce the chance of error in subclass if overrideable routines are kept simple
Hide sequences Good to hide the order in which events happen to
be processed Independently get data from the user and from a file Read the top of a stack and decrement StackTop
variable PopStack
13
Valid Reasons to Create a Routine - cont
Hide pointer operations Improve portability Simplify complicated boolean tests
Get the details of the test out of the way A descriptive routine name summarizes the
purpose of the test Improve performance
Having code in one place will make it easier to profile to find inefficiencies
Optimize the code in one place instead of in several places
14
Operations That Seem Too Simple
Assume the calculation in a dozen placespoints = deviceUnits *
(POINTS_PER_INCH/DeviceUnitsPerInch())
What does the expression mean? Convert a measurement in device units to a
measurement in points
Put the expression into a routine?
15
Function Version Function DeviceUnitsToPoints(deviceUnits
Integer): Integer DeviceUnitsToPoints = deviceUnits * (POINTS_PER_INCH/DeviceUnitsPerInch()) End Function
Function Callpoints = DeviceUnitsToPoints(deviceUnits) More readable – even approaching self-doc
Any other benefit of the function?
16
17
Design at Routine Level Cohesion:
how much do two routines have to know about each other? Criteria
size of the coupling how many things do two routines share?
Intimacy how closely coupled is the shared information? Ex: Function A(p1, p2, p3)
{ Function B(p1); Function C(p2); Function D(p3); } # using local variables rather than global variables increases intimacy and visibility# hide data, but not manipulation of it.
Flexibility how easily can you change the connection between routines? you want to be able to change any routine without impacting other routines
18
Design at Routine Level Functional cohesion – strongest and best
A routine performs one and only operation Sin, GetCustomerName, EraseFile
Assume they do what their names say they do
19
Cohesion Less Than Ideal Sequential cohesion – operations in routine
must be performed in a specific order share data from step to step don’t make up a complete function
Calculate Birthrate->age->retirement date Communicational cohesion - operations in routine
make use of the same data, aren’t related in any other way Print a summary and re-init the data passed to it
Temporal cohesion Operations are combined into a routine because they
are all done at the same time Read config file->init scratch file->set up a memory
manager and how an screen
20
Cohesion Unacceptable Procedural cohesion
Operations are done in a specified order and the operation don’t need to be combined for any other reason.
A routine gets an employee name, then an address, and then a phone number – matching the order in which the user is asked for
Another routine gets the rest of the employee data - procedural cohesion
Make sure the calling routine has a single, complete job: getEmployee() vs GetFirstPart…()
21
Cohesion Unacceptable - cont illogical cohesion
Several operations are stuffed into the same routine and one of the operations is selected by a control flag that is passed in
Control flow is the only thing that ties them together
Compute(), Edit(), Print(); Coincidental cohesion
The operations in a routine have no discernible relationship to each other
HandleStuff
22
Good Routine Names Describe everything the routine does
Describe all the outputs and side effects ComputeReportTotals - inadequate for ‘compute
report totals and open an output file’ ComputeReportTotalsAndOpenOutputFile – too
long and silly Not to use less-descriptive names To avoid side effects
Avoid meaningless, vague, or wishy-washy verbs HandleCalculation, PerformService,
DealWithOutput don’t tell you what the routines do
23
Good Routine Names - cont Don’t differentiate names solely by number
OutputUser, OutputUser1, OutputUser2 Make names as long as necessary
Optimum average length for variables: 9-15 Routine names tend to be longer
For a function, use a description of the return value printer.IsReady, pen.CurrentColor()
Use opposite precisely Show/hide, open/close, source/target,… FileOpen and _lclose
Establish conventions for common operations
24
Hong Long Can a Routine Be? Theoretical best max length: one screen or
one/two pages – approximately 5-100 lines non-comment, non-blank IBM once limited routines to 50 lines
Complex algorithm: 100-200 lines Decades of evidence say that routines of such
length are no more error-prone than short routines Be careful if you want to write routines longer
than about 200 lines
25
How to Use Routine Parameters Put parameters in input-modify-output order
The sequence of operations - inputting data, changing it and sending back a result
Conflicts with the C-lib convention If several routines use similar parameters, put
them in a consistent order Use all the parameters Don’t use parameters as working variables
int sample (int inputVal) {inputVal = inputVal * CurrentMultiplier(inputVal);…return inputVal;
}
26
27
How to Use Routine Parameters - cont Document interface assumptions about paras
Whether input-only, modified, or output-only Units of numeric parameters (inches, meters,…) Meanings of status codes and error values if
enumerated types are not used Ranges of expected values Specific values that should never happen
Limit the number of parameters to about 7
28
29