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

Add public debuggingName to WorkflowAction, use it in default toString() #1232

Merged
merged 3 commits into from
Nov 14, 2024

Conversation

steve-the-edwards
Copy link
Contributor

@steve-the-edwards steve-the-edwards commented Nov 14, 2024

This is a more useful default implementation and allows clearer overriding via debuggingName.

@rjrjr
Copy link
Contributor

rjrjr commented Nov 14, 2024

This will also block data class WorkflowActions.

Block them, or just prevent them from generating horrible toString() implementations?

@@ -31,6 +31,9 @@ import kotlin.jvm.JvmOverloads
*/
public abstract class WorkflowAction<in PropsT, StateT, out OutputT> {

// Debugging name, will be returned by `toString()`
public open val name: String = CommonKClassTypeNamer.uniqueName(this::class)
Copy link
Contributor

@rjrjr rjrjr Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're making name a first class public val, isn't the final toString() business heavy handed? We can just make sure our logging always uses name. And we won't have to interfere with use of data class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could, but we don't have control over that. if someone makes a massive data class MyAction: WorkflowAction with a tonne of members (as we have seen) then toString() will still print all those out.

final toString() prevents that and make sure that WorkflowAction logging is always based on the name which can only be so big (in reality)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but I'm saying the real problem is that we're using toString() in logging at all, which we do because we had no alternative. But now name exists and we can log that — avoiding any call to toString() in production code as nature intended. That seems like a complete solution, I don't see why we need to mess with toString() as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but I'm saying the real problem is that we're using toString() in logging at all, which we do because we had no alternative. But now name exists and we can log that — avoiding any call to toString() in production code as nature intended. That seems like a complete solution, I don't see why we need to mess with toString() as well.

Ahhh IC. that makes a tonne of sense

@steve-the-edwards
Copy link
Contributor Author

This will also block data class WorkflowActions.

Block them, or just prevent them from generating horrible toString() implementations?

I don't think there is a way that I've seen to subclass with a data class if toString() is final as you can't opt-out of the toString() implementation in the data class.

@rjrjr
Copy link
Contributor

rjrjr commented Nov 14, 2024

This will also block data class WorkflowActions.

Block them, or just prevent them from generating horrible toString() implementations?

I don't think there is a way that I've seen to subclass with a data class if toString() is final as you can't opt-out of the toString() implementation in the data class.

This compiles:

abstract class Foo {
  final override fun toString(): String {
    return super.toString()
  }
}

data class Bar(val s: String) : Foo() {

}

But I still think taking over toString() is a bridge too far.

@steve-the-edwards
Copy link
Contributor Author

This will also block data class WorkflowActions.

Block them, or just prevent them from generating horrible toString() implementations?

I don't think there is a way that I've seen to subclass with a data class if toString() is final as you can't opt-out of the toString() implementation in the data class.

This compiles:

abstract class Foo {
  final override fun toString(): String {
    return super.toString()
  }
}

data class Bar(val s: String) : Foo() {

}

But I still think taking over toString() is a bridge too far.

Nice! My assumption was wrong then. This is even better. let's talk offline about why you don't like final toString()

@steve-the-edwards steve-the-edwards changed the title Make WorkflowAction.toString() final and use name always Add public debuggingName to WorkflowAction, use it in default toString() Nov 14, 2024
@@ -1007,6 +1007,8 @@ public fun <PropsT, StateT, OutputT, RenderingT>
name: () -> String,
update: WorkflowAction<PropsT, StateT, OutputT>.Updater.() -> Unit
): WorkflowAction<PropsT, StateT, OutputT> = object : WorkflowAction<PropsT, StateT, OutputT>() {
override val debuggingName: String
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should update the @param for name to mention debuggingName instead of toString(). Just to draw people's attention to the better thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -31,6 +31,9 @@ import kotlin.jvm.JvmOverloads
*/
public abstract class WorkflowAction<in PropsT, StateT, out OutputT> {

// Debugging name, will be returned by `toString()`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Debugging name, will be returned by `toString()`
/** Debugging name. Handy for logging and returned by `toString()`. */

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -48,6 +48,9 @@ internal class RealRenderTesterTest {
private interface OutputWhateverChild : Workflow<Unit, Unit, Unit>
private interface OutputNothingChild : Workflow<Unit, Nothing, Unit>

// [WorkflowAction::toString] includes "@-${hashCode()}", so strip it.
private fun String.removeActionHashCodes(): String = replace(Regex("-@([0-9]*)"), "")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure where toString() is leaking in, but can you instead change this test to rely on debugginName directly and avoid the need for this function? Same for the other instances.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is a good candidate for that, but not the TracingWorkflowInterceptorTest as we want that to use the actual toString() or the traces won't be as useful.

steve-the-edwards and others added 2 commits November 14, 2024 21:25
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@steve-the-edwards steve-the-edwards merged commit e370cbb into main Nov 14, 2024
30 checks passed
@steve-the-edwards steve-the-edwards deleted the sedwards/action-naming branch November 14, 2024 21:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants