CIT 590 Assignment 6:
Library
Spring 2010, David Matuszek
You are going to implement software for your local library. The user of the software will be the librarian, who uses your program to issue library cards, check books out to patrons, check books back in, send out overdue notices, and open and close the library.
In a number of methods, we will make a distinction between what the program appears to do (its behavior), and what it actually does (its implementation). For example, when we "issue a library card" to a patron, we don't create some kind of a "library card object" and give it to a Patron object; the implementation will achieve the same result by simply recording the patron's name in a dictionary. The visible behavior is the same: A person who has been "issued a library card" will be able to check out books. Don't let yourself be confused by the differences between the behavior and the implementation.
I don't think you will need any additional classes, but you are likely to need some additional methods, not listed below. Feel free to write more methods (but remember to test them).
class Calendar(object)date class, but to keep
things simple, we will just use an integer (starting from 0) to keep
track of how many days have passed. We only need a couple of methods:
__init__(self)get_date(self)advance(self)class Book(object)title, its author (only one author
per book), and its due_date.
The due date is None if the book is not checked
out.
__init__(self, title, author)get_title(self)get_author(self)get_due_date(self)check_out(self, due_date)check_in(self)None. It is not this Book's job to return itself
to the Library's collection of available books.__str__(self)title, by
author.class Patron(object)__init__(self, name, library)Library object that he/she uses.get_name(self)take(self, book)give_back(self, book)return, but I hope you can see why I can't do that.) get_books(self)Book objects checked out to this Patron (may be the
empty set, set([])).send_overdue_notice(self, notice)class OverdueNotice(object)__init__(self, set_of_books)set_of_books, along with today's
date.)__str__(self)class Library(object)__init__(self)(title, author) tuples,
creates a Book from each tuple, and saves these in some
appropriate data structure of your choice. These Books form the
library's collection. Do
not assume that there is only one copy of each book.open(self)send_overdue_notices(self)open method, so that the librarian doesn't
have to do it as a separate command.)issue_card(self, name_of_patron)serve(self, name_of_patron)Patron object in a data variable of this
Library. In addition, the method should print out a
numbered list of the books (if any) currently checked out to this
patron.check_in(self, *book_numbers)Patron
(there must be one!), so return it to the collection and remove it from
the set of books currently checked out to the patron. The
book_numbers are taken from the list printed by the
serve command. Checking in a Book will involve
both telling the Book that it is checked in and
returning the Book to this Library's collection of available
Books.search(self, string)Books whose title or author (or both)
contains this string. For example, the string "tact" might
return, among other things, the book Contact, by Carl Sagan.
The search should be case-insensitive; that is, "saga"
would also return this book. Only books which are currently available
(not checked out) will be returned. In addition, to keep from returning
too many books, require that the search string be at least 4 characters
long.check_out(self, *book_numbers)Patron currently
being served (there must be one!), or tells why the operation is not
permitted. The book_numbers are one or more of the books
returned by the most recent call to the search method.
Checking out a Book will involve both telling the Book that it
is checked out and removing the Book from this Library's
collection of available Books.close(self)quit) can be used when the library is
closed.quit(self)allow_printing(self, allow)allow is
given as True, the methods may print; when
False, no printing is done.serve the patron. This will print a numbered list of books
checked out to that patron.check_in the books by the
numbers given above.serve the patron. You can ignore the list of books that this
will print out.search for a book wanted by
the patron.check_out zero or more books
by the numbers returned from the search command.search.Two of the methods above, check_out and
check_in, have an asterisk in front of the last parameter. That
asterisk is new syntax--it means that, when you call the
method, you can give as many book numbers as you please; you don't have to
give just one. Inside the method, the parameter
book_numbers is a tuple of all the numbers
(zero or more) that you gave it.
All of the methods in Library may be called directly by the librarian. Whenever the librarian calls one of these methods, some output should result. However, these methods also do quite a bit of work, and should be tested. So, do these methods print something out, or don't they?
My solution is to put in an additional variable, initialized to
True, that these methods must check before doing any printing.
An additional method, allow_printing, is added to the Library
class, so that the test methods have a way to turn off (or on) printing. This
method should normally be called only from the test methods.
You can put multiple classes in a single file. However, please turn in two files, named library.py and library_test.py. Tests should normally be kept separate from the program being tested.
Instance variables are variables that belong to an object, and instance methods are methods that are defined for an object. Instance variables and methods must be prefixed with self. , when used by the object itself. Local variables (including parameters) and global variables should not be prefixed with self. When an object uses the methods of another object, those methods must be prefixed by a variable that refers to the object; for example, book.get_title().
The test methods for each class can include a setup(self) method. This is a good place to declare global variables. For example, my test methods use
global lib
lib = library.Library()
You and your partner should decide who is to turn in the program, and you should submit one program for the two of you. Both of you will receive the same grade on the program.