1. Don't try and name things too eagerly. Naming is, if anything, the beginning of abstraction. As soon as something gets a name, it brings in mental baggage from everyone that reads it. Bad names lead to bad abstractions everywhere else.
1.1. When you're writing software, you probably have no idea what you're doing. You don't understand what you're trying to build, what the right shape, organization, style of code is for the domain you're trying to work with. Bad names are usually evidence of someone misunderstanding what they were building at an earlier time in the development process. But then the name stuck because everyone was using it... so the bad names proliferate.
1.2. So if anything, prefer a screamingly awful name that completely misses the mark than one that is full of baggage and opinion. Thingy is just fine by me.
2. If you put I in front of your interface names I will shout at you in an unkind way. This is 2019 - you don't need to use Hungarian Notation to express the type of a variable. If anything, the interface should name the general case and the implementation should name the concrete. Database could be the interface, PostgreDatabase could be the concrete type.
2.1. If your interfaces are describing behaviour (á la Go), use an agent noun based on the verb that captures the behaviour: Fetcher, JSONParser, etc.
4. Name length should be proportional to how long the variable will live, and how it's scoped. If it's just the iteration counter, i is fine. But if it is exported then I want to see a bit of verbosity.
4.1. This matters less with typed languages; I'm pretty confident I know what db is if it's declared as Database db = ...
5. Functions and method are actions - name them appropriately: fetch, read, get etc.
5.1. Name methods (and namespaced functions) fluently, taking into account the (likely) receiver name; file.write() not file.writeFile().
6. Stop trying so damn hard - you're probably giving it the wrong name anyway so come back to it tomorrow when you've had some time to think.
Edit: removed point 3 about screaming snake case for constants as I've been convinced it's just pointless
Edit: just want to point out that I pulled these out of the top of my head so I'd hate it if anyone quoted them back to me in a code review in six month's time
I am a software development engineer in test for Infosys. My job is officially to write automated tests in Selenium Webdriver. I'm also a web developer as a hobbyest
I didn't put it in the original, but I think a lot of the problem is that we give things names before we go as far as working out what they do. It's usually days or even weeks after I've written something that the right name becomes apparent - usually when I'm trying to talk about the code with someone else.
Yes - refactoring tools are your friend in this! 💯
I am a software development engineer in test for Infosys. My job is officially to write automated tests in Selenium Webdriver. I'm also a web developer as a hobbyest
I have a good example for this. I wrote a minesweeper game. I wrote a function called clearBlanks that does what it says, it clears blank squares in a contiguous region when you click on a blank. There's a function defined inside clearBlanks that I had named clear that was recursive. What it does is create an array of the squares adjacent to the ones passed in that need to be cleared.
It does not actually clear them. They get cleared after the recursion is complete and the array is returned back to the clearBlanks function that actually does clear them. So clear was the wrong name for it.
I renamed the recursive function getAdjacentSquares because that's what it actually does, it gets the squares adjacent to the ones passed in. It should probably be further renamed getAdjacentBlankSquares or getSquaresToBeCleared But then we start going down a rabbit hole of finding the perfect name.
The problem in naming is that often as we develop, what our functions do changes from what we initially intended. In this particular example, I rewrote this function (and crashed Chrome with stack overflow errors) several dozen times getting it to work and by the time it did work, getAdjacentSquares had nothing to do with actually clearing the squares.
I'm a software engineer working as a full-stack developer using JavaScript, Node.js, and React. I write about my experiences in tech, tutorials, and share helpful hints.
Don't try and name things too eagerly. Naming is, if anything, the beginning of abstraction. As soon as something gets a name, it brings in mental baggage from everyone that reads it. Bad names lead to bad abstractions everywhere else.
1.1. When you're writing software, you probably have no idea what you're doing. You don't understand what you're trying to build, what the right shape, organization, style of code is for the domain you're trying to work with. Bad names are usually evidence of someone misunderstanding what they were building at an earlier time in the development process. But then the name stuck because everyone was using it... so the bad names proliferate.
1.2. So if anything, prefer a screamingly awful name that completely misses the mark than one that is full of baggage and opinion. Thingy is just fine by me.
For these three, I agree that a developer should hold off on naming if they do not understand what they are trying to build. But I feel that developers should do some planning to know what they are building (assuming it is not a side project without any real goal). They should plan out the steps they need to achieve a particular end goal, then refine that into a more detailed technical to-do list for each step. I will often write the skeleton of the code with comments and function definitions before writing any code that actually does anything. It helps me to break down the problem into the smaller pieces to make it more manageable. After doing that, naming the variables is easy.
Top-level constants (in a library or call function) would be uppercase as they are there to ensure capacity of use for the space they live in, and that . For instance, your create_deck( num_cards ) one would be better as a variable or simply a literal numeric value such as 52, 54, 128 or so on. Or it would be function called as a higher order function, eg
where it's a constant; but it really is only used for one task and could be replaced with a match statement. This just avoids allocations in inlined code.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
Explicit? No. But here are my rules of thumb.
1. Don't try and name things too eagerly. Naming is, if anything, the beginning of abstraction. As soon as something gets a name, it brings in mental baggage from everyone that reads it. Bad names lead to bad abstractions everywhere else.
1.1. When you're writing software, you probably have no idea what you're doing. You don't understand what you're trying to build, what the right shape, organization, style of code is for the domain you're trying to work with. Bad names are usually evidence of someone misunderstanding what they were building at an earlier time in the development process. But then the name stuck because everyone was using it... so the bad names proliferate.
1.2. So if anything, prefer a screamingly awful name that completely misses the mark than one that is full of baggage and opinion.
Thingy
is just fine by me.2. If you put
I
in front of your interface names I will shout at you in an unkind way. This is 2019 - you don't need to use Hungarian Notation to express the type of a variable. If anything, the interface should name the general case and the implementation should name the concrete.Database
could be the interface,PostgreDatabase
could be the concrete type.2.1. If your interfaces are describing behaviour (á la Go), use an agent noun based on the verb that captures the behaviour:
Fetcher
,JSONParser
, etc.4. Name length should be proportional to how long the variable will live, and how it's scoped. If it's just the iteration counter,
i
is fine. But if it is exported then I want to see a bit of verbosity.4.1. This matters less with typed languages; I'm pretty confident I know what
db
is if it's declared asDatabase db = ...
5. Functions and method are actions - name them appropriately:
fetch
,read
,get
etc.5.1. Name methods (and namespaced functions) fluently, taking into account the (likely) receiver name;
file.write()
notfile.writeFile()
.6. Stop trying so damn hard - you're probably giving it the wrong name anyway so come back to it tomorrow when you've had some time to think.
Edit: removed point 3 about screaming snake case for constants as I've been convinced it's just pointless
Edit: just want to point out that I pulled these out of the top of my head so I'd hate it if anyone quoted them back to me in a code review in six month's time
Yep. A lot of my refactoring is "why the hell did I name it that?"
It's not difficult since most IDE's and even VS Code implement a "Rename symbol" functionality that makes refactoring a snap.
I didn't put it in the original, but I think a lot of the problem is that we give things names before we go as far as working out what they do. It's usually days or even weeks after I've written something that the right name becomes apparent - usually when I'm trying to talk about the code with someone else.
Yes - refactoring tools are your friend in this! 💯
I have a good example for this. I wrote a minesweeper game. I wrote a function called
clearBlanks
that does what it says, it clears blank squares in a contiguous region when you click on a blank. There's a function defined insideclearBlanks
that I had namedclear
that was recursive. What it does is create an array of the squares adjacent to the ones passed in that need to be cleared.It does not actually clear them. They get cleared after the recursion is complete and the array is returned back to the
clearBlanks
function that actually does clear them. Soclear
was the wrong name for it.I renamed the recursive function
getAdjacentSquares
because that's what it actually does, it gets the squares adjacent to the ones passed in. It should probably be further renamedgetAdjacentBlankSquares
orgetSquaresToBeCleared
But then we start going down a rabbit hole of finding the perfect name.The problem in naming is that often as we develop, what our functions do changes from what we initially intended. In this particular example, I rewrote this function (and crashed Chrome with stack overflow errors) several dozen times getting it to work and by the time it did work,
getAdjacentSquares
had nothing to do with actually clearing the squares.This is so thorough and great advice! Thank you for this response.
For these three, I agree that a developer should hold off on naming if they do not understand what they are trying to build. But I feel that developers should do some planning to know what they are building (assuming it is not a side project without any real goal). They should plan out the steps they need to achieve a particular end goal, then refine that into a more detailed technical to-do list for each step. I will often write the skeleton of the code with comments and function definitions before writing any code that actually does anything. It helps me to break down the problem into the smaller pieces to make it more manageable. After doing that, naming the variables is easy.
I agree with all of the other points. 😄
I've never understood why constants should be uppercase? I see no valuable semantic difference between these two forms of code:
create_deck( num_cards )
create_deck( NUM_CARDS )
The second form adds a visual clutter which provides no useful information to the reader.
I'd agree - but I think the convention is so widespread that I'd be surprised if it wasn't followed. Principal of least astonishment and all that.
I've seen normal casing on constants used on many projects.
It's something that nobody would notice about, nor complain about. Nobody would miss the uppercase constants.
OK, you've convinced me! I'm removing it now as it's really not that important.
Top-level constants (in a library or call function) would be uppercase as they are there to ensure capacity of use for the space they live in, and that . For instance, your
create_deck( num_cards )
one would be better as a variable or simply a literal numeric value such as 52, 54, 128 or so on. Or it would be function called as a higher order function, egA better example would be
where it's a constant; but it really is only used for one task and could be replaced with a
match
statement. This just avoids allocations in inlined code.