Handlebars is Logicless

Like, really, really logicless.

Handlebars is the templating system that I chose when writing Concussion, the engine that powers this blog. It’s one of the big names (I’d heard of it even though I’d never done any Node work before) and it has built-in support for Express via handlebars-express. Since it’s obviously so widely used, I figured it would be fine for my purposes. And while everything turned out fine in the end, I had to change the arrangement of responsibilities in my app to get around some unexpected problems, because as it turns out, Handlebars is logicless.1

The README points this out right at the top:

Handlebars.js is an extension to the Mustache templating language created by Chris Wanstrath. Handlebars.js and Mustache are both logicless templating languages that keep the view and the code separated like we all know they should be.

Which is all it has to say about the matter. Seems reasonable enough. If you’re doing anything approaching MVC, the view should be responsible solely for how the data is presented to the user. It shouldn’t do anything.

Handlebars takes this to a bit of an extreme.

There’s logicless, and there’s Logicless.

I think we can all agree that views (“templates” in Handlebars) shouldn’t directly act on models and shouldn’t implement business logic, but I do think that they should be masters of their own domain when it comes to turning data into something the user can see and interact with. By definition, they are a transform on a set of data. Handlebars recognizes this, and allows you to use all sorts of helper functions. You can include or omit a block of content based on the presence of a certain variable, call a function to properly format a value, or shell out to a sub-view (or “partial”).

What you can’t do is provide an arbitrary JavaScript expression to an if block, although you wouldn’t know it by reading the docs:

You can use the if helper to conditionally render a block. If its argument returns false, undefined, null, "", 0, or [], Handlebars will not render the block.

The if block can only accept a value (which could be a variable or the output of another helper). And because you can’t use an expression, you can’t do comparisons.

This should be a requirement of any templating engine.

Maybe I’ve just been spoiled by using PHP in the past, where (at least in CakePHP, the framework I’ve worked in) the templates are just regular PHP files, but I think having the basic ability to perform comparisons is absolutely central to a view’s ability to do its job. I want to be able to show (or not show) a section based on the view’s own choosing, not because a value is truthy or falsey.

Example: Pagination

This is a super simple example. Here’s how I want to accomplish a pagination view:

  • If the current page is greater than 1, show a link that navigates to page current - 1
  • If the current page is less than the number of pages, show a link that navigates to page current + 1

However, in Handlebars I have to do extra work in the controller to accomplish this:

  • If the current page is greater than 1, create a new variable previousPage = current - 1
  • If the current page is less than the number of pages, create a new variable nextPage = current + 1

Then in the template:

  • If previousPage exists, show a link that navigates to page previousPage
  • If nextPage exists, show a link that navigates to page nextPage

In addition to making more steps, this increases coupling between the controller and the view, something we should be always striving to reduce.2

GitHub Discussion

There’s a long and contentious discussion on Handlebars’ GitHub repository. The maintainers of Handlebars are gently sticking to their guns, which is understandable. Some of the commenters on that discussion are extremely dismissive. But there are many commenters who wish for more expressiveness in if blocks. Mike O’Brien sums it up best:

An if helper is there, IT IS LOGIC. So the whole logic-less argument is a total straw man

[…]

I totally agree with and understand not having business logic in templates. But unless you’re doing extremely trivial templates your going to have some view logic there. Handlebars obviously recognizes this since the if helper exists. Working around a hamstringed if helper by adding a bunch of view logic in your code is not the answer […]

Solutions

  • Prepare your data in such a way that your templates don’t need to perform any math or comparisons. This is what I’ve done – basically what I showed in the pagination example.
  • Build an unwieldy set of helpers (or one multi-purpose helper) as shown here.
  • Use a different templating system. EJS and Underscore templates look like good candidates – they read a lot like the PHP templates I’m used to, with all the good and bad that entails. doT also looks nice. Additionally, there are a lot of engines that allow comparisons out of the box but still disallow full access to JavaScript, if that suits your fancy.

