Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Don't name packages common nouns (brandur.org)
41 points by PaulHoule on June 7, 2024 | hide | past | favorite | 38 comments


Speaking of clobbering each other, min and max are names I had used for variables and functions all over the place. Suddenly they go and add global generic min/max functions and I'm shadowing like crazy.

I still don't understand why they aren't in a package, or better yet why they didn't just make math.Min and math.Max generic?


> min and max are names I had used for variables and functions all over the place

Shadowing is better than the very questionable decisions made by whoever wrote Windows.h...

  #include <Windows.h>
  #define NOMINMAX // comment out to break
  #include <algorithm>

  auto main() -> int
  {
    return std::min(42, 1337); // may break
  }


NOMINMAX is checked in windows.h to control whether it adds the macros. It needs to be defined before the inclusion.


The windows headers are so convoluted and huge that I just copy the necessary declarations into my own mini header. It’s a bit annoying at first but saves a lot of headache later.


This one made me lose a few strands of hair years ago.


> or better yet why they didn't just make math.Min and math.Max generic?

I don't know Go, but my first thought would go to lol no generics. Now that they do have generics I guess they could do it, but backwards compatibility may require them to use other names than `math.Min` and `math.Max`.

(Note: Go did have some generic built-in constructs from the start, and could have included `min` and `max`, similar to how OCaml did it. At the same time, you don't want too many primitives in your language if you can help it.)


C++ programmers have had this problem in win32 since C++14 when they added std::min and std::max, whereas MSVC has offered those as built in functions since the 1990s


This has long been a problem with win32 and windows.h. Search for "NOMINMAX". They're preprocessor definitions, so you can't even shadow them.


AMEN! I have been tired of packages, coding languages, everything being common nouns that don't even care if they duplicate each other for a long time. Mostly because it's confusing but this particular complaint gets me a lot. I'm glad to see someone else talking about this.


on the other hand, we should be able to search by concept


That could be done base on metadata like description, tags or categories.


In retrospective, I think it's obvious that Go's decision to have package and variable names be in the same namespace was a mistake. It is the main reason why people overuse single letter variable names, and have debates such as the one in the linked post.

I am guessing that using a different operator (e.g. rate::NewLimiter()) was deemed inelegant, but it would have avoided a whole set of problems.


retrospective? It was one of the first silly gotchas I hit picking up the language. And the stdlib authors chose those package names!

It's funny how when I was using Go, I couldn't wait until it got generics (which was only a matter of time despite the party line). When it finally got them, I was versed enough in the edges and nature of the language/ecosystem that I didn't really care anymore and moved on. I am glad that Go rose to popularity because it brought to light opinions that weren't all that popular: memory layouts matter and error values (rather than exceptions). I still prefer a sound type system over nil/zero values though.


Totally agree, it’s a bit of a strange design choice. I’d be curious to read about the tradeoffs made here, as it must have come up while developing the language.


Agree with it or not, it’s recommended by the docs:

> It's helpful if everyone using the package can use the same name to refer to its contents, which implies that the package name should be good: short, concise, evocative. By convention, packages are given lower case, single-word names; there should be no need for underscores or mixedCaps.

https://go.dev/doc/effective_go#names

Maybe the convention of single-letter variable names was meant to play nicely with this too (again, agree with it or not).

Can’t say I really care about this issue that much, it’s occasionally a slight nuisance, but show me a programming language that doesn’t have the occasional slight nuisance.

An explicit scope resolution operator would be a better solution than forcing package name changes, as called out by another commenter. Maybe that was left out to keep it simple? If anyone knows of a Go blog post about the decision to omit this feature I’d be curious to see it!


Counterpoint: His variable name of rate isn't really descriptive, which is almost worse than the package naming complaint.

What kind of rate? Time or volume or...something else entirely? Otherwise, the variable will be scoped within a function and go doesn't really promote global variables as a best practice.


FWIW, all my internal packages are suffixed with an x.

logx, errorx, typex, metricx...

They read just like "s" so it reads like the plural of their word, but conflicts are much rarer (there's plenty of "types" packages).

It also tells me which package is mine or third-party immediately.


Python 4 should implement namespaces that make it trivially easy to differentiate between local and external modules.


I guess I get it, but if you can alias the package name when you import then it seems like a non-issue.


They address that in the article, saying "but given this will be such a common problem for all the package's users, why make them do this?"

I agree, I don't think the default for a package should be a footgun. Or in the words of Michael Bolton "why should I change? He’s the one who sucks.”


I once worked under someone who felt strongly about us importing modules instead of classes. So instead of

    from sklearn.feature_extraction.text import TfidfVectorizer
    tfidf = TfidfVectorizer()
we were told to change it to

    from sklearn.feature_extraction import text
    tfidf = text.TfidfVectorizer()
to be compliant. Guess what variable name everyone used to store document text in every file.

Until this article, I always blamed this on the decision to blindly import modules instead of... well... whatever makes sense. Now I'm realizing if we all avoid common names for packages then this whole class of issue goes away.


> Until this article, I always blamed this on the decision to blindly import modules instead of... well... whatever makes sense. Now I'm realizing if we all avoided common names for packages then there would not have been an issue.

If your solutions depends on others to "do the right thing", it often isn't a viable solution.

However, how you import something in your own files, is something you most likely control.


Having a global style policy (for imports) doesn't seem like relying on others to "do the right thing". It's just style and is completely arbitrary.

Someone probably encountered a problem with having a mishmash of ways people do imports and thus began the policy. It's the type of policy where someone heaved a great big sigh and said, "this is why we can't have nice things."


I was specifically referring to the "Now I'm realizing if we all avoided common names for packages then there would not have been an issue" part as relying on others to do the right thing.

Having a internal policy about how to import something wouldn't be relying on others to do the right thing.


> Now I'm realizing if we all avoid common names for packages then this whole class of issue goes away.

The issue also just goes away if you just do it yourself with pretty much no effort:

    from sklearn.feature_extraction import text as feat_text
    tfidf = feat_text.TfidfVectorizer()


This is one of the benefits of having all your libraries/modules in a monolithic repo: You can refactor the names of everything pretty easily. It'd be a BIG commit but it's still a trivial task to rename something like `text` to `textual` or `text_anal` everywhere it's being used.

I've done it before. It's the type of thing where you'll find out immediately if you screwed up somewhere but modern IDEs usually do a pretty good job at such things (the free version of PyCharm will do it real fast and then you never have to open it again if it's not your thing).


Misses one other important point: if you search for a common name you will get results from all over. If the name isn't a common noun any search engine can find relevant results.


What an absolutely pointless gripe. And they wrote a whole blog about it...

Alias the package name or change your variable name.

Or don't use the package at all if the name upsets you that much.


The Go language is full conventions like this that are put on the programmer to make up for shortcomings brought about by the simplicity of the language.


My preference is common nouns, generally it's the most concise and precise naming, I understand the issue in Go however, so the argument carries weight. What I would say is redundant verbosity is a fair halfway house.

Namespacing in languages such as Rust (modules) are probably most favourable to me, i.e. f64::min/max ~ u64::min/max or a hypothetical crypto::rand() math::rand().


Also, in the spirit of inclusion & not making people uncomfortable suggesting certain packages, don't name them ... well, I don't know how to call this, but here's an example:

https://www.npmjs.com/package/clit


> Variable names in Go are camel case, so ratelimit will never clobber a variable name. Even if it that wasn’t the case, having variables called rate, limit, or rateLimiter is plausible and even likely, but ratelimit? Not a thing.

Not to say it invalidates the whole article or anything, but in what world would "ratelimit" never be used as a variable name? That still feels like a fairly reasonable name for a variable if we're ignoring the camel-case requirement.


The idea here is that many programmers would call it rateLimit, if they use CamelCase naming. If they don't, at least they can just switch to camelcase once they realize the issue, while that is not an option for single noun names


I think this falls under the category of "Don't be cute if you expect what you write to be used by many".


How about a sigil like $ for variables then. ;)


I wonder if this only counts for variable names in English? For example, if you're making a package that you would name, 'rate' perhaps translate that to a different language before naming your package. Examples:

    tasa - Spanish
    uku - Hawaiian
    sats - Danish
...or just be clever and call it something like 'irate' (the Apple version? haha).


I like how formatters took everyone’s opinions about formatting and dismissed them as invalid. Hopefully LLMs can do the same for names.


While you're at it, please try to make LLMs fix caching and off-by-one bugs too.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: