> 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
>
>