Think I’m wrong? Got something to add? Let me know on Twitter!


  1. Although you have to make it to their GitHub README to find out. Their homepage makes no mention of this limitation. 

  2. In this particular example there’s not a huge difference in how coupled things are, but the fact that I had to change what happens in my controller in order to make my view happy irks me enormously. We didn’t need to provide more data, the view just required it to happen in a certain way. That’s coupling. 


For a few weeks I’ve been working on a new iOS app, written in Swift. The problem domain is super simple: it’s just a list of what I’m calling “reminder snippets” – for now, basic Title / Value pairs – that are editable in the app, and show up in a Today View Snippet.

Screenshot of example app, Neumonic

Having the problem domain so small allows me to experiment with Swift and potential architectures. I’ve been incorporating some lessons I learned from colleagues at my last job, like using immutable model objects (Swift structs, naturally, for value semantics) and Repositories that are responsible for persistence, caching, and so on.

Protocols

I took the Protocol Oriented Programming talk from last year’s WWDC to heart, so every abstraction in the app is a protocol. (I’ve already written a bit about this talk here.) Specifically, I have a ReminderRepository protocol (with MockReminderRepository and PlistReminderRepository implementations) and a Reminder protocol, with one incredibly simple implementation.

public typealias ReminderID = String

public protocol Reminder{
    var id : ReminderID { get }
    var title : String { get }
    var value : String { get }
}

public protocol ReminderRepository {
    func getAllReminders(callback: Result<[Reminder]> -> Void)
    func getReminder(by id: ReminderID, callback: Result<Reminder> -> Void)
    func addReminder(reminder: Reminder, callback: VoidResult -> Void)
    func deleteReminder(reminder: Reminder, callback: VoidResult -> Void)
}

(Result is just a Success/Fail enum that contains some value on success and an error on failure)

Equatable

So far, so good. I really like this architecture. But problems start to crop up when I need to be able to compare Reminders, for instance, in an implementation of deleteReminder:

public func deleteReminder(reminder: Reminder, callback: VoidResult -> Void) {
    // Error. Can't call indexOf because reminder doesn't conform to Equatable
    if let index = reminders.indexOf(reminder) {        
        reminders.removeAtIndex(index)
        callback(.Success)
    } else {
        callback(.Failure)
    }
}

But if we make Reminder conform to Equatable, we lose the ability to have a heterogeneous array of types that conform to Reminder. (Details are in the Protocol Oriented Programming talk. Seriously, watch it.)

The solution given in the talk for general-case comparison is to implement an extension on our protocol. I thought I’d be clever and factor this out into a new protocol, HeterogeneousEquatable, and have Reminder extend from that.

public protocol HeterogeneousEquatable {
    func isEqual(other : Any) -> Bool
}

public extension HeterogeneousEquatable where Self : Equatable {
    public func isEqual(other : Any) -> Bool {
        if let typedOther = other as? Self {
            return typedOther == self
        }
        return false
    }
}

public protocol Reminder : HeterogeneousEquatable { /* ... */ }

Array.indexOf()

Now returning to the reason I initially wanted to make Reminders Equatable – so that I can call reminders.indexOf(someReminder). Right now we still can’t do that, because while we have roughly equivalent functionality, it doesn’t come under the auspices of the Equatable protocol.

Okay, so what if we just extend Array ourselves?

public extension Array where Element : HeterogeneousEquatable {
    func indexOf(element : Element) -> Index? {
        return indexOf({ (currentElement : Element ) -> Bool in
            element == currentElement
        })
    }
}

Great! Everything still compiles. Now we just have to call our overloaded implementation of indexOf:

public func deleteReminder(reminder: Reminder, callback: VoidResult -> Void) {
    // Error again. Sad face.
    if let index = reminders.indexOf(reminder) {        
        reminders.removeAtIndex(index)
        callback(.Success)
    } else {
        callback(.Failure)
    }
}

Now we get Using "Reminder" as a concrete type conforming to protocol "HeterogeneousEquatable" is not supported. Which is true. Reminder isn’t a concrete type. This is a shortcoming in the compiler; it needs things to be nailed down to concrete types here. One can assume that the reason for this is compiler implementation rather than an intentional limitation of the language at a design level. There’s a great Stack Overflow answer by Rob Napier on this.

A Mediocre Solution

Austin Zheng has a blog post about building a HeterogeneousEquatable (which he calls AnyEquatable), which is a good resource if you found my post hard to follow, but he doesn’t look at the case of implementing an extension on Array.

I asked about this on the swift-users mailing list, and Hooman Mehr pointed out that the best way to achieve this is to write a method in an unconditional extension on Array:

extension Array {
    func indexOf(element : HeterogeneousEquatable) -> Index? {
        return self.indexOf { (currentElement : Element) -> Bool in
            if let currentElement = currentElement as? HeterogeneousEquatable {
                return element.equals(currentElement)
            }
            return false
        }
    }
}

This makes me sad. It forces me to pollute the interface of Array with stuff that doesn’t apply in most cases, and it causes confusion about which implementation of indexOf will be called in an instance of [MyType] where MyType implements both Equatable and HeterogeneousEquatable. (The other option is to name it indexOfAny, as Hooman suggests, but I don’t much like that either.)

A Better Solution, Sometimes

I took my quest to the swift-evolution mailing list, and got better results, but they only apply in certain situations.

Dave Abrahams (the guy who gave the Protocol Oriented Programming talk in the first place!) showed that while we can’t use a value of type HeterogeneousEquatable (where the concrete type is unknown) where the requirement is Element : HeterogeneousEquatable, we can do that when the requirement is Element == HeterogeneousEquatable. That’s awesome!

But.

That means that the variable must be typed explicitly as HeterogeneousEquatable. Reminder, even though it extends from HeterogeneousEquatable, is not acceptable.

public extension CollectionType where Generator.Element == HeterogeneousEquatable {
    func indexOf(item: Generator.Element) -> Index? {
        return indexOf {
            return item.isEqual($0)
        }
    }
}

// ...

public func deleteReminder(reminder: Reminder, callback: VoidResult -> Void) {
    if let index = reminders.indexOf(reminder) {        
        reminders.removeAtIndex(index)
        callback(.Success)
    } else {
        callback(.Failure)
    }
}

Type HeterogeneousEquatable does not conform to protocol 'Reminder'

Conclusion

I’ve had to go ahead with the unconditional extension of Array. It’s the only thing that works properly for my use case, at least today.

It is my desperate hope that future versions of Swift will allow for this kind of abstraction – or just go ahead and solve the Equatable problem in a first-party way.

Denouement

Back when the WWDC talk was new there was a big kerfuffle in the Apple development community about the problem of heterogeneous collections of things that conform to a single protocol – how the decision to split protocols into “has Self requirements” and “doesn’t have self requirements” worlds was benefiting the compiler at the expense of the programmer. Michael Tsai has a good overview of the various blogs from that time, all of which are worth a read, including this post from Brent Simmons:

Something like this ought to come naturally and easily to a language, or else that language is not helping me write apps.

I’m generally very positive on Swift – I think when Swift 3.0 hits and the language starts to change a little more slowly, it will be the obvious choice for future projects – but it has some sharp edges for the time being, and if I was to start a production-ready project today, I’m not entirely sure whether I’d choose Swift or Objective-C.


Mike Ash’s Friday Q&A this week takes on Swift’s funny-looking String API. Most of what you’d normally want to do with strings is absent — for the time being, we should be using NSString methods — and it doesn’t allow us to iterate over its characters in the way we’d expect. As of Swift 2.0, we can’t do:

for char in "some string" { /* ... */ }

That’s because there are several ways to interpret the above code — do we want to iterate over all bytes in the string, assuming it’s represented as UTF-8? All Unicode code points? All grapheme clusters? The String API’s design in Swift 2 forces the developer to explicitly decide by exposing these possibilities as views on the string, leaving the system’s internal representation of the string as an invisible implementation detail.

From Mike’s post:

Swift’s String type takes an unusual approach to strings. Many other languages pick one canonical representation for strings and leave you to fend for yourself if you want anything else. Often they simply give up on important questions like “what exactly is a character?” and pick something which is easy to work with in code but which sugar-coats the inherently difficult problems encountered in string processing. Swift doesn’t sugar-coat it, but instead shows you the reality of what’s going on. This can be difficult, but it’s no more difficult than it needs to be.

This is an excellent companion to objc.io‘s must-read NSString and Unicode showing the implications for Swift.

If you want the Cole’s Notes version, Apple has a pretty good, much shorter explainer on their Swift blog.


Concussion

Or, how I came to write another blog engine no one asked for

I officially have a personal website / blog! I wrote my own blog engine for fun, which I don’t expect anyone else to use, but is nonetheless open sourced on GitHub.

The Story

I was rear-ended early this year and sustained severe whiplash and a minor concussion. I returned to work after a week or two, but my symptoms returned a month later, and I’ve been at home ever since.

When concussion symptoms last for more than three months, you are deemed to have Post-Concussion Syndrome. The mainstream protocol for getting better is to severely reduce the amount of mental and physical activity to engage in. Read for 15 minutes, then go rest. Listen to a podcast for 15 minutes, then go rest. If you have a few good days in a row, you increase your activity level a wee little bit. (I’ve had much better results following MMTR‘s PCS protocol, but that’s another story.)

For a long time, my doctor advised me to avoid screens. No TV, no cell phones, no tablets, no computers. For a techie like me, this was difficult.

As my condition improved and I was allowed to do little bits of computer time, I decided I would finally set up a personal website. After looking around at the usual suspects like WordPress, Ghost, and Jekyll, and concluding that they all met (exceeded) my needs, I decided to write my own anyways. It would provide me with a nice way to get my coding skills back up to speed, and it seemed a simple enough project that I could do it in sub-hour time increments.

The Blog Engine

I decided to branch out a little bit and implement my system in a technology I’ve not worked much with before, NodeJS.

I’m an avid listener of the Accidental Tech Podcast, and Casey Liss, one of the hosts, developed his own blog engine in Node, Camel, that aligned pretty closely with what I wanted to do: blog posts specified as Markdown files, no admin interface, super simple implementation. He also suggested deploying to Heroku, since there’s a great integration with git and Dropbox: deploy by simply pushing your branch to Heroku’s git remote, which is also synced with your Dropbox. That way, blog posts can be checked into the repository (and thus are versioned), and can be modified via Dropbox when you’re not at a development computer.

I read Casey’s source code, and while the rendering pipelines of our engines are nearly the same, the organization is quite different. Whereas Camel is arranged as a single app.js file, mine is at least partly modularized in an MVC-lite sort of architecture. (It’s a super small codebase, so going whole hog didn’t really make sense.)

I ended up using Express for the web server with Handlebars views. NPM came in incredibly useful, providing most of the meat of the engine, with Markdown rendering, code highlighting, and my favourite new (to me) technology, promises. I have quibbles, especially with Handlebars’ no-logic-in-views philosophy, but that’s the subject of another post.

In any case, the blog engine is called Concussion, it’s powering this site, and it’s available on GitHub.


Update March 7, 2016: Doug Gregor wrote about this problem on swift-evolution

This post is also available as a playground.

Seemingly the most-talked-about session from this year’s WWDC was Session 408: “Protocol-Oriented Programming in Swift”. Since Apple made all WWDC videos available to the public this year, you can watch it on Apple’s Website, or read a transcribed version on ASCIIwwdc. As promised, it’s a really interesting talk about how most abstractions should be modelled in Swift as protocols instead of base classes, and how that meshes well with generics in order to produce nicely architected code. Lots has been written on the subject, so I won’t repeat it all here – you can watch the session or read any of the number of blog posts on it.

