> I'm actually quite interested in this sort of thing and I 
> wrote a blog 
> article about it. You might or might not find it interesting. Other 
> people might (or might not) find it interesting as well:
> 
> http://freemarker.blogspot.com/2006/07/designerdeveloper-division-of-labor.html
> 
> There, you see that, I make no bones about what I think regarding 
> Velocity. It definitely seems to me that VTL is lacking certain basic 
> features that you would need to build reusable components. The macro 
> system is just too deficient.
> 

Jonathan,

I would agree with you that macro support in Velocity is not sufficient for 
constructing what might be called a "modular" or "component"-based system. As 
far as I am aware, it was ever intended for that purpose. Personally, I regard 
macro functionality as being more akin to what might be termed "snippets".

[for those who are interested in "modular" or "component"-based templating 
systems, read on ... ;D If not, you've probably stopped reading already anyway.]

For our usage of Velocity, I recommend against the use of macros for all but 
the most simple use cases. I do not do so because of limitations in Velocity 
macro support but because using this feature for the creation of reusable 
"components" would imply a level of scripting which I would argue is not 
optimally achieved within a templating language. All this talk of "macros" is a 
red herring, IMHO. Hence, we are not utilizing macros at all for the modular 
system I referred to in my original e-mail.

A display component is, for all intents and purposes, a domain object (or a 
facade upon one) some properties of which one wishes to expose for display 
purposes and, potentially, to decorate with additional display-specific 
properties. Additionally, a display component is an object the display context 
of which one requires to be able to detect and subsequently act accordingly 
thereupon. Consequently, I would suggest that the required functionality of a 
"component framework" extends to the following:

1. Obtaining an instance of a domain object
2. Determining the context in which that instance is being invoked

Neither of these requirements, I would argue, fall within the remit of a 
template language. This is why we are building our system in a manner that is 
entirely decoupled from Velocity.

Why mention it on the Velocity list? Because we _do_ want to render components 
that this system is capable of creating instances of. Therefore, we have built 
a Velocity client (basically, a Velocity directive ... and we made a tool for 
the hell of it - because it was so simple to do). This client obtains a 
component object instance, discovers the contextual display-related data (e.g. 
template name etc that the framework loads on the basis of the request) and 
renders it in-situ at the point the directive resides in the template.

At this point one might think "Hey, isn't that a built like a view-layer 
'pulling' data and isn't that A Bad Thing?"

Well, yes and no (to both parts of that question).

What the above enables us to do is to have something like the following:

--- in the main "view" template ---

#component("MyComponent", {"id":$myComponent.id}) ## the webapp is still 
responsible for pushing the id of the component you want to display into the 
view (amongst other data, in all probability)

--- end ---

... but we can have an entirely independent "component template" that makes the 
most of the beautiful simplicity of VTL and simply displays the properties of 
an object (info about which the template authors can obtain from javadoc)!

--- component template ("MyComponent.vm") ---

<h1>${this.heading}</h1>
<p>${this.text}</p>

--- end ---

Additionally, because we have access to contextual information about where the 
component is being displayed, we can (for example) easily get the Velocity 
client to use different templates based upon that data (in practice, this 
happens transparently on the basis of conventions)

However, because we have not written our components as VTL or Freemarker 
macros, we can easily go ahead and make alternative clients (e.g. a JSON client 
... or even a web services client using a RESTful or SOAP api ... or even a 
FreeMarker client! ;D) which re-use the exact same components.

But doesn't that mean having to create loads of java classes and restart the 
server (which would be a pain in the arse)?

Again, yes and no. If a component has to implement complex functionality, then 
yes: it requires implementation in Java - but that would be the appropriate 
place to implement such functionality.

On the other hand, one can simply use a named "dynamic component" to utilize 
the contextual data and rendering functionality available by way of the 
Velocity client in templates; e.g.

--- in the main "view" template ---

#component("DynamicComponent", {"name":"MyDynamicComponent"}) ## this basically 
making a map the property names and values for which are determined contextually

--- end ---

template is not quite as simple, but remains far more readable than some 
horrific macro spaghetti ...

--- component template ("MyDynamicComponent.vm") ---

<h2>${this.get("heading")}</h2>
<p>${this.get("text")}<p>

--- end ---

> Large, complex, modular sites using Velocity, eh? I suppose it's 
> possible. But really, you know, when you can't even #parse a set of 
> commonly used macros in a separate file, and there's no notion of 
> scoping or namespaces whatsoever, so that any variable 
> defined locally 
> in a macro potentially clobbers variables defined elsewhere 
> -- to rely 
> on that kind of tool to build something complex and modular, does not 
> seem like a very good technical decision. The tool simply lacks 
> necessary things for modularity.
> 

It's more than possible: we've already done it even without the formalized 
support provided by the "framework" I describe above (which is really just a 
bit of hackery on top of Spring) being in place - and we are by no means alone 
in that (rather simple) achievement.

Nonetheless, I think it would be foolishness to try and assert that Velocity is 
in some way "pure and flawless". Proper whitespace handling would be a 
requirement in my book (and, yes, I know FreeMarker has this already).

So why didn't we just make a FreeMarker client and use that?
1. Because we were already using Velocity (I know there is a template 
conversion tool, but there are other considerations such as familiarity of 
client-side developers with current systems, skills investment etc)
2. (And this is the main reason) Because Velocity explicitly does not attempt 
to be a solution which bundles everything and the kitchen sink. The clear 
delineation of responsibility (basically, taking a context+template and 
rendering) combined with clear extension points and an elegant syntax made it 
ideal for our purposes.

> 
> > 
> > There might be some common ground covered between us and 
> The Guardian here 
>  > which could be fed back into the Velocity project itself, perhaps?
> 
> Well, historically, lobbying Velocity developers for features 
> that you 
> need has not been a very fruitful path. I won't go on further about 
> that, but surely you can perceive that, even bending over 
> backwards to 
> be generous and all, you can't describe this as a very dynamic 
> environment, can you?
> 

From my reasoning above, you may have guessed that I am not lobbying for new 
features. Far from it: the restriction to a clearly delineated requirement is a 
virtue that Velocity possesses. I would never want it to come bundled with it's 
own "component framework", for example.

"Fed back into the Velocity project" might imply a couple of things:
1. Us potentially making available our framework code and Velocity client but 
as an entirely separate entity (in the same way that Malcolm and the Click 
project might be thought to "feed back" into the Velocity project).

2. The possibility of simply "donating" the code such that it might be 
maintained as a sub-project were we to decide against maintaining our 
development as an open source project (which is not a commitment to be taken on 
lightly).

Obviously, I cannot speak for The Guardian in any way on this subject and 
merely mentioned them in this context in case they were watching ;D

Best wishes,

Chris

********************************************************************************
   
DISCLAIMER: This e-mail is confidential and should not be used by anyone who is
not the original intended recipient. If you have received this e-mail in error
please inform the sender and delete it from your mailbox or any other storage
mechanism. Neither Macmillan Publishers Limited nor any of its agents accept
liability for any statements made which are clearly the sender's own and not
expressly made on behalf of Macmillan Publishers Limited or one of its agents.
Please note that neither Macmillan Publishers Limited nor any of its agents
accept any responsibility for viruses that may be contained in this e-mail or
its attachments and it is your responsibility to scan the e-mail and 
attachments (if any). No contracts may be concluded on behalf of Macmillan 
Publishers Limited or its agents by means of e-mail communication. Macmillan 
Publishers Limited Registered in England and Wales with registered number 
785998 
Registered Office Brunel Road, Houndmills, Basingstoke RG21 6XS   
********************************************************************************

Reply via email to