I'm working on a library of C++ wrappers/bindings, for another, C-ish, API.
The C'ish API has a "launch" function, which, among other things, takes a launch configuration structure (well, sort of, I'm simplifying things). Not every point in the space of values for this structure is valid. For example, it has a num_widgets field, which is integral, but a system only has a limited number of widgets, so if you exceed it - the launch will fail.
It's cumbersome for the user to just up'n'construct a full-fledged launch configuration. So, I provide a builder class which helps the user do it more conveniently and easily. The builder has methods for making all sorts of setting, such as setting the number of widgets, and a build method which produces a launch configuration.
Finally, one of the design goals of my wrapper class is to avoid excessive use of the underlying API, and perhaps even to minimize such excessive use. Not that using it is prohibitively expensive, but still.
Now for my question:
Should my build() method - or even earlier methods which set the number of widgets - check, as soon as is possible, that there are enough widgets on the system for the configuration to be usable? Or, alternatively, should I just let the user build what they asked for, and have the launch itself fail due to the invalid config? With the second alternative, note that I could furnish the builder with some sort of a validation method which could look this up.
I'm interested in what is customary in similar or somewhat-corresponding scenarios, and what users would are more likely to expect.
Notes:
- Assume that nobody builds launch configurations for use on other systems via serialization, or for simulation of other systems etc.
- There are no abstract and concrete builders, there's just one builder class and that's it.
- My library relies on C++11 or later being used, but I don't think that matters.
- The underlying API's launch function will reject an invalid configuration, but will often not tell you why it was rejected.