Saturday, December 27, 2008

Vim: ctags

ctags is a tool that figures out where various functions, classes, etc. are defined. Using ctags, you can use a hot key to jump to the definition of the symbol under the cursor.

To get started, install exuberant-ctags. In Ubuntu, this is just "apt-get install exuberant-ctags". Now, from within Vim:
:cd project_root
:!ctags -R .
:set tags=tags
To jump to the definition of the symbol under the cursor, use cntl-]. To get back to where you were, use cntl-o.

There's also a taglist plugin for Vim. Once you install that, you can use ":TlistToggle" to open up a window on the left that shows all the things defined in your open files. I have that mapped to "T" by putting the following in my .vimrc: "map T :TlistToggle<CR>".

Thanks to Benjamin Sergeant for helping me get started with ctags.

Friday, December 26, 2008

Editors: I Dig Komodo Edit


I think I'll switch to Komodo Edit for editing HTML, CSS, JavaScript, Python, Ruby, Perl, and PHP. I'll still use Vim for random text editing and for editing my outline files, and I'll still use Emacs for editing Erlang, Haskell, and Lisp, but I think Komodo Edit is better suited for Web programming.

This is going to be a fairly long review, so let me break it down into sections:
The Good Parts
One thing I really like about this editor is that it is more sophisticated than a default installation of Vim or Emacs, but less sophisticated than a full-blown IDE. I don't feel overwhelmed like I do with Eclipse. The download is only 37mb compared to 134mb for Aptana Studio, and you can really feel the difference. So far, it's been very easy to learn and use rather than feeling frighteningly complex.

Let's start with the basics. As you might expect, it does a beautiful job highlighting the various languages. It handles HTML that contains JavaScript and CSS quite easily. It doesn't have a smart indent mode like Emacs, but I've always disliked that feature anyway.

It supports Vi key bindings (more on that later). It knows how to reflow a paragraph, even if that paragraph has "#" at the beginning of each line. It can increase or decrease the indentation level. It has a column selection (aka rectangular selection) mode, which, by the way, is one of those things that separates great editors from mediocre editors. It has code folding, although that's never been all that important to me.

It can do autocomplete for symbols within the current file. Even better, it has code assist. If you type "import os; os.", it'll tell you what your options are. If you type "import os; os.path.join(", it'll tell you what the API for the method is. The code assist is very helpful when you're editing CSS. It'll give you a drop down for things like "background-color" as well as a drop down for the possible values. It can also jump to the definition of a function (more on that later).

It has the notion of a project, but it doesn't require you to set much stuff up. You just say, "This directory is a project." This lets you do project-wide searches, and it shows your files in a file explorer pane on the left. It does create a project file, which is of type .kpf, but that file contains only 7 lines of XML. It basically says to figure out everything on the fly. I don't feel like I have to convert to a new religion or convince all my coworkers to switch before I can start using it.

It recognizes syntax errors. If I improperly indent some Python, it complains. If I forget the ":" after a for loop, it complains. Forgetting the ":" is perhaps my single most common syntax error, so that's helpful. However, it doesn't have built-in support for PyChecker or PyLint like Pydev does (or so I've heard). Hence, it doesn't complain if I print a local variable before setting the local variable even though PyChecker could catch that.

It knows how to run external commands and do something useful with the output like Emacs does. I told it to run "make test", and I purposely made a test fail. I was able to click on a filename in the exception to go directly to the file. What's better, it has the concept of a toolbox where I can setup all sorts of little things like "make test" and click on them when I need them.

Using the Open/Find toolbar does indeed make it easy to do a project-wide grep. "Find in Current Project" is even easier since it understands the root of your project. It allows you to search using a string or a regex. The UI is pleasant. All the matches are shown in a pane so that you can click on them one at a time.

Some of the smaller niceties include the following. There's a line at the 80 column mark. (I can only get Vim to do that using an awful hack, and that drives me crazy.) It opens up the project and files I had open when I last used it. Macros work, even when you're using Vi commands. It's pleasant to look at (it could be prettier, but it ain't bad).
The Bad Parts
It tends to freeze the UI if you ask it to do something really hard like do a project-wide search in a directory containing 1.7g. That sort of stuff should run on a background thread so that the UI never freezes. What's worse, I had to force quit it when it froze while I was playing around with running external commands like "svn diff" (which did work at least once, by the way).