However, as I was watching the talk, I noticed a quirk with how protocol extensions work that I think is going to confuse people and lead to difficult-to-track-down bugs. I tweeted a screenshot of a playgound illustrating this. But unless you’ve been following along closely with Swift’s development, it probably doesn’t make much sense:

So here’s the more in-depth explanation.

The setup

Apple’s vision of protocol-oriented programming is built on top of Swift’s protocol extensions and default protocol implementations. (If you’re coming from a non-Apple development background, substitute “interface” for “protocol.”)

As an aside, the main feature that enables Apple’s vision of protocol-oriented programming (default protocol implementations) would have solved a big architectural problem for us at work. We use Core Data for many of our data objects, but not all of them. Therefore we have two base classes for model objects: one that inherits from NSObject and one from NSManagedObject. These two base classes provide almost identical base implementation for a bunch of functionality, which we’ve formalized by making both of them conform to a Model protocol. Each of the required methods from that protocol are implemented – usually identically – in the two base classes that conform to it. Default protocol implementations would have saved an awful lot of copy and paste in this situation!

Let’s say we have a protocol for a piece of our app that prints out textual representations of emotions:

protocol EmotionPrinter {
    func printHappiness() -> Void
    func printSadness() -> Void
}

This allows various implementations of the protocol to decide:

  • what they’re going to print
  • how they’re going to print it

But we want to be nice to implementers. We want them to be able to ignore one (or both) of these decisions if they don’t care about it. Let’s provide some default implementations:

extension EmotionPrinter {
    func printHappiness() -> Void {
        output("HAPPY")
    }
    func printSadness() -> Void {
        output("SAD")
    }

    func output(emotion: String) -> Void {
        print(emotion)
    }
}

To check it works, we can create an implementation that just uses the default implementations:

class BasicEmotionPrinter : EmotionPrinter {}
let basicEmotionPrinter = BasicEmotionPrinter()

basicEmotionPrinter.printHappiness() // Prints "HAPPY"

Now we’ll create a custom implementation which wants control over both what is printed and how it’s printed.

I’m too lazy here to invent an alternate method of printing. You could imagine rendering this in a UILabel or something. I’m just prepending some text and using print in this implementation of output.

class EmojiEmotionPrinter : EmotionPrinter {
    func printHappiness() -> Void {
        output("๐Ÿ˜€")
    }
    func printSadness() -> Void {
        output("๐Ÿ˜ญ")
    }

    func output(emotion: String) -> Void {
        print("Emoji Printer 3000 says \(emotion)")
    }
}

let emojiPrinter = EmojiEmotionPrinter()

emojiPrinter.printSadness()    // Prints "Emoji Printer 3000 says ๐Ÿ˜ญ"

Additionally, (as expected) even if the compiler doesn’t know the concrete type of an EmotionPrinter, the right version of output still gets called from inside each implementation of printHappiness or printSadness. Here the compiler types printer as EmotionPrinter.

let printerArray : [EmotionPrinter] = [basicEmotionPrinter, emojiPrinter]
for printer in printerArray {
    printer.printHappiness()
}

results in:

HAPPY
Emoji Printer 3000 says ๐Ÿ˜€

The confusing bit

Okay, so everything has been pretty straightforward so far. We have a default implementation that does one thing, and an implementation that overrides the defaults, and successfully does its thing, too.

Here’s where things get tricky. Let’s say we do something funky, like calling output directly on an instance of a type that implements EmotionPrinter. (And here’s where my example falls down a bit. In this example, it would take a very foolish programmer to call myEmotionPrinter.output("blah") but we’rd going to do exactly that.)

for printer in printerArray {
    printer.output("I am a banana ๐ŸŒ");
}

