August 20, 2012
Introduction
Today I am happy to announce playnice
, a Clojure library of tools to help build HTTP standards compliant servers.
Existing libraries for developing web services focus mainly on ease. They try to make it easy to get started. They implement a naive, yet functional, version of the HTTP spec. It is basically the simplified understanding of HTTP that we all think in. A client makes requests to URLs, and the server responds with either an error or content.
But the HTTP spec is more complete than merely matching URLs and methods. There are many error classes defined in the spec and much functionality dealing with the meta-level of the capabilities of the server itself. In addition, there are many de facto standards and workarounds that should be baked into the server.
Philosophy
- Make it easier to serve HTTP standard responses without confounding HTTP logic with business logic.
- Make it easier for limited or non-standard clients to access resources.
- As much as possible separate orthogonal functionality into composable chunks.
playnice
was named because it plays nice with others. The Web is a wide world, and there are lots of clients out there. You should follow the spec as closely as possible, but accept that not all clients are so strict. Also, there is a variety of input and output formats. You should play nice with them, if you can. playnice
is a library to help Clojure programs play nice with the rest of the web.
playnice
Opinions
URL first, method second.
HTTP is about resources, which are identified by URLs. Different resources accept different methods. If a GET at a URL responds 200, but a POST is not supported, a 405 should be returned, not a 404.
Routes are values that do not exist in the global namespace.
Routes are immutable and first-class.
The order of defining routes should not matter.
Reordering my routes should not change the behavior of my server. Routes are declarative.
Servers should support the OPTIONS method and correct handling of unsupported methods.
OPTIONS returns the methods that are defined for a given URL.
Servers should support the Accept and Content-type headers of requests.
The handler is the wrong place to parse the Content-type header to figure out what kind of data you have been given. playnice
currently supports HTML, JSON, TXT, and Clojure literals. I hope to have XML soon.
Servers should support de facto standards and common workarounds.
"Redirecting after form post" is a de facto standard for browsers. IE does not support DELETE method in AJAX, so the workaround is to do a POST with a special query parameter set to DELETE.
Status
playnice
is still in early development, but it already contains the following components:
- Route + method dispatch (replacing Compojure).
- Middleware for abstracting away input and output formats.
- Middleware for handling "redirect after form post".
- Middleware for working around browser limitations.
Please check out playnice
if you need an HTTP compliant web server.
August 17, 2012
Paul Callaghan:
Callaghan’s 1st Law: the need for mutable state in a language is inversely proportional to its flexibility in manipulating data
Put another way, mutable state is a lower-level idea and becomes less important when your language supports higher-level ways of working.
Agreed.
Experienced Haskell programmers know that the type system is a tool for getting work done, and a great language for playing with designs, and they exploit these aspects to help them get their work done.
The key word in the sentence above is "Experienced". It does take a long time to begin using the type system to your advantage.
It was however a time of exploration, when researchers explored various ideas to find a good way of both having our cake and eating it. Monads are one of the solutions they found, and essentially gave us a small but flexible API for working with “computations” (like IO operations or state modifications, or various combinations thereof) as opposed to simple data values, and did so elegantly within the standard langage (ie. no ad hoc extensions needed). It got even better when syntactic sugar was added.
Nice history lesson.
The piece ends with some good advice:
As a new explorer (very warm welcome, by the way!), when you look at Haskell material you may see some very unusual or scary-looking stuff. But do bear in mind that a lot of it is just playing around with abstractions on top of the core language, and probably does translate to something more intelligible. Try to work out what is being said about the data being manipulated, and then it might not look so bad.
August 17, 2012
Chris Granger:
Clojure now has a true double click experience for getting started.
August 17, 2012
James Gosling speaking about what influenced the JVM. Fascinating. The world was a different place, then. And the amount of optimization that the JVM does is truly impressive.
August 16, 2012
I recently wrote about the birth of JSON, which describes how JSON came to be and the story of its success. Crawford talks about how JSON (or a very close equivalent) was reinvented several times throughout the years.
What strikes me is that JSON turned out to be an Algrebraic Data Type (ADT). Specifically, it is a tagged union.
JSON ADT variants:
- Null
- Boolean
- Number
- String
- List
- Dictionary
With these six constructors, you can make all of JSON.
It's interesting because JSON is a point of intersection between Javascript and Haskell. Javascript is very dynamic, with a very weak sense of type. Haskell has strong typing. On close analysis, JSON is statically and strongly typed. In fact, JSON is a type.
Could its ADT nature be one of the secrets to JSON's success?
August 14, 2012
Steve Yegge:
Software engineering has its own political axis, ranging from conservative to liberal.
Steve, I am so often with you. Typically, you write stuff that is very concrete and easy to agree with. In fact, I agree with most of what you have written in your very long rants.
But this, I am afraid, is bullshit. Not right, not wrong, just bullshit.
I was giving you the benefit of the doubt until I read your list of categorized features, either conservative or liberal. That list made absolutely no objective sense. There is not one shred of a good idea in the dichotomy you gave.
The dichotomy conflates so many different dichotomies into a single one in the name of clarifying a terrible mess. In that way, it makes the same mistake as classifying people into conservative and liberal does. It does not help explain anything. And it only creates more fighting by arming people with names to call each other.
Which is more "liberal", Common Lisp or C? Common Lisp protects against the most common types of C errors: memory leaks and buffer overflows. Does that make Common Lisp more conservative because it protects the programmer from errors? But C has compile-time type checks! And "conservative" syntax! Bullshit!
But then came the clincher. When you said that Clojure was a conservative language, I came up with something which may actually have some merit: how opinionated the language is.
Clojure is strongly opinionated. So is Python. So is Haskell.
Clojure's opinions: state changes should be explicit, values should be immutable, functions should be separated from data, etc.
Python's opinion: code should be well-indented.
Haskell's opinions: functions should be pure, types should be consistent.
These languages may appear conservative because, in their respective worlds, the opinions are solidified into laws and imposed on the programmer. Python does not allow you to write unindented code. Haskell does not allow you to write programs with inconsistent types. You cannot mutate a Clojure map.
Perhaps, Steve, you mean to say that you don't like when a programming language's opinion is imposed on the programmer?
I personally like some laws and dislike others. For instance, Clojure's immutability is great. It's not just great because it's possible. It's great because it is enforced. Nothing can change my values--not me, not you, not anyone! And I like Haskell's type system in production but not during development. I like that my program is guaranteed to have consistent types on production. But in development, I'd rather run it and debug it (for some definition of "run" for a type-inconsistent Haskell program).
If you say it like that, it ceases to be bullshit. And then we can get back into a discussion. Question: Which features should be imposed on the programmer and which should not? Discuss.
August 14, 2012
Rich Hickey is a force of nature. The mark he will leave on programming will reach much farther than the Clojure programming language. The agenda he is setting forth will have as much impact on the notion of state as McCarthy conditionals had on structured programming.
Please listen closely. The main idea of this talk goes far deeper than "immutable good, mutable bad".
It is wonderful to be a part of this.
August 10, 2012
According to Daniel Spiewak, Clojure's vec requires, in the worst case, 7 array accesses and 14 bit operations.
On really large datasets--this just astonished me when I discovered it--on really large datasets this data structure [Clojure vec] beats java.util.ArrayList for lookup. It beats java.util.ArrayList for datasets that are in the 2 billion range. That is incredibly fast. java.util.ArrayList is an array, right? And we're beating an array.
July 30, 2012
Phil Windley set up his own URL shortener system. He made it use Apache. It could also work on Amazon S3 (like this very blog). It would be super cheap and virtually maintenance-free. I love it.
July 26, 2012
Beautifully typeset (with LaTeX). The only issue is that PDF pages are not the best way to view code on a screen. Code should scroll continuously. For that, I would still recommend the HTML version.