C Programming

advertisement
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
High-Quality Functions
•
A high-qualtiy 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
Cohesion and Coupling
• One measure of the quality of a function or module is often
described in terms of cohesion and coupling.
• Cohesion refers to how closely the operations in a function
or module are related.
– Strive for a high degree of cohesion
– String cohesion results in code with high reliability
• Coupling refers to how closely two functions or modules
are connected to each other
– Strive for a low degree of coupling
• Coupling and cohesion are complementary
Coincidental Cohesion
• 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
Logical Cohesion
• A function that performs one of several
operations based upon a control flag parameter
– A function that
• Prints student name OR
• Prints student age OR
• Prints student email address 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
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.
Communicational Cohesion
• A function that performs operations on the same
data but are not otherwise related
– A function named getNameAndPhoneNumber( ) that returns both
the name and phone number from a structure of student
information
– A function named verifyAgeAndID( ) that verifies that a
student’s age and UMBC ID are both valid from 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
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
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( ) - addes 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.
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.
• A cohesive module should contain data and a
group of functions that clearly belong together.
Function Coupling
• There are several levels of function coupling listed below
from high/tight/strong to low/loose/weak
– Content coupling - one function uses code inside another function (e.g. via
goto statement)
• Never acceptable
– Common coupling - two functions use the same global data
• Acceptable if the functions don’t change the global data
– Control coupling - one function passes a parameter to another to tell the
second function what to do (see logical cohesion)
• Never acceptable
– Stamp (data structure) coupling - a function passes a struct to another
function
• Acceptable if the 2nd functions uses all or most members of the
struct
– Data coupling - a function passes only the primitive data another function
needs
• The most desirable level of coupling
Module Coupling
• Module coupling refers to how the module relates
to the rest of the program.
• A module should provide a complete set of
operations that allow the module’s user to tailor
the operations to his own needs
•
Cohesion/Coupling Example
• A module that simulates an clock
• This module is not the best design since it
supports only a single clock, but it demonstrates
the concepts of cohesion and coupling
link to clock.h
link to clock.c
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.
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 gargbage in
• Check the values of all input data
• Check the values of all function parameters
• Decide how to handle bad parmeter 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);
Download