Should my program's “services” be responsible

2020-07-22 09:35发布

问题:

My program consists from several "services" (I'm not talking about SOA, so don't get confused), and each of these "services" is using some configuration (for example, a directory path). This configuration should be read from a configuration file, as they tend to change (without changing the program's logic, that is).

So my question is this - Should each "service" receive its configuration when invoked, or should it be responsible for getting its own configuration?

This question is actually very similar to this question, only mine is more specific about these:

  • My program's "services" aren't generic, and aren't supposed to be re-used by another. They already use generic tools, and their functionality is to simply connect between those tools. This means that it is not immediately obvious for them to receive their configuration, as their target is very clear and direct.
  • The target of these "services", being clear and direct, sometimes requires more than one action. This means that my "services" aren't necessary responsible for only one action (although you might separate between logic and preparations such as configuration).

Thanks.

回答1:

I would advocate a combination of these approaches, as long as you manage to implement it in an elegant way (I have seen this done in both elegant and horrendous implementations):

  • Have a data structure for configuration that can implement settings sub-sets (in Perl it is extremely simple with super-imposed hashes, in other languages it's a bit more wordy but overlaying maps on top of each other works as well). To try to be more precise, your data structures will be

    • A global Singleton Configuraton map

    • A "passed as parameter" local configuration map

  • Have a Configuration loader class, which can:

    • Take "passed as parameter" local configuration map

    • Take a set of keys needed by the component

    • Superimpose the local map onto global configuration map

    • Allow the components to query out the values from combined map.

  • This way, each caller of the services has a complete freedom to either live in a worry-free word and let each service take care of its own configuration needs, or for a more controllable behavior, has an option of passing specific configuration settings it wants to control to the service (either creating the settings values by hand, or cloning data subset from global configuration and adjusting it).

This has major testing benefit, since the test framework can pass specific configuration local overrides needed for each test.



回答2:

It sounds like your application is more a service than a tool (that is expecting to be loaded with different config options), So for anything but the most simplest configuration options I would say yes.

As your service gets more complex it will undoubtedly have a lot of configuration options, like db connection strings, external service urls, cache providers etc, smtp hosts, etc. After a while you're only going to be able to test it with a pre-set number of configurations options, you might as well save this in a config file and distribute it with the application.

For services that require dynamic configurations I normally send a 'refresh config' message to my service, essentially telling it to safely reload with the new configuration.