It doesn't provide good error messages when it doesn't like what you're doing. It tends to just ignore you instead. I found several cases of this.

"Go to Definition" only works for the current file. It doesn't know how to use something like ctags for the project as a whole. You can't even use it for the standard library. This is, perhaps, my single largest complaint. WingIDE is much better in this regard. The essential problem is that the "API catalogs" are pre-made. I found this comment on the issue:
We are going to document this CIX codeintel structure, and later, some tools to help build CIX API catalogs, we shall let everyone know when we have this ready.
In general, the code intelligence behaves a bit strange. It is easily confused. It also doesn't give me nearly as much information as WingIDE does.

It claims to support SCP, but I couldn't get it to work. Even when I used a server on a standard port and provided a username and password (even though I have an ssh key), it still wouldn't connect. Furthermore, instead of giving me a useful error message, it just timed out.

The Help / Help for Languages section is less than spectacular. When I clicked on the Python Reference, I got some ad page for Komodo. The other languages were better. They should probably have links for CSS, HTML, and JavaScript too a la W3Schools.

The Open/Find toolbar is useful, but I keep ending up in the wrong field when I hit tab for autocomplete. Furthermore, it doesn't add the trailing "/" when autocompleting directories like a shell would do. Last of all, when you run out of room in the widget, it doesn't scroll to the right; hence, you end up not being able to see what you're typing. This definitely isn't as nice as opening up a file with "C-x C-f" in Emacs. (By the way, Vim is even nicer in that it passes the path through the shell when using ":e". That means you can use environmental variables, etc. That means it even understands whacky zsh syntax.)

Project / Import from File System... doesn't show me a dialog. It just ignores me. I have no clue why or what it does.

When I tried to create a new project using an existing directory it kind of just ignored me. It turns out that it actually did create the project file. I would have expected it to automatically open the project, but it didn't. Nonetheless, I was able to open the project manually after I created it.

When you preview an HTML file, the CSS doesn't work. However, once I copied the file:// URL and gave it to Firefox, Firefox rendered the file properly. I'm not sure why.
Vi Key Bindings
Komodo Edit does support Vi and Emacs key bindings. Its support is useful, but, as you might expect, it's far from perfect. Perhaps I'm too accustomed to Vim.

"gg" does not go to the top of the file. You have to use ":0" instead.

You can't use "gq" to reflow the paragraph, but you can use "Shift-Apple-Q" instead.

If you use "shift-v" to highlight multiple lines and then ">" to indent them, the cursor must not be in the first column. Otherwise, the last line won't get indented.

"control-o" and "control-i" don't work. Hence, there's no easy way to jump to wherever you were recently.

Surprisingly, "*" and "#" do work for searching for the symbol under the cursor.

Rectangle select works, but doesn't do anything useful. According to the documentation:
With Vi emulation enabled, mouse selection and Vi visual blockwise selection ('Ctrl'+'V') will not trigger column editing. While in Input mode, use 'Alt'+'Shift' with the direction keys to make the column selection, and 'Esc' to exit column editing mode.
Using ">}" to indent the current paragraph doesn't work. "}" by itself does move the cursor. You can use "v}>" to achieve the same goal.

"cw tab tab tab" inserts three things into the undo list instead of just one. Of course, this is a pedantic complaint.

Using "%" to jump between "{" and "}" works, but it's off by one character.

"50i. esc" does not insert 50 periods.

":e" is worthless since it doesn't do autocomplete.
Why Not ...?
You might wonder why I like Komodo Edit over some of the alternatives.

Why not TextMate? Because it's commercial. I might tolerate closed source software in some situations, but I'd rather write my own editor than spend 8 hours a day using someone else's proprietary editor. Call me crazy.

Why not WingIDE? Because Komodo Edit is probably more useful for a wider range of languages.

Why not Komodo IDE? Because it's commercial. Sure, it has an integrated debugger, Python shell, and revision control functionality. However, those things add a lot of complexity. That would destroy the simplicity that I admire so much in Komodo Edit. Besides, I'm a shell junky anyway, and I can use the shell for those things.

Why not Vim? I like the code intelligence features of Komodo Edit. I can still make use of Vi key bindings.

Why not Emacs? Emacs ain't so hot when it comes to HTML with embedded JavaScript and CSS. nXhtml is very promising, but it isn't there yet. Komodo Edit can do more with less configuring and less learning.

