David Haley said: I guess. I start with intuition, as I think everybody does. I do try to expand intuition such that it passes clear tests; of course, intuition eventually encompasses those tests implicitly. Occasionally something will just "smell funny" and it's only after some reconstruction that I can point to the exact problems with it. If anything, this whole discussion has been an interesting exercise in fleshing out thoughts to proper arguments. :)
Heh, indeed. *grin*
David Haley said: When I go into code-review mode, especially for something that is being considered for a standard, it is true that I refuse to accept anything unless it is very clearly motivated. APIs are so easy to screw up and bloat that great care should be taken. There's a very good reason why Lua semantics are so clean compared to, say, PHP; niceties are added with extreme caution. I've said it before, but anything based on feeling or personal preference will fail to sway me; I need very clear examples of why the simpler solutions are inappropriate.
I'm doing things similarly to how Lua's doing them. I'm honestly curious, isn't that good enough reason, considering this is like a language extension unto itself?
David Haley said: For example, when I rewrote the complicated meta-table requiring dialog code into something far simpler, you said it was no good because it was "limiting". Well, ok. But to justify that statement, you made arguments based on which particular method more appealed to your sense of naturalness. You also said that mine was "harder to use" than yours, although I admit to finding that claim rather dubious. Basically, I think you object to it because it's not as "cool" and "shiny" (not meant to be derogatory). I have no objection to coolness and shininess per se, except when it adds complexity, and surely you agree that your meta-table-requiring approach is necessarily more complex in terms of stuff happening (for instance, it requires meta-tables...). I think you have a tendency to design things to "requirements" that you state as necessary, but haven't often called into question -- or at least justified here -- some of those basic requirements.
Heheh, I didn't say it was no good, I just think it was limiting in the particular case I gave. I also never said anything about implementing metatables, I pretty much dropped that example once you pointed it out.
David Haley said: A question worth asking yourself re: complexity isn't so much if you understand your own code now, but if you think that coming back to it in 18 months you'll find it just as easy to understand without putting time into re-understanding it.
I haven't so much as peeked at the code since my last posted change; maybe I'll give it a few more days and check back. *grin*
David Haley said: As Nick said, no, but I think they were also rather simpler in scope. I find it quite interesting that even the relatively simple serialization library required revisions down the road.
Fair enough. I think it would be reasonable to come to a compromise on what we think we need and what we can do without for now, release it, and see what the developers think. We can always fix things down the road, as with serialize.lua. Although it might be worth noting that, whatever the complexities of my version, I think it might be easier to add/remove from without breaking things when all's said and done (although I could be wrong - I've never particularly had to maintain a library before).
Two things I would like to see kept are the protocol, and relatedly my method of passing functions around. You should be able to solve the vast majority of problems that way, with enough wiggle room to not feel closed in by my design choices.
Oh, that reminds me - that's what I meant before, about catering to personal preference. I don't want to actually restrict the user, but instead give them some wiggle room, a comfort space.
Tree/graph serialization of tables could go either way, but I have no doubt that someone won't be happy if they actually want to serialize a graph, the most likely case being a doubly-linked list in my opinion. As for whether or not they're useful, I'm using a singly-linked list in my ATCP plugin to maintain the callbacks, since it makes it easy to remove one during iteration if there's an error when it's called (if the source plugin was disabled/removed). A doubly-linked list is only a step away.
Back to the protocol itself, I want to keep it because I think it's very easy for any language to translate/deserialize, since it uses Array*() methods rather than a Lua-specific serialization technique.
David Haley said:
Twisol said: My main metric is whether it makes it easier on the user.
This is a reasonable enough metric. But it's important to understand that it's not a one-dimensional question. If you're not careful with endless additions of syntactic sugar etc., you can end up with an implementation that's such a mess that fixing bugs and adding features becomes much harder than it needs to be.
Well, I personally think that my implementation is fairly open to changes. The protocol can easily be expanded by adding another set of conditionals to the serialization methods, for example. Everything's pretty clearly separated.
David Haley said: Also, sometimes, having a toolkit with fifty different kinds of hammers for very specific variations of nails can be much harder to (learn to) use than a toolkit with a two or three hammers that cover the vast majority of cases satisfactorily.
I'm not understanding this, though. There's only a few multi-purpose hammers, and you use them just like the other hammers you might be used to. You can access arbitrary values and expose arbitrary values. And clearly, if the value happens to be a function, there's a way to invoke it. That's all I see. What specific hammers do you see, so I can understand your point of view?
David Haley said: Superficial usefulness (as in, usefulness to the user) can be countered by internal complexity; it's also extremely important to make sure that things aren't any more complex than they need to be.
Well, I've stated several times that I think everything in my implementation is justified (and I've explained my views on why), and furthermore I do actually like the design when it comes right down to it.
David Haley said: I think that your other metrics are interesting but slightly misleading. An API isn't usually meant to "open possibilities", for example; it's meant to solve a problem, and the possibilities that are opened are those that come about from solving the problem easily. An API (of this sort) usually isn't a big open-ended project that ends up implementing a whole paradigm unto itself.
Sorry, that's basically what I meant. The idea is like, you only have a certain arm length, so you can only reach so far. If you simplify a problem area, lending your own reach to the mix, then that problem becomes simpler, and new ideas might come to light because they're closer within reach.
In the end, techniques such as callback functions, which were previously available but too much work to bother with, are now within easy grasp through the same syntax that you're used to. Hence, new ideas can and will come to light that use callback functions.
David Haley said: I get the impression that you're only thinking about this from the implementor's angle, not the user. You've stated explicitly that you want all these ways of passing functions around. Yes, yes, internally PPI doesn't care if the function has a name or not. But now, users have to decide how to structure their code around all these different "possible designs".
What I mean is, even in Lua you have a variety of ways to structure your code. PPI is no different, and it adapts readily to whatever techniques are available. PPI doesn't care if the function has a name or not because at the protocol level, it's not even a function, but a message ID akin to those sent by BroadcastPlugin. The Lua PPI simply maps them to proxy functions, which provides a deeper integration into the language's semantics.
David Haley said:
Twisol said: I think the great thing about my PPI is that I built it to just do the basics that I came up with at the time, and in the end it can do so much more, through exactly the same interface, and everything is still clear and makes sense semantically.
I would have thought that by now it was clear that what might be the most sensible thing semantically to you is not necessarily the most sensible thing semantically to others. Also, two words: "feature creep". Doing "so much more" is not always a good thing.
I never intended to do "so much more". It just happened to come out of the design I made. No, seriously - I never made that many big changes. The only game-changing additions I made were (1) allowing functions to be passed and returned (speaking from the Lua terminology; the protocol was simply expanded to include 'f:'), and (2) separating ACCESS and INVOKE into the two messages they are now, which I am very happy I did.
David Haley said:
Twisol said: I believe that you are still assuming that a PPI in any language has to look like a PPI in Lua. This is firmly not true, and I have never assumed that to be the case at any point in PPI's development.
"Has to"? No, of course not... "Should"? Actually, probably yes. Do not underestimate the value of consistency. I would say that you also should not underestimate simplicity, but I would feel like I'm repeating myself to an unsympathetic ear. ;-)
I went into this believing that the PPI could and should be adapted to the semantics of whatever language it was ported to, to give a closer feel to what users experienced with that language are used to. This is a core design choice that you clearly don't agree with, but I'd prefer to work with something that feels like part of the language than something that feels shoehorned in to fit. I'm not trying to convince you, but this is one of the design decisions that I won't go back on.
I'm not unsympathetic... I understand what you mean, I just disagree very much on this point. I made a choice - one that I think is a good one - and I've stuck with it.
David Haley said:
Twisol said: So far, I haven't seen anything in PPI that VBScript can't do without a little elbow grease
Ah, well, that's kind of the rub right there. The more stuff you add, the more "elbow grease" you'll need for other languages.
I'm not planning on adding anything else, now or ever. This is sufficient for everything I would need, and everything else I've considered would be far more complex than anything else I've added, or would absolutely kill the cross-language goal. Nobody says you can't use CallPlugin yourself, either.
It's not like this was a breeze to write in Lua. I did have to put in some elbow grease of my own here. The point is that PPI would have to be ported for every language that wants to use it, but PPI is the only part that needs to be re-implemented to understand the protocol. All existing PPI-using plugins don't have to change a thing, which is in stark contrast to my original LoadPPI, which used loadstring()() on a service plugin's 'Library' MUSHclient variable, requiring the service author to write the exposed methods for every supported language themselves.
David Haley said: If I had to choose a single takeaway for you from this entire discussion, it would be to realize that there isn't always one appropriate way of doing things; that there isn't necessarily a solution that is the best of all worlds; that there are always trade-offs. Adding features is never free.
PPI has been an exercise in compromise, though it might not seem that way to anyone else. I did have to weigh everything I added, and consider whether it would have undesirable adverse effects. There are plenty of things I could have added, but did not, because of this metric. I refer you to the post when I said "this must be desirable, that must be desirable, or the alternative must not be desirable" - that's another good metric for me. I understand your points, and believe me, I take them to heart.
EDIT: I tend to speak of the protocol and the implementation in the same breath, without noting which is which. If it's ever unclear what context I'm speaking in, pester me and I'll try to me more precise! |