6.5. One Little Job

 <  Day Day Up  >  

The framework of Unix pipes and filters is elegant. It is easier to create a program that does one simple job (a filter) than a program that does multiple jobs. For example, the word count program ( wc ) counts lines, words, and characters in the input file. The directory-listing program ( ls ) lists the files in a directory, one per line. To count how many files are in a directory, you pipe the output of the ls program into the input of the wc program and count the number of lines (e.g., ls wc ). [*]

[*] Unix commands represent another approach to the naming issue. The names are short. (Some people refer to them as cryptic.) Since these commands are typed over and over, the short names are reasonable in that contact.

Each class should capture one concept. Likewise, each method within a class should do one little job well. The Proxy pattern works in this way. Each proxy class can perform one operation (e.g., encryption or checking for security access violations). Once a proxy method has finished its task, it calls the corresponding method in another proxy object to perform further operations.

Multilevel delegation works in a similar manner. The lowest -level class performs simple operations. Higher-level classes perform more complicated operations, which are based on the lower-level operations. The lowest-level classes get used more often, and the higher-level classes are used less often, since they are designed for specific purposes.

For example, here is a File class that just reads a set of characters from a file:

 class File         boolean open (String filename)         void close( )         char read_a_char( )         void write_a_char(char char_to_write) 

The read_a_char( ) method internally might not read just a character from the operating system. The method might read an entire buffer and then return the characters one at a time. Performance is a quality-of-implementation issue, not an interface issue. However, if we found that we were calling read_a_char( ) in a loop in many places, we might add a more efficient interface method, such as read_array_of_char(char [] array) . This is an interface performance issue, not an internal implementation concern.

On the next level up, we might want to read characters until a newline is read. Instead of modifying File , we create a new class to read lines, and delegate the actual file reading to File . For example, we might have the following:

 class FileWithLines         String read_line_up_to_new_line_and_toss_new_line( ) 

Alternatively, we could have added this method to the File class. If we took that approach for other operations, we would be burdening the File class with a number of unrelated methods . The File class should do its one job well. FileWithLines can incorporate other methods dealing with line-oriented input. For example, we could add get_count_of_lines_read( ) , set_line_terminator( ) , and so forth.

In another project, we might read a file that contains keywords and associated values. The class might be as follows :

 class KeywordPair         String keyword         String value     class FileWithKeywords         KeywordPair read_next_keyword_pair( ) 

Once again, the file reading is delegated to the File class. If the keyword pairs were kept on separate lines, the reading might be delegated to the FileWithLines class.

DO A LITTLE JOB WELL AND YOU MAY BE CALLED UPON OFTEN

Methods and classes that perform specific jobs can be reused more often .


 <  Day Day Up  >  


Prefactoring
Prefactoring: Extreme Abstraction, Extreme Separation, Extreme Readability
ISBN: 0596008740
EAN: 2147483647
Year: 2005
Pages: 175
Authors: Ken Pugh

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net