> On Jan. 29, 2015, 5:50 p.m., Alexander Rukletsov wrote:
> > src/master/contender.cpp, line 82
> > <https://reviews.apache.org/r/30395/diff/1/?file=839643#file839643line82>
> >
> >     You can safely omit trailing underscores.
> 
> Michael Park wrote:
>     In this case, yes that is true. This topic has come up before and perhaps 
> it's better suited for the dev list so that we can get a community-wide 
> consensus on this.
>     
>     In general, I think we should try to avoid shadowing. *Especially* 
> between local variables (including function parameters) and member variables 
> because the member variable declarations are typically lexically not in scope.
>     
>     1)
>     
>     ```
>     struct Obj
>     {
>       // Original author: "Eh, we don't need to refer to the member 'foo' so 
> this is fine."
>       Obj(Foo &&foo)
>           : foo(std::move(foo)) {}
>       
>       Foo foo;
>     };
>     ```
>     
>     ```
>     struct Obj
>     {
>       Obj(Foo &&foo)
>           : foo(std::move(foo)) {
>         // New author: "ok, let's do some stuff with member 'foo'!"
>         // Oops... this will segfault.
>         std::cout << foo << std::endl;
>       }
>       
>       Foo foo;
>     };
>     ```
>     
>     2)
>     
>     ```
>     // Original author: "There's a member 'foo' but I don't need it for this 
> function."
>     Obj::F(const Foo &foo) {
>       // Do stuff with local 'foo' ...
>     }
>     ```
>     
>     ```
>     Obj::F(const Foo &foo) {
>       // Do stuff with local 'foo' ...
>       // /* ... */
>       // New author: (middle of debugging) "What state is (member) 'foo' 
> in...?"
>       // Local 'foo' gets printed instead, doesn't realize the problem until 
> they look above
>       // to find the shadowed variable and... fury.
>       std::cout << foo << std::endl;
>     }
>     ```
>     
>     In short, I think we should opt to stay away from running into issues 
> like this by not shadowing member variables.
>     It keeps us away from running into stupid bugs that waste developer's 
> time, and also eliminates the need to reevaluate if the names of variables 
> need to be changed when adding new code.

Some examples from the codebase of existing shadowing and problems which could 
be encountered working / refactoring around them.

stout/json.hpp: 
```
inline Value convert(const picojson::value& value)
{
  if (value.is<picojson::null>()) {
    return Null();
  } else if (value.is<bool>()) {
    return Boolean(value.get<bool>());
  } else if (value.is<picojson::value::object>()) {
    Object object;
    foreachpair (const std::string& name,
                 const picojson::value& value,
                 value.get<picojson::value::object>()) {
      object.values[name] = convert(value);
    }
    return object;
  } else if (value.is<picojson::value::array>()) {
    Array array;
    foreach (const picojson::value& value,
             value.get<picojson::value::array>()) {
      array.values.push_back(convert(value));
    }
    return array;
  } else if (value.is<double>()) {
    return Number(value.get<double>());
  } else if (value.is<std::string>()) {
    return String(value.get<std::string>());
  }
  return Null();
}
```
The foreachpair creates a second value which it uses in the assignment. Yes, 
this works right, but when scanning over the code if I don't catch that there 
was an additional definition embedded in the foreach...

stout/flags.hpp:
```
template <typename Flags, typename T1, typename T2>
void FlagsBase::add(
    T1 Flags::*t1,
    const std::string& name,
    const std::string& help,
    const T2& t2)
{
  Flags* flags = dynamic_cast<Flags*>(this);
  if (flags == NULL) {
    ABORT("Attempted to add flag '" + name + "' with incompatible type");
  } else {
    flags->*t1 = t2; // Set the default.
  }

  Flag flag;
  flag.name = name;
  flag.help = help;
  flag.boolean = typeid(T1) == typeid(bool);
  flag.loader = lambda::bind(
      &MemberLoader<Flags, T1>::load,
      lambda::_1,
      t1,
      lambda::function<Try<T1>(const std::string&)>(
          lambda::bind(&parse<T1>, lambda::_1)),
      name,
      lambda::_2);
  flag.stringify = lambda::bind(
      &MemberStringifier<Flags, T1>,
      lambda::_1,
      t1);

  // Update the help string to include the default value.
  flag.help += help.size() > 0 && help.find_last_of("\n\r") != help.size() - 1
    ? " (default: " // On same line, add space.
    : "(default: "; // On newline.
  flag.help += stringify(t2);
  flag.help += ")";

  add(flag);
}
```
If the delegated add had been written inline (flags[flag.name] = flag), then 
things wouldn't work right...


stout/os/killtre
```
inline Try<std::list<ProcessTree> > killtree(
    pid_t pid,
    int signal,
    bool groups = false,
    bool sessions = false)
{
  ...

  while (!queue.empty()) {
    pid_t pid = queue.front();
    queue.pop();
    
    ...
    
  }
}
```
If I need to modify the code inside the while loop to do something like exclude 
the original PID to resolve some sort of bug, I will have to rename a lot of 
variables for a small change in functionality. Most likely I won't notice that 
pid became even more local, and will first spend a while debugging why the code 
"Reads" right but doesn't do what it reads as.


- Cody


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


On Jan. 29, 2015, 3:58 a.m., Cody Maloney wrote:
> 
> -----------------------------------------------------------
> This is an automatically generated e-mail. To reply, visit:
> https://reviews.apache.org/r/30395/
> -----------------------------------------------------------
> 
> (Updated Jan. 29, 2015, 3:58 a.m.)
> 
> 
> Review request for mesos and Benjamin Hindman.
> 
> 
> Bugs: MESOS-1806
>     https://issues.apache.org/jira/browse/MESOS-1806
> 
> 
> Repository: mesos-git
> 
> 
> Description
> -------
> 
> etcd master contender + detector
> 
> 
> Diffs
> -----
> 
>   src/etcd/etcd.cpp PRE-CREATION 
>   src/master/contender.hpp 76beb5f973ae02507849233b6d73c43293669489 
>   src/master/contender.cpp c1bf82b621d6b46afe001acafe9ee53336726406 
>   src/master/detector.hpp 2905e2b3536e14e9df3570da172603e6ed81aae1 
>   src/master/detector.cpp 700eb9dde8e71648bacc00a82766634f77cf2d15 
> 
> Diff: https://reviews.apache.org/r/30395/diff/
> 
> 
> Testing
> -------
> 
> 
> Thanks,
> 
> Cody Maloney
> 
>

Reply via email to