CS/CE 218 Lecture -*-Outline-*- connection: so far we've looked at pieces of shell programs, now we'll concentrate on putting programs together in good packages. * modularity in shell programming advert: we see how to write maintainable shell programs. These techniques will be valuable also for C programming. ** principle of nonredunancy: don't ever duplicate code Q: What kind of information (knowledge) does a program contain? how to do something decisions (about how, representations for data, defaults, ...) Q: What problems are caused by putting the same information in more than one file? hard to change hard to keep consistent ... *** avoiding redundancy Q: What are some ways of writing the same code in more than one place? use variables use procedures use include files or linking turn programs into products derived from a single source Q: How can you explain a program to a user, without giving the user a redundant copy of information that may need to be changed? tell them what it does, not how it's done. tell them how to extract information from the program, not how the information is stored. *** abstraction by specification Q: What does a specification say? What does it not say? the specification says what is done, not how e.g., how to sort lines of a file (spec is to produce an ordered permutation of the original) e.g., how to print on a certain printer (spec is to produced printed output) ** ways to implement abstractions *** functions (section 13.8) can define local functions in a shell (not part of cshell!) Q: What do you think some of the advantages of using functions would be? avoids redundancy allows information hiding (function that is hidden); data structure that is hidden. prevents linkage (path lookup) problems I had a program "unit-examples" that called "unit-files" I didn't put ~leavens/bin/unit-files in unit-examples because it finds unit-files by my path but if you used it, you needed to put unit-files in your path. this may have some advantage in speed over starting a new subshell not in my tests, however... Q: What's the syntax for a function definition in the shell? examples: -------------- # file names for the unit (excluding Outline-files.txt) in each directory mainunitfiles() { for d do sed -n -e 's!^\*\** \([^A-Z].*\)!'"${d}"'/\1.txt!p' \ ${d}/Outline-files.txt done } # all file names for the unit (including Outline-files.txt) in each directory allunitfiles() { for d do echo ${d}/Outline-files.txt `mainunitfiles $d` done } -------------- Q: What happens if you define a function ``ls''? Which ``ls'' will be run if you type ``ls''? can type /bin/ls to get the standard one... *** abstract data types (ADTs, data abstractions) Q: How is an abstract data type specified? an ADT is specified by specifying some data objects and operations on those objects recall in emacs... Q: What information is hidden by an ADT? information about some data format (data structure) important because often want to change the format to make the program faster to add more information to accomodate new demands for information for convenience of the person entering the data... e.g., lecture notes note type: objects are files of lecture notes (like this one) operations: extract outline, extract examples, ... information hidden: exact format how to do the extraction **** groups, implementing ADTs in the shell source for a group (minus comments etc.) looks like: ---------------------- xGroup() { USAGE="Usage: $0 op1 [file ...] $0 op2 [file ...]" case "$1" in op1) shift # do the work for op1 ;; op2) shift # do the work for op2 ;; *) echo "$USAGE" >&2 exit 2 ;; esac } ---------------------- command using the xGroup ---------------------- #!/bin/sh # x -- command that implements the ADT x xGroup() { #... } xGroup $* ---------------------- use of the x command ---------------------- $ x op1 file1 another-file ---------------------- advantages of this style: information hiding (all stuff about x is in 1 file) related commands have a common prefix, so fewer files to manage and can use subcommands. If don't like subcommands, you can always define scripts as abbreviations (e.g., op1) can use xGroup in other shell scripts, without linkage problems examples: see my print or note commands **** include files for layered abstractions raise level of program by building new abstractions on top of old e.g., my unit and lecture-unit commands Problem: The unit command uses the noteGroup (or note command); I want students to use the unit command, without having my bin in their PATH Solution: Include the text of noteGroup in the unit command Problem: Then I have duplicated note, Solution: consider unit as a product, made by a preprocessor that does the inclusion. ------------------ #!/bin/sh # the file unit.sh include(unitGroup.sh) include(echo-debug.sh) unitGroup $* ------------------ ------------------ # unit -- lecture unit extraction group # the file unitGroup.sh # SYNOPSIS: this group of operations # understands the Outline-files.txt file # found in each lecture unit directory. include(echo-debug.sh) include(noteGroup.sh) unitGroup() { USAGE="Usage: $0 files [directory ...] $0 examples [directory ...] $0 handouts [directory ...] $0 outline [directory ...] $0 print [directory ...]" # ... mainunitfiles() { # ... } allunitfiles() { # ... } case "$1" in files) shift allunitfiles $* || exit 1 ;; examples) shift noteGroup examples `mainunitfiles $*` ;; handouts) shift noteGroup handouts `mainunitfiles $*` ;; outline) shift # Extract the outline used in a unit noteGroup outline `mainunitfiles $*` ;; print) shift print ascii `allunitfiles $*` ;; *) echo "$USAGE" >&2 exit 2 ;; esac } ------------------