This is more than just naming things. It’s also that Ruby allows you to monkeypatch _any_ method, even if it’s a Kernel method or already defined by a library or framework (like Rails).
It’s extremely powerful, which is great! But I want a linter that tells me, “Hey - you’re monkeypatching that. I’m going to fail this build unless you explicitly indicate you know what you’re doing”.
I don’t know of a convincing linter that has a complete solution to this. Feel free to chime in if you know of one! I’m guessing this is possible in Rubinius, but not sure about the standard Ruby VM.
You can create a Rubocop check that will complain abuot method_added and method_undefined. And to show that you know that you're calling them even though they're forbidden, just make a comment to tell Ruboocop to ignore. And make sure commits are code-reviewed, of course.
This doesn't really touch on what I think of when I think of "naming things is hard", which is not really technical or language-specific so much as semantic. When you name an abstraction (object, enum value, function name, etc) you are baking in assumptions about that abstraction that may not make sense a few years down the line. When the user connects to the websocket server, is that a Connection or a Socket or a SocketConnection or what? If they disconnect and reconnect, is that a Connection with two Sessions, or a Session with two Connections, or something else? Can a Connection be disconnected? Etc.
Maybe those aren't great examples, but the point is, I think the problem of finding names that accurately convey the right mental picture of what the underlying abstraction is intended to do is much, much harder than just trying to avoid conflicts with names of builtins. Particularly when the app changes over time and those abstractions evolve to be used in subtly different ways the programmer didn't foresee.
>Connection or a Socket or a SocketConnection or what?
I’d say provide as much context as you feel appropriate and iterate if it’s too much or too little. That’s the problem, many developers are terrified of renaming things as they learn more. Renaming is only an issue if you have many external consumers depending on you.
>Particularly when the app changes over time and those abstractions evolve to be used in subtly different ways the programmer didn't foresee.
Perfect abstractions never go stale, they just become obsolete. TCP/UDP are timeless. Quicksort and hash tables are timeless. They are never renamed or changed. You may swap them out as necessary, but they’re complete.
The issue arises when people put too many responsibilities or contexts onto an existing thing. This manifests itself as objects with hundreds of properties or functions with dozens of Boolean flags to toggle on or off contexts. It’s a sad thing indeed.
This is one of the main reasons I push people to pull out the thesaurus. You had an idea. You tried to put it into words, and either in your excitement or at a moment of frustration your brain latched onto one and it stuck, even if it’s not quite right, or only an archaic definition means what you meant.
Often enough the thesaurus has a word that is closer to your notion, or several options that go different ways and you have to decide which you meant. As you say, once the word is picked it starts to influence the thing. If you pick a better word you get a better influence.
https://relatedwords.org/ is also pretty neat for this. It's slightly less strict than a thesaurus so it can aid in exploring the semantic space a bit more.
I like to avoid naming things in my programs to avoid baking in those sorts of assumptions.
In short functions that can be as simple as choosing a name like "_", "x", or "rtn" to indicate to future me that the thing being described isn't super well defined and is only useful insofar as it lets the containing scope do what it's supposed to.
In slightly longer sections of code I'll often just reference registers or memory offsets directly. You need some kind of identifier to access whatever it is you're working with, but if the name isn't pinned down well by English you might as well just pick your favorite number for the task.
Names are important in places, but only if they aid understanding of the code rather than (intentionally or not) subverting the reader from details that do actually matter.
Had to deal with level db dependencies in JS today... they had a VERY hard time naming packages: level, leveldb, leveldown, levelup, sublevel, subleveldown, abstract level, abstract leveldown, encoding down, classic level, level codec, memdown, memory level, ...
Today's hairball was an approved AMI for the project whose environment is so old that a newly-installed node.js binary barfed on /lib64/libc.so.6 symbols.
Couldn't even compile node.js from source, because said tool chain was three GCC point versions too old.
> Ruby on Rails follows the paradigm of Convention Over Configuration, that means that, if we name things in specific ways, and put things in specific places, the framework will do its “magic” and we’ll have all the good benefits.
> This is really powerful, it enables us to write less code and get a lot of functionality for free. It’s one of the reasons why Rails makes building new apps so easy.
> But again, there’s a catch here and we have to be careful, conventions are great but we can get unexpected behaviors if we don’t know them.
Indeed, at this point the framework is tantamount to a language unto itself. See also PHP vs. WordPress.
Further still, we get into IDEs that take over the situation, e.g. Eclipse vs. IntelliJ. Not only do we have to fret the Java distribution, but have to deal with the tooling for editing/building the code.
Nor does the problem seem to improve over time, except through one's retirement.
I've found the hard part is coming up with a good abstraction or domain model, once you have that the names are obvious. Conflicts with keywords seems minor in comparison
26 comments
[ 3.3 ms ] story [ 79.3 ms ] threadThere are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.
This is a perfect encapsulation of the feeling when naming a variable: https://twitter.com/jenmsft/status/1381006038590099456?lang=...
What always gets me is code written by someone who just goes "well, there's already `process`, so let's call this method `process2`".
It’s extremely powerful, which is great! But I want a linter that tells me, “Hey - you’re monkeypatching that. I’m going to fail this build unless you explicitly indicate you know what you’re doing”.
I don’t know of a convincing linter that has a complete solution to this. Feel free to chime in if you know of one! I’m guessing this is possible in Rubinius, but not sure about the standard Ruby VM.
You can create a Rubocop check that will complain abuot method_added and method_undefined. And to show that you know that you're calling them even though they're forbidden, just make a comment to tell Ruboocop to ignore. And make sure commits are code-reviewed, of course.
What more could you want?
Phil was killed in an auto accident in Italy, as I recall. I thought he was one of the authors of this:
https://www.cs.unm.edu/~cris/481/redell-pilot.pdf
but apparently not.
Otherwise I've far too often heard this excuse to justify poorly written code in dire need of a refactor.
Maybe those aren't great examples, but the point is, I think the problem of finding names that accurately convey the right mental picture of what the underlying abstraction is intended to do is much, much harder than just trying to avoid conflicts with names of builtins. Particularly when the app changes over time and those abstractions evolve to be used in subtly different ways the programmer didn't foresee.
I’d say provide as much context as you feel appropriate and iterate if it’s too much or too little. That’s the problem, many developers are terrified of renaming things as they learn more. Renaming is only an issue if you have many external consumers depending on you.
>Particularly when the app changes over time and those abstractions evolve to be used in subtly different ways the programmer didn't foresee.
Perfect abstractions never go stale, they just become obsolete. TCP/UDP are timeless. Quicksort and hash tables are timeless. They are never renamed or changed. You may swap them out as necessary, but they’re complete.
The issue arises when people put too many responsibilities or contexts onto an existing thing. This manifests itself as objects with hundreds of properties or functions with dozens of Boolean flags to toggle on or off contexts. It’s a sad thing indeed.
Often enough the thesaurus has a word that is closer to your notion, or several options that go different ways and you have to decide which you meant. As you say, once the word is picked it starts to influence the thing. If you pick a better word you get a better influence.
In short functions that can be as simple as choosing a name like "_", "x", or "rtn" to indicate to future me that the thing being described isn't super well defined and is only useful insofar as it lets the containing scope do what it's supposed to.
In slightly longer sections of code I'll often just reference registers or memory offsets directly. You need some kind of identifier to access whatever it is you're working with, but if the name isn't pinned down well by English you might as well just pick your favorite number for the task.
Names are important in places, but only if they aid understanding of the code rather than (intentionally or not) subverting the reader from details that do actually matter.
Couldn't even compile node.js from source, because said tool chain was three GCC point versions too old.
[sigh goes here]
> This is really powerful, it enables us to write less code and get a lot of functionality for free. It’s one of the reasons why Rails makes building new apps so easy.
> But again, there’s a catch here and we have to be careful, conventions are great but we can get unexpected behaviors if we don’t know them.
Indeed, at this point the framework is tantamount to a language unto itself. See also PHP vs. WordPress.
Further still, we get into IDEs that take over the situation, e.g. Eclipse vs. IntelliJ. Not only do we have to fret the Java distribution, but have to deal with the tooling for editing/building the code.
Nor does the problem seem to improve over time, except through one's retirement.
Ideally, it looks at your code and your makeshift name, and suggests other names to consider.