I've written a lot of code in the boost/standard library style.
I've become increasingly annoyed at naming my variables when coding in
this style.
Looking to the standard library implementations for guidance isn't much
help as they often use conventions like local variables are named with a
leading double underscore and member variables are named with a leading
underscore and capital letter. I.E. things I'm not allowed to do as I'm
not a standard library implementer.
Good names are generally taken by types leading to distress when trying
to name objects and functions.
Here's a concrete example:
// type takes the most natural name
enum class format {
rgba,
rgb,
float // enum value wants reserved name
};
class image {
public:
// getter wants the same name
format format() const noexcept
{ return this->format; }
// setter wants the same name
void format( format format ) noexcept
// parameter wants the same name
{ this->format = format; }
private:
// member variable wants the same name
format format;
};
format bits_to_format( int bits )
{
// local variable wants the same name
format format = format::rgba;
if ( bits == 24 ) {
format = format::rgb;
}
return format;
}
// unrestricted template parameter does *not* want the same name
template< typename Format >
std::ostream& print_format( std::ostream&, Format format );
// Concept template parameter *does* want the same name
template< Format Format >
std::ostream& print_format( std::ostream&, Format format );
What I end up doing right now is something like:
// type takes the most natural name
enum class format {
rgba,
rgb,
float_ // add trailing underscore to reserved name
};
class image {
public:
// prefix getter with get_
format get_format() const noexcept
{ return _format; }
// prefix setter with get_
void set_format( format format_ ) noexcept
// trailing underscore on parameter
{ _format = format_; }
private:
// leading underscore on member
format _format;
};
format bits_to_format( int bits )
{
// cutesy abbreviation for local variable
format fmt = format::rgba;
if ( bits == 24 ) {
fmt = format::rgb;
}
return fmt;
}
template< typename Format >
std::ostream& print_format( std::ostream&, Format format_ );
// cutesy abbreviation for constrained template type
template< Format Fmt >
std::ostream& print_format( std::ostream&, Fmt format_ );
Having to come up with cutesy abbreviations for every local variable
that are still meaningful is especially distracting.
Surely enough code has been written that this has been solved.
I looked through several boost library implementations but didn't see
anything that stuck out as a clear convention.
Adobe's ASL library seems to append _t postfix to type names and _m
postfix to member variables.
They also use very terse names for template parameter type names as well
as parameter names and local variables. Like in:
template
On 7/03/2016 08:38, Michael Marcin wrote:
I've written a lot of code in the boost/standard library style. I've become increasingly annoyed at naming my variables when coding in this style.
While not necessarily completely in keeping with Boost style, these are my thoughts on it:
// type takes the most natural name enum class format {
This is not the most natural name, because you've lost context. It should be image_format or similar. This incidentally fixes most of your other issues as well. (It gets a bit more problematic if you make this a nested type of the "image" class, because then the natural name does become "format". This is probably an argument to avoid doing that.)
rgba, rgb, float // enum value wants reserved name
How about "floating" instead? It's usually not hard to come up with alternatives to keywords without using funky punctuation.
// getter wants the same name format format() const noexcept { return this->format; }
// setter wants the same name void format( format format ) noexcept // parameter wants the same name { this->format = format; }
Methods should typically be verbs and types should be nouns, which usually lets you avoid this. It's only problematic in cases like this where the noun and the verb are spelled identically. However renaming the type as above gets you out of this hole as well.
// member variable wants the same name format format;
Typically member fields (especially where private) ought to have a prefix/suffix. I generally subscribe to the "m_" prefix school of thought for these. Although it's not strictly necessary if you're following the explicit "this->" convention instead -- but while the compiler can readily distinguish between "this->format" member and "format" parameter inside a method, I don't like code like this as it's too error-prone for humans (both to read and to write). This is another reason I prefer the style where the type is "image_format", the parameter is "format", and the member is "m_format" (without "this->", although you can keep that if you prefer).
On 2016-03-06 22:38, Michael Marcin wrote:
I've written a lot of code in the boost/standard library style. I've become increasingly annoyed at naming my variables when coding in this style.
[snip]
What's your preferred convention? If possible please answer by modifying the initial concrete example and providing annotations.
// type takes the most natural name enum class format { rgba, rgb, floating_point, // avoid reserved keywords when possible float_ // ...or add a trailing underscore when not }; class image { public: // use a verb to form method names format get_format() const noexcept { return m_format; } // typically use an abbreviation for argument // and local variable names void set_format( format fmt ) noexcept { m_format = fmt; } private: // use m_ prefix for member variables format m_format; }; format bits_to_format( int bits ) { format fmt = format::rgba; if ( bits == 24 ) { fmt = format::rgb; } return fmt; } // I used to use the T suffix for typename template parameters template< typename FormatT > std::ostream& print_format( std::ostream&, FormatT fmt ); // ...and V for non-type template parameters, but I'm in the // process of dropping it template< format FormatV > std::ostream& print_format( std::ostream& ); // I'm not using concepts but I guess the suffixes would work template< Format FormatT > std::ostream& print_format( std::ostream&, FormatT fmt );
participants (3)
-
Andrey Semashev
-
Gavin Lambert
-
Michael Marcin