1

Suppose I am developing a class which implements some high-level application logic. I want the "configuration"/"attributes" of this logic to be modifiable at run-time (with some default values). Some attributes may be read-only, others may be read-write.

I am going to use a custom "networking" layer as an example:

class Network
{
public:
   void setConfigValueA(TypeA value);
   TypeA configValueA() const;

   void setConfigValueB(TypeB value);
   TypeB configValueB() const;

   //...
};

The way I have shown the code is to introduce a "getter" and "setter" method for each configuration attribute.

Examples for the network layer might be timeout values, error counters, modes, addresses, etc...

However, I am concerned that, if I have more than a handful of attributes, this technique becomes unwieldy. Or rather, it make the interface complex.

Another option I thought of is:

class Network
{
public:
   void setAttribute(AttributeID id, Variant value);
   Variant attribute(AttributeID id) const;
};

This doesn't make the underlying logic any less complicated (in fact, it probably makes it much more complex), but it does clean up the interface. It also allows me to add new attributes without modifying the interface. Some of the complexity here is converting the specific types into something generic that can fit in my Variant type. There also needs to be logic to set the appropriate value based upon the AttributeID.

To my knowledge, the latter option is similar to what ioctrl in POSIX achieves. A generic (unchanging) interface used to modify specific attributes of an underlying piece of code (e.g., a driver).

I am wondering, what other options are there to achieve this run-time attribute/configuration setting? Are there some examples/resources you could point me to?

4 Answers 4

3

The collected set of attributes of your configuration is nothing but a bunch of data which needs to be modeled like any other kind of data: by creating some data model or data schema for it. If you prefer DDD terms, you can also think of a Domain model, for the bounded context of the configuration of a certain domain aspect. As a domain model, however, it will be mostly an anemic domain model. Some OO hardliners may call this an anti-pattern, but for the case of a configuration a mostly behaviorless data model may exactly be what you need.

How this model has to look like depends ultimately on the specific attributes,

  • their semantics and relationships,

  • their commonalities and dependencies among each other

  • how many of them you have to manage

  • how uniform they are

  • how flexible and extendible you need the model to be

    (for example: do you really need to add new attributes without modifying the interface? If you are not designing a generic framework for configurations of all kinds, the answer is probably no.)

You design this the same way as you design a data model or object model for business data, applying all that you may have learned in the past about relational modeling, hierarchical modeling, OO modeling or Domain Driven Design, and how such a model expresses itself in C++.

The resulting model for a configuration will typically contain a root (or aggregate root class in DDD terms), like the Network class in your example, which I would call NetworkConfiguration. This root class can have getters and setters for primitive types as well as for custom child classes, if your configuration has a hierarchical structure. Those classes can also contain supporting methods, for example, for serializing the configuration in a file and deserializing it again.

In short, there is no special method for handling many runtime configuration parameters. The kind of model you need for configuration data is not different from a data model for any other kind of business data, and the techniques for creating such models are the same.

1

There’s no need to constrain yourself to integer IDs. Offer an interface that looks like a HashMap from strings to strings. Then it resembles the .yaml config file that your users are probably already accustomed to editing.

Case smash the keys to lower, so it’s hard for caller to mis-specify a key’s spelling.

1
  • My next question (which is opinion based) is, is it worth doing this? In other words, does it break the separation of concerns for the class to use/store its attributes AND perform the parsing of said attributes? Jan 17 at 21:26
1

A middle ground approach would be to have separate setters/getters for each attribute value type, so you only need to implement a moderate number of getter/setter pairs: setIntAttribute(AttributeId id, int value)/ int intAttribute(AttributeId id) and so on.

That way, your configuration module doesn't need to know much about the other modules, just the AttributeId enum and the possible value types, which are likely just a few (bool, int, string, maybe decimal/float).

The values could be read as strings and only be converted when accessed.

-1

Well huge configuration can become so hugely complex that it ends up becoming its own language. Thats how the Lua scripting language was born.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.