Hi guys. I just want to throw in what our approach to this problem is, along
with perhaps some added value. I don't necessarily call this architecture
"MVC" (although maybe some would), but rather we say we take a "Widget" or
"Component" approach, where it's the widget's job to define/encapsulate
itself in terms of UI, behavior, and modality (as in "this is a widget with
some server functionality and some client functionality, or this is a widget
that is purely executed within the client's context", etc...) - and there is
a "host" or runtime engine on the client that facilitates the transport
layer (ajax calls), widget instantiation, messaging, etc... that is also
"bridged" to any server side instantiations of the same widgets. So
basically, there are no "page" scripts (other than the runtime)... only an
expression (or composition) of functionality in terms of widgets and their
configurations and wiring. The controls encapsulate their own UI rendering
and data consumption needs, and fire out custom events for interesting
points in their existence ("the user clicked me, and clicked me here in this
row of my grid, and here is the data corresponding to that row"). This level
of abstraction / decoupling allows for mixed media/technology widget
implementations to run within a consistent compositional framework (meaning
a HTML/javascript widget can easily be mashed with a Flash or Silverlight
widget to create a composite application).

Here's the architecture at a high level (excuse me for not going into great
details on the implementation, as I'm really just trying to communicate a
potential pattern for you to explore):

While this architecture yields the most benefits if you are aiming to build
a full scale single page application (RIA), it can be employed in a simpler
application as well, which also means you will have left yourself in good
shape for scaling up to a full RIA later if needed/desired. It may be
somewhat overkill if you're just building a standard website or web page
with "AJAXy enhancements".

Basically, we define a control (or component, or widget - whatever you want
to call it), as a series of like-named files sitting in a folder on the
server (as convention we've adopted a 1 widget per folder organization
scheme to keep it easy to navigate). Each file pertains to a particular
concern. So, we have the UI definition (the template, or view if you will),
which is "myWidget.html" (or myWidget.template or myWidget.whatever,
depending on your rendering stack). Next we have the server side behavior
file (myWidget.cs or myWidget.php, etc). Then the client side behavior file:
myWidget.js. Then, for the typical case of rendering to a browser target, a
myWidget.css file for widget level style definitions or overrides. Ideally
you also want to make the system capable of being contextually aware of what
sort of client is requesting stuff, so you could potentially have other
"myWidget.foo, myWidget.bar" files for defining concerns that are specific
to XYZ technology (having said that, of course 90% to 95% of concerns today
are probably going to be related to HTML based technology)...

So, the client side runtime essentially contains a generic "factory" of
sorts that abstracts the transport level stuff, and is able to make calls to
the server for the definitions of the widget client behavior classes
(ideally on demand with the ability to preload if desired), as well as the
UI (template) definition and optionally the css file (if one exists). The
ideal implementation is smart enough to only request the definitions and
templates for a given widget class 1 time in a given session, and refer to a
local cache for each instantiation thereafter. Typically you'd filter all
such requests through a single endpoint ("getWidget.php or getWidget.aspx"),
which looks at the post params from the client side to figure out which
widget is being requested, packs the files up, invokes the server side
behavior of the widget if appropriate, grabs whatever HTML/json/javascript
might have resulted from that, and sends it back to the client. The reason
to use a single endpoint is to be able to do valuable things like: make sure
the user has permission to request this widget (based on the current auth
token for example), or implement a "batch" parsing engine at that endpoint,
allowing you to smartly piggyback 1 request to return multiple widget
definitions. Once the client receives all that stuff back, the runtime's
first job is to put the HTML on the page in the right place. The simplest
form of that is just setting innerHTML = "whatever HTML just came back" on
whatever container element was set for this widget instance when you
requested it. More advanced techniques would allow you to plug any other
widget in as a general "windowing" provider. Once the UI has been rendered,
you invoke the widget's client side "init" behavior, which would be where
DOM level event handlers are wired up, etc... and then invoke any additional
script that might have been generated from the server. From that point on,
that particulare widget instance is for all intents and purposes "on its
own". It really has no knowledge of any surrounding UI or HTML, or even
necessarily that any other widgets are on the same page. It is completely
decoupled from any other concerns beyond just it's own UI (the fragment of
HTML it was responsible for bringing into the page), internal DOM event
handling, and potentially any wiring to other widgets that was expressed in
your composition. It blindly fires out custom events when interesting things
happen (a DOM event is trigger for example), and it handles is own
re-requests to the server as appropriate to get data or invoke it's server
side RPC methods (if there are any).

The idea is to keep things as decoupled as possible, as well as to be as
efficient as possible in terms of what you actually load into the client and
when. If you have a tabbed interface where each tab is a rich set of
functionality, and the user never clicks the 3rd tab in a given session,
then you probably should not have sent any script or HTML to the client
pertaining to that tab. This pattern is called lazy loading, and is fairly
common. The trick of course is to find that balance between upfront load
time and per action latency. That can be mitigated to some extent by doing
some sort of predictve fetching, where you preload things that are likely to
be needed during periods of user idleness.

Anyway, I realize I kind of did a Big Ass Reply here. Just felt like writing
I guess. Hopefully you find some tidbits of value there. This was obviously
a fairly high level explanation, and there's a ton more you can do to really
be poised well for scalable development of advanced RIA type applications. I
think in general it sounds like you're on the right path though.

Happy coding :)


-- 
Ryan Gahl
Manager, Senior Software Engineer
Nth Penguin, LLC
http://www.nthpenguin.com
--
WebWidgetry.com / MashupStudio.com
Future Home of the World's First Complete Web Platform
--
Inquire: 1-920-574-2218
Blog: http://www.someElement.com
LinkedIn Profile: http://www.linkedin.com/in/ryangahl

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Prototype & script.aculo.us" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/prototype-scriptaculous?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to