290 likes | 310 Views
C Programming. Program Quality Some of the material in these slide is adapted from chapters 5 and 6 of “Code Complete” (see course resource page). A high-quality project. Ease of understanding Readable by someone who did not write the code Ease of implementation
E N D
C Programming Program Quality Some of the material in these slide is adapted from chapters 5 and 6 of “Code Complete” (see course resource page)
A high-quality project • Ease of understanding • Readable by someone who did not write the code • Ease of implementation • Small cohesive pieces are easy to code • Ease of testing • Each operation can be tested separately • Ease of modification • What to change is easy to identify • Correct translation from requirements • Easy to identify the code that implements each requirement
Top-Down Design • A central part of programming in a language like C is taking a large and complex problem and decomposing it into smaller problems that can more easily be solved. • This is not a one step process -- we further decompose the sub problems into sub-sub problems until the problems are eacg easy to solve • Real life examples • Bake a cake • Mow the lawn • Each sub-problem becomes a component
Program Components • In languages like C, component refers to a routine or module • A routine is a function or main program • A module is a collection of routines, data, variables, etc. • Typically one C source file and associated header file • Components… • hide internal details and processing from one another • hide design decisions • When a hidden design decision changes, only that component must be changed. • isolate complex parts of problem, where "decisions" need to be made. • provide layers of abstraction and information hiding
Why Use Functions? • Reduce Complexity • Most important reason • Hide information • Look for deeply nested loops and complex Boolean expressions • Avoid Code Duplication • Code will be more reliable and easier to modify • Improving performance • Optimization occurs in just one place • Promoting Code Reuse • Isolate Complex Operations • Complex algorithms, tricky Boolean tests
High-Quality Functions • A high-quality function is like a black box - you know the inputs and outputs, but not what happens inside • A high-quality function has a well-chosen name • A verb followed by a noun. The name should reflect what the function does • printGreeting( ) • getPositiveInteger( ) • A descriptive name of what’s returned • sin( ) • nextRandomInt( ) • Avoid vague names • outputReport( ) • performUserInput( ) • Follow naming conventions
Function Cohesion • Cohesion refers to how closely the operations in a function or module are related. • Strive for a high degree of cohesion • Strong cohesion results in code with high reliability • A study of 450 FORTRAN routines found that 50% of highly cohesive routines were fault free. Only 18% of routines with low cohesion were fault free.
Functional Cohesion • A function that performs only one operation • calculateAge( ) -- Calculates a person’s age, given their birthday • getFileName( ) -- Gets the name of a file from the user • displayStudenNames( ) -- Displays student names to the screen • appendValue( ) - adds a new value to the end of an array • Strive to achieve functional cohesion whenever possible. • Functions with functional cohesion are easy to name. If your function isn’t easy to name, that’s a hint it may not have functional cohesion.
Sequential Cohesion • A function with operations that must be performed in a specific order, with the output of one operation being the input to the next • A function that • Inputs the number of students • Inputs the final exam grade for each student • Calculates the min, max and average final exam grade • Displays the student grades • Displays the min, max, and average grade • Sequential cohesion is acceptable but can often be improved by writing separate function.
Communicational Cohesion • A function that performs operations on the same data but are not otherwise related • A function named getNameAndChangePhoneNumber( ) that retuns the name from, and modifies the phone number in a structure of student information • Communicational cohesion is considered acceptable if necessary for practical reasons • Note how the names of these functions are a clue to their communicational cohesion
Temporal Cohesion • A function that performs several operations which are related only because they must be performed at the same time • A function named initialize( ) that • Initializes an array • Initializes some variables • Seeds the random number generator • Prints instructions • These functions are considered acceptable, but have them call separate functions for each operation.
Logical Cohesion • A function that performs one of several operations based upon a control flag parameter • A function that • Prints student name OR • Inputs the student’s age OR • Prints a class roster OR • Prints a list of faculty members • Fix this by writing a separate function for each operation.
Procedural Cohesion • A function that performs operations in a specific order. Unlike sequential cohesion, these operations do not share the same data • A function that • Prints a revenue report • Prints a report of expenses • Prints a list of employee names and office numbers • Fix this by rethinking your design
Coincidental Cohesion • Virtually no cohesion at all • A function that performs unrelated operations • A function that • Checks for new email messages • Prints a list of students in a course • Changes my Unix password • Fix this by making a separate function for each operation
Function Cohesion Sumary • There are several generally accepted levels of cohesion listed here from worst to best. • Coincidental - a function that performs several unrelated operations • Logical - a function that performs one of several operations selected by a control flag passed to the function as a parameter • Procedural - operations performed in a specific order • Temporal - operations combined into one function because must all be performed at the same time (e.g. initialization) • Communicational - operations make use of the same data but are not related in any other way • Sequential - contain operations performed in a specific order, share data from step to step, but don’t make up a complete function when done together • Functional - a function that performs one and only one operation • Only functional, sequential, communicational and temporal are considered to be acceptable levels of cohesion
Module Cohesion • In C, a module equates of a .c source file which contains several functions and (possibly) data. • The cohesion of a module refers to how the data and functions within the module are related. • Consider the modules data and functions as whole. • A cohesive module should contain data and a group of functions that clearly belong together.
Function Coupling • Coupling refers to the strength of the connection between two functions. • Loose coupling is good, tight coupling should be avoided • Try to write functions that depend on other functions as little as possible • A study of 450 FORTRAN routines found that functions with a high degree of coupling had 7 times more errors than those with a low degree of coupling • Common Coupling Criteria • Size - the number of connections between functions • Fewer parameters are better • Primitives are better than arrays or structs • Intimacy and Visibility • Parameters are the most intimate (direct) and most visible connection • Shared data is less intimate and less visible
Data Coupling • A function passes only the primitive data that the called function needs • Most desirable (loosest) form of coupling intcalcRectangleArea( int length, int width); intsumArray( int array[ ], int size); intgetValidIntFromUser( char prompt[], int max, int min);
Stamp Coupling • One function passes a struct to another function • Also known as Data Structure Coupling • Acceptable if the function uses all or most of the data element in the struct typedefstruct rectangle { int height, width; POINT upperLeft, lowerRight double diagonalLength; enum color fillColor; } RECTANGLE; void printRectangle( RECTANGLE rectangle); // ok intcalcRectangleArea( RECTANGLE rectangle); // less ok
Common Coupling • Two functions access the same common (global) data. Acceptable if they don’t change the data. intmyGlobalVar = 99; int Function1 (int a) { if (a > 0) { myGlobalVar++; a = 0; } return a; } void Function2 ( ) { if(myGlobalVar > 0) myGlobalVar = 42; else myGlobalVar = -1; }
Control Coupling • A function passes an argument to another function to tell the called function what to do. • See “logical cohesion” • Generally requires the first function to know about the internal workings of the second function
Content Coupling • One function uses code inside another function (via “goto” statement). • “tighest” possible coupling • Never Acceptable int Func1 (int a) { printf ("In Func1\n"); a += 2; goto F2A; return a; } void Func2 (void) { printf("In Func2\n"); F2A: printf("At Func2A\n"); }
Function Coupling Summary • The levels of function coupling are listed below from low/loose/weak to high/tight/strong • Data coupling - a function passes only the primitive data another function needs • The most desirable level of coupling • Stamp (data structure) coupling - one function passes a struct to another function • Acceptable if the function uses all or most members of the struct • Common coupling - two functions use the same global data • Acceptable if the functions don’t change the global data • Control coupling - one function passes an argument to another function to tell the 2nd function what to do (see logical cohesion) • Never acceptable • Content coupling - one function uses code inside another function (e.g. via goto statement) • Never acceptable
Module Coupling • Module coupling refers to how the module relates to the rest of the program. • If the functions in a module are incomplete, outside functions may need access to the module’s data • No longer a black box • A module should provide a complete set of operations that allow the module’s user to tailor the operations to his own needs.
Information Hiding • Information hiding has indisputably proven its value in practice. • Integral part of structured programming (in languages like C) and in OOP • Most prevalent with respect to modules • The key is to keep “secrets”
Module Secrets • Hide design and implementation decision • Is a “clock” a struct, or just a few independent variables? • Does the clock keep 24-hour time or 12-hour time? • What is the format of the input file? • Secrets are kept through • The use of static data • The use of static functions • The interface (the contents of the .h file) should reveal as little as possible about how the module works. A module is like an iceberg -- you can only see the “top” of it.
Defensive Programming • Analogous to defensive driving • Don’t assume that “the other guy” is going to do the right thing. • Take responsibility for protecting yourself against drunken programmers • If your function is passed “bad” data, your function won’t be hurt.
Note necessarily GIGO • Garbage In does not mean Garbage Out • Rather • Garbage in, nothing out • Garbage in, error message out • No garbage in • Check the values of all input data • Check the values of all function parameters • Decide how to handle bad parameter values • Return false, or other error code • Print an error message and continue • Exit your program
assert( ) • When a bad parameter value is fatal to your function, catch it with assert( ). • assert( ) is a function which takes a single Boolean expression as a parameter • If the Boolean expression is true, nothing happens • If the Boolean expression is false, an error is displayed and your program terminates • Examples assert( age > 0); assert ( strlen(filename) < 20);