Often times when we start writing better code, we start to remove all those hard-coded values within our application and allow for certain features to become more configurable. Or we want to be able to configure our system to be run in different ways in different environments (e.g. development, test, production). However, with more configuration brings more problems. It is something that can easily get away from you within an application.
The objective of this exercise is to provide a single, simplistic reference point of configuration that aggregates several configuration sources.
The objective of the exercise is to accomplish the following:
For this exercise choose at least two input sources:
-
YML
Configuration:
fixtures/configuration.yml
Example :
lib/yml.rb
-
YML (User specific)
Configuration:
fixtures/user-configuration.yml
Example :
lib/yml.rb
-
Command-Line Parameters
Commands:
fixtures/command-parameters.md
Example :
lib/command.rb
-
Environment Variables
Commands:
fixtures/environment-parameters.md
Example :
lib/environment.rb
-
JSON
Configuration:
fixtures/configuration.json
Example :
lib/json.rb
-
XML
Configuration:
fixtures/configuration.xml
Example :
lib/xml.rb
-
Database
Example :
lib/database.rb
-
Webservice
Run
ruby lib/sinatra.rb
to start the service.Visit localhost:4567/configuration.json
Visit localhost:4567/configuration.xml
Visit localhost:4567/configuration.yml
After selecting the input sources, implement the initial strategy that will load these values.
Then, when you have all these values loaded, decide on way to represent the configuration in a way that would be easily expandable and flexible.
-
Expandable
A configuration system that you could later decide to add/apply a different input source or additional input sources with the most minimal design changes.
-
Flexible
A configuration system that would insulate your application from changes to the specifics of the input (e.g. Changing the names of the command-line parameters or the name-value pairs of the JSON).
-
How did you decide the order of which to apply the various configurations?
-
How did you choose to resolve conflicts?
-
How did you, or would you, make a user aware of how the configuration system resolved conflicts?
-
Did your design choices support easily adding a new configuration?
-
Did your design choices support changes in the layout of the configuration?
-
Chapter 1 - Sections 1.5 through 1.7
Appendix A - A.1 through A.3
Similar to the exploration of Rake
and ActiveSupport
in the previous
reading. Examining and exploring code is the most fruitful way to learn to be a
better developer. There are a number of libraries that you have likely employed
that provides a flexible configuration system. Explore these frameworks. Attempt
to answer the retrospective questions.
Each of the sections I have tried to outline a good starting point of where to being your examination. With all of these frameworks the accompanying tests are also great places as well.
-
Cucumber employs a system of default options, command-line options, and user profiles.
-
RSpec uses a local config file, global config file, command-line options and then to top it off provides the ability to further augment configuration through a block-based configuration system.
Start with the Runner class
Then look at ConfigurationOptions
-
Rails is a large beast, so do not get lost and do not wander too far. Here the object is simply to understand initially how Rails starts up.
Start with the bin
That should lead you to the cli
What does the
.railsrc
do for your Rails?Take a look at script_rails_loader
What happens in this command when you execute it within a rails application?
Then to the various commands
Within the short time allotted to the exercise it was likely that you were barely able to prove that your system was exandable or flexible. With this additional time finish your initial implementation and then:
-
Choose an additional configuration input source
-
Change one of your additional configuration sources slightly, requiring you to change how you parse the input.
-
Provide the ability to support but the origin configuration source and this new modified configuration source (this may be a configuration difference).
-
Copy a configuration feature from Cucumber or RSpec