Make sure and post about it when you do - I definitely want to see more momentum around this and was pleasantly surprised when I saw that solutions already existed. My favourite thing about it is that it transcends "technology". The fact that you've been working on this is no loss to someone else who's been working on something similar as the cost of changing from one solution to another is so dramatically low when all the value is retained within the templates themselves.
Likewise. Two other template engines you might be interested in are Knockout.js (http://knockoutjs.com/) and the template engine from the Lift web framework. Both play relatively well within HTML.
And Stanford has done some nice work on segmenting the DOM into semantic chunks. The site appears to be down now, but it's usually hosted at http://bricolage.stanford.edu/. Check out their paper on the "Bento" algorithm.
The lift book is worth a quick look if you are interested in templating engines. In short, instead of logic in the view, css selectors are used on the server side to transform small chunks of the website in a statically typed and safe (the dom structure is carried around as xml instead of a string which makes it possible to prevent most of the common security problems on the web) way http://simply.liftweb.net/
It seems to be serving that page in around 5 - 7 seconds but it's pretty heavily loaded. Yes I wish I'd gotten around to doing all that stuff that I know I should do in order to make it load faster than it does right now.
PS: If the site didn't load, how do you know it sucks?
It's a drag when what you're working on is such a unique snowflake that nothing really smart teams have worked on for years is able to help you.
I'm going to abuse a Bruce Schneier quote and suggest that if you're trying to get a job done and you start by writing a template interpreter, you're doing it wrong.
Dude.... I get laughed at for the things I do with templates (html page with 20k input elements) until people realize what I am doing with them (a bulk payment interface for paying 5000 invoices in a compact workflow).
I have found that any complete templating system has sufficient flexibility and extensibility to do what you want. Though I use Perl's Template Toolkit.
Hmm not really. I mean, what I want is HTML/JavaScript/CSS and then absolutely anything I choose on the backend. The framework is completely irrelevant. The fact that there is an "itemprop" attribute in the Pakyow view construction already invalidates it as an option for achieving what I'm putting forward here.
Every programmer is on a long, cyclical journey where every stepping stone feels like a new kind of enlightenment. Blogging allows them to share their brilliance with the world, showing how they are surely amongst the first to attain their new level of purity and zen.
The funny thing about this post is that the author tells us to get off our high horses and come down from our ivory towers... and then proceeds to make a series of highly conjecturable claims presented with no factual evidence beyond his own confident assertion that he's in the know. There's like, no chance that in two years he'll be advocating for his new new philosophy.
In the meantime, I'm left to wonder "Iain Dooley who?" and be glad that I'm confident enough not to read an opinion-as-fact article and assign it significant credibility.
PS: A good first editing step is to ask "does my opinion-as-fact blog post question the capacity and potential of a professional web designer to understand simple concepts like string interpolation, and could they find this insulting?" before assuming that you've got it all figured out.
Whilst this article is indeed an opinion piece and strongly hyperbolic (and perhaps even didactic), I'm not sure why that offends you. I don't have any statistics about large or small organisations putting this into practice so I'm not sure what other facts I could have included apart from the examples I provided.
The capacity of designers to understand anything isn't the subject of the post, so I'm not sure why anyone would be offended by that.
The idea is that it's easier to find someone to work on HTML/JavaScript/CSS in a static HTML context than it is to find someone familiar with whatever frameworks you're using and it's templating language, then to have that installed locally (especially when you're not working with a long term in-house team of designer/developers and don't have lots of time to spend on training people).
I also personally find it far easier and quicker to iterate and test new interface ideas quickly when working with static HTML so I like to be able to view my templates outside of the context of my application/framework etc. and then iterate without having to re-apply a bunch of templating code.
It's ok to write a little polemic here or there but don't be surprised when people react negatively to it. People are offended because you are saying they are incompetent at their profession.
Have the humility to understand that many of us have been doing this for years and have seen numerous attempts to revolutionize templating, and gasp have written webapps before the idea of templating really took hold.
If you want to persuade people to take up your ideas regarding DOM manipulation in the controller, I'd suggest not starting by telling people they are writing spahgetti code. It's a great way to get page views, it's a poor way to persuade people.
People probably would have reacted much better to your argument if you started with "Hey, I'm doing things this way and here's why it works for me" instead of "You're all idiots who write spaghetti code". Embedding XSL selectors in HTML attributes which is processed by a half-assed implementation of XSL in PHP is the kind of thing I think when thinking spaghetti code.
What you don't realize is that you've invented a new templating language based on XSL but with half the features. Those of us who've been around the block a few times like to call this inner-platform effect. We've also seen this idea before when it was pitched with J2EE and used XML with an XSL templating system.
Hi, thanks for the tips. I'm always interested in opinions on my writing style and how to communicate better.
Regarding your critique of Fragmentify, that's actually not so much what I'm advocating here as it is just the impetus for realising that there are 2 distinct components to templating which are: 1) the re-use of common assets, and 2) the application of some "logic" to display dynamic data.
It doesn't matter what you use to fragment your markup (I personally think that using XPath to manipulate an XML document isn't particularly off the mark but whatever, to each their own). Dreamweaver allows you to edit common assets pretty easily and then export a ZIP with head-to-foot complete HTML documents in it. I'm sure there are a million other ways to skin that cat.
What I'm saying is that the separation between "display logic" and "business logic" either doesn't exist or at the very least shouldn't be occuring between the backend and the frontend.
You could, if you wanted to, put your "view rendering" code in some other place in your application, but that's tangential to my case for completely removing any and all logic from templates and working solely with (and iterating solely with) HTML/CSS/JS when building your interfaces.
Personally I'd never use it because I intensely dislike the syntax of HTML and CSS and avoid it at all costs since discovering HAML/sass.
I find a text editor (vim in my case)/photoshop + haml/sass + live reload to be my most productive workflow, one screen for the text editor, one screen for the browser, when I save the browser reloads the page.
For me there are a lot of things that just work smoother by having the data populated, when I work with designers I just take whatever they give me (sometimes just a PSD) and work with it, if they need static HTML/CSS I just use wget/save as webpage to save the html and assets.
I revolutionized as well the templating 3 years ago with pure.js... This one is an intentional xslt for json.
The result is a thin ~400 followers on http://github.com/pure/pure, we use it for our web app, and I get regular thanks emails. Even some copycats appeared.
Nothing changed. Server power is still wasted sending HTML to idle terminals using a markup/logic soup like we do since 1995.
A pretty useless fight, but at least I'm happy I tried.
Why I (note: personal opinion) think that this article was arrogantly written and not for me:
You try to make a rant (because that's what it is) more interesting by adding random fake quotes/thoughts that you attribute to the reader, i.e. me. There's exactly one person that knows my thoughts and I don't feel represented by your 'quotes' - so everything in light green on that site is bullshit according to me. Lucky for me you colored the link-bait title in the same way, so..
Duly noted. The "strawman" argument thing I always find makes a post (particularly an opinion piece) easier or more entertaining to read (I may have read a little too much maddox in my time, though).
All depends on your goal. Maddox runs an entertainment website. It's not meant to convince anyone of anything or otherwise be productive. His style is in service to the purpose of the site, so it stands to reason that emulating it will have a similar impact on what your readers take away from your work.
It might have went over better had you attributed the quotes to some "third party", like "Mr. ERB Exponent, December 2011". You don't risk personally offending the reader. The tradeoff is it might make the joke a little less obvious. (I might Google for "Mr. ERB Exponent", thinking it's a web persona who was notorious for expounding on ERB.)
Writing is hard.
(For what it's worth, the attributions didn't bother me.)
Can't believe so many people here need their fragile egos propped up. I thought the fake comments were silly and entertaining... which is a nice way to break up an opinion piece.
I won't defend the author; my opinions here fall mostly inline with your own. But I still wonder if there isn't something deeper...
Presenting something as fact is an extremely quick way to find out if you're wrong. It's much faster than asking a question. The impulse to correct is stronger than the one to answer. So I interpret the post as the blogger's subconscious attempt at verifying and normalizing his opinions.
In this way, a blog is mostly a self development tool. I should start one of my own, I think. I never have before because I lack the hubris to think that my little discoveries are novel enough that anyone else would care. But I see now, maybe that's not the point.
Yeah, I'd say that's a pretty fair assessment. I personally find this style of writing more interesting to read (which is why I emulate that) but I'm also not particularly experienced at writing so it's good to get feedback on what works and what doesn't for particular audiences.
I am definitely using a blog as a means of getting "outside the vacuum", though, and as you say evaluating my own opinions by putting them out in public and seeing how people react.
"""In the meantime, I'm left to wonder "Iain Dooley who?" and be glad that I'm confident enough not to read an opinion-as-fact article and assign it significant credibility."""
Yeah. And I wonder "peteforde", who? Should we only listen to what established figures have to say?
The problem with your attitude is that nowhere you access what the author wrote --you just add critique how he told it: highly conjecturable claims presented with no factual evidence, etc.
The important stuff to ask is, was it a good idea?
(Good ideas don't always come with factual evidence you know). What you think of it? What counter-example can you find.
Basically you just told us: the author is unknown, he doesn't formally prove his idea. Well, DUH!
I read tons of posts with such qualities on the inter-tubes.
That doesn't stop me of getting something out of some of them, and a few of those are pure gold.
"""PS: A good first editing step is to ask "does my opinion-as-fact blog post question the capacity and potential of a professional web designer to understand simple concepts like string interpolation, and could they find this insulting?" before assuming that you've got it all figured out."""
Yeah, as if this is the gist of the post, and the litmus test of a technical idea is if it can hurt the feelings of web designers...
And I tried the concept using Nokogiri in Ruby. I found that in practice it gets really tedious. I had to make sure that every single element I wanted to manipulate had a unique id. Then I had to account for updating the content of an element versus an arbitrary attribute for that element. Or adding an attribute, like some data-* attribute. I realized why string interpolation is just so much easier.
There's also the problem where the DOM parser changes the original HTML in some way. How will it deal with conditional comments for IE? Or slightly malformed HTML that you want to keep that way?
At first I thought this (and even typed out a long explanation of "the reason why you cannot make the assumption that your resulting document will be manipulated with DOM" involving "what if you want to change the presentation layer to PDF"), but then I realized that nowhere did he advocate mixing the DOM manipulation into his other logic; it could just as easily be a completely separate pile of "presentation to HTML" code that was entirely unrelated to the "generate content to present" layer.
Precisely - in fact, if you want to change the output to JSON, you don't need the HTML templates at all. You just use the same code you were going to use to extract the data from your persistence layer and then output it however you want.
Hmm. I do understand what you are saying, but in most cases where you are outputting HTML, how is this really different from using templates? I see templates as a way to reduce redundant code. The examples on the blog post are simple (e.g. removing a node, which is easier with 'if' statement), but it will probably be messier.
Regarding alternative formats like JSON or PDF, I guess you can add a layer there.
First off, let me be clear (as I'm concerned that your bringing up this unrelated "messier" argument is the beginning of me being used as a proxy for the author): I am not generally arguing in favor, I was simply countering that specific argument against. I will now describe why they are different, but I do not want this to be taken as a defense of the method.
The way it is different is that it is an inversion of control inside the template, not that it is changing up the layering. You still have a "construct data" layer and a "present data" later, and you can still swap out the "present data" layer with something unrelated, such as a normal template engine or whatever else you wish to use to generate JSON or PDF.
However, inside the "template", rather than having HTML with embedded logic (where you can almost envision the HTML calling into the logic to insert text or execute flow control at specific points), you instead have logic that manipulates the HTML via DOM, modifying the HTML to contain text at specific points. You could probably even make a compelling argument that these are duals of each other.
I have a sneaking suspicion that for all the worthiness of the principle of separation of concerns, it's impossible to completely decouple presentation and logic -- you're going to either end up having some degree of model-related logic bubble up into the view, or you're going to have some kind of presentation-related logic seep down into the view.
What we've generally done as an industry is accept the former, but I'm not sure whether one is better than the other.
You are plain simply wrong.
First of all, logic in templates is something which is OK to have. Different templates display information in different manners.
Second thing, I don't think you've seen how awful and unmaintained code which manipulates DOM instead of templating looks like.
The point I'm making, though, is that the challenge of solving "maintainability of DOM manipulation code" is a simpler problem to solve than the creation of the perfect templating language.
What's more, a good DOM manipulation strategy and library can be really easily ported to any language, freeing up your templates to go wherever you may feel is appropriate in the future.
Instead of including if/then/else logic in the template, templates are duplicated for each branch and the logic is pushed up to the controller. This takes on hand-managing duplicate code (because there will discrepancies between the "logged in" and "logged out" version every time someone forgets they need to change two files, or doesn't notice there is a second version to touch) to avoid having any code in templates (which it labels as technical debt without support).
This does not seem like a worthwhile tradeoff to me. And the author doesn't address loops, which often want to have special treatment of first or last elements, even/odd rows, and other small bits of logic. When you combine these things, you're going to have a combinatorial problem, I can just imagine a shopping cart table with templates like shopping_cart_item_list__table_row__last_item__logged_in__even_row__multiple_quantities__discounted_item.html
And what's with the really confrontational tone? This article would've been improved by spending a couple hundred fewer words putting words in the reader's mouth and insulting their tools/code. There's a chance this could be useful in some situations, but I sure don't want to spend any time talking to this guy.
Loops with special treatment for first and last items is quite simply dealt with by including a list of items (for example) in the static HTML mockup, the first and last of which is different from the middle one.
EDIT: Also in response to the issue of double handling, I did mention this in the article:
In that second example of course, we've got a bunch of duplicate markup, but that's not our problem. That is the job of whatever system you're using to fragmentify your templates and re-use common assets
> As soon as I'm looking at more than one programming or
> markup language in the same file, I'm looking at
> spaghetti code.
By this definition the following is 'spaghetti code':
$dbh->do("delete from my_table");
Following his logic:
1. Realize there's SQL and Perl in the same line.
2. STOP EVERYTHING
3. Start attempting to fully abstract SQL into Perl
so that no one will ever need to write a line of
SQL again.
4. Die an old man, never having accomplished this task.
I've actually seriously considered keeping all my SQL queries in their own files, and reading them into local variables on load. It would allow them to be tracked and edited individually... but I now use an ORM.
I do keep the SQL queries in their own files. The only difference is that they get loaded into the db (as stored procs) at first and then called by name. Works well.
Agreed ORM's are usually very sub-optimal. They make sense only because application developers aren't db people. And this is the problem.
I suspect for certain parts of some apps, ORM's might work OK. But in general for applications of any complexity they will break down hard and fast, and lead to bad db design, bad performance, or both.
ORM is just less work. If you write in OOP you are already creating objects anyways. Then writing get, save, and update procedures is just a lot of extra work.
The problem is then you build databases around your ORM but if you are doing a single app database, why use an RDBMS at all?
In other words, I see an ORM as an antipattern because the subset of cases where it works really well at bridging the gap you probably don't really want an RDBMS in there anyway.
And if you do make it work (encapsulating your db behind updatable views) without running into this, it's a heck of a lot more work than hand-coding SQL.....
I don't consider that spaghetti code, but it does have problems. The big one is the tendency to assemble queries by string interpolation....
What we've done in LedgerSMB is quite simple. All db statements in new code (outside the mapper functions) are in stored procedures. Everything is mapped in there using a Perl API so in the new code (post-1.2) otherwise all SQL is in one set of files and all Perl is in another, with minimal overlap.
This sort of thing makes for very clean development. No, spaghetti code is making me have 15 files open in VIM trying to figure out which of them has the function that is being called in it, with several candidates all bearing the same function name (oh, the horrors).
In small doses, you can get things done quickly like this. However, it builds up over time into a ball of spaghetti, so yeah, maybe after the 5th or 6th blob of inline SQL, you might think about using an abstraction while you still can. I've worked (and work) on old projects with hundreds of SQL queries spread throughout the code, it _is_ spaghetti code and there are better ways to do it.
Actually, the bits of SQL everywhere is the #1 problem with the code. We spent weeks just auditing them all to remove SQL injection vulnerabilities. All the SQL are fragile bits of code, difficult to write meaningful unit tests for, since you can't separate database interaction from logic, etc.
The issue with inline SQL queries isn't the fact that SQL is mixed in with other programming languages itself. It's the propensity to write BAD SQL that's inlined because now you can apply the full power of the programming language to generate your SQL.
Stored procedures are a great way to abstract this out and force good SQL coding practices btw.
> Stored procedures are a great way to abstract this out and force good SQL coding practices btw.
How exactly do stored procedures prevent you from writing "BAD SQL"? They do no such thing.
Stored procedures are a great way of adding complexity to your code, complexity equals bugs and longer development time. There are reasons for stored procedures, but using them simply to remove SQL from your front end is not one of them. And certainly not because of a fear of "BAD SQL".
There are very few valid cases for stored procedures to generate queries like that. And at least with PostgreSQL, dynamic SQL can be spotted with automated searches pretty easily. It's pretty easy to simply add all filters that might be of interest:
WHERE (date_entered > in_date_from or in_date_from IS NULL) ....
Then you also gain testability. We can write test cases for the stored procedures because they have discrete entry points and make sure they are acting according to spec.
Why can't you use that type of code in your frontend?
Stored procedures make it much harder to understand the code since you can't just read the query - you have to find the stored procedure and check it there. (And be realistic - no one has perfect documentation.)
And heaven forbid you have to change the query - now you need to make sure no one else is using it, and you end up with tons of versions of similar stored procedures, not all in use, and many that could be combined.
It doesn't seem worth it to me.
I use stored procedures for data reduction - I want to keep the data in the database, and process it before sending it out. (Saves bandwidth vs doing it in the front end, and often it's faster too.)
But that's it. Using stored procedures just to wrap ordinary queries is a terrible (but very common) idea. (I am aware that it saves time on generating a query plan, but usually that's a case of premature optimization.)
And using it to enforce code policies? Way overkill.
ars: I don't know if we have reached max depth or if it is just a waiting period. The major issues are:
1) Testability. you can write test cases against a stored proc. You cannot write test cases against a SQL query embedded in the middle of a function in another programming language.
2) Single point of control. You can have one function that runs the stored proc there and check properly for SQL injection, ensuring that everything is free of SQL injection as far as front-to-backend is concerned (and in Pg, that only leaves SQL injection issues in dynamic SQL which can be searched for and audited separately).
So that's why not to put it there.
As to changing the query.... I only use databases which come with transactional DDL so that's not an issue as long as inputs and outputs don't change. If the inputs and outputs have to change, we can handle that too with transactional DDL and the fact that we make the interfaces discoverable. In this case, we'd
BEGIN;
DROP FUNCTION IF EXISTS foo_bar(...);
CREATE OR REPLACE FUNCTION foo_bar(...)...;
COMMENT ON FUNCTION foo_bar(...) IS $$...$$;
COMMIT;
Because of the way Pg works this shouldn't really cause issues for currently running queries.
As for finding the right function, since these are all called on a declarative interface so you know what the function name is quickly, and so it is a matter of quickly finding it in a directory of SQL files.
As for testability, don't underrate this. You can insert data, run your tests, and roll back. So for example for our 1099-MISC and INT handling, we run more than 40 tests on a pre-written data set that we can run without ever committing to production and which will never conflict with production data (and therefore does not lock other users out). That's approx. 20 tests per sproc there.
Well, the only time I have ever said exactly this was about SQL-Ledger which used a home-brewed template system (which sucks big time) and which is mostly spaghetti code (in the true sense, of logic wandering aimlessly between modules in ways difficult to understand and predict. Of course the fact that the template system sucked and the code was spaghetti were unrelated except the fact that they were authored by the same (IMHO inept) developer.
On to the article though.... I think that what the individual is discussing in fact is something different, which is the need for stable API's between layers of the application.
I am very skeptical of his idea that all projects can benefit from his proposed solution. Indeed in areas like complex reporting, a template is conceptually simpler than HTML mockups that have to be populated by Javascript. At that point XSLT on the client starts making a lot of sense.... However, not at all sure that's always a win compared to templates. But then XSL files pose all the issues he is complaining about!
The beauty of templates on the other hand is the ability to create diverse output. XSL is no different there. One can create a LaTeX file, an HTML file, a CSV. Anything else. For systems that need that diversity, going with HTML and Javascript is a net loss.
Funny, we've been doing this with a modified-Backbone.js site and have found it requires tedious, manual management of an excess of IDs and classes, plus an error-prone mountain of jQuery expressions.
What I'd really like to do is go 100% the other way: all functions, all the time.
A view could just be a named function, accepting the object(s) to be rendered as arguments, define some closures for callbacks/event handlers, then return a DOM structure.
For one-off actions, like the "save" and "cancel" buttons, callbacks don't descend into madness. Most UIs have very few commands which need true event handling. And the ones that do, the commands are often pretty simple one-button -> one-command. Sometimes many-buttons -> parameterized-command.
For everything else, you can use data-binding. If you're already writing lexically scoped render functions, you can trivially create a data-bindable local object in a variable to eliminate the event management process. Instead of an onclick event for a checkbox, you can trivially set the checked property to be equal to an observable value box containing a boolean. With the right abstractions, callback spaghetti is not an issue.
I've been thinking about some of the ideas in this rant for a while now. I might not have put it in quite such an opinionated manner (templating systems aren't usually my biggest problem), but I pretty much agree with a few things:
1) Fragmentation is a problem, particularly with some templating systems. Layouts should almost always be a single file. Things going inside the layout should probably be single files.
2) As long as templating means sprinkling extra tokens to process throughout a document, there's going to be some coupling problems. Transforming a document based on some external criteria is an interesting alternative.
There's certainly a number of transformation based solutions out there, some of them pretty powerful. But as I was thinking about this a few years ago, it occurred to me that maybe I don't want a powerful uber-transform set so much as I want a simple descriptive set of semantics for addressing content into nodes of a document.
Then I thought about where I'd seen this kind of thing come up before in the realm of document styling: DSSSL and XSLT vs CSS. The simple descriptive CSS won out and has worked out more or less well.
So... I came up with something I called `CAST` (Content-addressed Style Templating):
Basically, you use a subset of CSS selectors (or XPath queries) to pick out a node of a document, then you specify a content rule, and the engine drops a content string into the document node.
I ended up writing my blog around the idea. I ended up being pretty happy with a very simple set of rules, despite the fact that there's not much too the system beyond that -- for example, there are no rules for conditionally hiding a node based on whether or not it's needed, no rules for repeating certain nodes. I think those things might be nice, but it turned out if I was willing to push a little bit of the view down into model layer, I didn't need them at all, and I was (I kindof tend to think that any application is going to have a bit of model-view bleed-across anyway, you just have to figure out how you'd like to manage it).
If anybody's curious, this post made me get off my behind and put the code up on GitHub:
Yep this is pretty much the idea. The key thing is, though: however you do it on the backend, that's entirely a coding problem. DOM manipulation sucks? Well, solve that problem, which is where something like your CAST library comes in.
It's easier to solve the problem of making a nice, easy way to "address" content (I used "animate" but basically they're the same thing :) than it is to solve the multitude of problems caused by choosing a technology stack and creating templates in it for your application.
To be clear, the primary use case here is in a case like Etsy, right? This doesn't work so well when we want to have a consistent interface to create HTML, PDF, CSV, XLS, and ODS files, correct?
Presumably DOM manipulation really can't be done beyond applications which are HTML-only in any reasonable sense without getting back to the things you don't like about templating, right?
Well, the thing is that if your target output isn't HTML, then you wouldn't need to do any DOM manipulation. You'd just output whatever else it is you want to output (JSON, XML, PDF, whatever).
If you had, for example, a bunch of PDF code as a "template PDF" then you might just load that and do string replacement on whatever placeholder text you have in there - but yeah the primary use case I'm thinking of is in implementing web based interfaces.
Sorry einhverfr I can't reply to your comment - but what I think you're talking about is trying to abstract display for HTML, PDF, LaTeX, whatever into a common markup language or template, then repurpose that markup for each output format. Does that sound correct?
So like, you'd want to be able to have something like:
My argument to that would be that there's no realy need for that abstraction - you don't gain anything by it because you have to have some abstracted output engine that is capable of doing that HTML can already do, which is like, HTML :)
Hey, I'd love to continue the discussion, but I think the HN comments are kind of limited in how much they want you to discuss here, feel free to email me iain@workingsoftware.com.au
I will probably post something on the selection and design of our templating system for LedgerSMB in my blog too (http://ledgersmbdev.blogspot.com) by the end of the week.
Just to be clear, I am not entirely hostile to the idea here. I just think that there are plenty of cases where generating high quality printed content or the like doesn't work with it and templating is a lot cleaner in those environments. And when your application already requires templating for a reason like that, adding an entirely different way of handling another output format adds needless complexity.
One of the useful applications of dools' ideas is that you could have a mockup which included lorem ipsums or other dummy text. This would make it easier for web developers to test layout.
OTOH, as I say, I am not at all convinced that it is a net win for programs that generate multiple formats of output./
With good markup semantics and some conversion tools, you probably could generate PDF, CSV, XLS, and ODS from HTML. Some of the more powerful document transformation engines do feats like this.
I don't know, though. I tend to think that this is less a job for the view (and templates) than it is for smart models, or models with some kind of helper that assists them in knowing how to represent themselves in a given format.
its a little more like native software's gui.
that is, with website templating, its, well, template driven. pieces of codes are here and there in the template, following template's will.
with software, your app is code driven. the gui follows what the code tells, instead.
The moment a programmer thinks they know the ultimate solution to a problem is the moment they understand the problem the least.
No, templating is not perfect. Nothing a programmer does is perfect. Our job, as programmers, is to make stuff suck less. We break stuff until it works. We squash bugs until we can't find any more. That doesn't mean what we've built is perfect. It means what we've built is the best we could build with our current understanding of the problem.
I don't think of spaghetti code as the presence of logic in presentation code, I think of it as a lack of separation of what SHOULD logically be abstracted. I find the code it labels evolves over time as the common abstraction level of things increases and we move closer and closer to fully isolating concerns.
> A typical example written in PHP would look like this:
That's not how templating works, that's just some messed up code.
I totally disagree with the idea that having static HTML as templates and transforming them with DOM manipulation is better then templating. When you do DOM manipulations you make assumptions about the structure, if that structure is changed by somebody, you are screwed. The less assumptions you make the better. Also last time I checked DOM parsing was a relatively slow process, even if it would be better than templating it still has to justify the performance overhead.
Also let's not forget that writing if's are easier than writing DOM queries.
Templating allows separation of view logic and business logic, I find it much cleaner to have the view logic in the templates, this is in fact what the author complains about, but how is having both database calls and layout logic in the same place cleaner?
The main problem isn't templating engines. And although a better solution is always welcome, a bit of procedural code inside a template is not a big problem either.
The real problem is that so many projects and frameworks don't have a powerful enough View layer that is separate from the (preferably optional) templating engine. In many cases it's even worse, and the templating engine is the entire implementation of the view layer. This pushes a lot of view logic into the templates, where it quickly degenerates into spaghetti. (In even worse cases, any logic the templating engine can't handle gets coded inside the controllers, and view logic starts leaking through the layers.)
Fragmentation into purely static templates is only a solution if you've dealt with with all the other view-related issues, and still end up with too much logic in your templates. And by "too much" I mean that it results in errors and maintenance overhead, not just that it looks ugly.
Intensive use of logic inside templates is definitely a code smell, but you have to be careful not to address the wrong problem. The templating method itself is rarely the root cause.
124 comments
[ 2.5 ms ] story [ 179 ms ] threadAnd Stanford has done some nice work on segmenting the DOM into semantic chunks. The site appears to be down now, but it's usually hosted at http://bricolage.stanford.edu/. Check out their paper on the "Bento" algorithm.
PS: If the site didn't load, how do you know it sucks?
Instead of splitting up the task of templating in the following, arbitrary fashion: [broken]
We can create a non-arbitrary, completely objective separation where the view/template layer truly contains no logic what so ever: [broken]
Cool article; made me think about how I've been handling views. I think I agree with you, but I'll need to mull it over for a while. Thanks!
Oh dear. "BUT, ITS SANDBOXED ITS OK!" :)
I'm going to abuse a Bruce Schneier quote and suggest that if you're trying to get a job done and you start by writing a template interpreter, you're doing it wrong.
I have found that any complete templating system has sufficient flexibility and extensibility to do what you want. Though I use Perl's Template Toolkit.
As someone who really loved Jinja2 templates, I was very pleased to find Swig on Node.
The funny thing about this post is that the author tells us to get off our high horses and come down from our ivory towers... and then proceeds to make a series of highly conjecturable claims presented with no factual evidence beyond his own confident assertion that he's in the know. There's like, no chance that in two years he'll be advocating for his new new philosophy.
In the meantime, I'm left to wonder "Iain Dooley who?" and be glad that I'm confident enough not to read an opinion-as-fact article and assign it significant credibility.
PS: A good first editing step is to ask "does my opinion-as-fact blog post question the capacity and potential of a professional web designer to understand simple concepts like string interpolation, and could they find this insulting?" before assuming that you've got it all figured out.
The capacity of designers to understand anything isn't the subject of the post, so I'm not sure why anyone would be offended by that.
The idea is that it's easier to find someone to work on HTML/JavaScript/CSS in a static HTML context than it is to find someone familiar with whatever frameworks you're using and it's templating language, then to have that installed locally (especially when you're not working with a long term in-house team of designer/developers and don't have lots of time to spend on training people).
I also personally find it far easier and quicker to iterate and test new interface ideas quickly when working with static HTML so I like to be able to view my templates outside of the context of my application/framework etc. and then iterate without having to re-apply a bunch of templating code.
Have the humility to understand that many of us have been doing this for years and have seen numerous attempts to revolutionize templating, and gasp have written webapps before the idea of templating really took hold.
If you want to persuade people to take up your ideas regarding DOM manipulation in the controller, I'd suggest not starting by telling people they are writing spahgetti code. It's a great way to get page views, it's a poor way to persuade people.
People probably would have reacted much better to your argument if you started with "Hey, I'm doing things this way and here's why it works for me" instead of "You're all idiots who write spaghetti code". Embedding XSL selectors in HTML attributes which is processed by a half-assed implementation of XSL in PHP is the kind of thing I think when thinking spaghetti code.
What you don't realize is that you've invented a new templating language based on XSL but with half the features. Those of us who've been around the block a few times like to call this inner-platform effect. We've also seen this idea before when it was pitched with J2EE and used XML with an XSL templating system.
Regarding your critique of Fragmentify, that's actually not so much what I'm advocating here as it is just the impetus for realising that there are 2 distinct components to templating which are: 1) the re-use of common assets, and 2) the application of some "logic" to display dynamic data.
It doesn't matter what you use to fragment your markup (I personally think that using XPath to manipulate an XML document isn't particularly off the mark but whatever, to each their own). Dreamweaver allows you to edit common assets pretty easily and then export a ZIP with head-to-foot complete HTML documents in it. I'm sure there are a million other ways to skin that cat.
What I'm saying is that the separation between "display logic" and "business logic" either doesn't exist or at the very least shouldn't be occuring between the backend and the frontend.
You could, if you wanted to, put your "view rendering" code in some other place in your application, but that's tangential to my case for completely removing any and all logic from templates and working solely with (and iterating solely with) HTML/CSS/JS when building your interfaces.
I find a text editor (vim in my case)/photoshop + haml/sass + live reload to be my most productive workflow, one screen for the text editor, one screen for the browser, when I save the browser reloads the page.
For me there are a lot of things that just work smoother by having the data populated, when I work with designers I just take whatever they give me (sometimes just a PSD) and work with it, if they need static HTML/CSS I just use wget/save as webpage to save the html and assets.
The result is a thin ~400 followers on http://github.com/pure/pure, we use it for our web app, and I get regular thanks emails. Even some copycats appeared.
Nothing changed. Server power is still wasted sending HTML to idle terminals using a markup/logic soup like we do since 1995.
A pretty useless fight, but at least I'm happy I tried.
You try to make a rant (because that's what it is) more interesting by adding random fake quotes/thoughts that you attribute to the reader, i.e. me. There's exactly one person that knows my thoughts and I don't feel represented by your 'quotes' - so everything in light green on that site is bullshit according to me. Lucky for me you colored the link-bait title in the same way, so..
Writing is hard.
(For what it's worth, the attributions didn't bother me.)
Presenting something as fact is an extremely quick way to find out if you're wrong. It's much faster than asking a question. The impulse to correct is stronger than the one to answer. So I interpret the post as the blogger's subconscious attempt at verifying and normalizing his opinions.
In this way, a blog is mostly a self development tool. I should start one of my own, I think. I never have before because I lack the hubris to think that my little discoveries are novel enough that anyone else would care. But I see now, maybe that's not the point.
I am definitely using a blog as a means of getting "outside the vacuum", though, and as you say evaluating my own opinions by putting them out in public and seeing how people react.
Yeah. And I wonder "peteforde", who? Should we only listen to what established figures have to say?
The problem with your attitude is that nowhere you access what the author wrote --you just add critique how he told it: highly conjecturable claims presented with no factual evidence, etc.
The important stuff to ask is, was it a good idea?
(Good ideas don't always come with factual evidence you know). What you think of it? What counter-example can you find.
Basically you just told us: the author is unknown, he doesn't formally prove his idea. Well, DUH!
I read tons of posts with such qualities on the inter-tubes.
That doesn't stop me of getting something out of some of them, and a few of those are pure gold.
"""PS: A good first editing step is to ask "does my opinion-as-fact blog post question the capacity and potential of a professional web designer to understand simple concepts like string interpolation, and could they find this insulting?" before assuming that you've got it all figured out."""
Yeah, as if this is the gist of the post, and the litmus test of a technical idea is if it can hurt the feelings of web designers...
https://github.com/hij1nx/weld
And I tried the concept using Nokogiri in Ruby. I found that in practice it gets really tedious. I had to make sure that every single element I wanted to manipulate had a unique id. Then I had to account for updating the content of an element versus an arbitrary attribute for that element. Or adding an attribute, like some data-* attribute. I realized why string interpolation is just so much easier.
There's also the problem where the DOM parser changes the original HTML in some way. How will it deal with conditional comments for IE? Or slightly malformed HTML that you want to keep that way?
I ended up going back to Handlebars.
Regarding alternative formats like JSON or PDF, I guess you can add a layer there.
The way it is different is that it is an inversion of control inside the template, not that it is changing up the layering. You still have a "construct data" layer and a "present data" later, and you can still swap out the "present data" layer with something unrelated, such as a normal template engine or whatever else you wish to use to generate JSON or PDF.
However, inside the "template", rather than having HTML with embedded logic (where you can almost envision the HTML calling into the logic to insert text or execute flow control at specific points), you instead have logic that manipulates the HTML via DOM, modifying the HTML to contain text at specific points. You could probably even make a compelling argument that these are duals of each other.
What we've generally done as an industry is accept the former, but I'm not sure whether one is better than the other.
What's more, a good DOM manipulation strategy and library can be really easily ported to any language, freeing up your templates to go wherever you may feel is appropriate in the future.
This does not seem like a worthwhile tradeoff to me. And the author doesn't address loops, which often want to have special treatment of first or last elements, even/odd rows, and other small bits of logic. When you combine these things, you're going to have a combinatorial problem, I can just imagine a shopping cart table with templates like shopping_cart_item_list__table_row__last_item__logged_in__even_row__multiple_quantities__discounted_item.html
And what's with the really confrontational tone? This article would've been improved by spending a couple hundred fewer words putting words in the reader's mouth and insulting their tools/code. There's a chance this could be useful in some situations, but I sure don't want to spend any time talking to this guy.
EDIT: Also in response to the issue of double handling, I did mention this in the article:
In that second example of course, we've got a bunch of duplicate markup, but that's not our problem. That is the job of whatever system you're using to fragmentify your templates and re-use common assets
---
Your hotlinks to ditaa.org seem to be down because the server on the other end is serving stack traces ...
* http://ootips.org/yonat/patterns/phrasebook.html
* http://www.perl.com/pub/2002/10/22/phrasebook.html
* https://metacpan.org/module/Data::Phrasebook::SQL
"ORM is an anti-pattern": http://seldo.com/weblog/2011/08/11/orm_is_an_antipattern
I suspect for certain parts of some apps, ORM's might work OK. But in general for applications of any complexity they will break down hard and fast, and lead to bad db design, bad performance, or both.
In other words, I see an ORM as an antipattern because the subset of cases where it works really well at bridging the gap you probably don't really want an RDBMS in there anyway.
And if you do make it work (encapsulating your db behind updatable views) without running into this, it's a heck of a lot more work than hand-coding SQL.....
What we've done in LedgerSMB is quite simple. All db statements in new code (outside the mapper functions) are in stored procedures. Everything is mapped in there using a Perl API so in the new code (post-1.2) otherwise all SQL is in one set of files and all Perl is in another, with minimal overlap.
This sort of thing makes for very clean development. No, spaghetti code is making me have 15 files open in VIM trying to figure out which of them has the function that is being called in it, with several candidates all bearing the same function name (oh, the horrors).
Stored procedures are a great way to abstract this out and force good SQL coding practices btw.
How exactly do stored procedures prevent you from writing "BAD SQL"? They do no such thing.
Stored procedures are a great way of adding complexity to your code, complexity equals bugs and longer development time. There are reasons for stored procedures, but using them simply to remove SQL from your front end is not one of them. And certainly not because of a fear of "BAD SQL".
To be clear, they prevent one specific case of bad sql, namely queries that are written like this:
SELECT a.*, $col_list
$group_by$having;
Then when you go to find out how $where is define you see a lot of statements like:
if ($http_query->{date_from}){
WHERE (date_entered > in_date_from or in_date_from IS NULL) ....
Then you also gain testability. We can write test cases for the stored procedures because they have discrete entry points and make sure they are acting according to spec.
Stored procedures make it much harder to understand the code since you can't just read the query - you have to find the stored procedure and check it there. (And be realistic - no one has perfect documentation.)
And heaven forbid you have to change the query - now you need to make sure no one else is using it, and you end up with tons of versions of similar stored procedures, not all in use, and many that could be combined.
It doesn't seem worth it to me.
I use stored procedures for data reduction - I want to keep the data in the database, and process it before sending it out. (Saves bandwidth vs doing it in the front end, and often it's faster too.)
But that's it. Using stored procedures just to wrap ordinary queries is a terrible (but very common) idea. (I am aware that it saves time on generating a query plan, but usually that's a case of premature optimization.)
And using it to enforce code policies? Way overkill.
1) Testability. you can write test cases against a stored proc. You cannot write test cases against a SQL query embedded in the middle of a function in another programming language.
2) Single point of control. You can have one function that runs the stored proc there and check properly for SQL injection, ensuring that everything is free of SQL injection as far as front-to-backend is concerned (and in Pg, that only leaves SQL injection issues in dynamic SQL which can be searched for and audited separately).
So that's why not to put it there.
As to changing the query.... I only use databases which come with transactional DDL so that's not an issue as long as inputs and outputs don't change. If the inputs and outputs have to change, we can handle that too with transactional DDL and the fact that we make the interfaces discoverable. In this case, we'd
BEGIN;
DROP FUNCTION IF EXISTS foo_bar(...);
CREATE OR REPLACE FUNCTION foo_bar(...)...;
COMMENT ON FUNCTION foo_bar(...) IS $$...$$;
COMMIT;
Because of the way Pg works this shouldn't really cause issues for currently running queries.
As for finding the right function, since these are all called on a declarative interface so you know what the function name is quickly, and so it is a matter of quickly finding it in a directory of SQL files.
As for testability, don't underrate this. You can insert data, run your tests, and roll back. So for example for our 1099-MISC and INT handling, we run more than 40 tests on a pre-written data set that we can run without ever committing to production and which will never conflict with production data (and therefore does not lock other users out). That's approx. 20 tests per sproc there.
Something like SQL::Abstract (https://metacpan.org/module/SQL::Abstract) or Fey (https://metacpan.org/module/Fey) would slot in easy for most tasks like this:
On to the article though.... I think that what the individual is discussing in fact is something different, which is the need for stable API's between layers of the application.
I am very skeptical of his idea that all projects can benefit from his proposed solution. Indeed in areas like complex reporting, a template is conceptually simpler than HTML mockups that have to be populated by Javascript. At that point XSLT on the client starts making a lot of sense.... However, not at all sure that's always a win compared to templates. But then XSL files pose all the issues he is complaining about!
The beauty of templates on the other hand is the ability to create diverse output. XSL is no different there. One can create a LaTeX file, an HTML file, a CSV. Anything else. For systems that need that diversity, going with HTML and Javascript is a net loss.
What I'd really like to do is go 100% the other way: all functions, all the time.
A view could just be a named function, accepting the object(s) to be rendered as arguments, define some closures for callbacks/event handlers, then return a DOM structure.
But it turns into write-only code pretty fast when you have tons of callbacks flying around for highly interactive elements.
For everything else, you can use data-binding. If you're already writing lexically scoped render functions, you can trivially create a data-bindable local object in a variable to eliminate the event management process. Instead of an onclick event for a checkbox, you can trivially set the checked property to be equal to an observable value box containing a boolean. With the right abstractions, callback spaghetti is not an issue.
1) Fragmentation is a problem, particularly with some templating systems. Layouts should almost always be a single file. Things going inside the layout should probably be single files.
2) As long as templating means sprinkling extra tokens to process throughout a document, there's going to be some coupling problems. Transforming a document based on some external criteria is an interesting alternative.
There's certainly a number of transformation based solutions out there, some of them pretty powerful. But as I was thinking about this a few years ago, it occurred to me that maybe I don't want a powerful uber-transform set so much as I want a simple descriptive set of semantics for addressing content into nodes of a document.
Then I thought about where I'd seen this kind of thing come up before in the realm of document styling: DSSSL and XSLT vs CSS. The simple descriptive CSS won out and has worked out more or less well.
So... I came up with something I called `CAST` (Content-addressed Style Templating):
http://weston.canncentral.org/web_lab/CAST/about.html
Basically, you use a subset of CSS selectors (or XPath queries) to pick out a node of a document, then you specify a content rule, and the engine drops a content string into the document node.
I ended up writing my blog around the idea. I ended up being pretty happy with a very simple set of rules, despite the fact that there's not much too the system beyond that -- for example, there are no rules for conditionally hiding a node based on whether or not it's needed, no rules for repeating certain nodes. I think those things might be nice, but it turned out if I was willing to push a little bit of the view down into model layer, I didn't need them at all, and I was (I kindof tend to think that any application is going to have a bit of model-view bleed-across anyway, you just have to figure out how you'd like to manage it).
If anybody's curious, this post made me get off my behind and put the code up on GitHub:
https://github.com/westonc/CAST/
But it's in PHP, which I suppose will probably turn off a lot of the cool kids, so I should probably write a Ruby or Clojure version. :)
It's easier to solve the problem of making a nice, easy way to "address" content (I used "animate" but basically they're the same thing :) than it is to solve the multitude of problems caused by choosing a technology stack and creating templates in it for your application.
Presumably DOM manipulation really can't be done beyond applications which are HTML-only in any reasonable sense without getting back to the things you don't like about templating, right?
If you had, for example, a bunch of PDF code as a "template PDF" then you might just load that and do string replacement on whatever placeholder text you have in there - but yeah the primary use case I'm thinking of is in implementing web based interfaces.
So if you want a consistent interface, templating is pretty clearly the way to go, correct?
So like, you'd want to be able to have something like:
then do something like: My argument to that would be that there's no realy need for that abstraction - you don't gain anything by it because you have to have some abstracted output engine that is capable of doing that HTML can already do, which is like, HTML :)Hey, I'd love to continue the discussion, but I think the HN comments are kind of limited in how much they want you to discuss here, feel free to email me iain@workingsoftware.com.au
EDIT: oops, code formatting
I will probably post something on the selection and design of our templating system for LedgerSMB in my blog too (http://ledgersmbdev.blogspot.com) by the end of the week.
One of the useful applications of dools' ideas is that you could have a mockup which included lorem ipsums or other dummy text. This would make it easier for web developers to test layout.
OTOH, as I say, I am not at all convinced that it is a net win for programs that generate multiple formats of output./
I don't know, though. I tend to think that this is less a job for the view (and templates) than it is for smart models, or models with some kind of helper that assists them in knowing how to represent themselves in a given format.
with software, your app is code driven. the gui follows what the code tells, instead.
even if in both cases you have a mvc these days.
http://blog.choonkeat.com/weblog/2008/10/hquery-an-unobtrusi...
https://github.com/choonkeat/hquery
Nope. "hquery" is just a library I wrote to do USS in Rails. I believe any language / framework can have its own USS renderer.
I'm totally in agreement on this. Any language or framework can address this very simply - we don't need "one to rule them all".
No, templating is not perfect. Nothing a programmer does is perfect. Our job, as programmers, is to make stuff suck less. We break stuff until it works. We squash bugs until we can't find any more. That doesn't mean what we've built is perfect. It means what we've built is the best we could build with our current understanding of the problem.
I don't think of spaghetti code as the presence of logic in presentation code, I think of it as a lack of separation of what SHOULD logically be abstracted. I find the code it labels evolves over time as the common abstraction level of things increases and we move closer and closer to fully isolating concerns.
That's not how templating works, that's just some messed up code.
I totally disagree with the idea that having static HTML as templates and transforming them with DOM manipulation is better then templating. When you do DOM manipulations you make assumptions about the structure, if that structure is changed by somebody, you are screwed. The less assumptions you make the better. Also last time I checked DOM parsing was a relatively slow process, even if it would be better than templating it still has to justify the performance overhead.
Also let's not forget that writing if's are easier than writing DOM queries.
Templating allows separation of view logic and business logic, I find it much cleaner to have the view logic in the templates, this is in fact what the author complains about, but how is having both database calls and layout logic in the same place cleaner?
The real problem is that so many projects and frameworks don't have a powerful enough View layer that is separate from the (preferably optional) templating engine. In many cases it's even worse, and the templating engine is the entire implementation of the view layer. This pushes a lot of view logic into the templates, where it quickly degenerates into spaghetti. (In even worse cases, any logic the templating engine can't handle gets coded inside the controllers, and view logic starts leaking through the layers.)
Fragmentation into purely static templates is only a solution if you've dealt with with all the other view-related issues, and still end up with too much logic in your templates. And by "too much" I mean that it results in errors and maintenance overhead, not just that it looks ugly.
Intensive use of logic inside templates is definitely a code smell, but you have to be careful not to address the wrong problem. The templating method itself is rarely the root cause.