CS 535 Object-Oriented Programming & Design Spring Semester, 1999 Comments on the Programs |
||
---|---|---|
© 1999, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 11-May-99 |
Names
IFYOUUSECAPITALLETTERSYOUNEED
TO_ADD_SOMETHING_TO_SEPARATE_WORDS
How Useful are these Names? fileName
delimiter
Code Presentation
Tabs and spaces do not mix well
if (x == y ) { if (z == w ) blah else whereDoesThisGo? }
Documentation
public class Translator { HashMap dictionary = new HashMap();
public void addWords(String key, String words ) { Vector words = new Vector(); StringTokenizer parser = new StringTokenizer( words, "," ); while (parser.hasMoreTokens) { String word = parser.nextToken(); words.add( word); } dictionary.put( key, words ); }The argument "words" to addWords must be properly formatted
Don’t make the reader read the method to find out that it must be formatted and what the format is.
The field "dictionary" requires a vector as a value.
Don’t make the reader read the entire class to find that out
If you use files that contain formatted data, document the format in the file and in the code, give examples.
Parameters verses Fields
Avoid using fields as implicit parameters to methods in the same class. Explicit parameters make the dependency clear.
public class Translator { private String aValue; public void bar() { blah; blah; aValue = result of some computation; foo(); more blah; } private void foo() { String myData = aValue; Compute on myData; } }
Java’s Return Problems
Goal
boolean isValid( String value, String reasonInvalid ) { if ( value is not valid ) { reasonInvalid = "A reason"; return false; } else return true; }
Do not be tempted to do the following:
public class Foo { private String reasonInvalid; public boolean isValid( String value ) { if ( value is not valid ) { reasonInvalid = "A reason"; return false; } else return true; } public String getReason() { return reasonInvalid; } }
What are the solutions?
Use two methods
public class Foo { public boolean isValid( String value ) { if ( reasonNotValid( value ) == null ) return true; else return false; } public String reasonNotValid( String value ) { if ( value == null ) return "null not allowed" ; else if ( value.length() == 0 ) return "empty strings not allowed"; else return null; } }
Pass in an object to hold the reason
public class Foo { public boolean isValid( String value, Reason explain ) { if ( value == null ) { explain.text = "null not allowed"; return false ; } else if ( value.length() == 0 ) { explain.text = "empty strings not allowed"; return false ; } else return true; } }Throw Exceptions
public class Foo { public void validate( String value) { if ( value == null ) throw new NotValidException( "null not allowed"); else if ( value.length() == 0 ) throw new NotValidException( "empty strings not allowed"); } }This should not be used too often.
Some Translator Solutions
We need to deal with one and two step translations
One step translations
Interface solution
public interface Translatable { public String translate( String word ); public boolean contains( String word ); } public class OneStepTranslation implements Translatable { HashMap dictionary = new HashMap( ); public String translate( String word ) { return (String) dictionary.get( word ); } public boolean contains( String word ) { return dictionary.containsKey( word ); } }
public class TwoStepTranslation implements Translatable { OneStepTranslation foreignToEnglish = new OneStepTranslation( ); OneStepTranslation englishToForeign = new OneStepTranslation( ); public String translate( String word ) { String englishTranslation = foreignToEnglish.translate( word); return englishToForeign.translate( word ); } public boolean contains( String word ) { if (! foreignToEnglish.contains( word ) ) return false; String englishTranslation = foreignToEnglish.translate( word); return englishToForeign.contains( englishTranslation ); } }Now the Translator class can use Translatables
It only has to create the correct type originally
A Second SolutionWord This class represents a word with its translations into multiple languages
public class Word { /** * Keys = languages as strings * Values = Set of strings, each string is a translation of this word into the give language */ HashMap translations = new HashMap(); public boolean containsLanguage( String language ) { return translations.containsKey( language ); } public Set translateTo( String language ) { return (Set) translations.get( language ); } public void addTranslation( String language, String text ) { String[] newTranslation = { text }; addTranslations( language, newTranslation ); } public void addTranslations( String language, String[] text ) { if ( !containsLanguage( language ) ) translations.put( language, new TreeSet() ); Set existingTranslations = (Set) translations.get( language ); List newTranslations = Arrays.asList( text ); existingTranslations.addAll( newTranslations ); } public Set languages() { return translations.keySet(); } }
WordIndex The class represents an index of words objects. The index maps language - word translations pairs (Spanish, madre) to word objects.
public class WordIndex { /** * keys = Strings of the format lanuage@text. For example english@mother * Values = Word objects that contains translation of the text into other languages */ TreeMap languageWordIndex = new TreeMap(); private static final String LANGUAGE_TEXT_SEPARATOR = "@"; public void add( Word newWord ) { Set languageSet = newWord.languages(); Iterator languages = languageSet.iterator(); while ( languages.hasNext() ) { String language = (String) languages.next(); add( language, newWord ); } } public boolean contains( String language, String text ) { return languageWordIndex.containsKey( key( language, text )); } public Word get( String language, String text ) { return (Word) languageWordIndex.get( key( language, text )); } private static String key( String language, String text ) { return language.toLowercase().trim() + LANGUAGE_TEXT_SEPARATOR + text.toLowercase().trim(); } private void add( String language, Word newWord ) { Set translationSet = newWord.translateTo( language ); Iterator translations = translationSet.iterator(); while ( translations.hasNext() ) { String aTranslation = (String) translations.next(); languageWordIndex.put( key( language, aTranslation), newWord); } } }
Translator Class
Now the translator class can contain a WordIndex. The index is used to look up words.
Copyright ©, All rights reserved.
1999 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.
Previous    visitors since 11-May-99