This assignment will require you to loosen up those file I/O and Regex muscles. You'll need to read in a dictionary file and create a simple parser that will search for words within it. This is a good chance to practice highly modular design and work with "micro classes" which can help you perform a variety of specific tasks.
You will need to verify that things work anyway, so why not implement a simple automated test suite..?
You will build a simple word search tool on the command line in Ruby. Even though it's called a "Dictionary", to keep it simple we're actually just searching for words in a word list (which is our "dictionary").
The architecture of this is going to feel a bit strange at first. Specifically, we'll break it up into 5 highly specialized classes:
DictionaryUIis the main class which handles the user interaction loop.
DictionaryLoaderis a helper class whose single responsibility is to load in the dictionary.
Dictionaryis the class which wraps the loaded dictionary.
DictionarySearcheris an analysis class whose sole responsibility is to perform any analysis on the dictionary you provide it.
ResultsSavertakes a batch of results and writes them to a file.
It may feel a bit strange to break out all these separate classes but this type of object orientation is quite common. Each class should only have ONE responsibility -- this is a way of enforcing this.
By having a single
DictionaryLoader class to handle all the loading operations, your main
DictionaryUI doesn't care where the dictionary actually comes from. Imagine you wanted to be able to load dictionaries from your local filesystem via XML or from the web via a URL... It would be the job of your
DictionaryLoader to call the appropriate
WebLoader subclasses if the application was sufficiently complicated.
By having your
DictionarySearcher in its own class, you again allow
DictionaryUI to fully delegate the analysis logic and processes to a class whose sole purpose is performing those tasks. The same is true of
ResultsSaver since it fully encapsulates the task of figuring out how to save your results.
Create a simple application which loads in the dictionary file you downloaded during the setup step and allows the user to perform simple searches on it.
DictionaryUIclass to handle the user interaction loop. The first prompt is for the location of your dictionary file.
Create a class
DictionaryLoader whose purpose is to perform the loading and processing of the specified dictionary file before returning it as an instance of a
Dictionary. Remember that classes don't need to be big!
> d = DictionaryUI.new > d.run # Where is your dictionary? ('q' to quit) > "path/to/myfile.csv" > ...
Return statistics about your dictionary when it is first loaded, including word count and words by starting letter:
... > "path/to/myfile.csv" # Dictionary successfully loaded # Your dictionary contains 12345 words. # Word frequency by starting letter: # A: 123 # B: 456 ...
DictionarySearcherwhich takes a dictionary and contains methods that perform searches on it.
Next, allow the user to perform one of four types of searches:
These can be done with Regex or not... you should use whatever you're least comfortable with! The results should return the full word, regardless of match type.
Once the search is complete, display the number of matches and those matches:
# What kind of search? # 1: Exact # 2: Partial # 3: Begins With # 4: Ends With > 3 # Enter the search term > fuz # Found 7 matches: # FUZE # FUZEE # FUZHOU # FUZZ # FUZZILY # FUZZINESS # FUZZY ...
If saving to a file, prompt the user for the name of the file to save results to. If it already exists, ask whether to overwrite it or not. Create a
ResultsSaver class which takes a batch of results and writes them to a file.
... # Found 1 match: # FUZZY # *** # Do you want to save results? y/n? 'q' quits. > y # What filepath should we write results to? > results.txt # That file exists, overwrite? y/n? 'q' quits. > y # File successfully overwritten!
Play with this and verify that searches and saving works properly. What other search types can you come up with?
$ git push origin master).
Write a basic test suite which verifies that each of your classes behaves the way you expect it to. Be mindful to include edge cases!
The solution will be available here on Github once you've unlocked it.