Why not jEdit? I've just never felt very drawn to it.
Conclusion
Well, I like it. It's far from perfect, but I can definitely see how to be productive with it. If you'd like to see it in action, check out the Komodo IDE screencast, and just ignore all the things that aren't in Komodo Edit.

Thursday, December 25, 2008

Emacs: nXhtml


In response to the comments in Software Engineering: The Right Editor for the Right Job, I took a look at nXhtml for Emacs.

The scope of nXhtml is impressive. Take a look at the picture. This is a snippet of HTML / JavaScript that I was testing as a part of something else. I hit tab on every line to make it indent things. nXhtml isn't getting the indentation perfectly correct, nor is it getting the syntax highlighting completely correct (why is "beacon" in red?); however, this is worlds better than what comes with Aquamacs by default.

I think nXhtml is a promising project.

Next up, I'm going to check out Komodo Edit. It does make sense to me that since Emacs is written in Lisp, it would be one of the best editors for Lisp, whereas since Komodo Edit is based on XUL (aka Firefox), it would be one of the best editors for editing HTML, CSS, and JavaScript. Of course, I'll have to wait and see.

Software Engineering: The Right Editor for the Right Job

Imagine if you were reasonably skilled with all text editors and all IDEs. Which would you prefer for which tasks?

Clearly, if you're coding elisp, Vim would be a bad choice. Of course, what would be the point? More seriously, Emacs is written in Lisp and has SLIME, the Superior Lisp Interaction Mode for Emacs. Duh, no brainer.

For Scheme, there's something nice to be said about DrScheme's editor. Although, if we stick with the premise of knowing all text editors reasonably well, I'm guessing you might still stick with Emacs.

However, Emacs isn't perfect for everything. For instance, it my have a built-in Web browser, but I can guarantee you that I won't be giving up Firefox just so that I can use Emacs form widgets.

Similarly, Emacs is a little weak on the HTML, CSS, JavaScript side. Aquamacs comes with a fantastic mode for Latex, but if you want to edit an HTML file that has CSS and JavaScript in it, it's less than pleasant. mmm-mode and nXhtml-mode aim to fix this, but (from what I've heard) they're less than fun to set up. Pretty much out-of-the-box (i.e. turn on syntax highlighting, auto-indent, etc.), Vim is much nicer for editing an HTML file with CSS and JavaScript in it. From what I can see in the Aptana IDE videos, Aptana is even slicker.

What about Python? Emacs has very good Python integration, including integration with the shell. However, Vim is also pretty pleasant to use for Python. I've heard multiple times that Wing IDE (commercial) is the best Python IDE available, but Pydev (for Eclipse) also seems very active.

Ruby seems to be a no brainer. The entire core team uses TextMate. Of course, the choice is tougher if you object to using a closed source editor. I've seen other Rails coders use RadRails inside Aptana.

If you're coding Erlang, you should probably stick with Emacs. It was the standard editor among the guys who wrote Erlang. I've heard people joke that the only way to make sure you haven't gotten ".", ";", and "," confused is to make sure Emacs is indenting it right.

Similarly, Emacs is probably a good fit for Haskell, at least based on the Haskell coders I've met.

What do you use to edit config files on a remote system? The conventional wisdom is Vi, of course. However, these days, many editors (including Emacs, Vim, and Gedit) support editing over scp. Hence, you don't have to put up with HP-UX's version of Vi (I've heard it's awful) just because you're on a remote system--assuming you have network access.

Concerning Emacs vs. Vim specifically, I think that if there's a well written Emacs mode, you're better off with Emacs. In other cases, you're better off with Vim. In general, Vim's understanding of most programming languages is much weaker, but it comes builtin with support for many, many more of them. Furthermore, Vim is much better out of the box dealing with multi-mode files like HTML, CSS, and JavaScript files.

Furthermore, it's so nice to be able to say something like ":set sw=4 sts=4 et ai" which means "set the shift width to 4 spaces, set soft tab stops to 4 spaces, emulate tabs, auto indent". That might not be as smart as smart indentation mode in Emacs, but it sure is a time saver if there is no smart indentation mode for the syntax you're editing.

I still think that Vim is the fastest editor for straight text editing if you're a touch typist and you really know it well. A lot of "switch hitters" agree with this sentiment. "2dw" = "delete two words". "j." = "go down a line and do it again". Nice ;)

What about Java? Because of the nature of Java, I know very few people who don't use an IDE for Java. I've heard many people say IntelliJ is the best, but it's commercial. Eclipse is the big open source option. Surprisingly, I've heard a lot of nice things about NetBeans; I think they must have put some serious effort into it lately.

If you need something super general purpose and multi-platform, I've heard lots of good things about jEdit, but I can't think of any language for which jEdit is a must have compared to all other editors.

Ok, last tip: if you're coding in Turbo Pascal, any editor will do--as long as it's made by Borland and uses a yellow on blue font ;)

Happy Hacking!

Monday, December 22, 2008

Web: Robust Click-through Tracking

I have a web service that provides recommendations. I want to know when people click on the links. The site showing the links (imagine a book store) is separate from my web service.

Let's imagine a situation. My server generates some recommendations. The site shows those recommendations. After 10 minutes, my server goes down because both of my datacenters go down. I want to know if the user clicks on a link, but if my server is down, that must not block the user from surfing to that link.

I see how Google does click-through tracking. It's simple, non-obtrusive, and effective. However, as far as I can tell, it requires the server to be up. Well, they're Google ;) It's different when you're a simple web service that must never ever cause the customer's site to stop working.

I came up with the following:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<title>Click-through Tracking</title>
<script type="text/javascript">
function click(elem) {
(new Image()).src = 'http://localhost:5000/api/beacon';
return true;
}
</script>
</head>

<body>
<p>
<a href="http://www.google.com"
onclick="return click(this);">click me!</a>
</p>
</body>
</html>
Note a few things. It doesn't mess with the href. It works whether or not the third-party server (localhost) is up. It does talk to a third-party server, but it does so using an image request; hence, the normal cross-site JavaScript constraints aren't imposed. It has all the qualities I want, and I actually think it's a pretty clever trick. However, I'm worried.

I like the fact that loading an image is asynchronous. I'm depending on that. However, what if it takes the browser 1 second to connect to my server, and only 0.1 seconds to move on to Google (because that's what the link links to). It's a race condition. As long as the browser makes the request at all, I'm fine. However, if it gives up on the request because DNS takes too long, I'm hosed.

Does anyone have any idea how the browsers will behave? Do my requirements make sense? Is there an easier way?

Sunday, December 21, 2008

Python: Web Beacons in Pylons

A Web beacon is usually an image tag that refers to a 1x1 clear gif on a remote server. The remote server is able to track that the gif was seen when the browser tries to download it. If you're using Pylons, here's how to implement that beacon in a way that won't be cached:
CLEAR_GIF = 'GIF89a\x01\x00\x01\x00\x91\xff\x00\xff\xff\xff\x00\x00\x00\xff\xff\xff\x00\x00\x00!\xff\x0bADOBE:IR1.0\x02\xde\xed\x00!\xf9\x04\x01\x00\x00\x02\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02T\x01\x00;'
...
def some_action(self):
# Do interesting things here...
response.headers['Content-Type'] = 'image/gif'
response.headers['Cache-Control'] = 'no-cache'
response.write(CLEAR_GIF)

Python: Timesheet Calculator

Little programs are so much fun to write ;) Here's one that adds up the hours in my time sheet.
#!/usr/bin/env python

"""Add up the hours in my hours.otl file.

The file should have the following format::

12/21/2008
3.25 hours working on project-specific domain names.

The date must be in margin 0. The number of hours must be indented.

Testing::

nosetests --with-doctest addhours.py

Note, I'm positive that this script could be replaced by a one line
awk script, but whatever. It was fun to write.

"""

from cStringIO import StringIO
from optparse import OptionParser
import re
import sys

TEST_DATA = """\
12/18/2008
7 Hours programming.

12/19/2008
8 Hours hacking.
"""

hours_regex = re.compile(r"^\s+([0-9.]+)")

__docformat__ = "restructuredtext"


def process_file(f):
"""Add up and return the hours in the given open file handle.

This may raise a ValueError if the file is malformed.

Test::

>>> process_file(StringIO(TEST_DATA))
15.0

"""
total = 0
for line in f:
match = hours_regex.match(line)
if match is not None:
total += float(match.group(1))
return total


