Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Code health] Rename on* functions #2439

Open
scolsen opened this issue Apr 11, 2024 · 3 comments
Open

[Code health] Rename on* functions #2439

scolsen opened this issue Apr 11, 2024 · 3 comments
Labels
type: code health Improvements to readability or robustness of codebase
Milestone

Comments

@scolsen
Copy link
Contributor

scolsen commented Apr 11, 2024

We have some functions throughout the app that are called on...Result... on...Click... and similar. These names are really opaque and do not convey anything about the actual behavior that's happening when the function is called. It'd be better to convey semantics in these names instead of intended/current call site use, e.g. onTakePhoto --> startPhotoCapture, onSignInButtonClick --> attemptUserSignIn etc.

@scolsen scolsen added the type: code health Improvements to readability or robustness of codebase label Apr 11, 2024
@gino-m
Copy link
Collaborator

gino-m commented Apr 11, 2024

We have some functions throughout the app that are called on...Result... on...Click... and similar. These names are really opaque and do not convey anything about the actual behavior that's happening when the function is called. It'd be better to convey semantics in these names instead of intended/current call site use, e.g. onTakePhoto --> startPhotoCapture, onSignInButtonClick --> attemptUserSignIn etc.

I saw a related ToTT about naming recently, and I partly disagree with the idea that naming handler methods as such is necessarily a bad thing. Like setters and getters, they're such a common pattern that a consistent naming convention can add clarity. For additional clarity, those methods could call "action" methods that actually do things (eg startPhotoCapture()) rather than implementing that logic themselves. Also, on* is such a pervasive naming pattern in Android SDK and related APIs that even if we try to eliminate it from our own classes, we'll still end up having references to onClickListener and the likes in our code. Change my mind! :)

@scolsen
Copy link
Contributor Author

scolsen commented Apr 11, 2024

It is a definite tradeoff. The on* style conveys, in the context of the enclosing class, that we basically intend that functionality to be used in a handler. OTOH, it conveys nothing at point of use in e.g. the fragment layout:

class ... {
  // oh cool, this is a handler
  fun onSignInButtonClicked() ...
}

// elsewhere..........

// Huh? What does this do?
onClick = frag.onSignInButtonClicked()

Contrarily, giving more semantic names doesn't convey the handler intention within the enclosing class, but it gives readers in the layout fragment way more context:

class ... {
  // ok this attempts a sign in, where's it used exactly?
  fun attemptSignIn() ...
}

// elsewhere..........

// oh cool, we'll attempt to sign in when this button is pressed
onClick = frag.attemptSignIn()

So I think it depends on what we think is more valuable. I'd also argue that the naming scheme overemphasizes a shared property that isn't important. Knowing that all the various action handlers we have are ui handlers doesn't really benefit us since it's rare that we'd ever modify all of these functions based on this shared characteristic, in spite of this, the naming scheme really puts this shared characteristic front and center.

I think names with terms like button in them are also problematic because it means we'll need a rename if we ever happen to change the control component we bind the behavior to.

Maybe we can get the best of both worlds by adopting a nice suffix instead of a prefix, and by dropping references to buttons etc. What about, e.g. attemptSignInAction, takePhotoAction -- this would convey more meaning at call sites while still making this class of methods nice and control f-able.

As for the android terminology, I think that's necessary and makes sense given android's role as the platform. I think it makes less sense for application logic to mirror this approach. In fact, listeners are another example where using the on... pattern just states the obvious and is redundant most of the time .setOnClickListener(onButtonClick()) v. setOnClickListener(uploadMedia())

Just my 2c, the tott is what inspired this. I'd be happy to drop it if we don't feel strongly, but I did touch the photo fragment recently and felt that it'd have been easier to reason through what was happening if the On.... had more meaningful names. Instead, there were a bunch of onSelectPhoto that then calls onPhoto that in turn calls onBlah so it became quite confusing.

@gino-m
Copy link
Collaborator

gino-m commented Apr 11, 2024

Ok, I'm convinced: As I read your response I realized I was thinking of event handlers as the primary means of documenting the result of a particular UI interaction. However, with both Compose and XML Data Bindings handlers are already described in a discoverable, non-ambiguous way. In that case adding another level of indirection is unnecessary.

The one potential exception I can think of is when an event triggers multiple semi-related actions. In that case we have to option of putting all the effects in the method name (showConfirmationDeleteTheThingAndAddTheOtherThing()), or regressing to the handler method naming style. That said, I assume actions can usually be generalized in a way which doesn't expose all the sub-routines involved, so this edge case may just be a hallucination rather than an actual issue.

@gino-m gino-m modified the milestones: Community ownership, Icebox Apr 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: code health Improvements to readability or robustness of codebase
Projects
Status: No status
Development

No branches or pull requests

2 participants