Skip to content

Conversation

@amstan
Copy link
Contributor

@amstan amstan commented May 25, 2015

This is an example what i meant by my comment at #4 (comment).

More importantly, I think there is even a quite bad disadvantage, since all callbacks are called, even if they are empty functions. At least for the process callback, this adds unnecessary overhead.

The only function which could cause a performance penalty is process, and that one needs to be overridden anyway. While I could implement something that detects that nothing inherited most callbacks so don't set_*_callback on them, all the non-process callbacks happen very rarely so I don't think it's worth it.

their code gets more explicit and more readable

Spamming set_*_callback in my init is not my idea of readable when i have other stuff to worry about there too.

For the final merge I'm proposing everything under PythonicClient to the Client proper. It even has a way to disable the extra functionality by passing method_callbacks=False. I could work on the docstrings too a little so all set_*callback methods refer to the on* methods for the callback signatures (and move the signatures there while I'm at it).

amstan added 4 commits May 25, 2015 02:34
In python we can assume everything's successful until there's an exception.
There's no reason all the functions have to explicilty return that they had
SUCCESS. If there's a None returned it means there's no exception and we
can tell C the operation was successful.
We now pass the delayed_usecs to the callback as an argument.
This class has a few methods which can now be overriden without requiring
needing to call any set_*_callback functions.

An example usage of it was implemented which is similar to chatty_client.
@mgeier
Copy link
Member

mgeier commented May 26, 2015

Thanks a lot for this PR!
I like some of the commits, but not all of them ...

aa5472b:

This is a really nice idea, I didn't like the return values very much myself.

But if we do this, we should go all the way and completely drop the return values from the callbacks.
If an exception occurs, CFFI will automatically return the value from the error argument, so we could unconditionally return the success value.
There would be no need for the module constants SUCCESS et al. anymore, they could become _SUCCESS or similar.

There is only one case where I'm unsure, namely the process callback.
I'm not sure if "don't call again" is really meant as an error or just as an equally reasonable alternative to "call again".

If a user wants to stop the callback without there being an exception already, she will have to raise an exception herself.
What exception shall we suggest our users to raise in this case?

A few exception classes that come to mind: EOFError, RuntimeError, StopIteration or simply Exception.
It doesn't really matter what they raise, but I think it would be good to provide a meaningful suggestion.

If you somewhat agree, it would be nice if you could make a separate PR for this, then we can discuss the details there.

9111629:

I like this idea!
Do we even need the separate property if we pass it to the callback?

479d374:

This one I don't like.

I don't agree that this is Pythonic, on the contrary, I think it's much too Java-esque!

Forcing those poor callback functions onto a class for no good reason doesn't seem like a good idea to me.
Especially the example is a bad example (or rather good for what I'm trying to say), since not a single callback method uses self, so there is no reason for them to be methods in the first place.

I'm not saying that I want to forbid users to inherit from jack.Client, but if they do, they should register their callbacks explicitly.
I think it's also quite unlikely that they actually need all the callbacks.

The only function which could cause a performance penalty is process, and that one needs to be overridden anyway.

That's not true (the first part is, but the second part isn't).
E.g. one could implement some kind of JACK connection manager, without needing the process callback.

While it's true that the only place where it actually matters performance-wise is the process callback, I still think that it's stylistically ugly to call all callback setters in the beginning (even if none is needed) and then call all those empty callbacks (even if none is needed).

Spamming set_*_callback in my __init__ is not my idea of readable when i have other stuff to worry about there too.

That's a fair point, but I guess most users will only need a handful of callbacks [citation needed ...].
And those that need more can make a separate class like you showed in your commit, no need to mix the callback setup with other initializations ...
I just don't think it's the right thing to do within the library.

If we can find an example application where deriving from jack.Client actually makes a difference for the better, we can add it there.
But we shouldn't call it "Pythonic".

Just as a little side note: I don't like the names "on_*()" ... is there any "true" Python library (i.e. not something ported from another language) that uses this nomenclature?

It even has a way to disable the extra functionality by passing method_callbacks=False.

I don't like this option.
If anything, it should be a separate class with a separate name, because the behavior is significantly different.

48b150e:

I don't think that's an improvement at all, but of course that's highly subjective.
The scope of function arguments should be quite clear to the reader and I think using the same name in all functions actually makes them easier to read.

Is there any role model for your suggestion?

I guess we won't find anything like this in the standard library because the BDFL hates callbacks in general ...

@mgeier
Copy link
Member

mgeier commented Jul 22, 2015

What do you think about #24 as alternative to your first commit here?

What about my other comments?

@mgeier
Copy link
Member

mgeier commented Aug 18, 2015

I cherry-picked your second commit into #25, any comments or suggestions for improvements?

I've already merged #24.
I'm not planning to merge the rest of your suggestions for now (for the reasons given above), but I'm of course open for discussions!

@mgeier
Copy link
Member

mgeier commented May 9, 2016

@amstan Do you want to follow up on this?

If not, I'll close this at some point.

@mgeier mgeier closed this Oct 23, 2016
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.

2 participants