def main():
"""Run the program.

Deal with optparse, printing nice error messages, etc.

"""
parser = OptionParser("usage: %prog < hours.otl")
(options, args) = parser.parse_args()
if args:
parser.error("No arguments expected")
try:
print process_file(sys.stdin)
except ValueError, e:
parser.error("Malformed file: %s" % e)


if __name__ == '__main__':
main()

Friday, December 19, 2008

Emacs: vimoutliner

I've been drinking too much caffeine lately, and if you know me, you know what that means--I start getting weird urges to play with Emacs.

One of the things that always drives me crazy about Emacs is indentation. It's hard to get it to do what I want it to do in cases where there is no mode that matches what I'm coding. I have a ton of files written using vimoutliner, and I don't feel like switching them to Emacs' own format. It's a simple outline format. Four space wide tabs are used for nesting.

I could never figure out how to get Emacs to just "do the right thing" with these .otl files. I finally figured out the right magical incantation, thanks to some hints from Jesse Montrose. Updated:
;; Add support for Vim outline files.
(defun otl-setup ()
(setq outline-regexp "\t+")
(setq indent-tabs-mode t) ;; Use real tabs.
(setq tab-width 4))

(setq auto-mode-alist
(cons '("\\.otl$" . outline-mode)
auto-mode-alist))
(add-hook 'outline-mode-hook
'otl-setup)
Viola! Editing .otl files just became possible!

Thursday, December 11, 2008

Python and Ruby: Regular Expression Anchors

In Python regular expressions, multiline mode is off by default. The documentation says:
When [multiline mode is] specified, the pattern character '^' matches at the beginning of the string and at the beginning of each line (immediately following each newline); and the pattern character '$' matches at the end of the string and at the end of each line (immediately preceding each newline). By default, '^' matches only at the beginning of the string, and '$' only at the end of the string and immediately before the newline (if any) at the end of the string.
In Ruby regular expressions, the multiline modifier (m) is also off by default. However, '^' still matches the beginning of each line.

Hence, in Python, the following does not match:
re.match(r'^foo', '\nfoo\nbar')
Interestingly enough, this does not match in Perl either:
"\nfoo\nbar" =~ /^foo/
In Ruby, it does:
/^foo/.match("\nfoo\nbar")
Both Python and Ruby support the "\A" operator which explicitly matches the beginning of the string (not the line).

To make matters even more confusing, in Python "\Z" matches the "end of the string." In Ruby, "\Z" matches the end of the string except for the final newline, whereas "\z" matches the end of the string. Ruby is similar to Perl in this regard.

I was surprised to discover such subtle differences existed. Things like that make expert-level proficiency in multiple languages extremely difficult.

Wednesday, December 10, 2008

Computer History: Doug Engelbart

I went to a talk yesterday. It was the 40th anniversary of Doug Engelbart's 1968 "mother of all demos". In the demo, Engelbart demonstrated:
  • The first computer mouse
  • The first graphical user interface
  • The first personal, interactive, networked computer
  • The first use of hypertext (i.e. text with links)
I had heard about the demo but never watched it. It's available on YouTube, and it's definitely a must see. Doug had a grand vision of using the computer as a tool to help people accelerate how quickly they could solve problems. That goal has always fascinated me.

Robert Taylor, whose funding led to the creation of the ARPANET, told a pretty good joke, which he himself said was probably apocryphal. Rather than retell it, I grabbed a copy from here:
Whenever you build an airplane, you have to make sure that each part weighs no more than allocated by the designers, and you have to control where the weight it located to keep the center of gravity with limits. So there is an organization called weights which tracks that.

For the 747-100, one of the configuration items was the software for the navigation computer. In those days (mid-1960s), the concept of software was not widely understood. The weight of the software was 0. The weights people didn't understand this so they sent a guy to the software group to understand this. The software people tried mightily to explain that the software was weightless, and the weights guy eventually went away, dubious.

The weights guy comes back a few days later with a box of punch cards (if you don't know what a punch card is, e-mail me and I will explain). The box weighed about 15 pounds. The weights guy said "This box contains software". The software guys inspected the cards and it was, in fact, a computer program. "See?", the weights guy said, "This box weighs about 15 pounds". "You don't understand", the software guys responded, "The software is in the holes".
Allan Kay was also there. Allan is always fascinating to listen to. He said something that I thought was useful. He said that there is a difference between "new" and "news". "News" is when something happens and you get an update that it happened. News is simple and easy to assimilate. Something is "new" when it changes the rules of the game. When something is "new", it's impossible to fully understand the ramifications.

He had a great example. When the printing press came out, people thought it was "news". Suddenly, it was cheaper to print books. What they didn't understand was that it was actually "new". The printing press allowed ideas to spread more quickly, more broadly, and more accurately than ever before. It was impossible for them to understand just how profoundly the printing press would affect the world.

Monday, December 01, 2008

Books: RESTful Web Services

I just finished reading RESTful Web Services. I'll summarize. At its worst, it was boring and dogmatic. At its best, it helped me to formalize my understanding of REST, and it gave me a protocol-level introduction to a variety of topics like the Atom Publishing Protocol, microformats, S3, del.icio.us, HTML 5, etc.

One thing I found particularly frustrating is the author's attitude toward RPC. Basically, his stance is that RPC is synonymous with all things evil. Consider the following quote:
This is why making up your own HTTP methods is a very, very bad idea: your custom vocabulary puts you in a community of one. You might as well be using XML-RPC. [p. 105]
Ok, so using XML-RPC is just as bad as sending "EAT / HTTP/1.0" to a server. WTF?

I've implemented services using CORBA, JRMI, XML-RPC, and a couple times with REST. At the risk of calling the emperor naked, I liked XML-RPC the most. REST might look nicer at the wire level, but at least in Python, XML-RPC is a heck of a lot easier to code for. None of the author's client examples can match the simplicity of using an XML-RPC service in Python. Sure, you can say that XML is ugly, but I never actually had to deal with XML when using XML-RPC. The libraries did it for me. However with REST, I have to slog through XML all the time.

Another thing that frustrated me about this book was how often it relies on standards that aren't yet standard. The back of the book says, 'This book puts the "Web" back into web services.' Unfortunately, this book makes use of HTML 5, a couple different IETF Internet-Drafts, and HTTP methods that my browser doesn't actually support. It should have said, "This book shows you how great REST would be if we had the perfect web."

One thing I really liked about this book was the checklist for creating Resource-Oriented Architectures, which I'll quote here:
  1. Figure out the data set.
  2. Split the data set into resources.
  3. For each kind of resource:
    1. Name the resources with URIs
    2. Expose a subset of the uniform interface
    3. Design the representation(s) accepted from the client
    4. Design the representation(s) served to the client.
    5. Integrate this resource into existing resources, using hypermedia links and forms.
    6. Consider the typical course of events: what's supposed to happen? Standard control flows like the Atom Publishing Protocol can help (see Chapter 9).
    7. Consider error conditions: what might go wrong? Again, standard control flows can help. [p. 216]
Aside from that, here is a list of quotes that I found surprising, frustrating, interesting, or simply entertaining (especially when taken out of context):
Now, lots of architectures are technically RESTful...More than you'd think. The Google SOAP API for web search technically has a RESTful architecture...But these are bad architectures for web services, because they look nothing like the Web. [p. 13]
Service-Oriented Architecture...This is a big industry buzzword...A book on service-oriented architecture should work on a slightly higher level, showing how to use services as software components, how to integrate them into a coherent whole. I don't cover that sort of thing in this book. [p. 20]
ProgrammableWeb...is the most popular web service directory...Its terminology isn't as exact as I'd like (it tends to classify REST-RPC hybrids as "REST" services). [p. 368]
I do my bit to promote WADL as a resource-oriented alternative to WSDL. I think it's the simplest and most elegant solution. [p. 25]
If a web service designer has never heard of REST, or thinks that hybrid services are "RESTful," there's little you can do about it. Most existing services are hybrids or full-blown RPC services. [p. 27]
Another uniform interface consists solely of HTTP GET and overloaded POST...This interface is perfectly RESTful, but, again, it doesn't conform to my Resource-Oriented Architecture. [p. 125]
Web services are just web sites for robots. [p. 132]
I need to truly capture the capabilities of my service. XHTML 5 has a feature called the repetition model, which allows me to express an arbitrary number of text boxes without writing an infinitely long HTML page. [p. 136]
You may have noticed a problem in Example 6-3. Its form specifies an HTTP method of PUT...I'm using the as-yet-unreleased XHTML 5 to get around the shortcomings of the current version of HTML. [p. 153]
The two derivations from the HTML you're familiar with are in the method attribute...and the brand-new template attribute, which inserts a form variable ("username") into the URI using the URI Templating standard (http://www.ietf.org/internet-drafts/draft-gregorio-uritemplate-00.txt). [p. 155]
Note that the Internet-Draft itself says:
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."
I had to hack Rails to get the behavior I want, instead of the behavior Rails creator David Heinemeier Hansson wants. [p. 168]
It's been a while since I presented any code. Indeed, coming up with the code is currently a general problem for REST advocates. [p. 167]
There's no good way to do that in Rails. [p. 189]
The if_found method sends a response code of 404 ("Not Found") if the user tries to GET or DELETE a nonexistent user. [p. 199; Hey, I thought DELETE was supposed to be idempotent!]
Of course, using the web service just means writing more code. [p. 209]
Clients could work on a higher level than HTTP...The idea here is to apply higher-level conventions than REST's, so that the client programmer doesn't have to write as much code. [p. 212]
The ActiveResource/ActiveRecord approach won't work for all web services, or even all Rails web services. It doesn't work very well on this service...As of the time of writing, it's more a promising possibility than a real-world solution to a problem. [p. 212]
If you want to do without PUT and DELETE altogether, it's entirely RESTful to expose safe operations on resources through GET, and all other operations through overloaded POST. Doing this violates my Resource-Oriented Architecture, but it conforms to the less restrictive rules of REST. [p. 220]
But every resource works basically the same way and can be acccessed with a universal client. This is a big part of the success of the Web. The restrictions imposed by the uniform interface (safety for GET and HEAD, idempotence for PUT and DELETE) make HTTP more reliable. [p. 222; The web was successful despite the fact that GET is often not safe and PUT and DELETE aren't available in Web browsers.]
How can you DELETE two resources at once?...You might be wondering what HTTP status code to send in response to a batch operation...You can use an extended HTTP status code created by the WebDAV extension to HTTP: 207 ("Multi-Status"). [p. 230]
Yet again, the way to deal with an action that doesn't fit the uniform interface is to expose the action itself as a resource. [p. 232]
I'll translate. If you feel the need to use verbs other than GET, PUT, POST, and DELETE, just convert your verb to a noun. REST consists of converting all interesting verbs into nouns so that you only have to use basic verbs like GET, PUT, POST, DELETE, HEAD, and OPTIONS.
[Browsers only support GET and POST.] If the server supports it, a client can get around these limitations by tunneling PUT and DELETE requests through overloaded POST...Include the "real" HTTP method in the query string. Ruby on Rails defines a hidden form field called _method...Restlet uses the method variable...The second way is to include the "real" HTTP action in the X-HTTP-Method-Override HTTP request header. [p. 252; That's a pretty good summary of how to stick to the web's uniform interface.]
A web service that sends HTTP cookies violates the principle of statelessness...What about cookies that really do contain application state? What if you serialize the actual session hash and send it as a cookie...This can be RESTful, but it's usually not. [p. 252]
POST Once Exactly (POE) is a way of making HTTP POST idempotent, like PUT and DELETE...Post was defined by Mark Nottingham in an IETF draft that expired in 2005. [p. 283; He is relying on a long-expired Internet-Draft to show how to implement a feature.]
I cover four hypermedia technologies in this section. As of the time of writing, XHTML 4 is the only hypermedia technology in active use. [p. 285]
As of the time of writing, WADL is more talked about than used. [p. 290]
If all you're doing is serializing a data structure for transport across the wire (as happens in the weblogs.com ping service), consider JSON as your representation format. [p. 308]
In 2006, IBM and Microsoft shut down their public UDDI registry after publicly declaring it a success. [p. 309]
Suffice it to say that security concepts are much better specified and deployed in SOAP-based protocols than in native HTTP protocols. [p. 311; Which isn't to say I like SOAP.]
Two-phase commit requires a level of control over and trust in the services you're coordinating. This works well when all the services are yours, but not so well when you need to work with a competing bank...I generally think it's inappropriate for RESTful web services. [p. 313]
Refer [is a] request header...Yes, it's misspelled. [p. 401; That would explain why I always misspell it!]
Anyway, sorry for going so long. I hope some of those quotes entertained you as much as they entertained me.

Grammar: Predicates

I've noticed that certain programmers love grammar, so I hope you won't mind the following:

"The predicate is the subject of this sentence."

What's the subject? "The predicate" is the subject of this sentence.

What's the predicate? The predicate is "is the subject of this sentence."