Archive for the ‘Programming’ Category

Testing and PHP

I’ve discovered that after a certain point, I become allergic to not having tests. It doesn’t manifest in hives or in anaphylactic shock, or any of the regular symptoms. It actually results in a brain freeze. There’s just so much code I can write before my brain refuses to go any further. In a way, maybe it’s more like a phobia. I’m simply afraid to write the next piece of code, knowing how tenuously linked to reality I am by that point, and the next code could be simply the beginning of the cascade of horrible ideas and messy disgusting code.

I wasn’t always this way. For quite a while I was completely happy with not documenting, not testing, and just writing line after line of incomprehensible code. Now, I can’t stand having poorly-documented code, and while I can still stomach writing a project for a while without tests, I hit a point eventually where I just can’t go any further without knowing what lies behind is thoroughly tested.

So it is with a project I’ve been working on that I hope will help me out at work: PGModel. I have been working on it for quite some time, though rather sporadically. It’s simply an ORM for PHP that is designed to be compatible all the way back to PHP 5.1 (I know it’s been end-of-lifed forever, but the project’s documentation goes into more detail on the “why”). And it does a few particular ORM-like things already, such as basic dataset loading and associations. These are all inspired, as the README states, by Sequel.

But while all of this is relatively simple at this point, it’s still already very complicated, and the more I write the more I worry that I’m missing critical bugs. So, I finally wrote myself a testing suite. It’s simple but I think it adheres to at least a subset of the Test Anything Protocol, and allows me to write a large number of tests fairly quickly and easily.

Unfortunately, there are some drawbacks. I could allow a function to be called à la call-user-func-array() to handle checking for exceptions, but it’s rather inelegant. As it stands, though, there’s no other way to check for exceptional cases, as closures didn’t become available until PHP 5.3. It’s also currently completely done from a memory of how testing works in Test::More from Perl, and as such is almost definitely far less feature-complete than a full testing suite.

There’s also already a unit testing suite written for PHP, but it’s sadly only compatible back to 5.2.7. So, I think, as long as I’m stupidly insistent on sticking with 5.1, I’ll keep using this. Who knows, maybe I’ll learn to love it, over time. But for now, I can finally scratch that itch and secure my code (more than it has been, at any rate) with proper testing.

My First #YAPC

This past week I finally attended my first YAPC. While previously I’d attended the excellent Surge conference hosted by OmniTI as a commuter, and the brand-spanking-new DCBPW by the DC and Baltimore Perl Mongers, this was my first full-immersion conference with flying out of town and everything, and it was quite an experience.

My work sponsored myself and two coworkers to attend the three-day conference. They were going to send us to the two-day workshops beforehand but unfortunately they sold out before the long process of travel paperwork completed. Still, I think we got a very worthwhile event.

As with most conferences, there was a lot of value in simply being around other people who are passionate about Perl. If I’ve got one big regret about this past week, it’s that I didn’t spend more time talking to those people. It’s not for their lack of trying, however. Everyone I did meet was very friendly and willing to talk, and more than once we were told by conference organizers to simply introduce ourselves to others. I’m unfortunately far too quiet for my own good, even among such good company. While the Linode-sponsored beer garden certainly helped me feel more comfortable with expressing myself, I mostly wound up expressing myself through dance.

One of the big topics throughout the days, however, wasn’t even just about Perl programming, but Perl culture, and expanding that culture through diversification. Michael Schwern (@schwern) gave the keynote on Wednesday morning, and impressively dove straight into waters which have been churning and sinking many ships for a couple of years now: women and minorities in a culture dominated by white males: the “geek” culture. Still, he brought it up in a non-combative, humorous way that still got everyone talking, and I think that’s the whole point. As he said, he wasn’t going to solve the diversity problem in 50 minutes at the start of YAPC::NA, but it was quite awesome to see everyone get into the topic and discuss it throughout the conference with as much weight as how we were going to solve the next big computational problems in Perl.

Speaking of the next big problems… For me, my latest issues have been focused around web development, and I’m mentioning that almost purely so I can segue into my favorite scheduled talk of the conference: Glen Hinkle (@tempire)’s Introduction to Mojolicious. For a long while now, any time I’ve wanted to throw anything onto the web, I’ve reached straight for Sinatra, because it’s so fast to install, quick to write in, and so easy to deploy to Heroku. Now, I’m feeling like the rewrite I started of my own blog may be scrapped and redone in Mojo. So, while many talks captured my interests, nothing quite changed my whole attitude on a topic like the Mojo Intro.

Oh, yeah, and Damian Conway’s recorded talk on Regexp::Debugger? Ho-lee crap. Rocked my socks off.

