These free mini-courses will give you a strong foundation in web development. Track your progress and access advanced courses on HTML/CSS, Ruby and JavaScript for free inside our student portal.
Scroll down...
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:
DictionaryUI
is the main class which handles the user interaction loop.DictionaryLoader
is a helper class whose single responsibility is to load in the dictionary.Dictionary
is the class which wraps the loaded dictionary.DictionarySearcher
is an analysis class whose sole responsibility is to perform any analysis on the dictionary you provide it.ResultsSaver
takes 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 XMLLoader
or 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.
DictionaryUI
class 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
...
DictionarySearcher
which 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.