Hacker News new | ask | show | jobs
by jboy 3644 days ago
This article is a good start, but I found it much too light on detail. Each section ended just when I was ready for it to dive into details! For example, in the final section "Make it easy to digest":

> Using prefixes in names is a great way to add meaning to them. It’s a practice that used to be popular, and I think misuse is the reason it hasn’t kept up. Prefix systems like hungarian notation were initially meant to add meaning, but with time they ended up being used in less contextual ways, such as just to add type information.

OK, great, I agree -- but what are some suggestions/examples of good prefixes? What are some examples of bad prefixes that we should avoid?

To illustrate the sort of detail I'd like to read, here is an example of my own of good/bad method names that would be greatly improved by judicious use of prefixes.

My standard go-to example for ambiguous naming is the std::vector in the C++ STL. There is a member function `vec.empty()`: Does this function empty the vector [Y/N]? Answer: No, it doesn't. To do that, you instead use the member function `vec.clear()`. There is no logic a priori to know the difference between `empty` & `clear`, nor what operation either performs if you see it in isolation. You must simply memorize the meanings, or consult the docs every time.

In the C++ style guides I've written, I've always encouraged the prefixing of member function names with a verb. Boolean accessors should be prefixed with `is-`. The only exception should be non-boolean accessors such as `size` (which has its own problems as a name). Forcing non-boolean accessors to be preceded by a verb invariably results in names like `getSize()`, where `get-` adds no useful information, clashes with the standard C++ naming style for accessors, and really just clutters the code with visual noise.

Using these prefixes: (depending upon your project's preference for underscores or CamelCase)

  .empty -> .isEmpty() or .is_empty()
  .clear -> .makeEmpty() or .make_empty()
As an additional benefit, the use of disambiguating prefixes also enables the interface designer to standardize upon a single term "empty" to describe the state of containing no elements in the vector, rather than playing the synonym game ("empty", "clear", etc.). The programmer should not need to wonder whether "clear" empties a vector in a different way.
1 comments

is_emtpy and make_empty are just going to irritate every C++ programmer in the business, since all the STL containers use empty and clear.
Some C++ programmers, perhaps. But I've just explained why `empty` & `clear` are ambiguous. Even if `empty` & `clear` can never be removed from the STL containers, there's no requirement that these ambiguous names must be propagated to new code.

But focusing exclusively on these two names is missing the forest for the trees. These two names are just a particularly striking example that illustrates the benefit of prefixes. A codebase that applies useful prefix naming will be an easier codebase to understand.

And applying prefix naming consistently will also make it easier for a new developer to contribute to a codebase, since there will be no ambiguity about what to name new functions, nor what to expect them to be named. `is_empty` & `make_empty` would simply be part of that consistency.

I agree with you, but honkhonkpants raises a good point - sometimes you must bow to existing convention, even if it doesn't meet current best practice.
"Sometimes you must bow to existing convention" is indeed a reasonable point, so I suppose I should clarify/refine my position.

If you're implementing an STL-like container in C++, then absolutely -- you should stick with the convention: `empty`, `clear`, `size`, etc. To deviate from that convention would be an exercise in confusing the users of your code. You should make a note in the class comment that it deviates from any other project-wide naming scheme because it conforms to the STL container interface, and move on.

But if you're creating a C++ class that is NOT intended to be an STL-like container (or if you're not working in C++!), then I'd argue that it would be better to go with `is_empty` & `make_empty` (if you're applying this prefix naming scheme across the rest of your codebase) for the benefits I've described above.

I think make_clear is just not good style. It conflicts in meaning with std::make_unique, which allocates a std::unique_pointer. When I see make_clear I think it allocates a new, empty object.