0

I'm dealing with creating a few internal libraries for a project that can offload emails and logs to a queue (Service bus, storage queue).

The issue I'm having is how to configure the the queueing endpoint, without passing it in, which would require the projects using said library to be aware of the queue endpoint as well. The other option would be to pass in the environment and switching to the URL from there inside the library, which would have those values hard coded.

Is there a better pattern? Should I be hitting yet another centralized service to get this endpoints so no one is required to know the value?

Thank you!

3 Answers 3

3

How much configurability a software requires, and how much hardcoding of such parameters is acceptable depends highly on the way how the software will be operationally used.

For example, do you expect a potential need to change endpoints during your holidays? Then make them configurable, so operations don't have to ask you to change the libraries during your vacation. Maybe a simple configuration file per lib or service is enough, you have to work this out with the colleagues from operations.

Or do you expect the requirement to change the same endpoint shared by a dozen services, simultanously, for keeping the downtime next to zero during operation? Then a centralized service would start making sense, otherwise it looks pretty overengineered to me.

So clarify your goals! Configurability is not an end in itself, it is a means to an end.

4
  • Thanks Doc Brown. The issue I can see is this is probably going to be an internal nuget package. So updating the URL, and having it go into effect would require all projects using said package to update as well. I don't believe the URL would change, unless something unexpected happens! Jun 14, 2022 at 14:02
  • 2
    @KryptoBeard: as I wrote, it is a question of operational requirements, which only you can analyse, not strangers from the internet.
    – Doc Brown
    Jun 14, 2022 at 14:25
  • "unless something unexpected happens!" Reason enough to err on the side of flexibility
    – Ian Jacobs
    Jun 15, 2022 at 23:35
  • @IanJacobs Not at all -- developers often suck at naming things, so it's often best simply not to give them the option of choosing their own names. Flexibility can be highly detrimental and become the root cause of a mountain of technical debt and operational headaches if it leads to inconsistent and wildly uncontrolled names for things like queue names in production. Jun 17, 2022 at 12:19
2

Option 2 is fairly common in today's projects, but it's because of the frameworks. Many support configuration overloading out of the box.

A pattern of configuration overloading by source could be *:

  • Config servers
  • Env vars
  • Runtime properties
  • Command line arguments
  • Config files in the file system (local or remote)
  • Packaged config files
  • Hardcoded (default) configurations.

Basically, the framework loads these sources in reverse order. Each source adds new entries to the configuration or replaces existing ones following last to arrive, win strategy.

The last two are the ones we use in local env while coding and testing. Others are focused on supporting more execution environments over which we have no control. For example, production. This is a good way for the IT team to set sensible configurations (e.g passwords, seeds, tokens, URL, IPs, ports, etc) without sharing this information with you. In consequence, this information is unlikely to end in any repository.

A good and reasonable alternative would be making lib's code more parametrizable. Or provide with ports and adapters, so the consumer can adapt lib's configuration to its configuration solution.

Should I be hitting yet another centralized service to get this endpoints so no one is required to know the value?

Centralised remote configuration services are by any meaning one more failure point for which you must have a failover operation. One more service to be secured, maintained, monitored, etc.

Hiding information from developers should not be the reason to make configuration so complicated. These services make sense when you need control over the lib because you have none over the application implementing the lib.


* From highest to lowest priority. Usually, the external configuration has priority over the internal, but it is not an essential condition

1

As @Doc Brown said, there is no one right answer, but when it comes to libraries, I tend to err on the side of flexibility and not making decisions for the consumers of my library. What happens if another project wants to reuse this library? They wouldn't be configured the same way as your project.

To have the best of both worlds it's comparably simple to expose a couple of different extension methods for Default Options as well as an option for consumers to configure how they see fit.

It's pretty simple for all consumers to pull from a common configuration as well (KeyVault, ConfigToken, etc...) pass it in, and not have to worry about the default option in the library, so in the end it's about deciding what you want to optimize for?

  • Flexibility
  • Simplicity for consumers
  • Supportability
  • ????

Your Answer

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

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