Posts Tagged: Frameworks


3
Sep 08

Zend_Paginator

On and off for the last two or three months, Jurriën Stutterheim and I wrote Zend_Paginator, the pagination component for Zend Framework. Yesterday it was officially released as part of Zend Framework 1.6.

This was our first contribution to the framework, and was very much a collaborative working relationship. I first created a proposal in about half an hour on Christmas Eve 2007 for how I thought a pagination component should work after being dissatisfied with existing solutions. It contained some good ideas about flexibility, but on its own it was half an idea, at best. So I promptly forgot about it.

Then Jurriën came along and created a proposal based on his Zym_Paginate component, which was part of Zym Framework, itself an extension of Zend Framework.

At the urging of Zend, we merged our proposals. We refined our ideas, incorporating aspects from each of our proposals in addition to brand new thoughts. Then I wrote a new component from scratch based in part on Jurriën’s existing work. He wrote the excellent unit tests (with 100% code coverage, not always easy to achieve!), and I wrote the DocBook documentation. I also can’t overstate the positive impact the community had, particularly from Bryce Lohr who prompted us to decouple and reorganize major portions of the component.

Anyway, I’m very happy with how it turned out. There are still a few issues, most of them minor—and because of the component’s flexible design, there are almost always workarounds. They should be fixed in time for 1.6.1.

Here’s some praise for the component:

Upcoming Zend_Paginator in 1.6 is absolutely brilliant. Wasted time be gone.
Joakim Nygård

The new Zend Framework 1.6 release candidate includes a Zend_Paginator class, which is an excellent thing to have around because I know I’ve re-invented that wheel on every site I’ve developed. My only criticism of the new Zend_Paginator is it offers a daunting amount of possibilities.
Chris Beer

This really is a beautifully crafted component, very elegant, very classy.
—David Mintz, via e-mail

I’ve seen dozens of different paginators in the last couple of years, and to be honest, this one is by far the best. You got everything right! I can’t wait for this component to hit the incubator.

It’s great, well done guys.
Federico Cargnelutti

Like this post? You might also like Coalmine, my centralized error tracking service for your apps. Coalmine captures errors and all kinds of helpful debugging information, notifies you, and makes it all searchable. Check it out!

30
Aug 08

ORM comes to the iPhone: SQLite Persistent Objects

Although I cut my “programming teeth” on functional database APIs, I happily gave them up years ago in favor of ORM—and I have no desire to go back.

Naturally, the iPhone a certain NDA-bound platform of indeterminate nature has no ORM layer for the bundled SQLite library.

So I was pretty thrilled to stumble onto Jeff LaMarche‘s SQLite Persistent Objects. Think Active Record, except instead of the database telling your model what it’s supposed to look like, the model tells the database what it should look like. Jeff calls the pattern “reverse Active Record”, but I think it looks a lot like Data Mapper.

The best part is that it works exactly like you’d expect:

Person *person1 = [[Person alloc] init];
person1.givenName  = @"John";
person1.familyName = @"Doe";
person1.birthdate  = [NSDate dateWithString: @"1908-11-24 04:12:00 -0800"];
[person1 save]; // Inserts a new row
[person1 release];

Person *person2 = [[Person alloc] init];
person2.givenName  = @"John";
person2.familyName = @"Smith";
person2.birthdate  = [NSDate dateWithString: @"1945-09-13 03:54:00 -0800"];
[person2 save]; // Inserts a new row
[person2 release];

// Oh wait, they both go by Jack

NSArray *people = [Person findByGivenName: @"John"];
for (Person *person in people) {
    person.givenName = @"Jack";
    [person save];
}

It’s still in the very, very early phases of development (it’s at revision 5), so there are some issues to work out, like what happens when the schema changes.

There are also currently a few bugs preventing SQLite Persistent Objects from, uh, compiling at all. I’ve submitted a patch (removed) that addresses these issues. I’ll update this entry when it’s been applied to trunk. (Update: It appears to have been patched.)

Regardless, it’s worth keeping an eye on, even if you don’t use it right away. Seriously, download the source and check it out.

Like this post? You might also like Coalmine, my centralized error tracking service for your apps. Coalmine captures errors and all kinds of helpful debugging information, notifies you, and makes it all searchable. Check it out!

22
Jan 07

Prototype has a new website

A few days ago the Prototype core team launched a brand-spanking new website (with documentationfinally!). It’s built on Mephisto, a Rails wiki, and has a clean design like you would expect. Also nice: it has what looks to be a link to the latest compressed snapshot. No more raking!

Like this post? You might also like Coalmine, my centralized error tracking service for your apps. Coalmine captures errors and all kinds of helpful debugging information, notifies you, and makes it all searchable. Check it out!

20
Dec 06

Does Ajax have a place in the application framework?

“Where’s Ajax?” It’s one of the questions that keeps popping up in reference to Zend Framework. I suppose it’s human nature: most people just don’t get as excited about the fundamentals of the project as I do—the MVC implementation, the Lucene-derived search engine [update: not so much], the caching component. They want flashy stuff. They want Ajax. And they don’t want to work too hard for it.

In the last 10 months, application frameworks have scrambled to be Web 2.0-compatible by creating their own Ajax components. In doing so, they have failed to consider the issue of whether they should, and instead concerned themselves primarily with whether they could. Not surprisingly, this has led to questionable implementations.

