You are currently browsing the category archive for the ‘Usability/Interfaces’ category.

Recently, I took a look at ADOdb, ADOdb-Lite, and PDO to find a replacement for PEAR::DB. I’ve looked at PEAR::MDB2, and not been happy with it for the same reasons I’m not happy with PEAR::DB:

  1. Since the application is tied to Postgres, there’s not much benefit from getting a database-agnostic driver. I’d rather have something that supports my database well, instead of all databases in a mediocre and outdated fashion.
  2. Not directly a complaint of PEAR itself, but my manager prefers wrapping existing OSS solutions to modifying the source (less concern about patches). Wrapping around PEAR::DB introduces all sorts of efficiency problems, since whatever data processing happens gets done twice. So not anything for the fault of PEAR, but it doesn’t fit with the development method of “wrap” vs “inject”.
  3. Following from #1, PEAR supports older versions of PHP/Postgres than I need, with the result that it won’t use all of the modern functionality I want.

For those of you who are curious, I did discover that ADOdb does use the existing pg_*() functions. Plus, the ADOdbs both target database independence through API-level SQL generation, instead of raw SQL. I ended up going with PDO for my project with a few modifications:

  • Exceptions are enabled by default
  • query() can take parametrized statements (why isn’t this done by default?)
  • Fetchmode is associative by default, so i can foreach a record
  • Statement execute() returns $this instead of an error code (I’m using exceptions anyways) so I can chain other functions onto it
  • I’ve added a few fetch*() functions for clarity in common use-cases

All of these modifications are intended to improve PDO’s overall usability (interfaces aren’t just for end users).

class PDO_ extends PDO {

  function __construct($dsn, $username, $password) {
    parent::__construct($dsn, $username, $password);
    $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  }

  function prepare($sql) {
    $stmt = parent::prepare($sql, array(
      PDO::ATTR_STATEMENT_CLASS => array('PDOStatement_')
    ));

    $stmt->setFetchMode(PDO::FETCH_ASSOC);
    return $stmt;
  }

  function query($sql, $params = array()) {
    $stmt = $this->prepare($sql);
    $stmt->execute($params);
    return $stmt;
  }
}

class PDOStatement_ extends PDOStatement {

  function execute($params = array()) {
    parent::execute($params);
    return $this;
  }

  function fetchSingle() {
    return $this->fetchColumn(0);
  }

  function fetchAssoc() {
    $this->setFetchMode(PDO::FETCH_NUM);
    $data = array();
    while ($row = $this->fetch()) {
      $data[$row[0]] = $row[1];
    }
    return $data;
  }
}

The end result of this is that I can use the connection much more naturally. It’s not quite a fluent interface, but you can see that it’s improved:

chained fetches after statement execution:
$stmt = $db->prepare(
    'SELECT first, last FROM users WHERE uid = ?');
$user1 = $stmt->execute(array(1))->fetch();
$user2 = $stmt->execute(array(2))->fetch();
parametrized direct querying:
$uid = $db->query(
    'SELECT uid FROM users WHERE first = ? AND last = ?',
    array($first, $last));
fetching an associative array of $uid => $username:
$users = $db->query('SELECT uid, username FROM users')
    ->fetchAssoc();
selecting a single aggregate:
$count = $db->query('SELECT COUNT(*) FROM users')
    ->fetchSingle();

I also add RAII-style transactional programming. This object can be created at the top of a function and committed at the bottom of the function. If an exception is thrown in between, it will automatically roll back the transaction that it started upon creation. This is useful in cases where exceptions are not being handled, but must bubble up to higher layers in the code.

class Transaction {

  private $db = NULL;
  private $finished = FALSE;

  function __construct($db) {
    $this->db = $db;
    $this->db->beginTransaction();
  }

  function __destruct() {
    if (!$this->finished) {
      $this->db->rollback();
    }
  }

  function commit() {
    $this->finished = TRUE;
    $this->db->commit();
  }

  function rollback() {
    $this->finished = TRUE;
    $this->db->rollback();
  }
}

This little guy is really convenient. Any model-level code that works with the database typically doesn’t need to address database errors (actually, I usually let them bubble up to the global error handler, which can then log it and print an apologetic 500 HTTP response).

