Last active
March 9, 2016 21:35
-
-
Save p-jackson/f96ff7796a91ab289a3b to your computer and use it in GitHub Desktop.
How I might go about reading from a settings file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string> | |
#include <unordered_map> | |
using namespace std; | |
// I've left the types explicit for clarity, but in real code | |
// I'd probably use `auto` | |
// The settings object is a hash table of keys and values. Everythings strings, | |
// no fighting the type system, no 3rd party libraries, everything is C++ 101. | |
const unordered_map<string, string> userSettings = parseSettings("path/to/settings.ini"); | |
// Returns a new settings object that has default settings applied. | |
const auto settings = applyDefaultSettings(userSettings); | |
// Abort app if there's some issue with the settings file. | |
if (!validateSettings(settings)) | |
return; | |
// Get some setting that is supposed to be a string | |
const string url = settings.at("servicePublicUrl"); | |
// What, convert to `int` every time you want to read the setting? | |
// Yeah why not? Why create an abstraction if there's no bugs? | |
// This will throw if the string doesn't represent an integer. But I | |
// think an exception is appropriate here since we called | |
// `validateSettings` earlier. | |
const int port = stoi(settings.at("somePortSetting")); | |
// `toBool` is your custom function that converts "yes", | |
// "true", etc. strings to a boolean. | |
const bool fastMode = toBool(settings.at("doFastMode")); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string> | |
using namespace std; | |
// The settings file is now represented by a struct. Awesome type safety | |
// benefits. Performance benefits because the compiler can inline things. | |
// It might "feel righter" to because you aren't parsing the non-string | |
// values over and over. | |
// Only downside is any change to the settings file format requires a | |
// change here, which will probably require a re-copmile of your entire | |
// app. | |
struct Settings { | |
string servicePublicUrl; | |
int somePortSetting; | |
bool doFastMode; | |
vector<string> someUserList; | |
}; | |
// The one and only parse of ints/bools/lists will happen here. | |
const Settings userSettings = parseSettings("path/to/settings.ini"); | |
// Returns a new settings object that has default settings applied. | |
const auto settings = applyDefaultSettings(userSettings); | |
// Abort app if there's some issue with the settings file. | |
if (!validateSettings(settings)) | |
return; | |
// Such type safety, wow. | |
// Mistype the property name? Get a compile error. | |
// Use the wrong type for a property? Get a compile error. | |
// Ground breaking stuff! | |
const string url = settings.servicePublicUrl; | |
const int port = settings.somePortSetting; | |
const bool fastMode = settings.doFastMode; |
Oh and I think the whole thing hinges on calling validateSettings
up front so that exceptions in stoi
and toBool
would be just that: exceptional.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
At first this feels yuck right? The DRY principle is gospel isn't it?
Yes, calls to
stoi
andtoBool
will be scattered throughout your code. I'm kind of assuming most of the configuration options for dRunner are strings so it won't be that bad. But still, it doesn't seem right.Lately I've been thinking more about these ideas:
I've already mentioned 1 to you, but 2 is something I'm hearing more of around the place too. I first heard it from the React people, but this article also puts it very well.
Obviously I don't think a special abstraction for a bag of properties is bad. It's a pretty useful in lots of situations, which is why property_tree got added to Boost. And I also regularly cheat on both properties and preemptively abstract when it feels right. But I've been trying to lean in this direction more.