To determine whether or not a change should be made in my own applications, I apply a rubric. First, is the change essential? If so, the choice is clear; do it. If not, I continue to ask questions. In which ways would the change be beneficial? How would it be harmful? And so on.

Naturally, this same set of questions is applicable to the topic at hand, so let’s examine each in turn.

First, is it essential? Application frameworks are designed for the server-side. What interaction does Ajax have with the server, besides requesting a given URL via GET, POST, or some other method, and interpreting the result? None; this process is the same as a standard Web request. Ajax, therefore, does nothing new or spectacular from the point of view of the server, so it’s not fulfilling a fundamental need.

Is it beneficial? Most Ajax components wrap JavaScript libraries like Script.aculo.us or Dojo, even to the point of using identical method names. For those with a basic understanding of JavaScript, how much time is saved here over using those libraries directly, really? For those without that understanding, is it wise to incorporate technology into your application without knowing how it works, at least broadly? Better to spend a day learning JavaScript and the principles behind XMLHttpRequest and then choose a JavaScript library that best matches your needs and programming style. Why write more lines in Java with Wicket when you could just write JavaScript directly?

As far as I can tell, most of these components exist simply so that developers can stay cozy and warm within the cocoon of their favorite language, without having to venture out into another one. This is a particularly common attitude among Java developers, as Google Web Toolkit illustrates. Although it has plenty of stated benefits (some of them of questionable validity), let’s be frank—the real reason to use it is to never have to write a line of JavaScript. Is JavaScript so bad that it’s better to have to compile it from some other language, especially when excellent debuggers like Firebug exist?

Is it harmful? One of the most basic tenets of modern web development is the separation of presentation and logic, but Ajax components often ignore this concept. Although some implementations involve the creation of entire forms from within the controller, let’s assume a more intelligent design, as a view helper.

Even with a view helper implementation, you’re suddenly presented with a problem: unless the code is prepared in some way prior to run-time (similar to a “compile” step), you’re now most likely mixing JavaScript event handling with your HTML. Some people don’t even realize that this is a problem. However, just as server-side logic should be separated from the view (as with a multitier architecture) and style should be separated from content (as with CSS), behavior has no place within the presentation. That is to say, JavaScript belongs in a separate, included file. It’s called “unobtrusive JavaScript“.

As typically implemented, Ajax components also have the practical effect of preventing those without JavaScript from using the application at all. That includes visitors using screen reading software, most visitors using some sort of mobile browser, and many corporate users straining under IT paranoia. Altogether, these can account for up to 5% of all visitors to a public website. If frameworks are generating inaccessible code, then it is just as much their fault as the fault of the developer using the tool.

Conclusion

It seems clear to me that Ajax components add no real value if the code is not prepared prior to run-time, and little value if it is. Instead of creating Ajax components, framework developers should let JavaScript library developers handle Ajax simplification and focus on other matters. JavaScript is good and it has its place, but not within the application framework.

Like this post? You might also like Coalmine, my centralized error tracking service for your apps. Coalmine captures errors and all kinds of helpful debugging information, notifies you, and makes it all searchable. Check it out!

30
Nov 06

Prototype extensions

Prototype may be ubiquitous, but there’s some functionality it has yet to cover. Here are a couple of useful extensions I’ve run across lately to fill in the gaps:

Cookie, by Carlos Reche

JavaScript already does a pretty good job of getting and setting cookie values on its own, but this extension makes it trivial. The simple Cookie object gives you access to get(), set(), erase(), and accept() methods.

var Cookie = {
  set: function(name, value, daysToExpire) {
    var expire = '';
    if (daysToExpire != undefined) {
      var d = new Date();
      d.setTime(d.getTime() + (86400000 * parseFloat(daysToExpire)));
      expire = '; expires=' + d.toGMTString();
    }
    return (document.cookie = escape(name) + '=' + escape(value || '') + expire);
  },
  get: function(name) {
    var cookie = document.cookie.match(new RegExp('(^|;)s*' + escape(name) + '=([^;s]*)'));
    return (cookie ? unescape(cookie[2]) : null);
  },
  erase: function(name) {
    var cookie = Cookie.get(name) || true;
    Cookie.set(name, '', -1);
    return cookie;
  },
  accept: function() {
    if (typeof navigator.cookieEnabled == 'boolean') {
      return navigator.cookieEnabled;
    }
    Cookie.set('_test', '1');
    return (Cookie.erase('_test') === '1');
  }
};

Event.wheel(e), by Frank Monnerjahn

This tiny extension (about a dozen lines) adds support for mouse wheel events—handy for any number of things, like manipulating a gauge or slider, or scrolling something sideways. Frank based this code on an example by Adomas Paltanavičius.

Object.extend(Event, {
  wheel:function (event) {
    var delta = 0;
    if (!event) {
      event = window.event;
    }
    if (event.wheelDelta) {
      delta = event.wheelDelta/120;
      if (window.opera) {
        delta = -delta;
      }
    } else if (event.detail) {
      delta = -event.detail/3;
    }
    return Math.round(delta); //Safari Round
  }
});

And a usage example:

Event.observe(document, 'mousewheel', yourCallbackFunction, false);
Event.observe(document, 'DOMMouseScroll', yourCallbackFunction, false); // Firefox
Like this post? You might also like Coalmine, my centralized error tracking service for your apps. Coalmine captures errors and all kinds of helpful debugging information, notifies you, and makes it all searchable. Check it out!