function addUser($db, $username, $friend_users) {
  $txn = new Transaction($db);

  $db->query('INSERT INTO users(username) VALUES (?)', array($username);
  $uid = $db->query('SELECT currval(?)', array('username_id_seq'))
    ->fetchSingle();

  $stmt = $db->prepare('INSERT INTO friendships(uid1, uid2) VALUES (?, ?)
  foreach ($friend_users as $fuid => $fname) {
    $stmt->execute(array($uid, $fuid));
  }
  $txn->commit();
}

No exception handling required at all. If anything throws an error (e.g. an invalid friend), the stack unwinds and $txn automatically rolls back the transaction in its destructor.

Advertisements

…is that it takes so long to type things! I’ve always thought Hungarian Notation was a foolish thing for classes and interfaces (e.g. CRotationMatrix and IAffineTransformation), but now I’ve decided why.

  • Anyone who uses a code-completing IDE should be able to type in any class or interface name and get at least a hint about it’s type. This is particularly relevant to Java, which appears to be a “tools-required language” by design with its verbose but easy-to-parse style.
  • Anyone who uses a “man’s man” editor like vim/emacs/editplus should at least have access to some basic text-searching utilities. Something like `grep 'class TheClassName' path/to/repo -R` or (in PHP-land) surfing to http://php.net/functionname is typically sufficient.
  • Most code I’ve come across in dynamically-typed languages like PHP or Python doesn’t require a distinction between “implementing an interface” and “extending an implementation”. I know PHP allows the abstract class keyword, and I can’t really say that I like it.

So who really wants to see the C or I in front of their class/interface name? I dunno, but it’s not me. I don’t buy the argument of “it makes code more self-evident/documenting”, because jumping to a definition and seeing

interface AffineTransformation ...
class RotationMatrix ...

is just as readable (moreso I think because of the conciseness) as

interface IAffineTransformation ...
class CRotationMatrix ...

I think I would shoot myself in the face if I had to program with CRotationMatrixAffineTransformation.

Module Names

Module names are another gotcha that I don’t like. Now, I’m not a regular Java programmer, so tell me if there’s some awesome reason that I’m overlooking.

I’m currently working on some Lucene and Nutch code. They are (respectively) defined in modules org.apache.lucene and org.apache.nutch, and when I play in an 80-character-wide ssh account, the pathnames tend to wrap around my screen unless I start symlinking everything.

It’s all nice and great to know that my particular version of Lucene came from org.apache and not com.ibm, but I think I’d much rather just use the module lucene without organizational domains getting involved.

  • If a codebase is transferred between organizations, they eather have to deal with the headache of renaming everything and breaking backwards-compatibility, or keeping names as-is and just knowing that the “current controlling organization” is wrong. What if I downloaded something from Apache’s website that still referenced com.ibm modules (maybe originally developed by IBM and then donated). The license is in a big JavaDoc at the top of every page, I don’t need to see it referenced everytime I need to import a module.
  • it adds unnecessary levels. Am I really worried about multiple groups creating lucene modules and having to deal with both of them? Not really, because of the concept of trademarks. If I create a software product called Vista, you can bet Microsoft will have something to say about it. It doesn’t matter if I’m com.wordpress.tombarta.vista (which is bad anyways, because I could change hosts anytime) or just vista. If I use the same name as some other product, people will be confused, and organizational namespaces won’t do a hoot about that.

Ok, I’ve bashed Java enough tonight. I really should find more languages to dislike, or more good things about the Java language. I don’t necessarily want Java to change… I just want other things to replace it. Like some ultra-sweet combination of Python and C++.

Edit: I’ve tagged this in Usability because I certainly consider a programming language to be a user interface the same way I consider a software developer to be a digital content creator.

You know what the problem is with web applications? They’re entirely at the mercy of my web browser. I just wrote a few paragraphs and fat-fingered the back button, and lost it all. I know the adage “save early, save often”, but the whole web browser thing is just annoying. Firefox has session-store that recovers my input if the browser crashes… it should be part of the back/forward procedure as well.

I stopped at my bank today (the big white Bank One on Mattis) and noticed a few pleasing things about the building’s internals:

  1. Most banks have a desk with pens and deposit/withdrawal slips accessible before you get to the tellers, to allow a sort of pipelining. In this bank, the desk was in the atrium and stood out as the only bankish piece of furniture.
  2. Benches in the atrium promoted it as a place of waiting.
  3. The semicircular customer service desk had the first person I saw, and the smooth shape I think is inviting.
  4. The tellers are in a zig-zag row /\/\/\/\ instead of all in a line ——. This gives each teller and each patron a bit of a cubbyhole without requiring walls between tellers, so the space still appears open from a distance. The cabinets behind the tellers are also zig-zag, giving them a sense of partitioning and further highlighting the entire teller area as “different” from the rest of the internal space.
  5. The private rooms for the higher-level bankers are all partitioned by some sort of dark frameless glass, which increases the overall feeling of openness. A few of these glass walls were not at right angles, breaking up the regularity of the floor plan (more natural, less sterile).

I probably put way too much thought into that as a patron, but the openness and “craggyness” (for lack of a better word, the opposite of axis-aligned rectangles) definitely made me feel more comfortable.

When I was at Lockheed-Martin, we (the interns) always joked about painting the hallways bright colors. Every building in their campus was very regular, with axis-aligned rectangles and off-white undecorated walls. The few decorations that existed were very corporate in nature – awards, project posters, and motivational crap. Of course, the culture there was very similar to their buildings, and I must assume that there is some interrelation; they must like the boring walls, the “lowest common denominator” that could not possibly offend anyone, but could definitely kill souls.