You are currently browsing the category archive for the ‘RAII’ 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

I was originally going to write my thoughts about exceptions vs. error codes in the context of PHP development, but I got completely sidetracked. So instead, I’m going to talk a little bit about Java. Please remember that I have written a grand total of about 30 lines of Java code in the last 5 years, and I could very well be talking out of my ass. But I like to think I’m not an idiot, even if I’m not fluent in the language.

There’s a particular API wart I’ve seen with Java file I/O. I can’t find any references right now (sorry!), but I’ve seen it mentioned in the context of Java, RAII (which Java doesn’t have, yet some people do argue to that effect), checked exceptions, and general error-recovery strategies.

This (pseudocode) is the core of what you have to do when you open a single file in Java:

void doFileIO() {
  File file;
  try {
    file = new File(path);
    // do stuff with file
  }
  finally {
    try {
      file.close();
    }
    catch (IOException e) {
      // couldn't close the file... but why? and do we care?
    }
  }
  return;
}

Why is that so ugly? Read the rest of this entry »

I love RAII. Unfortunately, most popular enterprisey languages don’t support it. I’ve seen people claim that Java’s finally is essentially RAII, but that’s not quite right. I hate seeing try/catch/finally scattered throughout application code.

One thing I definitely haven’t seen is any mention of RAII in PHP. Nasty ugly weak PHP that’s fallen out of favor with the hip. I can’t possibly be the only persion to have thought about this, because one of the bugfixes in PHP 5.2 is properly ordered destructors. However, since most people aren’t developing for PHP 5.2, I suppose it’s not a surprise that the subject isn’t googleable. Anyhow, prior to PHP 5.2, objects in the same scope would be destructed in arbitrary scope (usually the order in which they were declared, which sounds backwards), so multiple resources acquired in one function couldn’t be interdependent without invoking undefined behavior. That’s bad, but it’s not a show-stopper.

Read the rest of this entry »

I was looking at Doug Ross’s blog the other day; in particular his beef with exception-based programming. I definitely have more C++ experience than Java, so whenever I think about exceptions I think in the context of exception safety, transactional semantics, and RAII. Here’s my take on what he said:

Exceptions tacitly encourage abdication of cleanup responsibility… But the problem is, very few people are disciplined enough to set try, catch and finally clauses for every single method.

I would never expect every single method to have a try/catch/finally block associated with it. In my opinion, that’s a waste of the exception model, and severely limits its advantages. When I layer code, I want to consider sources (in the dark hearts of libraries) and sinks (in the application interface or controller) of exceptions. I try to minimize the exception handling (try/catch/finally) performed anywhere in between.

Wait! How can less exception handling produce better results? In C++ at least, the answer is “stack management”. Local objects (anything not allocated with new) are created on the stack. If an exception occurs, the stack is unwound, calling destructors for all instantiated local objects. If all of my setup code occurs in C++ object constructors, and all of my teardown code occurs in the object destructors, then the compiler will essentially write my try/catch/finally itself. I don’t have to worry about setting flags for what teardown needs to complete; that information is implied by the objects on the stack.

Now, code has transformed from this:

try {
    file = open(myFileName);
    file.readInto(myDataStructure);
finally {
    if (file) file.close();
}

to this:

openFile(myFileName);
openFile.getFileObject().readInto(myDataStructure)

If readInto raises an exception, the destructor of openFile will close the file properly, and I don’t need to worry about it whenever I try to use files. There’s definitely a benefit to be able to avoid this boilerplate checking. The associated cost, then, is creating objects like openFile that act as sentries on my stack. Read the rest of this entry »