Context
Goal: a Java utility that can apply multiple filters to a text stream
Like connecting Unix commands with pipes
Plan:
Write some use cases to clarify requirements
Implement a prototype
Critique the prototype
I've looked ahead, and know that configuration will be its biggest shortcoming
Learn some useful things about:
XML
Reflection
Come back and finish the program off
What's a Use Case?
A short story about a particular person accomplishing a single task with a piece of software
Use cases are:
An interface between customers and developers
A way for developers to keep track of what they're supposed to be doing
And make sure it's internally consistent
A guide for testing
Typically start a development cycle by writing new use cases
Not "what do we want to do to the software?"
But "what do we want the software to do?"
Once use cases are done, go back and extract:
Visible system features (screens, buttons, etc.)
Invisible features (e.g. database of marks)
Format:
Each use case is a single sequence of actions
Refer to other use cases to handle other sequences
Alternate user action with system response
Example
Software is a web-based system for checking grades on assignments
Angela is a student in CSC207
Title: "Compare Mark To Average When Grades Available"
Goal: compare her mark on Assignment 3 to the class average
Steps:
Open web browser
Browser displays Angela's usual home page
Go to course home page
Browser displays course home page
Click link marked "Grades"
Browser displays marks page, which contains a four-column table
Each row is assignment number, assignment name, due date, and average grade
Note: if assignment has not been graded, that cell in the table is grayed out
See "Compare Mark To Average When Grades Not Available"
Bottom of page has link marked "Log In"
Angela clicks on "Log In" link
Browser displays page with username/password fields
Angela fills in CDF user ID and password correctly and presses "Submit" button
Otherwise see "Incorrect User Name Or Password"
Browser displays marks page
Table now has fifth column showing Angela's mark for each assignment
And "Logout" link at bottom of page
This seems like a lot of detail for something so simple
But when your system can do several thousand things, you need a way to keep track of them
And a way to communicate those capabilities to customers before you start construction
Use Cases for Filter Program
We may ask you to write these as an exercise...
Think about what you do with the Unix command-line tools
Requirements
Specify filters using:
Command-line arguments
Configuration file
Use:
Built-in filters
Filters supplied by users
This turns out to be the biggest issue
Both types of filters may need specific arguments
E.g. pattern to search for in each line
Input and output:
Input:
Standard input
Multiple input files
Multiple input files and standard input
Output:
Standard output
Single output file
Do not support both, or multiple output files, for now
Output must be incremental
Cannot read all input, then process, then produce all output
Filters:
Produce some output before reading any input
Produce one line of output for each line of input
Produce multiple lines of output for each line of input
Produce one or more lines of output for some lines of input, but none for others
Produce one or more lines of output after input exhausted
Error situations:
Bad command-line arguments
Badly formatted configuration file
Bad configuration of individual filters
Non-existent filters
Unreadable input files
Unwriteable output file
Filter throws exception
Prototype Design
Use a fixed set of filters to start with
Each identified by a name and zero or more configuration parameters
Parameters passed to filter as strings
Since the alternative is guessing from string contents what data type to use
Main program:
Reads configuration
Creates filters
Reads input from source(s) a line at a time
Passes data through filters in order
Writes output
Handles exceptions
A Few Thoughts
Must handle command-line arguments and configuration files
Both are lists of strings
Can copy relevant command-line arguments into a list
So have MultiFilter.configureFilters() take a list of strings as its argument
May want to trace behavior of filters when testing
Use a Boolean flag to turn debugging output on and off
Can handle output by putting a special "filter" after all user-specified filters
Copies its input to System.out or an open file
Exercise for the reader: explain why we don't handle input the same way
Connecting Filters
Two options:
A list, with MultiFilter responsible for moving one filter's output to the next filter's input
A recursive chain, with each filter responsible for passing its output to the next filter in the chain
![[Possible filter arrangements]](../img/filters/arrangement.png)
Problem with option 1: what happens if a filter produce multiple lines of output for a single line of input?
E.g. a filter that duplicates each line of input
Could hand a (possibly empty) list of output lines back to MultiFilter for each line of input
But that seems clumsy
And if a filter produces a lot of output for some input lines, it is also inefficient
So use option 2
Each filter has a reference to the next in the chain
MultiFilter feeds input to the first one
Recursive calls inside filters' filter() methods do the rest
Testing
Figuring out how to test something is part of designing it
If you can't think of a way to test it, maybe you ought to use a different design
Things to test:
Configuration of individual filters
Behavior of individual filters
Overall configuration
Both from file and from command-line
Behavior of chained filters
Look at combinations of all types of behaviors
How to test:
Want to use JUnit
Do not want to depend on external files
So give MultiFilter a setInput() method
Give it a BufferedReader wrapped around a StringReader
And an output filter that writes to a list of strings
Can then store test input in test class, capture output, and compare
$Id: filter.html,v 1.1.1.1 2004/01/04 05:02:31 reid Exp $