1 Modularity Heuristics The material for this lecture is drawn, in part, from The Practice of Programming (Kernighan & Pike) Chapter 4 Jennifer Rexford.

Slides:



Advertisements
Similar presentations
A C++ Crash Course Part II UW Association for Computing Machinery Questions & Feedback.
Advertisements

Programming Paradigms Introduction. 6/15/2005 Copyright 2005, by the authors of these slides, and Ateneo de Manila University. All rights reserved. L1:
Software Engineering and Design Principles Chapter 1.
Chapter 10.
Starting Out with C++: Early Objects 5/e © 2006 Pearson Education. All Rights Reserved Starting Out with C++: Early Objects 5 th Edition Chapter 6 Functions.
1 Generics Professor Jennifer Rexford
. Plab – Tirgul 2 Const, C Strings. Pointers int main() { int i,j; int *x; // x points to an integer i = 1; x = &i; j = *x; ijx 1.
Design The goal is to design a modular solution, using the techniques of: Decomposition Abstraction Encapsulation In Object Oriented Programming this is.
Chapter 6. 2 Objectives You should be able to describe: Function and Parameter Declarations Returning a Single Value Pass by Reference Variable Scope.
Chapter 1 Principles of Programming and Software Engineering.
1 ES 314 Advanced Programming Lec 2 Sept 3 Goals: Complete the discussion of problem Review of C++ Object-oriented design Arrays and pointers.
© 2006 Pearson Addison-Wesley. All rights reserved2-1 Chapter 2 Principles of Programming & Software Engineering.
1 Modularity The material for this lecture is drawn, in part, from The Practice of Programming (Kernighan & Pike) Chapter 4.
University of Washington CSE 351 : The Hardware/Software Interface Section 5 Structs as parameters, buffer overflows, and lab 3.
Introduction to C programming
Comp 245 Data Structures Software Engineering. What is Software Engineering? Most students obtain the problem and immediately start coding the solution.
University of Calgary – CPSC 441. C PROGRAM  Collection of functions  One function “main()” is called by the operating system as the starting function.
Types for Programs and Proofs Lecture 1. What are types? int, float, char, …, arrays types of procedures, functions, references, records, objects,...
07 Coding Conventions. 2 Demonstrate Developing Local Variables Describe Separating Public and Private Members during Declaration Explore Using System.exit.
Copyright 2003 Scott/Jones Publishing Standard Version of Starting Out with C++, 4th Edition Chapter 6 Functions.
Chapter 6: Functions Starting Out with C++ Early Objects
CS212: Object Oriented Analysis and Design Lecture 6: Friends, Constructor and destructors.
Modularity Lecture 4 Course Name: High Level Programming Language Year : 2010.
Object Oriented Programming Elhanan Borenstein copyrights © Elhanan Borenstein.
Low-Level Detailed Design SAD (Soft Arch Design) Mid-level Detailed Design Low-Level Detailed Design Design Finalization Design Document.
Introduction CS 3358 Data Structures. What is Computer Science? Computer Science is the study of algorithms, including their  Formal and mathematical.
File IO and command line input CSE 2451 Rong Shi.
File I/O, Project 1: List ADT Bryce Boe 2013/07/02 CS24, Summer 2013 C.
Chapter 6 Introduction to Defining Classes. Objectives: Design and implement a simple class from user requirements. Organize a program in terms of a view.
1 CSCD 326 Data Structures I Software Design. 2 The Software Life Cycle 1. Specification 2. Design 3. Risk Analysis 4. Verification 5. Coding 6. Testing.
Memory Layout, File I/O Bryce Boe 2013/06/27 CS24, Summer 2013 C.
Basic I/O in C Computer Organization I 1 August 2009 © McQuain, Feng & Ribbens Stream Model of I/O header file: A stream provides a connection.
Lecture 10: Modular Programming (functions) B Burlingame 13 April 2015.
Alternate Version of STARTING OUT WITH C++ 4 th Edition Chapter 6 Functions.
Starting Out with C++ Early Objects ~~ 7 th Edition by Tony Gaddis, Judy Walters, Godfrey Muganda Modified for CMPS 1044 Midwestern State University 6-1.
1 Brief Version of Starting Out with C++, 4th Brief Edition Chapter 6 Functions.
© 2006 Pearson Addison-Wesley. All rights reserved2-1 Chapter 2 Principles of Programming & Software Engineering.
© 2006 Pearson Addison-Wesley. All rights reserved 2-1 Chapter 2 Principles of Programming & Software Engineering.
A FIRST BOOK OF C++ CHAPTER 6 MODULARITY USING FUNCTIONS.
Fall 2015CISC/CMPE320 - Prof. McLeod1 CISC/CMPE320 Today: –Review declaration, implementation, simple class structure. –Add an exception class and show.
Lecture 4 – Function (Part 1) FTMK, UTeM – Sem /2014.
Chapter 16 Pointers and Arrays Pointers and Arrays We've seen examples of both of these in our LC-3 programs; now we'll see them in C. Pointer Address.
Chapter 6 Functions. 6-2 Topics 6.1 Modular Programming 6.2 Defining and Calling Functions 6.3 Function Prototypes 6.4 Sending Data into a Function 6.5.
Advanced Programming in the UNIX Environment Hop Lee.
Real Numbers Device driver process within the operating system that interacts with I/O controller logical record 1 logical record 2 logical record 3.
CS 265 Jianbo Zhao. What is interface? Interface is a detailed boundary between code that provides a service and code that uses it. An interface defines.
Principles of Programming & Software Engineering
Error handling I/O Man pages
ECE Application Programming
INC 161 , CPE 100 Computer Programming
Types for Programs and Proofs
ECE Application Programming
Principles of Programming and Software Engineering
The material for this lecture is drawn from Princeton COS217.
CGS 3460, Lecture 41 Apr 21, 2006 Hen-I Yang
About the Presentations
CSC215 Lecture Input and Output.
Stack ADT & Modularity 2 implementations of the Stack abstract data type: Array Linked List Program design: modularity, abstraction and information hiding.
I/O in C Lecture 6 Winter Quarter Engineering H192 Winter 2005
CSC215 Lecture Input and Output.
CSC 143 Error Handling Kinds of errors: invalid input vs programming bugs How to handle: Bugs: use assert to trap during testing Bad data: should never.
File Input and Output.
Chapter 16 Pointers and Arrays
Modularity Jennifer Rexford
Programming Languages and Paradigms
Module 12 Input and Output
Generics Jennifer Rexford.
ENERGY 211 / CME 211 Lecture 8 October 8, 2008.
Standard Version of Starting Out with C++, 4th Edition
Presentation transcript:

1 Modularity Heuristics The material for this lecture is drawn, in part, from The Practice of Programming (Kernighan & Pike) Chapter 4 Jennifer Rexford

“Programming in the Large” Steps Design & Implement Program & programming style (done) Common data structures and algorithms (done) Modularity <-- we still are here Building techniques & tools (done) Debug Debugging techniques & tools (done) Test Testing techniques (done) Maintain Performance improvement techniques & tools 2

Goals of this Lecture Help you learn: How to create high quality modules in C Why? Abstraction is a powerful (the only?) technique available for understanding large, complex systems A power programmer knows how to find the abstractions in a large program A power programmer knows how to convey a large program’s abstractions via its modularity 3

4 Module Design Heuristics We propose 7 module design heuristics And illustrate them with 4 examples Stack, string, stdio, SymTable

Stack Module Stack module (from last lecture) 5 /* stack.h */ enum {MAX_STACK_ITEMS = 100}; struct Stack { double items[MAX_STACK_ITEMS]; int top; }; struct Stack *Stack_new(void); void Stack_free(struct Stack *s); int Stack_push(struct Stack *s, double d); double Stack_pop(struct Stack *s); int Stack_isEmpty(struct Stack *s);

6 String Module string module (from C90) /* string.h */ size_t strlen(const char *s); char *strcpy(char *dest, const char *src); char *strncpy(char *dest, const char *src, size_t n); char *strcat(char *dest, const char *src); char *strncat(char *dest, const char *src, size_t n); int strcmp(const char *s1, const char *s2); int strncmp(const char *s1, const char *s2, size_t n); char *strstr(const char *haystack, const char *needle); void *memcpy(void *dest, const void *src, size_t n); int memcmp(const void *s1, const void *s2, size_t n); …

7 Stdio Module stdio module (from C90, vastly simplified) /* stdio.h */ struct FILE { int cnt; /* characters left */ char *ptr; /* next character position */ char *base; /* location of buffer */ int flag; /* mode of file access */ int fd; /* file descriptor */ }; #define OPEN_MAX 1024 FILE _iob[OPEN_MAX]; #define stdin (&_iob[0]); #define stdout (&_iob[1]); #define stderr (&_iob[2]); … Don’t be concerned with details

8 Stdio Module stdio (cont.) … FILE *fopen(const char *filename, const char *mode); int fclose(FILE *f); int fflush(FILE *f); int fgetc(FILE *f); int getchar(void); int fputc(int c, FILE *f); int putchar(int c); int fscanf(FILE *f, const char *format, …); int scanf(const char *format, …); int fprintf(FILE *f, const char *format, …); int printf(const char *format, …); int sscanf(const char *str, const char *format,...); int sprintf(char *str, const char *format,...); …

9 SymTable Module SymTable module (from Assignment 3) /* symtable.h */ typedef struct SymTable *SymTable_T; SymTable_T SymTable_new(void); void SymTable_free(SymTable_T t); int SymTable_getLength(SymTable_T t); int SymTable_put(SymTable_T t, const char *key, const void *value); void *SymTable_replace(SymTable_T t, const char *key, const void *value); int SymTable_contains(SymTable_T t, const char *key); void *SymTable_get(SymTable_T t, const char *key); void *SymTable_remove(SymTable_T t, const char *key); void SymTable_map(SymTable_T t, void (*pfApply)(const char *key, void *value, void *extra), const void *extra);

Agenda A good module: Encapsulates data Is consistent Has a minimal interface Detects and handles/reports errors Establishes contracts Has strong cohesion (if time) Has weak coupling (if time) 10

11 Encapsulation A well-designed module encapsulates data An interface should hide implementation details A module should use its functions to encapsulate its data A module should not allow clients to manipulate the data directly Why? Clarity: Encourages abstraction Security: Clients cannot corrupt object by changing its data in unintended ways Flexibility: Allows implementation to change – even the data structure – without affecting clients

Encapsulation Example 1 Stack (version 1) Interface reveals how Stack object is implemented That is, as an array Client can access/change data directly; could corrupt object 12 /* stack.h */ enum {MAX_STACK_ITEMS = 100}; struct Stack { double items[MAX_STACK_ITEMS]; int top; }; struct Stack *Stack_new(void); void Stack_free(struct Stack *s); void Stack_push(struct Stack *s, double item); double Stack_pop(struct Stack *s); int Stack_isEmpty(struct Stack *s); Structure type definition in.h file

Encapsulation Example 1 Stack (version 2) Interface does not reveal how Stack object is implemented Client cannot access data directly That’s better 13 /* stack.h */ struct Stack; struct Stack *Stack_new(void); void Stack_free(struct Stack *s); void Stack_push(struct Stack *s, double item); double Stack_pop(struct Stack *s); int Stack_isEmpty(struct Stack *s); Place declaration of struct Stack in interface; move definition to implementation

14 Stack (version 3) Interface provides Stack_T abbreviation for client Interface encourages client to think of objects (not structures) and object references (not pointers to structures) Client still cannot access data directly; data is “opaque” to the client That’s better still Encapsulation Example 1 /* stack.h */ typedef struct Stack * Stack_T; Stack_T Stack_new(void); void Stack_free(Stack_T s); void Stack_push(Stack_T s, double item); double Stack_pop(Stack_T s); int Stack_isEmpty(Stack_T s); Opaque pointer type

15 Encapsulation Examples 2, 4 string “Stateless” module Has no state to encapsulate! SymTable Uses the opaque pointer type pattern Encapsulates state properly

16 Encapsulation Example 3 stdio Violates the heuristic Programmers can access data directly Can corrupt the FILE object Can write non-portable code But the functions are well documented, so Few programmers examine stdio.h Few programmers are tempted to access the data directly /* stdio.h */ struct FILE { int cnt; /* characters left */ char *ptr; /* next character position */ char *base; /* location of buffer */ int flag; /* mode of file access */ int fd; /* file descriptor */ }; … Structure type definition in.h file

Agenda A good module: Encapsulates data Is consistent Has a minimal interface Detects and handles/reports errors Establishes contracts Has strong cohesion (if time) Has weak coupling (if time) 17

18 Consistency A well-designed module is consistent A function’s name should indicate its module Facilitates maintenance programming Programmer can find functions more quickly Reduces likelihood of name collisions From different programmers, different software vendors, etc. A module’s functions should use a consistent parameter order Facilitates writing client code

19 Consistency Examples 1, 4 Stack (+) Each function name begins with “Stack_” (+) First parameter identifies Stack object SymTable (+) Each function name begins with “SymTable_” (+) First parameter identifies SymTable object

20 Consistency Example 2 string /* string.h */ size_t strlen(const char *s); char *strcpy(char *dest, const char *src); char *strncpy(char *dest, const char *src, size_t n); char *strcat(char *dest, const char *src); char *strncat(char *dest, const char *src, size_t n); int strcmp(const char *s1, const char *s2); int strncmp(const char *s1, const char *s2, size_t n); char *strstr(const char *haystack, const char *needle); void *memcpy(void *dest, const void *src, size_t n); int memcmp(const void *s1, const void *s2, size_t n); … Are function names consistent? Is parameter order consistent?

21 Consistency Example 3 stdio … FILE *fopen(const char *filename, const char *mode); int fclose(FILE *f); int fflush(FILE *f); int fgetc(FILE *f); int getchar(void); int fputc(int c, FILE *f); int putchar(int c); int fscanf(FILE *f, const char *format, …); int scanf(const char *format, …); int fprintf(FILE *f, const char *format, …); int printf(const char *format, …); int sscanf(const char *str, const char *format,...); int sprintf(char *str, const char *format,...); … Are function names consistent? Is parameter order consistent?

Agenda A good module: Encapsulates data Is consistent Has a minimal interface Detects and handles/reports errors Establishes contracts Has strong cohesion (if time) Has weak coupling (if time) 22

23 Minimization A well-designed module has a minimal interface Function declaration should be in a module’s interface if and only if: The function is necessary to make objects complete, or The function is convenient for many clients Why? More functions => higher learning costs, higher maintenance costs

24 Minimization Example 1 Stack /* stack.h */ typedef struct Stack *Stack_T; Stack_T Stack_new(void); void Stack_free(Stack_T s); void Stack_push(Stack_T s, double item); double Stack_pop(Stack_T s); int Stack_isEmpty(Stack_T s); Should any functions be eliminated? While we’re on the subject, should any functions be added?

25 Minimization Example 1 Another Stack function? void Stack_clear(Stack_T s); Pops all items from the Stack object Should the Stack ADT define Stack_clear()?

26 Minimization Example 2 string /* string.h */ size_t strlen(const char *s); char *strcpy(char *dest, const char *src); char *strncpy(char *dest, const char *src, size_t n); char *strcat(char *dest, const char *src); char *strncat(char *dest, const char *src, size_t n); int strcmp(const char *s1, const char *s2); int strncmp(const char *s1, const char *s2, size_t n); char *strstr(const char *haystack, const char *needle); void *memcpy(void *dest, const void *src, size_t n); int memcmp(const void *s1, const void *s2, size_t n); … Should any functions be eliminated?

27 Minimization Example 3 stdio … FILE *fopen(const char *filename, const char *mode); int fclose(FILE *f); int fflush(FILE *f); int fgetc(FILE *f); int getchar(void); int fputc(int c, FILE *f); int putchar(int c); int fscanf(FILE *f, const char *format, …); int scanf(const char *format, …); int fprintf(FILE *f, const char *format, …); int printf(const char *format, …); int sscanf(const char *str, const char *format,...); int sprintf(char *str, const char *format,...); … Should any functions be eliminated?

28 Minimization Example 4 SymTable Declares SymTable_get() in interface Declares SymTable_contains() in interface Should SymTable_contains() be eliminated?

29 Minimization Example 4 SymTable Defines SymTable_hash() in implementation Incidentally: In C any function should be either: Declared in the interface and defined as non-static, or Not declared in the interface and defined as static Should SymTable_hash() be declared in interface?

Agenda A good module: Encapsulates data Is consistent Has a minimal interface Detects and handles/reports errors Establishes contracts Has strong cohesion (if time) Has weak coupling (if time) 30

31 Error Handling A well-designed module detects and handles/reports errors A module should: Detect errors Handle errors if it can; otherwise… Report errors to its clients A module often cannot assume what error-handling action its clients prefer

32 Handling Errors in C C options for detecting errors if statement assert macro C options for handling errors Write message to stderr Impossible in many embedded applications Recover and proceed Sometimes impossible Abort process Often undesirable

33 Reporting Errors in C C options for reporting errors to client (calling function) Set global variable? Easy for client to forget to check Bad for multi-threaded programming int successful; … int div(int dividend, int divisor) { if (divisor == 0) { successful = 0; return 0; } successful = 1; return dividend / divisor; } … quo = div(5, 3); if (! successful) /* Handle the error */

34 Reporting Errors in C C options for reporting errors to client (calling function) Use function return value? Awkward if return value has some other natural purpose int div(int dividend, int divisor, int *quotient) { if (divisor == 0) return 0; … *quotient = dividend / divisor; return 1; } … successful = div(5, 3, &quo); if (! successful) /* Handle the error */

35 Reporting Errors in C C options for reporting errors to client (calling function) Use call-by-reference parameter? Awkward for client; must pass additional argument int div(int dividend, int divisor, int *successful) { if (divisor == 0) { *successful = 0; return 0; } *successful = 1; return dividend / divisor; } … quo = div(5, 3, &successful); if (! successful) /* Handle the error */

36 Reporting Errors in C C options for reporting errors to client (calling function) Call assert macro? Asserts could be disabled Error terminates the process! int div(int dividend, int divisor) { assert(divisor != 0); return dividend / divisor; } … quo = div(5, 3);

37 Reporting Errors in C C options for reporting errors to client (calling function) No option is ideal What option does Java provide?

38 User Errors Our recommendation: Distinguish between… (1) User errors Errors made by human user Errors that “could happen” Example: Bad data in stdin Example: Too much data in stdin Example: Bad value of command-line argument Use if statement to detect Handle immediately if possible, or… Report to client via return value or call-by-reference parameter Don’t use global variable

39 Programmer Errors (2) Programmer errors Errors made by a programmer Errors that “should never happen” Example: pointer parameter should not be NULL, but is For now, use assert to detect and handle More info later in the course The distinction sometimes is unclear Example: Write to file fails because disk is full Example: Divisor argument to div() is 0 Default: user error

40 Error Handling Example 1 Stack Invalid parameter is programmer error Should never happen Detect and handle via assert Exceeding stack capacity is user error Could happen (too much data in stdin ) Detect via if ; report to client via return value /* stack.c */ … int Stack_push(Stack_T s, double d) { assert(s!= NULL); if (s->top >= MAX_STACK_ITEMS) return 0; s->items[s->top] = d; (s->top)++; return 1; }

41 Error Handling Examples 2, 3, 4 string No error detection or handling/reporting Example: strlen() parameter is NULL => seg fault stdio Detects bad input Uses function return values to report failure Note awkwardness of scanf() Sets global variable errno to indicate reason for failure SymTable (See assignment specification for proper errors that should be detected, and how to handle them)

Agenda A good module: Encapsulates data Is consistent Has a minimal interface Detects and handles/reports errors Establishes contracts Has strong cohesion (if time) Has weak coupling (if time) 42

43 Establishing Contracts A well-designed module establishes contracts A module should establish contracts with its clients Contracts should describe what each function does, esp: Meanings of parameters Work performed Meaning of return value Side effects Why? Facilitates cooperation between multiple programmers Assigns blame to contract violators!!! If your functions have precise contracts and implement them correctly, then the bug must be in someone else’s code!!! How? Comments in module interface

44 Contracts Example 1 Stack Comment defines contract: Meaning of function’s parameters s is the stack to be affected; item is the item to be pushed Work performed Push item onto s Meaning of return value Indicates success/failure Side effects (None, by default) /* stack.h */ … /* Push item onto s. Return 1 (TRUE) if successful, or 0 (FALSE) if insufficient memory is available. */ int Stack_push(Stack_T s, double item); …

Contracts Examples 2, 3, 4 string See descriptions in man pages stdio See descriptions in man pages SymTable See descriptions in assignment specification 45

Agenda A good module: Encapsulates data Is consistent Has a minimal interface Detects and handles/reports errors Establishes contracts Has strong cohesion (if time) Has weak coupling (if time) 46

47 Strong Cohesion A well-designed module has strong cohesion A module’s functions should be strongly related to each other Why? Strong cohesion facilitates abstraction

48 Strong Cohesion Examples Stack (+) All functions are related to the encapsulated data string (+) Most functions are related to string handling (-) Some functions are not related to string handling: memcpy(), memcmp(), … (+) But those functions are similar to string-handling functions stdio (+) Most functions are related to I/O (-) Some functions don’t do I/O: sprintf(), sscanf() (+) But those functions are similar to I/O functions SymTable (+) All functions are related to the encapsulated data

Agenda A good module: Encapsulates data Is consistent Has a minimal interface Detects and handles/reports errors Establishes contracts Has strong cohesion (if time) Has weak coupling (if time) 49

Weak Coupling A well-designed module has weak coupling Module should be weakly connected to other modules in program Interaction within modules should be more intense than interaction among modules Why? Theoretical observations Maintenance: Weak coupling makes program easier to modify Reuse: Weak coupling facilitates reuse of modules Why? Empirical evidence Empirically, modules that are weakly coupled have fewer bugs Examples (different from previous)… 50

51 Weak Coupling Example 1 Design-time coupling f() move() getLat() getLon() getAlt() setLat() Simulator Airplane Simulator module calls many functions in Airplane Strong design-time coupling f() Simulator Simulator module calls few functions in Airplane Weak design-time coupling Function call setLon() setAlt() getLat() getLon() getAlt() setLat() Airplane setLon() setAlt() move()

52 Weak Coupling Example 2 Run-time coupling f() sort() getN() setN() Client Collection Client module makes many calls to Collection module Strong run-time coupling f() sort() getN() setN() Client Collection Client module makes few calls to Collection module Weak run-time coupling One function call Many function calls

53 Weak Coupling Example 3 Maintenance-time coupling f2()f3() ClientMyModule Maintenance programmer changes Client and MyModule together frequently Strong maintenance-time coupling f2() f3() ClientMyModule Maintenance programmer changes Client and MyModule together infrequently Weak maintenance-time coupling f1() Changed together often

54 Achieving Weak Coupling Achieving weak coupling could involve refactoring code: Move code from client to module (shown) Move code from module to client (not shown) Move code from client and module to a new module (not shown)

Summary A good module: Encapsulates data Is consistent Has a minimal interface Detects and handles/reports errors Establishes contracts Has strong cohesion Has weak coupling 55