You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Vjeran Marcinko <vj...@email.t-com.hr> on 2010/01/29 09:53:53 UTC

Back to request-driven frameworks...What a step back!

Hello,

I rarely write here, and that's always when I have a problem with some part
of Tapestry, but this time I want to praise it a bit since I had to work
recently on some project made in reques-driven framework (Spring MVC). For
years I have been working just inTapestry, so I just forgot how it is to
work again in this old-school type of way, and what a step back it was!

Probably everyone is thinking now how good is that one can encapsulate some
piece of HTML and action inside a component, and reuse it afterwards. Well
yes, but that wasn't THE thing I missed most when working on new project.

First thing that I missed was the structure of application's web portion. I
am a big fan of domain-driven design (DDD) which teaches us that our code
should be aligned with our mental model. When one thinks about web
application, we always think in terms of pages and actions that are given on
them, so it is natural that our code should be structured this way - classes
that represent pages, and methods on them that represent actions on that
pages. Also, many web pages require certain parameters to be displayed at
all, and they should be enforced somehow.
Instead, in Spring MVC (any probably many others similar frameworks) one has
freedom to structure web controllers any way they want. Hell, you can have
just one controller for whole app and cram all request handlers into it.
There is no notion of "page request" or "action request" that are so natural
to our mental model, just low-level HTTP request thinking there.
Some would say that freedom is good, but I don't. Just think how many
developers truly understand how to structure whole app, and have enough
self-discipline to enforce that. It's much better when framework forces you
to think and develop in proper way.

And the biggest selling point of Tapestry compared to these frameworks was
amount of care one has to give to URLs and parameters. To be honest, you
have to think abou them in Tapestry to some degree also, but that degree is
so much smaller when compared to Spring. Tapestry allow you tu reuse
compile-checking so much more, and refactoring which is essential part of
any serious development becomes practicaly painless then. Just for example,
in my "ViewCompany" page I can navigate to its employees. In Spring MVC I
had to write:

<a href="$linkTool.uri("admin/employees/view").param("employeeId",
loopedEmployee.id)">View Employee</a>

although it's quite short, I had to take care about bunch of non-type-safe
string such as "admin", "employees", "view", "employeeId" etc...
Instead in Tapestry, I enhanced PageLink component with my tape-safe version
that accepts configured page instances:

<t:safepagelink t:page="configuredEmployeePage">Vew
Employee</t:safepagelink>
..and in page class:

@InjectPage
private EmployeePage employeePage;

public EmployeePage getConfiguredEmployeePage() {
    return employeePage.configured(loopedEmployee.getId());
}

Voila! I don't care what package is my page located in, or if it's name gets
changed, or if required parameters for its display change since I know my
compiler will notify me. Non-type-safe string here is
"configuredEmployeePage", but it's just one, and it's what I call "local
string" - it is only tied to accessor in the same page class one is working
on, and therefore much easier to think and care about, compared when one has
to think about all other templates in app where this page is referenced.
This framework quality really shine not only during
initial page development, but especially later when you start to refactor
things. You simply have much more control upon whole application.

Just to clarify - method "configured" that I place in each page is basically
just calling "onActivate" that configures activation context and also
returns self as return value. The nicest possible way to implement this
render request would probably be via constructor, something like:

public EmployeePage getConfiguredEmployeePage() {
    return new EmployeePage(loopedEmployee.getId());
}

, but I understand that page pooling and maybe some other features stand in
way.

Anyone reading this, feel free to vote for my JIRA issue to upgrade PageLink
for this type-safe way of rendering page links :)
https://issues.apache.org/jira/browse/TAP5-757
It's really trivial update to tapestry code

Regards,
Vjeran


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org