I’d expect this code to produce the output:

I am a banana ๐ŸŒ
Emoji Printer 3000 says I am a banana ๐ŸŒ

But instead the output is:

I am a banana ๐ŸŒ
I am a banana ๐ŸŒ

Here’s an even weirder way to illustrate the same thing:

let castEmojiPrinter : EmotionPrinter = emojiPrinter;

emojiPrinter.output("๐ŸŒ")      // Prints Emoji Printer 3000 says ๐ŸŒ
castEmojiPrinter.output("๐ŸŒ")  // Prints ๐ŸŒ

emojiPrinter and castEmojiPrinter are two references to the same point in memory. I find it very surprising that based on what the compiler knows about the type (as opposed to the actual runtime type) can cause method dispatch to behave differently.

Apple’s rationale

As Dave Abrahams says in the WWDC talk:

You might ask, ‘what does it means to have a requirement that’s also fulfilled immediately in an extension?’ Good question.

The answer is that a protocol requirement creates a customization point.

A protocol requirement is anything that goes in your protocol declaration, like printHappiness and printSadness in my example, and is considered a customization point. Anything else that goes into a protocol extension is not. The latter is something that the default implementation wants to maintain control over.

This makes sense on the face of it. When you’re doing class-based polymorphism, you mark some methods as public or protected to allow subclasses to customize behaviour, and others as private or final to prevent that. In many cases what Apple’s done here is desired behaviour, and I think it forms an important feature in their approach to protocol-oriented programming.

But it’s a subtle and important difference in how the entire rest of the type system works in Swift. Everywhere else we have some form of dynamic dispatch – the runtime type determines which implementation of a method gets run, but here we have the compile-time type making that decision.

We made a mistake

With this “customization point” rationale in mind – that protocol requirements are customization points and methods in a protocol extension are not – this means that we made a mistake in modeling our protocol. I said that we wanted implementations to be able to decide what to print and how to print it. That means that output is a customization point and should have been included in the protocol definition:

protocol EmotionPrinter {
    func printHappiness() -> Void
    func printSadness() -> Void
    func output(emotion: String) -> Void
}

Try it out in the playground – it works the way you’d expect.

Language design is hard

If I were designing Swift (which, I should make clear, I should not be allowed to do) I think I would favour consistency with the rest of the type system over the expressiveness of “customization points” mixed in with other methods.

My first thought would be to mark the protocol extension’s implementation of output as final. That way by default everything is a customization point, similar to traditional subclassing, except for things specifically marked as “you can’t override this.”

But that doesn’t work because of the nature of protocol extensions. It’s conceivable that the EmotionPrinter protocol and EmojiEmotionPrinter implementation could be provided as part of a system library or 3rd party framework. Then I might have written the protocol extension on EmotionPrinter, providing default implementations for any types I was writing that conformed to that protocol.

And here’s the crux: by definition, any type that conforms to a protocol was designed with the knowledge of the protocol’s requirements. But it may not have been designed with the knowledge of any extensions on that protocol. EmojiEmotionPrinter implements a method output. But if I add a protocol extension with a final implementation of a method called output, that would have to cause a compile error, since EmojiEmotionPrinter is now overriding a method marked as final. And I think Apple chose to avoid this situation because it’s nonsense for code that a consumer of a framework writes to cause compile errors in the framework on which that code depends.

That situation would be both confusing and destructive. Code X that doesn’t depend on code Y shouldn’t fail to compile because of some change in code Y.

Epilogue

In a traditional subclassing pattern, EmojiEmotionPrinter would inherit from a base class that provided default implementations – and by definition would be aware of the existence of an output method in its superclass. But in this case it’s being modified after the fact, by a third party to conform to a protocol and its default implementation. Apple’s rules on dynamic vs static dispatch here are just one of many equally-or-more-confusing solutions to this problem. In the end, it’s just another quirk of Swift (and there are many!) that we’re going to have to keep an eye out for.