" /> Bill de hÓra: February 2007 Archives

« January 2007 | Main | March 2007 »

February 28, 2007

Off by one

"Doesn't matter where it came from - one source might be the result of a SPARQL CONSTRUCT query against a bunch of scuttered material."

The point isn't where the data came, it's that the data has been organized and marshaled in advance into a domain model before being passed to the rendering layer. It has to be, or the basic publishing exercise becomes too complicated - in Danny's example everything becomes a for loop filtering over value streams instead of simple field gets on an object. RDF backed data needs to be fitted into a domain before it plays nice with the web stack - anything else is a rip and place of at least two layers. I've been saying this for a few years now. Trying his example against arbitrary graphs will get a feel for the richness involved. The problem is some people will point out that if the data is organized into domain models, handling/storing arbitrary RDF isn't necessary. IOW, if the vcard example was actually realistic, RDF isn't warranted.

So, that took a while to figure out

base.html

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>{% block title %}Stubbie Title{% endblock %}</title>
    {% include "base_meta_inc.html" %}
{% block extraheader %}
<link rel="alternate" 
   type="application/atom+xml" 
   title="atom" href="/{{weblog.slug}}/feed/atom.xml" />
{% endblock %}
  </head>
  <body 
      id="{% block bodyid %}home{% endblock %}" 
      class="{% block bodyclass %}home{% endblock %}">
    <div id="container">
      {% block "content-header %}
        <div id="content-header" class="header">
        </div>
      {% endblock %}
      {% block columnwrap %}
        <div id="columnwrap">
          {% block content %}
            <div id="content-main" class="main">
            </div>
          {% endblock %}
          {% block content-sidebar %}
            <div id="content-sidebar" class="sidebar">
            </div>
          {% endblock %}
        </div>
     {% endblock %}
     {% block footer %}
         <div id="footer" class="main"> 
         </div>
     {% endblock %}
    </div>
  </body>
</html>

weblog/main_weblog.html

{% extends "base.html" %}
{% block "content-header %}
  <div id="content-header">    
    {% include "skins/weblog_logo.html" %}
    {% include "skins/weblog_content_header.html" %}
  </div>
{% endblock %}
{% block extraheader %}
   {{ block.super }}
<link rel="alternate" 
   type="application/atom+xml" 
   title="atom" href="/{{weblog.slug}}/feed/atom.xml" />
  {% include "skins/extraheaders_inc.html" %}
{% endblock %}
{% block content %}
  <div id="content-main" class="sidebar">
    {% include "skins/main_weblog_content_inc.html" %}
  </div>
{% endblock %}
{% block content-sidebar %}
  <div id="content-sidebar" class="sidebar">
    {% include "skins/main_weblog_sidebar_inc.html" %}
  </div>
{% endblock %}
{% block footer %}
  <div id="footer">
    {% include "skins/weblog_footer_inc.html" %}
  </div>
{% endblock %}

skins/

  • extraheaders_inc.html
  • weblog_logo.html
  • weblog_content_header.html
  • main_weblog_content_inc.html
  • main_weblog_sidebar_inc.html
  • weblog_footer_inc.html

It's a start I suppose. Thank God for Django templates is all I can say. Writing composable makefiles back in the day was easier than figuring out skinnable templates. "Support multiple weblogs" - I must be insane

File under 'I need meaningful work that involves floating point numbers'

Shipping faster than you can upgrade

Charles Miller

Confluence 2.4 would be developed in a strict six week time-box from inception to release. Anything we had done at the end of those six weeks we'd ship. Anything not finished would be safely tucked away where nobody could see it, and carried over to the next development cycle.

links for 2007-02-28


February 26, 2007

Verisimilitude

This is not the link to the appearance, but not actuality of, hypertext as the engine of application state.

And neither is this.

February 24, 2007

Confederacy

Mike Champion: "those “legacy systems chugging along” work a whole lot better than HTTP for end to end secure, reliable messages, and the IT managers of the world have no interest in moving to the “modern” world of HTTP’s quality of service. There are only a handful of Web companies who have managed to do all this stuff (Amazon, eBay, etc.) that work has required hundreds of millions of dollars to hire extremely bright people who still required several iterations of their architectures to get to the current quality of service levels … and they do *not* interoperate with one another except via 'behind the eyeballs' integration (or read-only operations, of course)."

I hear this from time to time. If the web is fundamentally unsuitable for enterprise work then 'WS' has to be one of the most bone-headed marketing blunders in software history. So perhaps this is the real source of tension - why are these technologies called "Web Services"?

Aside from mine is better is better than yours, I do have a specific practical problem with these technologies being labeled as 'Web'. On every project I've ever worked on that has had enterprise and web dimensions, I've had to waste cycles on how the web tier should be modeled. Enterprise developers instinctively model the web interface as being composed of controllers and service endpoints. These are the same enterprise developers that will bore you tears about how Service Layers are crap (because they skimmed Martin Fowler or Eric Evans) and that we should all be using objects "properly" in the middle tier, often irrespective of whether you needed a object domain model or not. There's now an entire generation of enterprise devs who think WS and SOA are in fact how the Web should, or does work. It'd be farcical if there wasn't real money and real schedules involved. The irony is that you can apply good OO modeling practices as laid down by Ambler, and before him Fowler, and before him Booch, almost as is to web tier design (and then go on to consider the object representations and how aggregations should work). Getting people straight on this becomes more and more important when you realize that the Web is not just the presentation tier anymore; it's becoming a data integration and machine-oriented publishing layer. The presentation layer is being pushed down to the client machine in the form of AJAX, XUL and Flex.

links for 2007-02-24

February 23, 2007

He who would pun would pick a pocket

"And finally, they can’t spell 'its'. Really, really, offensive."

I suspect it's a pun on 'IT'.

Machine Tags

dehora's bookmarks tagged with "http:/example.org/spamnet" on del.icio.us

I had no idea you could put URLs into del.icio.us tags. Semweb folks will be thrilled as they can apply overlays for RDF processing, especially for tagtags. But is this a spam/link vector?

QOTD

""Tagging works well when people tag "their" stuff, but it fails when they're asked to do it to "someone else's" stuff. You can't get your customers to organize your products, unless you give them a very good incentive. We all make our beds, but nobody volunteers to fluff pillows at the local Sheraton."

links for 2007-02-23

February 22, 2007

links for 2007-02-22

February 21, 2007

links for 2007-02-21

February 20, 2007

links for 2007-02-20

February 19, 2007

Aspects and Middleware

Phillip J. Eby:

But this doesn't make any sense. If your application requires that API to be present, then it's not middleware any more! Middleware, you see, exists in order to wrap applications with additional behavior. If you can't arbitrarily decide whether to stick it in front of an application, it's not middleware any more. It's part of the application.

PJE describes pointless decoupling via WSGI middleware. No argument from me. In the Java world, that a problem is optimally obtained by using AOP for everything. The kinds of things you could could farm out to aspects are much like the ones you can farm out to middleware. Where the variation comes into play is that the set of issues that crosscut an application will vary depending on how you design your application (for example if you use OO domain models, threads and logging will crosscut your application), and on the environment (for example if you are building a webapp or a CMS, character encoding will crosscut your application). I gather this sort of thing is why some people see AOP as a technique of limited application, rather than a programming paradigm - something along the lines of, you don't design a program with AOP, you use it to duck and dive around a program.

links for 2007-02-19

February 17, 2007

links for 2007-02-17

February 16, 2007

Out of time

Messaging causality for a non-originating system:

  • messages of origin must come into a system before leaving that system
  • acknowledgements for messages of origin come into a system after the origin message has left the system.
  • an origin message that has been sent or acknowledged cannot no longer be unsent.

Those truths are non-contingent, ie they are true in all possible messaging systems that accept and send messages of origin. However for an observer who is reacting latently to the system's events:

  • events about acknowledgements for origin messages can appear before events about origin messages.

This is the kind of thing SOA proponents need to be thinking about and writing down if they want to build useful large-scale systems.

links for 2007-02-16

February 15, 2007

You lost me right there

Alex Blewitt: "The general idea of REST (and you should take time out to read Roy Fielding's PhD thesis on the subject if you haven't done so already) is to make URLs associate with specific items, and to use PUT as well as GET and DELETE to be able to iteract, and not cookie-based state or server-side hooks. "

Well, now. That's hardly the nutshell version I had in mind. On a more general note about this JSR and how the 'REST community' is reacting to it - I haven't been as unimpressed with a technology community since the WS crowd were depicting the REST crowd as a bunch of toymaking clownpunchers a few years back. I'm shocked, shocked to find that ex-cathedra opining is acting in place of technical criticism - still.

Not every framework gets a Springer book

available to order.

{{ name }}

"But what about roundtripping through dreamweaver?"


February 13, 2007

links for 2007-02-13

February 10, 2007

apples and oranges

It's friday, we're in the kitchen. Dinner is nearly ready.

- so Dad. Dad, once I can figure out the problem, I can do the sums. It's the problem that's hard. The first bit.

- I don't think I understand. Can you show me a problem in your homework book?

- Yes. The book's in my bag. I'll get it.

She runs off to the hallway, comes back with a math book opened to the last page.

- This, one, look. Number nine.

- Ok, let's see. "if you have to drive 9 1/4 Km and you've driven 5km and 585m, have far do you have left to drive?"

- That one. How you do that? I mean, I can do it. It's take away. But how do you figure out what to do?

- Ok. They're trying to test you on a few things here. The first thing that you have to do is get these two numbers into the same form. If you can the make numbers like each other, then you can take one away from the other and that will give you the answer. Both of the numbers have kilometers, but one has a meters bit and the other has a quarter.

- A quarter is fraction of a kilometer. We did fractions last year.

- Right. We can make these numbers the same in a few different ways. Which do you think is easier to subtract, meters or quarters?

- Meters

- Then how many meters is a quarter of kilometer? No, first. How many meters are there in a kilometer?

A pause.

- 1000.

- Good. What's a -

- Quarter of 1000. That's 250 meters.

- That's right. So one thing they're testing you on is whether you know how many meters are in a kilometer. Without that you can't make the numbers the same. Anyway. Now, how many meters are there in 9 kilometers?

- 9000.

- and what's 9000 and 250?

- there's 9250 meters.

- Yes. how many meters in 5 kilometers?

- 5000. And 585 is 5585 meters. I need to... take... 5585 meter from 9250 meters?

- Exactly. Now, do see what you need to do? When you have two amounts that aren't written down the same way you have to find out how to write them down the same way. That can be hard sometimes, but the pattern they're trying to teach you is to when you have to work with two different kinds of numbers is to find out how they can be made into the same types of numbers. Which is what you did just now. You turned everything into meters.

- Ok...

- A lot math is about seeing what the patterns are underneath the numbers. Once you know patterns, you can solve problems without worrying too much about what the numbers are.

- Ok...

- Now here's one. How would take away 3 apples from 5 oranges?

- immediately - You need to find out what fruit is.

She runs off to play guitar hero with her brother. Her mother, who has been half-listening all along, turns around, and says,

- I had no idea. I was going to say you can't take apples away from oranges.

- So was I. I'd never think of turning them into fruit.

- Dinner'll be ready in minute. Tell them to come in.

- Cool.

February 09, 2007

links for 2007-02-09

February 07, 2007

links for 2007-02-07

django: display the name of a choice field instead of its value

Sometimes in django, you want to display a field choice's name and not the choice value (which is usually an integer). Here's one way to do that.

Function:

def get_choicename(obj, fieldname):
    """
    given an object and a field which has a choices argument, 
    find the name of choice for that field instead of its stored 
    database number svalue
    
    returns the tuple ( '$field$_choicename', field_choicename
    """    
    field_key=int(getattr(obj, fieldname))
    field = obj._meta.get_field(fieldname) #*
    field_choicename=[val for key,val in field.choices if key==field_key][0]
    return '%s_choicename'%fieldname, field_choicename

Example:

from utils import get_choicename

class MessageTracking(models.Model):
    """
    """
    STATUS_CHOICES = (
        (MessageTrackingState.UNKNOWN, 'unknown'),
        (MessageTrackingState.OPEN, 'open'),
        (MessageTrackingState.SENT, 'sent'),
        (MessageTrackingState.RECEIPTED, 'receipted'),
        (MessageTrackingState.CANCELLED, 'cancelled'),
        (MessageTrackingState.OVERDUE, 'overdue'),
    )
    uid = models.CharField(maxlength=48, default="", blank=True, db_index=True) 
    date_received =  models.DateTimeField(db_index=True, blank=True)
    date_sent =  models.DateTimeField(null=True, blank=True, db_index=True)
    date_sent_expected =  models.DateTimeField(null=True, blank=True, db_index=True)
    status = models.PositiveIntegerField(choices=STATUS_CHOICES, default=0, blank=True, db_index=True)
    insert_time = models.DateTimeField(auto_now_add=True, db_index=True, editable=False)

    def status_nicename(self):
        return get_choicename(self, "status")[1]


{% block content %}
<h2 class="pagetitle">Serial No: {{ object.uid }}</h3>
<p>date received: {{ object.date_received }}</p>
<p>date sent: {{ object.date_sent }}</p>
<p>date sent_expected: {{ object.date_sent_expected }}

<p>status: {{ object.status_nicename }}</p> {% endblock %}

#* Indeed, there's a whole meta layer in there.

February 06, 2007

We see no silver bullet

Scott Rosenberg:

"programmers are programmers because they like to code -- given a choice between learning someone else's code and just sitting down and writing their own, they will always do the latter. And the programmer who says, it will be faster for me to write it, rather than to learn it, is usually correct. Except that what he will write, most likely, is something that will work but will not have its rough edges worked out, will not have the benefits of a piece of software that has actually been used for a few years, where the bugs have been found and the users have given feedback and have helped you figure out where the problems are. So what they will often be handing you at the end of that I-can-do-it-faster-myself thing is something that works, but that is kind of a mess in certain ways. Whereas the thing that you were going to pull off the shelf, maybe it will take the programmers a while to learn it, but once they learn it enough to hook it up to this project you are creating, what they are hooking up will probably have a lot fewer problems."

Wow. The problem here is that somebody accountable for a software project, but who doesn't know much about the activity of software development, might just believe this.

The counter-arguments are depressingly easy to state. One is integrated innovation - project failure due to issues with integrating third party dependencies and/or delays in key components. Another is "last 20% equals next 80%" syndrome - missed requirements or changes ensure the COTS option does not meet needs and the project proves to be extraordinarily difficult to bring over the line via customization, as the COTS component was never designed to be customized or meaningfully extended to begin with. In the worst case the subsystem has to be ripped out and rebuilt, derailing the schedule. Perhaps Rosenberg doesn't know, but "hooking up" software is an entire industry sector in and of itself, one of the most complex - it's called systems integration.

"We see no silver bullet. There is no single development, in either technology or in management technique, that by itself promises even one order-of-magnitude improvement in productivity, in reliability, in simplicity." - Fred Brooks

Developing software isn't hard because of just one thing, just one dimension of activity. In the meantime, trash talk about programmers, who are some of the most intelligent and inventive people you can find, is unlikely to produce better results.

Topic Oriented

Norm Walsh: topic oriented authoring

February 05, 2007

Journal Migration I: export entries from

As mentioned elsewhere, I am moving off Movable Type. In favor of my own codebase. I've decided weblogs are to this decade as editors were to the 1970s. You have to write your own. It's a pretty thin rationale - the 1970s more or less sucked as I recall*.

Cool URI Tax

I would very much like to preserve this journal's URL space. It's turning out that coding a weblog might be less working than porting the entries while preserving URLs. URLs matter. It's not just me you know - the W3C's Cool URI dogma more or less says I'm a random idiot if I don't do this or didn't have the forethought to use software that doesn't make this anything but a snap. Nothing's worse than being a random idiot.

So. I've been writing a parser/loader against MT's export file. MT does not export Atom/RSS entries as you might expect, it outputs a line based dump format.


Trackbacks

It turns out that the MT dump format does not export trackback URLs. I thought this was bad. MT does tell me whether the trackback is enabled for the entry and lists out received trackback details, but not the URL. I said to myself - "this renders MT's 'export entries from' feature as at best, underwhelming - I'll have to go to the DB to get at the trackback table. This in turn will be awkward as MT does not appear to output any kind of keys in the export that I can uses to cross-reference the database with. I do mean any kind - not just pks, there are no URLs or slugs sent back - it's just data. I will have a Cool URI crisis if I don't solve this." 3 minutes (of actual) thought later, I realised it didn't matter. Trackback URLs are dynamically discovered either off the entry's html page (as commented out RDF! I know! It's crazy!) or perhaps in the entry's XML as an extension. They don't need Cool URIs.

Comments

The comments themselves do need Cool URI work because MT builds permalinks for them. Two points of mention on that.

Fragment IDs. First, my MT templates output links to 'comments' and 'permalinks' in each entry's HTML page as fragment identifiers (I think most MT templates keyed off the default one do that). That's ok I suppose - I can write a mapping for "#comments" and "#trackbacks" and have them redirect into some... urk, wait. I can't do that. Fragments don't function properly at the HTTP layer - for example they don't redirect**.

Primary keys. Second, the comments themselves have permalinks - again using fragment identifiers. Unfortunately these look like this: "#comment-104897". I suspect that number at the end is an autoincrementing primary key, and that key is not in the export file. This time, 3 minutes of thought has not dispelled the idea that I'm going back to the database to get the comment pks. Did I mention that MT does not appear to output any kind of keys in the export that I can uses to cross-reference the database? Urk.

Conclusion.

It would be a very good thing if future versions of weblog tools exported content as Atom/RSS and not some custom file format.

Irrespective of MT defaults and biases, my use of fragment identifiers has been shortsighted. I chose Django for my weblog's codebase, and with good reason. It has direct support for dealing with exposed URLs of this kind. Something like '#comment-104897' can be mapped so that '104897' can be selected against the 'random_idiot_legacy_fragid' field in the content model***. And it can be done so that you don't need to think about preserving legacy fragment identifiers in html for all eternity (read: I come up with some templating hack to auto-embed them into the entry html pages).

As an aside, this exercise would be more problematic if the journal used MT's default of serving URLs with the entry primary key as the slug. At least the current approach of building the URl space with Years, Months and Titles means the current URL space can be reversed engineering from the data. Having to migrate auto incremented keys from an export file that doesn't supply them would bite, even though it looks like I will have a small-scale-alike problem with comments. I understand this might be counter-intuitive, as it seems I'm favoring natural keys over synthetic ones.


* I tell my children the 1970s in Ireland really were in black and white, just like old movies, but with more rain. Color come to Ireland around about 1982, and there was color reality in the US as far back as the 1960s. They don't believe me.

** At this point, I'm tempted to conclude that fragment identifiers or anything like them hurt if Cool URIs are the goal. Any URL that points into a HTML page (a representation that can change over time) is going to have a hard time remaining cool; it's a very high bar for publishers and especially for template/site designers. I missed the W3C memo explaining how the fragment id feature they recommend for HTML is Cool. I wonder how stable purple numbers will prove to be in the age of templates.

*** My second Django evaluation project involved a content migration exercise, and that was deliberate. Django can deal with legacy and/or rubbish URLs because it dispatches using regular expressions and has direct support for slugs in URLs, via regex groups. If you're going to commit to a web framework, a content migration exercise is a good way to stress its design.

February 03, 2007

links for 2007-02-03

February 02, 2007

links for 2007-02-02

February 01, 2007

links for 2007-02-01