Hacker News new | past | comments | ask | show | jobs | submit login

A good example would require an entire source tree, as the full technique requires a different structure and flow of code for the entire application. That's why I found it a bit hard to fit into an article. Anyway, I'll give a shot at giving a more concrete example here.

Very naïve code might do something like this:

  function render_some_info($imageid) {
	$image = ImageFactory::get($imageid);
	echo '<div class="container">';
	echo '<img src="',$image->get_src(),'">';
	echo '</div>';
  }
You get the data about the image in the ImageFactory call and output it on the spot. In a better MVC architecture, that factory call would be in a controller. But for the sake of the argument, lets imagine that you couldn't predict that $imageid early enough, it came from another data fetching/logic.

What we would do with datex would look like that:

  function render_some_info($imageid) {
	$datex = new_datex();
	echo '<div class="container">';
	$datex->merge(new ImageDatum($imageid));
	echo '</div>';
	return $datex->end();
  }
The datex object captures the DOM output, and the datum object, keeping the order. The datum object is just a shell, it contains only the $imageid at this point, nothing else.

The $datex object returned by this method, is then merged into the general output tree that represents your page.

Processing continues until you've built your entire page. You still haven't touched the DB or cache for anything about that $imageid.

Then the resolving phase happens, you traverse your $datex tree object, that contains your entire page, and you look for all objects of type ImageDatum. Say you have 10 of them, you get the $imageid they contain, remove the dupes, then you do your efficient one-time DB query that gets the URL data for all these images at once. You iterate through all the ImageDatum objects and give them the data they need.

Once you've ran out of datum objects that needed data, you know that they're all resolvable (populated). You run through the $datex tree once more, you echo all the DOM you find, and you call ->render() on all the objects you find. In the case of ImageDatum your render() method will look like:

  function render() {
    echo '<img src="',$this->src,'">';
  }
Where the $src member was populated by the resolving phase of datex (right after hitting the DB once).

Does that give you a better idea, or do I need to go into more details about this specific example?




I think that gives a good idea. It helps to see how someone on the consuming side of your API would do things, without having to know any of your internals.

In other languages/contexts, this has been called things like promise objects -- i.e., the object promises to give you certain data in the future when you request that data. It defers the computation of that data until the last possible moment. You guys go one step extra by retrieving all your promises from factories, so fulfillment of those promises can happen in a way that requires the least number of passes, or is optimized in some other way.

Is that a fair characterization of your technique? It's pretty cool


Yeah, I think you have a good understanding of what we do. It gives a lot of control over when, in which order and how you group your data needs, and allows you to "drop" promise objects in the output. You can create dependencies between promise objects too (what we call "datum" in my example), which creates a web of relationships between these objects that lives in parallel to the realm of their DOM placement.

A typical use case for that kind of dependency is advertisements on deviantART. We serve different ad inventory depending on whether or not there is mature content on the page. Our ad datum objects thus depend on all the image/thumbnail datum objects being resolved first. That dependency between datum object classes is defined in the code and guarantees that we never serve the wrong inventory.

Before datex we had to be really careful never to output an image after the ad code had been called. And of course we have a banner at the very top of the website, above any image in the DOM. That meant we had to use templating, output buffering and all sorts of convoluted ways to make sure that we generated the ad code after all images had been output, then inserted the ad back at the top of the page where it belonged.

Now we can just render the page in logical top-to-bottom order, merging the ad datum object into the datex stream at the very beginning of the page generation, then move on and merge image datums as they come. We know that the dependency will always be respected; the ad datums will see their data populated after all the image datums have been processed.


To me what's most interesting -- and something you touched on briefly in your article -- is that it seems this concept could be a powerful way to tie in Ajax and lazy loading (like Facebook does where parts of the page are loaded after the main DOM, to enhance perceived loading speed) in addition to being a better way to structure your regular procedural top-to-bottom page load, including providing a crawlable alternative/mobile view of highly dynamic content.


I agree this concrete example should be in the article -- I sort of got the idea from the article but this really solidified the concept in my mind. Very interesting stuff.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: