I have a rule called “name it what it does, not how it’s used” which is a mistake I often see with junior developers and sacrifices information density
Eg it’s more helpful for readability to do “onClick => updateDate()” rather than “onClick => handleClick()”
(Not the best example and I’ve seen far more egregious, but those examples are escaping me now)
I’m an engineering lead and I made a rule of using the handleClick() style instead of updateDate() in our codebase. The reasoning is that the latter sounds more like an atomic, standalone function, whereas handleClick() may have some internal checks that could eventually call something like updateDate(), but the internal checks are beyond the responsibility of the updateDate() function.
> may have some internal checks that could eventually call something like updateDate
This sounds like exactly the kind of pre-mature optimization that leads to overly-abstract function names throughout the codebase. Your point is a good one, once the function does something more than `updateDate()`. But until then, just call it `updateDate()`. As a bonus, this way any time you do choose to use `handleClick()`, the name is conspicuous enough that you pause to see what side effects it might have.
It’s not premature optimization, it’s just boilerplate because it’s a pattern that happens so often.
Besides, there’ll be less work if the requirements do in fact change, and there’s nothing wrong with accounting for the possibility of change when you’re writing code because what you write now constrains what you can write in the future.
I agree. It's also nice to know when you see a `handle` function, it is getting slotted into an `on` somewhere. Within the handle I prefer to call functions such as updateDate().
But this whole thread brings up something about coding that has always irked me, it's very opinion based. When two people strongly hold the opposite opinions on the same team, it can be a massive hassle for absolutely zero benefit.
When two people strongly hold the opposite opinions on the same team, it can be a massive hassle for absolutely zero benefit.
On teams, or in life in general, IMO when there is no consensus, or even an anti-consensus, the only rational global decision is not to make a global decision.
Maybe we're talking about different kinds of issues. In the context of opinion-based disagreements (rather than matters of fact or evidence), an anti-consensus seems to indicate that there isn't (and can't be) one right answer. If one group imposes its will on another group, or appeals to the powers that be to do so on their behalf, the second group will definitely become hostile to the first. Thus, anything other than "agreeing to disagree" and moving on to areas where you do agree would just build more resentful, disconnected hostility.
Personally I would have both and within the handleClick() function do whatever it needs to do and call an atomic updateDate() function (assuming it's updating the date globally). Although for anything generalized standalone function I like to put that in its own namespace, such as helper.updateDate().
Or be explicit. Call it AtomicUpdateDate if such functionality is really desired. Nobody should assume any operation is atomic ... Unless it is explicitly stated to be so.
Yes my example was if updateDate literally just updates the date - I take this a step further too, Eg if the function has some extra checks, I’ll name it maybeDoX(), which is a somewhat uncommon practice in common programming languages
I completely disagree with this example. Only in first order implementations does that click just change the date. As you refine UX you may add some debounce, error handling, alternative behavior, etc. DOM events rarely end up corresponding to such simply expressed handlers.
Also when you are reading the reverse, it’s not clear on what on what updates date. The worst scenario is when two listeners share a handler.
It entirely depends on what the function is receiving.
In your example, assuming we're looking at a React codebase (since this seems to square with React's style of events, etc), the resulting data being set into the updateDate function would be an event.
This, unfortunately, doesn't make any sense for a function by the name of updateDate to receive. I would expect to receive at least a new date to update with in the parameters, or ideally in a functional world, both the state to update and the new date we want applied to it. Anyone thinking they could simply reuse the updateDate function somewhere else is going to be woefully disappointed they largely cannot, since it would have been constructed around receiving an Event object.
In that case, I find the "handle" nomenclature to be very useful, as it appears to be largely shorthand for functions design to handle an _event_ (and we tend to see this pattern being used in various React libraries and documentation). React does have a few of these shorthands it tends to use (such as useEffect largely being short for useSideEffect).
Ultimately, I recommend using both functions. One, a handleClickUpdateDate function (notably not a hyper-generic handleClick function which conveys nothing) that receives the event and pulls out the necessary information out of that event to determine what the date is that the user has selected. It then will call the updateDate function with only that date, which creates a nice, reusable updateDate function if we need it anywhere else.
This roughly squares with the idea of having functions that handle the data transport layer (such as receiving data via HTTP or gRPC, etc) whose responsibility it is to receive those events, pull out the necessary information out of the package, route the request to the correct controller, and ultimately return the result in a shape that satisfies the original transport mechanism. In this case, our handle* function is responsible for receiving the original transport of data, then routes the request through to the appropriate controller which is entirely unaware of the means of data transport.
It also means we have a nice, easily testable unit of updateDate to verify our state modification is working to our liking without needing to assemble an entire Event object.
I’d agree in some cases, but then you get weird debouncing code in your update date function. Because, no one wanted to change the onClick function name in 38 different places when it starts to do more.
Here is a great example that came up last week. Almost exactly like the OP. (It is even an onclick!)
I have a C# .net MVC web project. All of the JS, .cshtml templates and C# controllers are in the same visual studio solution. So it has complete vision into the code.
So the boundary is from cshtml template to javascript function and then another one from the js function (ajax call) to C# controller.
Visual studio has complete vision, but loses the connection at each boundary, so intellisense says that the C# controller function is never called.
I am not criticizing Visual Studio, it is a great tool, but this is a hard problem.
Depends on the size of the function. If these are literal one liners: don't break them up. When they are shared between multiple pieces it's more useful. Ie: submit request has multiple callers.
the benefit for handleClick in a react codebase at least is, aside from convention, generally there will only be one click action per component and then you can see right when you come into the component - hey there is a click somewhere in this component.
In that case what I find preferable is onClick => handleClick()
I completely agree with this, but I additionally advocate for function/method names to be formed verb-object. Plus IMHO active, descriptive verbs are best, instead of 'do', 'handle', or 'manage'. As others have mentioned, handle click might be appropriate as a shim/landing point for satisfying an interface. Logic is best when focused without unnecessary dependencies/side effects.
The best naming comes along with a strong design and architecture, when all the pieces can justify their existence and boil down to the essence of what the system is trying to accomplish.
Agreed, and something to add in the explanation of what to do is the "why."
When someone (or you) is reading the code later, you see a method call and know exactly what it does. This prevents you from having to click in or find it just to figure out what it does.
Frequently, if you click into a vaguely named method, it doesn't do the thing you were searching for and you wasted a little time and need to backtrack, only to repeat the cycle with other vaguely named methods.
This example is not good for talking about naming as there is no proper design which would have a function like this. In any proper design there would always be a separate function for each of the concerns.
That is all well and good, until you have many components all needing to handle clicks. Then it is better to do a handleClick abstraction and put the updateDate inside it.
Eg it’s more helpful for readability to do “onClick => updateDate()” rather than “onClick => handleClick()”
(Not the best example and I’ve seen far more egregious, but those examples are escaping me now)