So, in all, it was a great experience, and one I hope to repeat at future YAPCs. While I’m hoping to attend one abroad one day, for now I fear I will just have to stay local. If YAPC::NA proved anything to me, though, it’s that there’s a wealth of value even in that.

Postgres Triggers, Why Do You Hate Me?

Actually, in spite of the melodramatic post title, figuring out triggers in PostgreSQL has been relatively painless. Of course, I had a pretty firm grasp of them in MySQL, and thus the major migration headache is realizing that the code handling the trigger has to be defined separate from the trigger itself.

The issue for me, however, is that (unlike Peter Eisentraut)  I have a sordid love affair with schemas. For me, it’s not just about addressing the potential naming conflicts, but breaking down the tasks our database/frontend performs into more manageable blocks. Put it this way: I have over 100 tables, functions aplenty, and datatypes (as ENUM now has to be a datatype) to spare. While I recognize that it’s not impossible to manage, and there’s many systems that probably have a volume of data far exceeding mine, it still does wonders for my sanity if I can break those down so I only have to look through at most 25 tables at a time. They’re not randomly selected, they are geared towards similar ends and logically fit together, and I think schemas really helps on that front.

My solution to Peter’s problem of localized search paths is obtuse, but it works: I deliberately name the full path in anything that’s going inside a stored procedure. It’s a very tedious and defensive posture, but it has worked pretty well, at least up until now. This is where we get back to triggers: triggers in PostgreSQL are not named according to the same conventions as almost everything else in the DBMS. While most times, in the docs “simple_name” by itself is tantamount to “public”.”simple_name” (as the default search path is ‘”$user”, public’), this is not so for triggers. They are associated with the tables for which they are defined. While in hindsight, this makes sense, it took some time to figure this out (also, Michael Graziano pointed me in the right direction after I bitched about it). What would have been far more simple is if, anywhere in the documentation, they had simply specified this strange behavior. Even a hint, when executing “CREATE TRIGGER my_schema.do_something” other than a bland “syntax error at ‘.’” would be nice.

The other part of my problem with triggers doesn’t have anything to do with the trigger mechanism itself, but an issue I’ve encountered in the database as a whole. There is, as far as I can tell, no mechanism for creating connection-level or database-level custom variables. You can make variables obviously in any of the procedural languages. However, setting a variable, like MySQL’s “SET @@my_custom_variable := ‘some custom value’;” just doesn’t seem to exist. While this may not seem like a feature that would be particularly useful (after all, there are the aforementioned procedural languages), I’ve been finding it quite problematic.

When we were on MySQL, we used wxPerl and wxRuby as front-ends to connect directly to the database using database-level logins, and I was able to write auditing fairly handily: not only could I have information about the table on what data was modified and when, I could also log who modified the data. That doesn’t seem all that amazing, except that this was all database-side. The clients had to change exactly 0 code. You could even optionally issue a “@@COMMENTS := ‘my editing comments’;” and have it apply to all of the changes automatically until you unset it, providing an easy-access way to comment the audit log. I knew this was going to be problematic switching to rails, as ActiveRecord only ever connects as one user, and uses special models to manage logins. However, with MySQL, I could just ensure that the client issued a “@@CURRENT_USER := ‘whomever@address’;” before starting work. This, while obtuse, still has the database doing the majority of the legwork. I could easily reject any statements that occured before that variable was assigned, to make sure that changes made should always include complete auditing data.

PostgreSQL has denied my attempts at a simple solution to this, however. I’ve been searching, but the easiest solution seems to be to make a special table which holds “current connection” information and somehow tie the connection ID to the user ID that way. This seems pretty complicated, and I’m not sure how safe it is to assume that the connection ID will be unique for an arbitrary length of time (as I’m not sure what mechanisms exist for periodically purging the table of stale IDs). If there is any other way around this, I’d love to hear about it.

Boring Life Update

Having spent a decent portion of today talking about programming with rakaur and dKingston, I feel I have the urge to actually do some programming.  I do that for my job, of course, but that’s not really what I’m talking about.  I’ve been doing that all day today, and while it’s nice to get a task done, writing database interfaces for government processes isn’t exactly illustrious.  I don’t hate my job, though the people I work with can be, shall we say, frustrating; I just want to do something other than this.

Recently, I went off the deep end and acquired an iPhone, which I’m almost certain heralds the apocalypse in some way.  However, it presents an interesting opportunity: I could learn another language and actually write some interesting things.  I’m assuming the ideas for those things will come later, after the learning part.  The more important thing is to actually do something new, while I have the vibe for it.

Also, I never posted those things I promised I would a week or two ago.  Turns out, I had no Internet connection.  Of course, now I’ve totally lost interest in them.  One’s written up, but it’s terrible, so I guess I’ll post it, and just trash the other.

Return top