for
CSCI 301: Great Ideas in Computer Science
(c) 1993, 1994, 1995 John E. Howland, All Rights Reserved
Department of Computer Science
Trinity University
715 Stadium Drive
San Antonio, Texas 78212-7200
Internet: jhowland@ariel.cs.trinity.edu

At the top level, we have that part of the system which deals with the overall system; a sort of system overview.
We will attempt to illustrate this top-down methodology with an example. As with all of the topics covered so far in this course, we will model this system using the Scheme programming notation. One might actually use some language other than Scheme (such as C) to implement a database system. However, the approach we use is valid since one might use Scheme to implement a prototype system and then use the C programming language for the production system. This is an illustration of an important technique known as software prototyping. Just as an engineer always builds at least one prototype machine before giving the go-ahead to begin production of the machine, software engineers should also use this same technique. Scheme is a particularly good language for prototyping as we shall soon see.
Since most Scheme systems are already interactive systems, we can simplify our prototype design by using the Scheme top-level as our prototype's top-level.
Similarly, we can use the Scheme syntax for our commands. This means that we can use the Scheme system's read-eval-print loop (the second level in our system diagram) as our prototype's second level and third level. It should now begin to be obvious why Scheme is a good prototyping language for interactive systems. We are already down to the fourth level of our design and we have yet to begin to design or implement any programs!
Another aspect of this design method of building a system from the top down in distinct layers is that it is possible (and desirable) to attempt to make each layer of software independent from the layers above and below it. This involves design of some sort of abstract interface between the layers.
The most important benefit of design layers is that it should then be possible to change the software in one layer (provided the new version of that layer adhears to the same interface above and below) without having to change any other part of the software design.
This is a lofty design goal. In practice, it is often very difficult to achieve.
(define people '( (howland (john (professor (computer (science))))) (howland (glynne (nail (manufacturer)))) (clinton (bill (president (USA)))) (clinton (hillary (First-lady (USA)))) (perot (ross (former (presidential (candidate)))))))
Following is a function which will lookup up a key in a database.
(define lookup
(lambda (key datalist)
(if (null? datalist)
'()
(if (equal? key (caar datalist))
(cdar datalist)
(lookup key (cdr datalist))))))
(lookup 'clinton people) ==>((bill (president (usa))))
lookup just finds the first match in the database. Most databases of any size will have multiple matches for a given key. Following is a function which will lookup all matches of a given key.
(define lookup-all
(lambda (key datalist)
(if (null? datalist)
'()
(if (equal? key (caar datalist))
(cons (cadar datalist)
(lookup-all key (cdr datalist)))
(lookup-all key (cdr datalist))))))
(lookup-all 'clinton people) ==>
((bill (president (usa))) (hillary (first-lady (usa))))
Notice that by the way we have constructed the data associated with each key in the people database, that the result of using lookup-all is to produce a new database which might be used as the database for a lookup operation.
(lookup 'hillary (lookup-all 'clinton people)) ==> ((first-lady (usa))) (lookup 'bill (lookup-all 'clinton people)) ==> ((president (usa)))Next we consider the problem of adding items to an existing database. The result of this operation is a new database. Hence to actually add an item to an existing database we need to re-define the existing database to be the result of add-data.
; A function to add an item to a database.
; To actually change datalist we must use
; define as in the following:
; (define db (add-data '(smith (jim (broker))) db))
(define add-data
(lambda (item-pair datalist)
(cons item-pair datalist)))
(add-data '(konstam (aaron (professor))) people) ==>
((konstam (aaron (professor)))
(howland (john (professor (computer (science)))))
(howland (glynne (nail (manufacturer))))
(clinton (bill (president (usa))))
(clinton (hillary (first-lady (usa))))
(perot (ross (former (presidential (candidate))))))
To
actually change the people database we must:
(define people (add-data '(konstam (aaron (professor))) people)) people ==> ((konstam (aaron (professor))) (howland (john (professor (computer (science))))) (howland (glynne (nail (manufacturer)))) (clinton (bill (president (usa)))) (clinton (hillary (first-lady (usa)))) (perot (ross (former (presidential (candidate))))))We now address the problem of removing items from a database. As in the previous database operations we form a new database which is a copy of the old database less the item being removed.
; A function to remove the first item matching
; key from a database.
; To actually change the database we must
; use define as above.
(define remove-data
(lambda (key datalist)
(if (null? datalist)
'()
(if (eq? key (caar datalist))
(cdr datalist)
(cons (car datalist)
(remove-data key (cdr datalist)))))))
(remove-data 'howland people) ==>
((howland (glynne (nail (manufacturer))))
(clinton (bill (president (usa))))
(clinton (hillary (first-lady (usa))))
(perot (ross (former (presidential (candidate))))))
people ==>
((howland (john (professor (computer (science)))))
(howland (glynne (nail (manufacturer))))
(clinton (bill (president (usa))))
(clinton (hillary (first-lady (usa))))
(perot (ross (former (presidential (candidate))))))
We need to be able to remove all items matching a given key.
; A function to remove all items matching
; key from a database.
; To actually change the database we must
; use define as above.
(define remove-all-data
(lambda (key datalist)
(if (null? datalist)
'()
(if (eq? key (caar datalist))
(remove-all-data key (cdr datalist))
(cons (car datalist)
(remove-all-data key (cdr datalist)))))))
(remove-all-data 'howland people) ==>
(clinton (bill (president (usa))))
(clinton (hillary (first-lady (usa))))
(perot (ross (former (presidential (candidate))))))
Since
we did not redefine people, the original people database is
unchanged.
people ==> ((howland (john (professor (computer (science))))) (howland (glynne (nail (manufacturer)))) (clinton (bill (president (usa)))) (clinton (hillary (first-lady (usa)))) (perot (ross (former (presidential (candidate))))))
Here is the database-operation-maker.
(define database-operation-maker
(lambda (operation database)
(lambda (key)
(operation key database))))
(define people-looker (database-operation-maker lookup people))Similarly we can define:
(define people-all-looker (database-operation-maker lookup-all people)) (people-looker 'howland) ==> ((john (professor (computer (science))))) (people-all-looker 'howland) ==> ((john (professor (computer (science)))) (glynne (nail (manufacturer))))Next we consider the problem of more permenant storage of our database in a filesystem. As it stands now, our database is stored as a Scheme list in the main memory of our computer. It is vulnerable to loss if the power to the computer goes down for example.
We need two utility functions for storing and retrieving Scheme objects as files.
; A function to write a lisp list to a file.
(define write-to-file
(lambda (filename obj)
(let ((port (open-output-file filename)))
(write obj port)
(close-output-port port))))
(write-to-file "test" '((a b) c d)))
; A function to read a lisp list from a file.
(define read-from-file
(lambda (filename)
(car
(let ((port (open-input-file filename)))
(let f ((value (read port)))
(if (eof-object? value)
(begin
(close-input-port port)
'())
(cons value (f (read port)))))))))
(read-from-file "test") ==> ((a b) c d))Suppose we have the following database file
(read-from-file "people") ==> ((konstam (patricia (editor (newspaper)))) (konstam (aaron (professor (computer (science))))) (eggen (maury (professor (computer (science))))) (howland (john (professor (computer (science))))) (howland (glynne (nail (manufacturer)))) (clinton (bill (president (usa)))) (clinton (hillary (first-lady (usa)))) (perot (ross (former (presidential (candidate))))))
; A function to lookup the first item matching
; key from a database stored as a file.
(define lookup-file
(lambda (key filename)
(lookup key (read-from-file filename))))
(lookup-file 'eggen "people") ==> ((maury (professor (computer (science)))))
; A function to lookup all items matching
; key from a database stored as a file.
(define lookup-all-file
(lambda (key filename)
(lookup-all key (read-from-file filename))))
(lookup-all-file 'clinton "people") ==> ((bill (president (usa))) (hillary (first-lady (usa))))
; A function to add data to a database stored
; as a file.
(define add-data-file
(lambda (item-pair filename)
(write-to-file filename
(add-data item-pair
(read-from-file filename)))))
(add-data-file '(pitts (gerald (professor (computer (science))))) "people")Then
(read-from-file "people") ==> ((pitts (gerald (professor (computer (science))))) (konstam (patricia (editor (newspaper)))) (konstam (aaron (professor (computer (science))))) (eggen (maury (professor (computer (science))))) (howland (john (professor (computer (science))))) (howland (glynne (nail (manufacturer)))) (clinton (bill (president (usa)))) (clinton (hillary (first-lady (usa)))) (perot (ross (former (presidential (candidate))))))
(define database-file-operation-maker
(lambda (operation filename)
(lambda (key)
(operation
key
(read-from-file filename)))))
(define people-file-looker
(database-file-operation-maker
lookup
"people"))
(people-file-looker 'howland) ==> ((john (professor (computer (science)))))Other people-file database operations are easily defined. Such functions are left as an exercise for the reader.