> On June 2, 2015, 3:38 p.m., Marco Massenzio wrote:
> > 3rdparty/libprocess/3rdparty/stout/include/stout/flags/flags.hpp, line 184
> > <https://reviews.apache.org/r/34943/diff/1/?file=976658#file976658line184>
> >
> >     too much choice, IMO - there are (if I counted them right) 8 different 
> > `add()` variants to choose from (none of them documented :)
> >     
> >     It's virtually impossible for folks to figure out which to pick and 
> > this leads, I believe, to the current 'code by copying' approach.
> >     
> >     I would cull it down to no more than 2-3 different options, with some 
> > sensible default values.
> 
> Benjamin Hindman wrote:
>     I completely agree this needs documentation, which I'll take on in a 
> different review. But there are really only 4 variants here:
>     
>     (1) The flag _is_ a class member.
>         (A) The flag has a default value (i.e., is _not_ an Option<T>).
>         (B) The flag does not have a default value (i.e., _is_ an Option<T>).
>     
>     (2) The flag is _not_ a class member.
>         (A) The flag has a default value (i.e., is _not_ an Option<T>).
>         (B) The flag does not have a default value (i.e., _is_ an Option<T>).
>     
>     All 4 of these options can optionally have a validation function, but 
> since we can't capture the default validation function with the existing 4 
> functions we have to do the delegating function trick, resulting in 8 
> functions. Bottom line, this needs to be documented (and if someone has a 
> better suggestion to avoid the delgating function trick I'm all ears).

Why should the callers care if it has a default value, type-wise?

My thinking was, let's always use an `Option<T>` for the flag; a, possibly 
`None()`, default value and a `required` bool flag:
```
template<typename T>
void add(Option<T>* option, 
         const std::string& name, 
         const std::string& help,
         const Option<T>& const default = None(),
         bool required = false)
```
and similarly for the class member.

So, all we have are *two* options, and no doubt as to which one to use.
I'm sure I'm missing a ton here, though... especially given that:

```
  Option<string> foo;
  Option<string> bar;

  Option<string> def_foo{"default-foo-val"};

  flags.add(&foo, "foo", "this is foo!", def_foo, true);
  flags.add1(&bar, "bar", "this is BAR");
```
works as intended, but:
```
flags.add(&foo, "foo", "this is foo!", "default-foo-val", true);
```
causes a compile error (even though, I can totally see an `Option(const T& _t)` 
constructor that should "just work" (as it very much does for `def_foo`).


> On June 2, 2015, 3:38 p.m., Marco Massenzio wrote:
> > 3rdparty/libprocess/3rdparty/stout/tests/flags_tests.cpp, lines 500-504
> > <https://reviews.apache.org/r/34943/diff/1/?file=976659#file976659line500>
> >
> >     so, with your approach, everyone, every time that they add a required 
> > flag, will have to, essentially, copy & paste this code.
> >     
> >     what I had envisioned, was a simpler way (eg, by adding a `bool 
> > required = false` arg) that, if true would automatically do this validation 
> > step in `FlagsBase`
> >     
> >     (of course, we could add another `add()` method that has that 
> > signature, that just internally implements this and calls one of the other 
> > `add()` ones - making it the ninth option :) )
> 
> Benjamin Hindman wrote:
>     I wasn't trying to solve the "required" flag problem, I was just trying 
> to show an example of a validation function. But I violently agree that this 
> is therefore a horribly bad example that sets a bad precedent, so I've 
> replaced this with a different validation function.
>     
>     I also agree that we should introduce a simplier way, such as a bool as 
> you suggested (or better an an enumeration). This doesn't completley solve 
> the problem, however, since a flag without a default value will still be an 
> Option and still require one to do 'CHECK_SOME(flags.flag)'. Got any other 
> ideas?

> horribly bad example
I never said that :)

As mentioned above, a flag should *always* be an `Option<T>` with the 
difference that, if we had marked it as `required` then we'd be confident that, 
once loaded, it does have a value (so, no need to `CHECK_SOME()`) or it would 
have already failed.

For the optional (aka `non-required`) ones (without a default value) obviously 
they could be `None()` but that is an "expected outcome" and the caller can 
take whatever action they deem appropriate.

>From the 'client' perspective:

1. I told you it was `required` --> there must be a value (or you'd have failed 
before getting back to me)
2. I gave you a default value --> there must be a value (possibly the default 
one)
3. It's neither required, nor has a default --> its absence (`isNone() == 
true`) has a meaning to me and I'll take appropriate action
4. It's required, and I gave you a default value --> I'm bad at logical 
thinking ;-)

I would also propose (similarly to the --help case) to add an 
`onMissingRequired()` "hook" with the default implementation 
```
void onMissingRequired(const string& name)
{
  exit(EXIT_FAILURE) << usage("Missing required flag --" + name);
}
```
so that the caller can also take some alternative action.


- Marco


-----------------------------------------------------------
This is an automatically generated e-mail. To reply, visit:
https://reviews.apache.org/r/34943/#review86225
-----------------------------------------------------------


On June 5, 2015, 2:48 p.m., Benjamin Hindman wrote:
> 
> -----------------------------------------------------------
> This is an automatically generated e-mail. To reply, visit:
> https://reviews.apache.org/r/34943/
> -----------------------------------------------------------
> 
> (Updated June 5, 2015, 2:48 p.m.)
> 
> 
> Review request for mesos.
> 
> 
> Repository: mesos
> 
> 
> Description
> -------
> 
> Also refactored existing 'lambda::bind' arguments to use C++11 lambdas, 
> enabling us to get rid of our "loader" and "stringifier" functors.
> 
> 
> Diffs
> -----
> 
>   3rdparty/libprocess/3rdparty/stout/include/Makefile.am 
> 6ac2f04a6a1d8db1725972a3b4b46a0dd734566f 
>   3rdparty/libprocess/3rdparty/stout/include/stout/flags/flag.hpp 
> 87606d860dea3235ec70d127d3379065d42dc90b 
>   3rdparty/libprocess/3rdparty/stout/include/stout/flags/flags.hpp 
> ee855da6128c2d671eb2fc7eaa2c0aab2341aebb 
>   3rdparty/libprocess/3rdparty/stout/include/stout/flags/loader.hpp 
> 51d3ab020bd2bae1f12b66cac0da5383c813d5d7 
>   3rdparty/libprocess/3rdparty/stout/include/stout/flags/stringifier.hpp 
> fda5ae1328a23a4371475652f921341dce7448d5 
>   3rdparty/libprocess/3rdparty/stout/tests/flags_tests.cpp 
> 80450185f60c5b273face490e0bb9e695b0cb984 
> 
> Diff: https://reviews.apache.org/r/34943/diff/
> 
> 
> Testing
> -------
> 
> make check
> 
> 
> Thanks,
> 
> Benjamin Hindman
> 
>

Reply via email to