dpp Replished: Web Framework Manifesto... http://bit.ly/qMDl3M Lift holds up pretty well to the original criteria 11-07-06 3:04 PM |
djspiewak @dpp I had never read that before. Very enlightening! It explains why Lift's Comet support is tilted the way it is (toward full repaint). 11-07-06 3:50 PM |
djspiewak @dpp I still think that style of Comet is a very bad one, but at least now I know you didn't end up there by accident. :-) 11-07-06 3:50 PM |
djspiewak @dpp It's interesting also that the manifest lists a few points that haven't been hit in Lift (e.g. session tied to window). #stillokbyme 11-07-06 3:51 PM |
dpp @djspiewak I'm all ears for a better model of comet. Also, please see http://simply.liftweb.net/index-6.3.html#toc-Section-6.3 11-07-06 7:05 PM |
tylerweir @dpp @djspiewak Yes, I'm interested in any improvements in design or implementation. 11-07-06 7:25 PM |
djspiewak @dpp I've had this discussion with you before. You disagreed last time. :-) 11-07-07 1:39 PM |
djspiewak @dpp Basically, viewing AJAX and Comet as a low-level transport for synchronizing *server* controlled state is a false metaphor. 11-07-07 1:40 PM |
djspiewak @dpp Lift's whole philosophy of Comet, and to a lesser extent AJAX, is based around the notion that all state is server-controlled. 11-07-07 1:40 PM |
djspiewak @dpp This may work for simple apps that you want to jazz up with a little refresh-free interaction, but it falls over with non-trivial stuff 11-07-07 1:41 PM |
djspiewak @dpp Web apps are going further and further in the direction of non-trivial, client-managed state (e.g. OT is impossible without it). 11-07-07 1:42 PM |
djspiewak @dpp My suggestion: ditch reRender, SetHtml, and any mechanism which encourages server-driven state. 11-07-07 1:43 PM |
djspiewak @dpp Those mechanisms may be useful, but they are also *very* dangerous in the hands of those who don't know better. 11-07-07 1:43 PM |
djspiewak @dpp Those mechanisms may be useful, but they are also *very* dangerous in the hands of those who don't know better. 11-07-07 1:43 PM |
djspiewak @dpp In their place, you should have first-class support for calling into and from JavaScript, giving developers full control. 11-07-07 1:44 PM |
djspiewak @dpp In other words: partialUpdate $ Call and ajaxInvoke would be the main client-server interaction model. 11-07-07 1:45 PM |
djspiewak @dpp Now, I don't really know that it would be good for Lift to do such a complete about-face at this point, but you did ask. :-) 11-07-07 1:46 PM |
tylerweir @djspiewak @dpp So would you see Lift offering a client-side lib or something to facilitate communication? Maybe involve websockets? 11-07-07 1:47 PM |
tylerweir @djspiewak @dpp If there was a well-known method to xferring state b/n client and server, would that help? 11-07-07 1:48 PM |
djspiewak @tylerweir @dpp No need for a client-side lib. Invoke fictions via Comet, and render JavaScript functions which perform AJAX callbacks. 11-07-07 1:49 PM |
djspiewak @tylerweir @dpp Part of the beauty of this model is it can be swapped seamlessly XHR/WebSockets. 11-07-07 1:50 PM |
tylerweir @djspiewak @dpp This is similar to your response to the JS DSL, is that fair? 11-07-07 1:50 PM |
djspiewak @tylerweir @dpp Too high-level. I think clients should have full control of their state. 11-07-07 1:50 PM |
djspiewak @tylerweir @dpp Too high-level. I think clients should have full control of their state. 11-07-07 1:50 PM |
djspiewak @tylerweir @dpp In a similar vein. :-) The JS DSL discussion only came up because Lift encourages that style of programming. 11-07-07 1:51 PM |
djspiewak @tylerweir @dpp Imagine writing a chat client outside a browser. Would you have the chat server manage every bit of state for the client? 11-07-07 1:52 PM |
djspiewak @tylerweir @dpp Or would you allow the client to control its own destiny and communicate with the server as it makes sense? 11-07-07 1:53 PM |
tylerweir @djspiewak @dpp Right. I see your point and appreciate where you're coming from due to Vibe. I'm going to mock up a chat app in this style 11-07-07 1:54 PM |
dpp @djspiewak @tylerweir 1-The #Lift mailing list is the place for this discussion & 2-nothing you're asking for isn't already part of Comet 11-07-07 2:01 PM |
djspiewak @dpp @tylerweir I'm asking for *less*, not more. I know Lift can do what I want, we use it that way with Vibe, but it's like pulling teeth. 11-07-07 2:03 PM |
It would be great to see more blogs about Lift and specially what you
are describing.
Regards,
Diego
> Thanks,
> Antonio
>
> --
> You received this message because you are subscribed to the Google Groups
> "Lift" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/liftweb/-/G_fmIZ0YPPIJ.
> To post to this group, send email to lif...@googlegroups.com.
> To unsubscribe from this group, send email to
> liftweb+u...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/liftweb?hl=en.
>
--
Diego Medina
Web Developer
(305) 788-4954
di...@fmpwizard.com
http://www.fmpwizard.com
What stacks / servers would you recommend looking at as food for thought?
thanks.
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/hhUiFM2qeywJ.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Let's see if I can re-summarize my opinion here, since Twitter is not
the best medium for deep discourse (it's just the easiest to use while
breezing through the Alps on a high-speed train).
First of all, I'm going to assume that we're all down with the notion
of client-managed state. If you need me to motivate that for you,
just say the word and I'll nail my theses to your door post. Suffice
it to say that many features that users are starting to expect in
modern web apps require the browser to manage a great deal of state
that *cannot* be managed by the server, simply due to concurrency and
latency issues. OT is an extreme (but fitting) example of this.
Lift's entire stack is *deeply* biased toward the server-managed state
idea. I'm actually astonished that you haven't run into the issues
this causes. The best example, one which caused us a huge amount of
grief on Vibe, is the render/fixedRender issue. If you're doing
*anything* with client-side state, you need to be using fixedRender,
otherwise the server will wack your CometActor seemingly on a whim.
Technically, this only happens if another tab has opened in that same
session showing that same CometActor *after* some partialUpdate(s)
have taken place, but that's not quite as unusual of a case as it
sounds.
Oh, and when I say "biased", I do mean "biased" and not just
"defaulted". Using fixedRender does solve the aforementioned problem,
but a) you need to know that it's there, and even David Pollak had
forgotten about it, and b) you can't *just* do a fixedRender, you also
have to def render = NodeSeq.Empty. So, render with its associated
client-state-wacking behavior is very definitely the standard mode of
operation for the framework.
Let's look at another example more obvious in the API: SHtml and all
of its AJAX goodies. How many functions does this object have now?
I've lost count, and so many of them are overloaded that a simple
search doesn't suffice. In any case, it's a lot. We have things like
ajaxText, ajaxButton, etc. All of these are components that allow you
to bind form (and sometimes non-form) elements to AJAX events,
allowing the server to fully manage the state of those components.
However, this is exactly *not* what you want when you're doing an app
which has any sort of client-side state. Instead, you want to control
the form elements yourself, dealing with them from within JavaScript
and sending the values to the server under your own control.
In order to do this, you need Lift to create a function mapping in the
session which accepts an XHR request on a particular
(cryptographically-identified) URL and routes the data to a
corresponding Scala function, which you have presumably defined to
handle the data input. In the entirety of SHtml, in all of its vast
sprawling network of components, AJAX utilities and functions, how
many API elements do you suppose are devoted to this all-important
task?
Two. (ajaxCall and ajaxInvoke; good luck figuring out the difference
between the two, and I assure you that you will need to use both)
What's worse is these functions are actually quite primitive and seem
to be intended more as low-level constructs used by higher-level,
officially blessed SHtml functions like ajaxText and ajaxButton. One
of the things we did on the Vibe project was wrap ajaxCall and
ajaxInvoke in a DSL which allows us to trivially render a Scala
function value as a JsExp (specifically, a JavaScript lambda). I
promise, we're still trying to open-source this…
Lift has a large library of combinators and tools designed
specifically to allow the server to do all of the DOM manipulation and
state management. Specifically, I'm thinking of the JsCmd/JsExp
stuff. Out of all these combinators, we should really only have one
(Call) and the value primitives (Str, JsTrue, JsFalse, etc). All that
is served by the others is to encourage Lift users to push their
JavaScript in a badly mangled form into the server, where it is bound
by XHR latency (which is very much higher than most people think) and
tangled with server-side logic.
I could go on and on. There are bugs that we have found in Lift (now
all fixed, to my knowledge) that arise specifically in the context of
heavy client-side managed state.
There is also the utter lack of
documentation on how to use Lift to write applications which have such
client-managed state in any serious form.
All in all, it seems like
non-trivial client-managed state is an after-thought in Lift.
Something that is supported more by accident on the basis of the fact
that it is necessary to support server-managed client state (e.g.
ajaxText delegates to ajaxInvoke).
The whole framework, the API, its
examples, and its optimizations are all geared toward a very server-
oriented model of programming. Also, David's recently-republished web
framework manifesto makes it clear that he feels (or at least *felt*)
that server-managed client state is the ideal.
I believe this is a problem. No, that's not really strong enough. I
believe this is a huge, cataclysmic, will-eventually-kill-the-
framework-if-we-don't-stop-it sort of problem.
Modern web
applications are starting to seriously leverage the browser as a rich
client platform. Not all webapps will need to take advantage of this
technique, but many will (and many more than we think). Lift can't
just support client-managed state as an "also ran" system, it needs to
be a first-class aspect of the framework. In fact, if I were starting
Lift from scratch, I would have made client-managed state the
*default* with server-managed state a get-er-done gimmick tucked in a
back corner right next to Rails's scaffolding.
In practical terms, this would translate into a number of
consequences:
- SHtml's AJAX support would be (blissfully) simple: a single
ajaxLambda function which takes a Scala function and renders it into a
JavaScript lambda that invokes the Scala function via AJAX. The arity
and parameter types of the Scala function can be controlled via
typeclasses (basically, this is what Vibe's AJAX API does). The
ajaxText, ajaxButton, ajax* madness would all be either eliminated or
moved into a much less default-y location
- render would behave like fixedRender does currently. I honestly
can't see any need whatsoever for the old behavior, but if we really
want it, we could tuck that into a "volatileRender" or something like
that.
- reRender would be removed. This is another one that I think is
utterly useless and causes *major* issues for anyone who uses it (if
you haven't hit those issues yet, don't worry, you will).
Granted,
it's very convenient, but if we had a nicer syntax for
partialUpdate(Call(...)), then any halfway-decent web developer could
replicate the behavior of reRender in almost as many characters.
There's no need to add a default-looking syntactic sugar for something
which is so very, very hostile to client-managed state
- partialUpdate(Call(...)) would get a nice syntactic sugar. I'm not
thinking anything fancy. Maybe, cometCall("function.name", param1,
param2)?
I just want something which newcomers will see that smacks
of "this is the way we're *expected* to do Comet in Lift". Right now,
that something which newcomers see is reRender, and that's a problem.
- JsCmd and JsExp would probably go away, at least to a large degree.
This is a dicy issue though, because I'm assuming that we can still
return JavaScript values from AJAX functions and pass those values
into cometCalls. Unless we want to restrict such values to simple
primitives (string, boolean, int), we need something at least a *bit*
like JsExp. Maybe the solution would be to use typeclasses, similarly
to how we would need to apply them to support the aforementioned
ajaxLambda function in SHtml.
- SetHtml, SetById, and all of the many reincarnations of this same
idea would be axed. These have the same issue as reRender: they smack
of defaultyness, they're very dangerous and they're nothing that
couldn't be replicated in two shakes by an obvious application of
Call(...) coupled with jQuery in the browser.
Obviously, all of these would be backward-incompatible changes if we
applied them to Lift as it stands today. Remember, I said that this
is what I would do if I were designing Lift from scratch, not if I
already had a largely-mature web framework with a large user base.
The trouble is that I don't know if we can improve here in a backward-
compatible way. If you go through my list above, you'll see that 90%
of it is *removing* stuff, not adding things. In fact, the only thing
of substance that I add is ajaxLambda! In short, I'm not sure this is
the right direction for Lift today, but it sure is the direction I
wish Lift had gone yesterday.
Daniel
On Jul 7, 8:23 pm, Antonio Salazar Cardozo <savedfastc...@gmail.com>
wrote:
> I don't have any deep thoughts to add, but I must say I don't see how using
> Lift this way is like pulling teeth. We've used Lift comet with a high
> degree of client-managed state since the beginning for OpenStudy, and I'm
> just in the endgame of transitioning us to an even more client-centric model
> using Knockout JS. These transitions have required far far more change on
> the client than on the server (indeed, in this case the comet just had to be
> changed from sending down XML to JSON, which was a matter of adding some
> lift-json rendering of the relevant entities). But I guess it depends on use
> case -- for myself, I've never even considered using the `default' (if it
> can be called that) re-rendering approach, and I've never felt disadvantaged
> for it.
>
> The only part of this that has been a little more annoying has been dealing
> with dropping functions onto the client from a comet when I'm also dropping
> XML in and chaining functions in from the comet's superclass (which provides
> additional functionality). But that's extremely isolated nastiness that
> happens once or twice and can be abstracted out easily.
>
> I'd be glad to put up more details in a blog post if anyone is interested.
> Thanks,
> Antonio
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
package reactive.web.demo.snippet
import reactive._import web._import javascript._import JsTypes._
import net.liftweb.util._import Helpers._
class JsEventStreamDemo extends Observing {trait window extends JsStub {def alert(s: $[JsString]): $[JsVoid]}val window = $$[window]
val clicks = DOMEventSource.clickval jses = clicks.jsEventStream.map{ (_: $[JsObj]) => "Button clicked"$ }
//this function will be executed in plain javascript, with no ajax involved!jses.foreach { v: $[JsString] => window.alert("Fired: ".$ + v) }
//alert from the server too!jses.toServer[String] foreach { v => reactive.web.alert("Server says: '"+v.toString+"'") }
def render ="button" #> clicks}
Well, there is a tone of things in that post, and I'm clearly
unqualified to judge the validity of 90% of them... You know, my team
and me are simple server-side guys, who are building a server management
application. We wanted it to be nice looking, but we really seems to be
far from Vibe need, are clearly no JS developpers, and had little to no
time to spend on that...
And for our use case, Lift JS/Ajax/Comet rendering work just perfeclty,
and is amazingly simple. Ho, clearly there is no
thousand-of-users-updating-social-info-concurrently in our app, just
some server-side indicator to be update in real-time, some ajax to avoid
full page reloading, and that's all.
After almost two year of Lift, I can say that Lift's Ajax/Comet/JS
support is one of the thing I deeply like in the framework - well, that
and templating with CSS selectors that are a pure wonder.
So perhaps we clearly all the client-side content management thing...
But for now, we just cheers what Lift bring to us, javascript
illeterate, regarding what we can do in the timeframe allocated for UI
niceties.
Cheers,
--
Francois Armand
http://fanf42.blogspot.com
--
So when you wrote all those paragraps about how Lift had fundamental
design flaws that were going to "kill the framework" but were too
ingrained to be fixed...you were really saying that you want more
scaladoc and examples for render and reRender? And a new function
called ajaxLambda?
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.