Hey Matt (and fellow cfuggers :)
Okay, the first clarification I need to make is that I was wrong
regarding the capabilities of xml processing and so also incorrect
about part of the core mach-ii functionality (though I think the fact
that I wouldn't have had this confusion without the introduction of a
completely separate static language [xml] into the framework bears
mentioning - I was confused because I didn't think xml provided a
particular capability to the framework). In specific, my understanding
was that, given an xml node, for instance
<event-handler event="world_hello" access="public">
<notify listener="helloworld"
method="world_hello"
resultKey="request.event_name" />
<announce event="hello" />
<notify listener="helloworld" method="world" />
<view-page name="hello_header" />
</event-handler>
That the representation of this node in CFML would simply be a
structure containing an announce array, a notify array and a view-page
array. (Good example of the concept, bad example of mach-ii, I'm
aware. :) In fact, the xmlchildren element of the node object is not a
structure, it's an array (I thought it was a structure) and so mach-ii
can (and does) process each sub-node in the event-handler node in
order rather than being required to choose an arbitrary order to
process nodes by type. Which eliminates the confusion about the
possibility of events announcements which are a combination of xml
announcements and listener method announcements not occurring in the
order the xml indicates.
Still... the "simple" process of determining what events should
execute and in what order to produce the page view at the end of the
request _still_ makes my head spin. Partly because the order of events
is arbitrary (order and name), but this is also true of Fusebox and
the onTap framework, so it's obviously not something I can point to as
an outstanding diference of Mach-II. What Mach-II ads to the necessary
evil of arbitrary event-names tho is the need to order events as a
chain instead of being able to nest or layer events...
Believe me, I'm really not trying to make this an onTap vs. Mach-II
debate (although I do understand how it likely appears this way).
Rather, my hope is to shed some light on some difficulties I've had
with Mach-II, in order to explain them so that they can be better
understood. If I end up using onTap analogies more than anything else
it's just because it's what I'm most familiar with. It's the same
thing I'd want if I knew someone else were having a problem with the
onTap framework -- feedback to get an understanding of that
difficulty. The hope of course being that it helps people figure
things out and makes the process easier for them, regardless of the
framework they choose (or get stuck with because their boss chose it),
even if it only makes it easier for them to articulate the
difficulties they face. As an individual I find myself often
struggling to articulate _why_ it is that something is difficult for
me rather than simply saying that it's difficult. :)
So... now that I've rambled on about my purpose. :) When I look at a
2-dimensional page of web content, whether it's an application or a
site, I don't see a chain of events that leads up to the end result.
Instead I see lots of different little bits, all of which appear
somewhere within the larger page. I see style sheets, I see layout, I
see navigation, I see annoying banner and popup advertising. :)
(though I see less popup advertising lately -- good killers :) Now the
order these things are created in isn't really relevant to me looking
at the page, and so when I go to write software to produce that
result, I don't tend to think about it at high-levels as a chain of
events the way Mach-II requires at least for myself.
I suspect this is an issue for a lot of developers, because I think
most people don't tend to be oriented to thinking about the world at
large as chains of events. I think that's something that generally
requires cultivation. I think most people tend to think about the
world at large mostly in terms of the first 2 or occasionally 3
dimensions, because the effect of visual accuity is more tangible to
them than the effect of time. For instance, when you go to drive a
nail into the wall, I don't think most people think about this as a
chain of events starting with picking up the hammer and ending with
the nail in the wall. I think instead they simply focus on the hammer
and the nail and "do it" without thinking about the order.
Now... if I'm working on a bit of code in ColdFusion, everything I
write executes in order, one line after another... but the
introduction of xml in mach-ii changes this (not as much as I thought,
but still). Given again, the example from above of a single
event-handler element in the xml:
<event-handler event="world_hello" access="public">
<notify listener="helloworld"
method="world_hello"
resultKey="request.event_name" />
<announce event="hello" />
<notify listener="helloworld" method="world" />
<view-page name="hello_header" />
</event-handler>
Now... when this xml gets parsed what happens... the
1 - event world_hello begins
2 - method world_hello is called
3 - method world is called
4 - page-view hello_header is displayed
5 - event hello begins
But this isn't the order of the code... the order of the code is
1 - event world_hello begins
2 - method world_hello is called
3 - event hello is announced
4 - method world is called
5 - page-view hello_header is displayed
Again, I know it's a bad example of mach-ii, but it's a good example
of the concept. I think that to most developers who've not got lots of
Java background, it's going to be counter-intuitive that the major,
core-component (event-handlers) of the framework don't execute
"in-line".
But getting back to why this was an issue for me personally. I'm
thinking about a page (hypothetically of course), and I know in
advance of ever writing any code everything that I want on that page.
Now, some of the things I want on this page are displayed in other
event-handlers. I have to make a choice between either repeating a
number of the listener calls and page views from the other
event-handler (duplicated code = baaaad)... :) or making sure that the
other event is announced before my page view executes... so in order
to do this I have to put my page view in another event-handler (this
is that "little dance" I was talking about)... Now I've separated my
end result (my page view) from my vision or idea (my page) by placing
it in an entirely other part of the application (a separate event),
with the only reason being that it's a limitation of the framework
that I can't execute events "in-line".
So now I have this chain of events
<event>initiate page </event>
<event>get content for page </event>
<event>display page </event>
When what I wanted was a singular event (a page request):
<event name="mypage">
<event>get content for page</event>
<event>display page</event>
</event>
This is really for lack of a better illustration. Because my page (my
conceptual page) isn't a chain of events, it's a single object (the
bounding event) and so when I think about it, I want to have a way to
have it _entirely_ encapsulated in a single object the way I think
about it. Now individual components of it may be separate events or
sub-processes or processes drawn from elsewhere, but I don't want to
be separating my singular idea into a _sequence_ of multiple separate
events ... I suppose... now that I've put more thought into it... if
mach-ii had some sort of meta-event-handler that contained other
related event handlers it would bother me less (although I think I
would still be bothered by it).
For a more tangible example of why I don't want to separate it into a
sequence instead of more of a nested structure, I know when I'm
initiating the page in the first event in the chain (which I perceive
as starting from an http request) what page-view I want to use to
display it. However... If there's any chance that the 2nd event might
need to announce other events, I can't actually declare my page view
until the 3rd event and I can't declare my third event until the end
of the 2nd event. So what I want (the page view) is in a different
place from where I know what I want (the first event), and I can't
even declare the what I want (announce the view-page event) in the
place where I know that I want it. At least not that I'm aware of.
But you notice that in both cases, the display is still the last item
in the chain of events, whether the chain is a queue or a series of
nested "in-line" events. So it still conforms to MVC in either case.
> I think "rather careful" may be overstating this.
> Computers do things in order, that's the nature
> of the beast, but I haven't once seen this as a
> problem in my Mach-II work. In onTap if you don't
> specify, from my understanding things still get
> executed in alphabetical order, so although you
> didn't specify the order, there is still an order
> to it. If you do need things executed in order,
> you have to number them. I don't see how this is
> radically different than putting listener and event
> calls in a certain order in Mach-II.
Actually... now that I've thought about it some more, I think this is
a better way to explain it. Only being able to announce events which
get added to a queue instead of executing them "in-line", forces me to
"divide" the mechanism which actually provides the sequence. In other
words, you don't simply declare a sequence and then execute stuff in
that sequence. You declare the first item or so in the sequence,
execute those, those declare the next couple, and so on. Sure this
could be called good "loose-coupling", but if you're talking about a
high-level view of a single page, I'm wanting one place to go to find
the "top-level" sequence of events for that page. Other additional
nested events might have their own sequences and they should be stored
in their rightfull places, rather than being mixed in or intermingled
with the sequence of "top-level" events that generate the page which
_I_ think is better loose coupling. (footnote: They're not really
"In-Line" I don't think, they're still going to be encapsulated into
an event or a process custom tag and I kinda perceive the term
"in-line" as meaning no encapsultation.)
Granted, this is of course all based on terms as I understand them and
I don't have any degrees or anything, so I may occasionally mangle the
verbage also.
>>The issue isn't simply having different code bits execute
>>in a particular order -- it's executing a not-predefined
>>set of events (specifically) within a single event-handler,
> Not sure what you mean by "not-predefined." We have to
> put a stake in the ground somewhere otherwise the computer's
> not going to know what to do, so at some level the events
> have to be defined in order for the computer to be
> able to execute them.
By "not-predefined" I just mean that events announce other events. And
so when you execute a public event via an http request, you may not
necessarily know (and certainly the "top-level" event-handler can't
know) how many events will execute on the page (though mach-ii does
have a configurable limit). But that the number of events may vary
even during different executions of the same event, since events can
be announced conditionally within listener methods.
> (That's not to say your event can't consist solely of a
> page-view, which is pretty common.)
Yea, that kinda bugs me (although I'll admit it's a minor complaint).
I'd rather hear that it's almost unheard of. To my way of thinking, an
entire event-handler for nothing but a page view as a common practice
is busy work. Especially considering that I already had to declare a
name for the page view and associate that with a physical path rather
than simply providing the path.
> You announce all your events related to the view, get
> whatever you need, then display the view. It *almost*
> sounds like you want to be able to throw a view out to
> the user and still do some things in the background,
> which just wouldn't be the way I would ever think
> about doing things.
It's not generally speaking the way I do things either. Although it is
the only way I would ever want to implement a progress bar, so I think
there are exceptions to that rule. The dhtml progress bar is something
that doesn't work _within_ Fusebox 3 (you have to leave the framework
to implement one), and I'd be hesitant to try implementing one with
FB4 or Mach-II for fear of discovering the same problem. The Login
component uses ... not a progress bar per se, but a progress display
that's incremented in much the same way to indicate that the component
is being installed. For the Login component this only takes a moment
(it's a pretty small component), but for larger components, the
install progress could be fairly time consuming in terms of someone
waiting on the browser, and you'd want to let them know that
something's happening and it hasn't just stalled. There are other ways
to implement that -- hidden frames and flash movies come to mind
immediately as means I've considered to accomplish the same task --
the problem is that in both cases this introduces _large_ numbers of
extra moving parts, and particularly without a _very_ well tested (and
easy to use) solution trying to launch into implementing it that way
is a nightmare I wouldn't wish on anyone. Flex may become that
well-tested, easy-to-use answer in the future, but it's not here yet.
>>I still really want to be able to execute events
>>immediately before completing the current and all other
>>queued events -- or at the very least insert an event
>>into the queue immediately following the current event
>>which still isn't perfect, but would get me closer to
>>what I'd like to see. Of course, there may be a
>>way to do that which I've just not seen in the
>>documentation yet.
> I'm still not getting this--the way you describe this
> it's almost as if you want to insert events on the fly
> while an event is processing, which I don't understand
> how you would do in any framework, language, or program.
> As I said above, in my experience events get executed
> immediately based on the order you call them, but if
> there's something I'm missing, please clarify.
Oh it's an integral part of the onTap framework...
/login/authenticate/300_fail.cfm
<cfif auth.success>
<cfmodule template="#request.tapi.process()#"
netaction="login/authenticate/fail"
return="request.content">
</cfif>
This is of course just an example... I think the actual login
component has something vaguely similar to this in it. I'm sure it's
not identical tho, I know the netaction variables aren't hard coded.
In any event, following the example, this would be one possible way to
get content for the page from the login/authenticate/fail process
before the login/authenticate process has finished executing. Then at
the end of the login/authenticate process it includes its display
template. All nice and MVC and everything happens in order and
"in-line".
Given time and exposure to Mach-II I suspect I'd get to a point where
I wouldn't ever announce events in the xml, just because I'd want to
be able to use variables to announce them just in case there's some
reason to conditionally swap the event. Static language is one of my
beefs with using xml in general, has nothing to do with Mach-II
specifically.
>>But in all honesty, whether you call it an "action page"
>>or not, you always end up writing the same code, so you're
>>_still_ writing action pages (a web-accessible page that
>>executes code in response to a form submittal) regardless
>>of the framework, and regardless of what you call it.
> True, but my point was that since the "action page" isn't
> really a page, but a method call to a CFC, it's a little
> more cohesive than your example seemed to indicate.
Ahh sorry... Nah, I'm all for cohesive components. :)
>>Perhaps I haven't understood the semantic of Mach-II
>>quite the way it's been intended... I equate an
>>event-handler to an onTap framework process -- which is
>>to say, an encapsulated collection of smaller codebits
>>which are all part of a larger reuseable structure.
> This is more or less true, although I would think of it
> more along the lines of "an encapsulated sequence of
> method calls and/or events that may or may not
> terminate with a view-page call."
Although there are a number of other "codebits" asside from method
calls and event announcements that can go into an event-handler, like
setvariables and filters... which is why I stuck with the more generic
terms. :)
> That's probably splitting hairs a little, but I think
> given that onTap is largely file-based (from the little
> I know about it), whereas Mach-II is heavily CFC-based,
> there is a distinction as to where the "code bits" lie
> and this is directly related to the fundamental notions
> of how the frameworks behave in my mind.
It's true that the onTap framework is largely based on file structure
(as well as custom tags and udf's), as oposed to being dependant on
CFC's for its core functionality. I'm not necesarilly convinced that
the choice of modular components has all that much to do with
behavior. Certainly there are syntactical differences, but the end
result at least if not much of the "meta-structure" end up being the
same. You'll have to forgive me for my tendancy to use "broad
strokes". :) For myself there's very little difference (if any)
between using CFC's and using custom tags. Now this may be largely
because I use custom tags in ways that most other developers don't.
heh :) Dunno...
but it does result in my generally thinking that CFC's don't do
anything for me but add headaches related to their portability. Which
unfortunately gets a lot of zealots thinking that I'm not a good
developer because I don't prefer to use them, but then I guess they've
opened a lot of conceptual doors for people who weren't already
working this way and so they don't see how it's possible that I could
know how they work and what they do and still not see any tangible
benefit from them. They just think I don't understand CFC's which
ain't the case. I was creating linked lists in C++ in spite of not
having a BS in Computer Science before I even started working with CF3
and then shortly thereafter started working on getting those same OO
or OO-esque features in my CF applications. Granted, the onTap
framework isn't inherently OO and it didn't come about until much
later.
>>These are the sorts of things that I wouldn't
>>necessarily want to put all in the listener
>>methods because I expect they might need additional
>>sub-component expansions (filters, plugins, notifying
>>other listeners, etc.) which are available to an
>>event-handler, but not available or at least not
>>readily available to the smaller listener method
>>component.
> This may be true--I can't really say since I haven't
> messed with plugins and filters yet. I suspect,
> however, that if you were running into the issue
> you describe you would go about things in another
> way to avoid the issue (if indeed there is one).
> When you use words like "this might need that" it
> again sounds to me like the issue is with writing
> highly cohesive methods, etc. so nothing other than
> the view really "needs" anything else (other than
> maybe an argument to get the right data back).
Well in theory there has to be a point at which there's some element
(or chain of elements) that's not highly cohesive... There has to be
some point at which there's a larger code entity which includes
smaller highly cohesive sub-components. These larger, not-highly
cohesive components (event-handlers I assume) are the ones I'm
concerned about working with and having a tough time managing flow
between.
A shopping cart (as a random example). In any given event in the
shopping cart you may suddenly need to add additional filters,
listener notifications, etc which may do stuff that may or may not be
directly related to the shopping cart ... maybe it performs
statistical analysis for reporting, so it needs to notify a separate
statistics listener.
I guess the best example I can give of something that I've actually
seen explained as an "good example of mach-ii" that bothers me is the
login... I remember seeing some writing about an example of
implementing a login with Mach-II that goes something like this:
event: authenticate
check username and password against the db and either
---
event: loginuser
or
event: loginfail
which likely displays a login form page view with an extra request
variable to indicate an error message.
and either of those latter events will display a page view if
necessary or redirect the user to the next page. It's actually not all
too disimilar from the way the same would be implemented in onTap. The
thing is this just doesn't strike me as a "chain of semi-to-un-related
events"... to me, the loginuser and the loginfail events are obvious
sub-elements of the authenticate event and so ought to be encapsulated
within the authenticate event... In this particular example there
might be no reason they couldn't be (just writing everything into the
listeners), unless perhaps you suddenly need a filter or some other
external component for either or both the loginuser or loginfail
events, particularly if you need a filter that's only going to be
applied to one or the other. Given that any number of things might be
initialized during the login I wouldn't be surprised at any number of
things being integrated into the loginuser event which initializes
their "session" which wouldn't be desirable or in some cases even
plausible to have in the same event with the loginfail stuff. (Very
technical term there. :) It seems to me like there are a number of
situations where this arrangement is the only logical answer in
mach-ii even if their being separate events doesn't seem very
intuitive (at least to me).
Anyway, I know I cut out a bunch of stuff and didn't reply "in-line"
to specific comments. That was largely because I'd noticed a number of
ideas being repeated (partly my fault I know :) and a number of them
all went back to the xml question which I've clarified as being simply
some confusion on my part. If I've left anything pertinent out, please
let me know. :) And I hope I've been able to explain my own
difficulties enough to help you some with your presentation for this
upcoming month, which I'm looking forward to. :)
( Getting the vegetables ready now. :P )
s. isaac dealey 214-823-9345
team macromedia volunteer http://www.macromedia.com/go/team
chief architect, tapestry cms http://products.turnkey.to
onTap is open source http://www.turnkey.to/ontap
-----------------------------------------------
To post, send email to [EMAIL PROTECTED]
To unsubscribe:
Send UNSUBSCRIBE to [EMAIL PROTECTED]
To subscribe / unsubscribe: http://www.dfwcfug.org