1. Rounded Corners - 164 (Shopping)

    October 29th, 2007

    Ikea. What other furniture store lets you drop in late Saturday night, head straight to the aisle, pick up furniture, and then drive home to spend the rest of the night putting them together? Not to be confused with spending the weekend furniture shopping. I’m too young for that. Putting them together, on the other hand, now that’s an idea for a theme party.

    Self-check lines. Can’t decide if I love them or hate them. The Ikea scanner was dyslectic, hard time picking up the bar code. The Safeway one could pick them from a distance. But neither one lets you punch in a quantity, so with ten of the same you need to scan them one by one by one by one by one.

    Then there’s this annoying guiding voice that just slows you down. Clearly needs a ‘been there, done that, just let me through’ expert button you can push to make it shut up.

    Function and form. I have a soft spot for products designed for people like me. They do things different and better. They aim to please. And they look great. What can I say, I appreciate good packaging. Extra points if they’re designed right here in the Bay Area. And I do like companies that don’t treat me like a bonehead consumer. So I’m switching.

    One piece at a time, the house is filling up with method products.

    Earthlink. Pretty darn pissed. If you remember, I had trouble reaching functional tech person to help me fix the flaky DSL line. Decided to cancel. Apparently not without paying an early termination fee for the few months of rejected dysfunctional service left on my service. Did it work? Not really. Turns out they “forgot” to cancel my service. Stay away.

    Quine. Just for fun, let’s see if we can cut Ryan Davis’ original two characters short:

    _="_=%p;$><<_%%_";$><<_%_

    Above, the SuperTest: who’s the superest hero of them all?

  2. Rails fixies: JSON as input, See Other and [].to_xml

    October 23rd, 2007

    If you have a few moments, please read and tell me what you think would be the better option for each of these.

    1. JSON says

    Here’s a nice party trick:

    respond_to do |format|
      format.html
      format.xml  { render :xml=>@item }
      format.json { render :json=>@item }
    end

    When I’m feeling particularly evil, I walk over to someone still struggling to dual-render XML and HTML using indecipherable XSLT, ask them when JSON transformation will hit the roadmap, watch them squirm, jot these few lines on a piece of paper, put it on the table and quietly walk away.

    OK, not really. Actually I’m struggling doing it the other way around. Wouldn’t it make sense that I could GET a representation, change it, and PUT it back?

    For XML it turns out to be quite simple:

    def update
      Item.update params[:id], params['item']
    end

    Rails grabs the request body, an XML document with the document element item and stuffs the entire thing into a parameter with the same name.

    If you’re lazy you get rewarded. Let Rails do all the form building for you, and its magical helpers will use field names like item[name], item[count] and item[tags][]. Those are nicely parsed into a hash called item, so the above code will also work with hForm.

    But what about JSON? Test case please:

    curl -d "{ name: \"foo\", count: 2, tags: [ \"bar\" ] }” -H “Content-Type: application/json”

    The data is here, alright, and it’s the same structure we got back on the previous GET, but there’s nothing wrapping it up. JSON is naked. No XML document element name we can use to decide which parameter to place it in. Which means, one of these:

    Option 1. All JSON objects are called such:

    def update
      Item.update params[:id], params['item'] || params[:json]
    end

    This works nicely as long as you remember to always param[:json], which given my propensity to easily forget, is why I’m not particularly thrilled.

    Option 2. All non-named params are always called the same:

    def update
      Item.update params[:id], params['item'] || params[:data]
    end

    Looks the same, but is not. This option is forward looking and anticipates the possibility of some future technology we would want to use without having to go back and fix old code.

    Option 3. It always is data:

    def update
      Item.update params[:id], params[:data]
    end

    Even XML documents get called data. Everything gets called data. Which doesn’t work for query parameters or forms, but just for completeness I had to list this as well.

    Option 4. Name inference:

    def update
      Item.update params[:id], params['item']
    end

    This only works because the controller is called ItemsController, and the downcased singular name is item, and so we can infer what the JSON object should be called more often than not.

    I’m personally leaning towards a combination of both #1 and #4, so you can :json or :item it. What do you think?

    2. Are JSON objects hashes or arrays?

    All the use cases I have are for receiving records, whether represented as JSON objects or XML documents:

    <item>
      <name>foo</name>
    </item>
    
    { name: "foo" }

    But I do have code that renders collections, and contemplating the idea of receiving multiple records as inputs:

    <items type='array'>
      <item>
        <name>foo</name>
      </item>
    </items>
    
    [ { name: "foo" } ]

    The thinking at Rails core is that hashes are enough, although there’s no such restriction on XML input. Have you considered a use case for receiving arrays (XML and/or JSON)?

    3. redirect_to vs. see_other

    Here’s something you see quite often in Rails apps:

    def create
      article = Article.create(params[:article])
      redirect_to article
    end

    It seems like the right thing to do. It handles a POST request by creating the new resource, and then redirects the client to that resource (here, using polymorphic routes, a nice addition in Rails 2.o). Except it doesn’t, redirect_to will send back a 302 (Found) status code.

    The 302 status code tells the client that the resource is found in a different location. By which we mean the original resource, so the proper thing to do is head over to the new location and do the POST all over again. Not what the controller author had in mind!

    Per the HTTP specification, you would want to send back a 303 (See Other). Redirects (301, 302, 307) tell the client that the resource moved, and please can you try sending the same request over to the new location. 303 tells the client the request went through, got processed, please check the other location for the result.

    So how come this happens and the world doesn’t fall apart? Turns out browser developers got lazy, and some handled 302 and 303 the same way. People wrote CGI scripts by brushing through the HTTP spec and just testing out what works in the browser. And copying other people’s code. Eventually this bug got codified into the Undocumented HTTP Specification. So redirect_to doesn’t break browsers.

    When people write client applications that talk to a Web service, they either go lazy or go HTTP. Those that go lazy (send request, extract Location header) won’t break, but they’re losing an important HTTP feature: the ability to move resources and leave behind a forwarding address. Those that go full HTTP will either raise and error or attempt a second POST.

    I think we need to fix this, and get people to write services properly from day one.Option 1. Rails (2.0) gives you two options, both of which are examples for elegant use of hashed arguments:

    head :see_other, :location=>article_url(article)
    redirect_to article, :status=>:see_other

    Both return 303, as HTTP intended it to be, so not much to complain, except we all know how likely it is that people will take the extra step to add an obscure status code that so far hoards of developers ignored.

    Option 2. Temporary/permanent redirect and See Other are not the same thing, let’s make the difference known and introduce a see_other method:

    # Use this in response to an HTTP POST (or PUT), telling the client where the new resource is.
    # Works just like redirect_to, but sends back a 303 (See Other) status code.  Redirects should be used
    # to tell the client to repeat the same request on a different resource, and see_other when we want the
    # client to follow a POST (on this resource) with a GET (to the new resource).
    def see_other(options = {})
      if options.is_a?(Hash)
        redirect_to options.merge(:status=>:see_other)
      else
        redirect_to options, :status=>:see_other
      end
    end

    Option 3. Or sprinkle a bit of magic on redirect_to:

    def redirect_to(options = {}, response_status = {}) #:doc:
      if options.is_a?(Hash) && options[:status]
        status = options.delete(:status)
      elsif response_status[:status]
        status = response_status[:status]
      else
        status = request.post? ? 303 : 302
      end
      . . .

    Which one do you think is better?

    4. [1, 2, 3].to_xml

    This works:

    { 'foo'=>'bar' }.to_xml

    This throws with a violent exception:

    [ 'foo', 'bar' ].to_xml

    Any particular reason why it would be bad to XML-ize an array of primitive values?

  3. Rounded Corners - 163 (Serendipity)

    October 15th, 2007

    IZ VAR LIEK 0?
      YARLY
        VISIBLE "NO MOAR"!
      NOWAI
        VISIBLE VAR!
    KTHX
    VISIBLE " BOTTLZ OF BEER N TEH WALL!"

    So simple. What’s the difference between Web and SOA? One is free in every sense, the other is a vendor offering. One is a messy bazzar, the other a governed cathedral. One springs bottom-up, the other dictated top-down. One is pragmatic simplicity, the other designed complexity. But none of these capture the dichotomy as well as “Planned vs. Seredipitous Reuse“:

    Yet, on the Web, we do this all the time. The Web architecture is all about serendipity, and letting a thousand information flowers bloom, regardless of whether it serves some greater, over arching, aligned need. We expose resources based on use, but the constraints on the architecture enables reuse without planning. Serendipity seems to result from good linking habits, stable URIs, a clear indication of the meaning of a particular resource, and good search algorithms to harvest & rank this meaning.

    Supposedly, serendipity is 3rd hardest word to translate, yet seems to work nicely on a global scale.

    The Tao of critics. Reg at it again.

    Vanity buttons. I got the one on the left, and every time I use it, I miss the one on the left.

    Dead wrong. The problem with weather prediction, especially one as far fetching as global warming, is that all we’ve got are models. And models are sometimes wrong as many “non-believers” hope. Unfortunately, wrong works both ways.

    Theory of language niches. Is it true, there’s only room for two in each category?

    Above, portion of 99 beers implemented using LOLcode.

  4. Rounded Corners - 162 (foobar)

    October 10th, 2007

    Foobar-ed. Nice to know there’s an RFC (3092) on the etymology of “Foo”. I wonder how many specs use foo bar and include RFC 3092 as a normative reference.

    Green shifted. Interesting term:

    The problem is that the project status “green shifted” as it rose through the various levels of management. The people on the ground were very clearly reporting a red project status, our project manager wanted to play it safe so reported yellow status, and his manager was more political yet and reported green status.

    [Ed note: Firefox crashed and restarted with linked page, but without all the linking posts, so apologize if credit is missing.]

    Still alive. IMS, 39 years old, with an upcoming version 10, focusing “on strengthening the software’s service-oriented architecture (SOA) features.”

    Varnished. The architecture of varnish: let the OS do its thang, point at things, don’t let threads idle, and keep them separated. (Via Barry)

    Missionary. Why Gordon hates mission statements:

    In fact, I can’t think of a single catch-phrase that motivated individuals through an extended period of time, except for perhaps “Go forth and multiply,” but one could easily see that the instruction wasn’t really necessary, just the equipment and instinct.

    When I hear “mission statement” I think of that signature that comes at the end of a press release, and since you already lost the reader in the second paragraph, does it matter what they don’t say?

    Picture, Wi-Fi detector t-shirt, guaranteed to get you unlaid.

  5. Rounded Corners - 161 (Credits)

    October 9th, 2007

    Credit Tim Bray. RubyForge is getting a much needed upgrade:

    We’re migrating RubyForge to a new server this evening. This will mean a spot of downtime for various things, but hopefully not too much. Thanks to Tim Bray for getting us a nice new server!

    Listening to you. AT&T revises their ‘thou shalt not speak foul of us’ TOS:

    We are revising the terms of service to clarify our intent. The language in question will be revised to reflect AT&T’s respect for our customers’ right to express opinions and concerns over any matter they wish. And we will make clear that we do not terminate service because a customer expresses their opinion about AT&T.

    Verizon … can you hear me now?

    Lighthearted. Excuse me while I keep linking to InfoWorld, but they just keep showing a personality, and I like that:

    Google, the newly-christened $600-per-share company, unveiled on Tuesday evening the fifth generation of its Google Enterprise Search Appliance.

    While you’re at it, check out some of the Google search experiments going on in the lab.

    Music to my ears. NIN, Radiohead, and rumors about Oasis and Jamiroquai. Exciting times.

    Extortion. Now for something quite the opposite.

    I’m beginning to like the old Microsoft, you know, that company that made its fortune selling bad software to customers with deep pockets:

    Only Microsoft could possibly see a big panel of buttons and think “this must be what our customers want”.

    Supply, demand, all of that. Not so big on the new Microsoft, who’s business model is extracting money from people who don’t use their software:

    Microsoft CEO Steve Ballmer says Red Hat Linux uses intellectual property owned by Microsoft and that Red Hat’s customers should pay Microsoft for it.

    Dear Microsoft. Die. Already. You agony is painful to both of us. Thanks.

    Above, xkcd, a seriously funny geek comic.

  6. Rounded Corners - 160 (Resourced)

    October 9th, 2007

    Resourced. This whole ROA vs SOA debate, where are we going with that?

    You know, these services don’t come out of thin air and certainly don’t connect themselves, so on any given day you need to decide which technologies to use to make that happen. It’s SOAP vs REST boxing match brought to you by the S.O.A Federation. I placed my bets, but I’m watching closely because it’s still a fair fight.

    I also get resource thinking, which is something entirely different. Everything is a resource, resources are linked, and besides the few servers in my back yard, I can reach and touch resources across the world. Cool. Magnificent. Awe. Brave new world. Also a staged fight, we already know who takes the first round by a KO, but still selling tickets for this match.

    But now I’m hearing on the PA that “people who SOA do not REST”. Darn. I really thought REST stood a chance in this fight. I may cry a bit.

    Then we’re off to commercials, where I learn that “if you or someone you know has a chronic resource pain, ask your doctor about prescription R.E.S.T,” and I’m wondering to myself, what is a chronic resource pain? What are the symptoms? How do you know you have it?

    Where was I going with this? Oh yeah. I know cheerleaders need some letters to shout out, but before we get to that, can we take a quiet moment to reflect and articulate what problem we’re trying to solve. In one sentence or less:

    I _____________________________ and I used resources for that.

    Born. RFC 5023 (APP) is born.

    Also. OAuth 1.0 final draft (that was fast!)

    Simplified. OpenID site redesigned with a much improved ‘where do I get one?‘ page. The explanation is still geek-oriented, but definitely a step in the right direction. (Via Simon Willison)

    Guaranteed. Amazon S3 Service Level Agreement. (Also via Simon Willison)

  7. n-Tier Apps and Client-Side Caching

    October 8th, 2007

    Nick Sieger brings up an interesting question. Imagine an n-tier application and you’re using HTTP to connect the tiers together. That wasn’t the question, just a good practical advise to follow. The question was, can you place a proxy server between the tiers and reap all the benefits?

    Specifically in the context of Rails and ActiveResource:

    The great thing is that existing HTTP reverse proxies can be used without having to mix the caching code in with your application code.

    You can get a cached installed in a few minutes, switch over by setting HTTP_PROXY, and bingo. Could it be that easy?

    The Glass Half Empty

    If you’re serving the same data to all your clients and there’s little transformation happening on the client, then a reverse caching proxy is the way to go. It’s as close as it gets to a free lunch, performs and scales better than loading the database.

    It breaks in two cases, though.

    The first, when you’re serving different content to different clients on the same resource, and you don’t want the proxy server leaking those secrets away. Say you’re authenticating, admins get a different view than pedestrians, and both are served by the same URL. Rails assumes that by default, a good assumption to make, and sets Cache-Control to private, telling the proxy not to cache anything. It still allows caching in the client, but you’re probably not running a caching client.

    The second place it breaks is when the client does non-trivial transformation on the data it receives. Imagine a client pulling in 10MB of data to calculate ‘total of orders’. Hitting the cache when there’s no change could save a trip to the database, but you still end up processing all that data again.

    I’m saying “could” because the Rails magic involves running the action in full, creating a response document, calculating the ETag and then deciding not to send it back. On the Web that makes a noticeable difference in client response time, your browser will thank you. When you’re running two machines in the data center or even same rack, you won’t see any performance or scalability gains. It’s still database access all the way down.

    The Glass Half Full

    All of which is fairly easy to fix, for Rails or any other framework, but requires that we remove some of the child-proofing and expect adults to pay more attention to caching. Not horribly complex, but no transparent benefits either.

    cache_in_public. If you only ever return the same content for a given resource, but possibly 403/404 for unauthorized clients, you can change Cache-Control to public/must-revalidate. My HTTP sources tell me this will work for a caching proxy without leaking to rogue clients. Something like:

    cache_in_public :index, :show

    acts_as_sourced. If you do significant work on the client, you want to handle caching directly, sending ETag/Last-Modified and avoiding redundant work on unchanged data. This can be simplified by creating a plugin that handles conditional GETs:

    class Computed < ActiveRecord::Base
      acts_as_sourced
    end
    
    Computed.retrieve(url).save

    if_modified. Now that you’re bona fide caching all over the place, or as often as you possibly can, you’ll want to eliminate those round trips to the database by checking for changes before doing any work. Something like if_modified:

    def show()
      if_modified @record do
        render :action=>'show'
      end
    end

    While we’re at it, paying attention to caching and having fun, we should also consider conditional PUTs:

    resource.update do |record|
      record.count += 1
    end

    Side Effects

    And those are quite unfortunate, so we’ll have to keep that in mind.

    You see, caches are side effects. Any request going through a cache will not necessarily return the correct result. That depends entirely on the state of the cache and how resources are handled by the server. How do you prove the code is correct?

    More than server-side and client-side support, this will need a good testing framework to make sure the cache abstraction doesn’t leak, and developer awareness for what needs to be tested. It’s not rocket science, but there still is a barrier to entry of Memcached complexity, though with more benefits.

  8. Rounded Corners - 159 (As seen on TV)

    October 8th, 2007

    As seen on TV. Steve Vinoski on the similarities between ESB and the bargain multi-tools they sell you on late-night TV:

    Frankly, if I were an enterprise architect today, and I were genuinely concerned about development costs, agility, and extensibility, I’d be looking to solve everything I possibly could with dynamic languages and REST, and specifically the HTTP variety of REST. I’d avoid ESBs and the typical enterprise middleware frameworks unless I had a problem that really required them (see below). I’d also try to totally avoid SOAP and WS-*.

    Speaking of marketing. This is one brilliant product. It’s all natural, hypoallergenic and fragance-free. Dermatologically tested. It protects sensitive skin from dryness. No side effects. Which is reason enough to call it the Expert Sensitive Refreshing Facial Spritz. Ingredients: water. At £3.99 for a single bottle, it works out to £32.92 a liter.

    The juxtaposition of ESB and a £3.99 water-spray bottle, not by accident.

    Humanized. Long read, but worth taking a break from coding and going through this post, especially if you’re involved in open source and think that people matter more than code:

    The difference between the Mozilla and Firefox was that Mozilla was the result of developers contributing every web-browser feature they could think of. It only started to become humane once the Firefox team applied a unifying principle — “Does this help Mom surf the web?” — and pared away features that didn’t fit. It’s not enough to duplicate what has come before; even in an established category, a product still needs a unifying design, based on a clear vision of what users need to accomplish.

    Yes, yes and yes. Brian ‘Bex’ Huff, on the day repeating reads no longer return the same result:

    The same may hold true for databases… for sufficiently complex systems, a database only represents a vague approximation of the state of your organization. This problem will only get worse when people implement SOA across the enterprise… which will enable complex interactions and dependencies across business units that were never before possible… Empowering? Yes. Important? Yes. Scary? Yes.

    Via Santiago Gala:

    I think the metaphor illustrates best that we need to drop the pretense of having a consistent, precise representation of the world and settle for abstractions that are fuzzier but more expressive.

    It wasn’t there to begin with. Curtis Poe doesn’t think MySQL and PostgreSQL are all that relational:

    In the relational model, instead of tables, you have relations. There are a number of differences, but the key one here is that a relation does not allow duplicate tuples (analogous to “rows”). In SQL, you can also create views. Views sort of look like tables, but depending on the implementation, you have various limitations to how you can update, insert, and delete with them.

  9. Rounded Corners - 158 (Upside down thinking)

    October 5th, 2007

    Some inert, some explosive. So it’s not that stakeholders don’t believe in quantum dynamics, they just prefer to play with chemicals:

    So there are two issues: what people believe about how projects work, and what deals people negotiate with each other. I believe that the adversarial negotiation games do contribute to fixed schedules, I agree with that. But I think it’s often evidence of stake holders who have embraced Theory P, not the opposite.

    Complexity, not the root of evil after all. Let’s leverage our synergetic complexities:

    This idea of “using” complexity creatively is very useful, I think, because it gets at what it really is that programmers actually do all day. The old joke that IT is the business of building new and improved problems works because it’s acknowledges the simple, awful truth that the end result of technology is usually the replacement of one kind of complexity with another kind of complexity (if not the wholesale manufacture of more complexity).

    Live free or buy more of the same. Mark Pilgrim doesn’t “understand this continuing obsession with buying things that you need to break before they do what you want.” Counter culture within a counter culture?

    My current theory is that it’s some twisted form of wish fulfillment. “I wish this company understood the value of openness, but they don’t, so I’m going to keep buying their closed, crippled shit until they get it.” Yeah, let me know how that works out for you.

    I would say the same, typing this on my Linux notebook, but I don’t think that’s the root cause.

    Don’t underestimate the strong cognitive dissonance that happens when people fight for open source and open standard, to free data and media, only to shell their hard earned cash for amazing products that unfortunately stand in contrast to all those principles. Those apps are highly effective, just not for the problems they claim to solve.

    Open, when we say it is. Giles Bowkett on the problem that is the Rails trademark (and similar open source projects).

    No distractions. Taking the browser in a different direction, distraction-free Webapps using WebRunner. And to get you started, the Google essentials, and 32 ToDo/GTD apps.

    Picture: the Internet explained thanks to Engrish.com.

  10. Rounded Corners - 157 (The funnies)

    October 5th, 2007

    Language trolling. Funny summary of what my feeds read like:

    Erlang: If I may, I’ve been running some ideas by the other panelists, all at the same time of course, not that that’s any big deal…

    Ruby (rolling its eyes): And here we go with the concurrency…

    Digg-a-book-apedia-r. Word of advise. Do not drink while reading this list:

    Nothing - and I mean NOTHING - is going to add four zeros to the end of that number in three months short of hiring Arthur Anderson to handle the bookkeeping.

    The OH FUCK moment. Apparently, Microsoft Search is not just far behind the big guys. It’s so far behind, Microsoft can’t tell how far behind they really are. And so, another lame press release leads to another funny post:

    It’s days before QA — or even before launch — when everyone needs to have everything done. Not “mostly done.” Not “almost done.” Really done. Done done.

    Immutable#. As much as I don’t respect C# as a language choice, it deserves a special place in my feed reader. C# is the other white Java, but C# actually follows all the recent fashion trends, baths and exercises regularly, and doesn’t bitch and moan “in my days ..”. Anyway, when C# squeaks, no pun intended, I listen.

    Here’s one sample post:

    Immutable data structures are the way of the future in C#.

    Reimbursed to code. Can open source development be a tax write-off?

    The status of a nonprofit foundation would allow software companies get a tax write-off if they let employees work on jQuery, said John Resig, jQuery’s founder and Mozilla’s JavaScript evangelist.

    NBKG: Never Bring a Knife to a Gunfight, via discipline and punish.