Entries For: 2007
- December (1)
- November (1)
2007-12-07
Clients without Code!
Web UI best practices, to the extent that practice makes perfect.
How many times has someone slaved over a web page with complex server side code embedded in it. This page is passed over to a front end engineer. Next day you update your project from the repository and suddenly all the server side code is broken.
How many times does a simple change in presentation require getting a hold of the server side engineer to make the change even though it's trivial.
The problem is our primary artifact, the web page, consists of markup/code from three domains. The html/csss markup that governs presentation, javascript code that can govern both client side interaction and server communication, and server side markup/code like jsp/asp/rhtml/velocity/freemarker.
Often this mix results in the most modern and up to date spaghetti code where it is difficult to determine what is happening and where (especially as an app evolves over time). Plus you have pages that won't render outside of a complex test environment, resulting in some of your team members flying blind when making changes.
After some initial resistance, a front end guy I work with recently picked up velocity templating. But I think this was an exceptional situation. To expect that he also pick up enough jsp, struts, tapestry,rhtml, etc., etc, etc. to render a model or at least not to &%@#-up my server side code, is neither reasonable or desirable (though it would make my life infinitely better on legacy projects). Carlos, are you listening?
To counter these tendencies, I've been moving towards a style of web development which aims at a clean separation of concerns between tiers/technologies/ and project roles. I call it "No code at all in the client!"
In this approach, the web tier contains nothing but html and css. The Wicket framework is a good example of this way of doing things. Here is the markup for a complex ajax page with lots of linked form elements:
<?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml" > <wicket:panel> <p>Grant Access</p> <form wicket:id="accessForm" > Select Department;<select wicket:id="selectedDepartment"></select><br/> Select name:<select wicket:id="selectedUser"></select><br/> <input type="submit" value="Add" wicket:id="ajax-button"/> </form> <p> The following accounts have been granted access to work on your behalf for your projects:</p> <form wicket:id="grantedForm" > <select wicket:id="grantedUsers"/> <input type="submit" value="Remove" wicket:id="ajax-button"/> </form> <p>The following users have requested access to your account's projects, pending your approval. Select whether to approve each account.</p> <form wicket:id="requestedForm" > <select wicket:id="requestedUsers"/> <input type="submit" value="Approve Accces" wicket:id="approve"/> <input type="submit" value="Deny Accces" wicket:id="deny"/> </form> </wicket:panel> </html>
This page will render properly in any browser. Css styles be applied to it, and additional javascript functionality added, without any risk of breaking the server side interaction. The complete form functionality is specified server side, taken care of in java. Here's an example of adding a dropdown list to a form that updates the contents of another dropdown via AJAX when its selection changes:
departmentList.add(new AjaxFormComponentUpdatingBehavior("onchange") {
protected void aonUpdate(AjaxRequestTarget target) {
target.addComponent(UIHelpers.resetDropDown(userList,
userManager.fetchForDepartment ( (Department)departmentList.getModel().getObject())));
}
});
A more radical version of this approach is to generate all the output server side and display it on the client via embedded script tags (like in this example from the R2J feed from CNET:
<script src='http://i.i.com.com/cnwk.1d/html/export/r2j/News-19.html'></script>
If you follow the link, you'll notice that it returns a javascript snippet that renders an rss feed in html. Here's a part of it:
document.write('<div id="r2j-feed"><div id="r2j-title">
<a href="http://www.news.com/&tag=r2j">CNET News.com</a></div>
<div id="r2j-tdesc">Tech news and business reports by CNET News.com.
Focused on information technology, core topics include computers, hardware,
software, networking, and Internet media.</div>
<div id="r2j-head">...');
The HTML developer can style the emitted content and there's almost no danger at all of breaking the client-server interaction. The web page can be deployed on any web server (no need for Tomcat, Rails, or whatever) and it can get its dynamic data from any other server on the internet without the need to worry about cross-site scripting issues. Richer interactivity can be gotten by passing JSON messages back and forth with javascript. I've been increasingly using this style of development for clients with minimal IT expertise and infrastructure. If A full featured featured web app can be deployed on a $10 a month Go-Daddy account with the back end provided by one of my hosted servers or one in the EC2 cloud.
2007-11-19
Rails Slow
Processor cycles are cheap, developer cycles are dear. Until you run the unit tests.
Love Ruby!
It's a little bit scary not being to lean on the compiler for things parameter type checking, but the Rubyistas assure me I'll get used to it. Being used to writing a lot of unit tests helps.
So I start my first Rails app. Loving Ruby! Happy to use the equals operator instead of endless getters and setters. Happy to use duck typing instead of extracting another interface when I want to treat things polymorphically. A little sad to have to learn yet another markup language for the HTML templates.
So I write some tests and I write some code (sometimes I do it the other way around).
Lo, as soon as I require '/../test_helper' and run my rake task, the testing harness takes nearly a full minute to initialize. This happens every time! In contrast, I have an asp.net app with 200 tests, half of which, regenerate the database schema between runs. Everything runs in well under a minute.
I've only see a few posts on the internet complaining about the Rails test fixtures. Using a statically typed language I'm used to running my unit test suite after almost every change to my code. With Ruby I only want to do this more often. A friend says that he likes Rails because it makes him do all the things he wouldn't do as a Perl hacker, separate concerns, write tests. Can it be that most Rails developers don't actually run their tests?
I found myself writing tests (designing my software) so as to avoid requiring '/../test_helper'. This doesn't seem good. What the language and Rails gave, the pokeyness of the test harness took away.
I see that there are ways around this: http://blog.jayfields.com/2006/06/ruby-on-rails-unit-tests.html. But us this something an average Rails developer will do? And eventually you are going to write tests that hit against the database, whether you call them unit tests or not.
It seems like a deal breaker to me, but no one else seems to have noticed.