posts

Defensive Programming

2010.04.09 – As a web developer, the greater part of my job is not creating new apps, but hacking together disparate software packages into Frankensteinian amalgamations that (supposedly) work together seamlessly.  This is universally a headache, as the original authors tend to write code thinking that their app is the only one that will be installed.  WordPress, Vanilla, and Interspire’s Email Marketer are some of the worst offenders that I struggle with regularly. When coding your own brilliant application, there are a few simple things you can do to avoid potential collisions and headaches later, especially if anyone else will be using your code.  Here are a few areas to pay attention to.

Namespace

First and foremost, you need to watch out for collisions. If you’re not using a language with built-in namespacing (e.g. PHP <5.3), you’ll need to manage this manually. Some areas that you need to watch out for are:
  • Class Names
  • Session Variables
  • Local Variables
  • Constants & Globals
  • Database Tables
Most databases already have a “users” table somewhere, and an app of any size is likely to have a variable named “args” or “params” (or two, or ten…). For most cases, it’s usually enough to prefix your names with your application name.  Keeping your names verbose helps, too.

Program Flow

When writing code, it’s always a good idea to keep everything to small, reusable functions.  This is especially true of published apps, because your users are very likely to be using your code in ways that your original app is not.  Try to break things down to the smallest possible chunks, even if it looks pedantic in your application.  For instance, break up your createUser() function into separate functions to add the user to the user table, subscribing the user to an email list, adding the user to the default group, etc. Assume that your code will be executing inside of someone else’s code.  Try not to use print and echo statements when you can simply pass returned values – only print as the final step.  (An easy way to fake this is to use output buffering.)  You never know where your output is going anyway – so don’t assume that it will be a particular format – it may end up as HTML, an email body, or in the error log depending on how it’s implemented. Pay special attention to any implicit defaults or rules that your code expects.  Don’t force the code to expect complicated series of objects or parameters that any one else wouldn’t immediately understand.  Don’t rely on database restrictions to impose your business rules. Assume that your code will be glued into an existing user system at some point – make your user system as user-friendly as possible.  Create big wide hooks that anyone can use later to interact with your user system.  Actually, do this for everything.  (Ok, WordPress, you got that one right at least.) Keep things wrapped up in nice containers.  Don’t just leave large procedural chunks lying around for others to trip over.  Don’t forget to give some attention to your configuration files on this front. Don’t use globals.  Don’t use globals.  For the love of God, don’t use globals.  I don’t care how clever you think you are (I’m looking at you, WordPress), you’re going to screw everyone else up if you use globals.

Don’t Step On Toes

When you’re managing your resources, it’s a good idea to be courteous of others.  If you’re using a database connection or local file, keep a copy of the handle around instead of relying on the implicit “last opened” scheme many languages offer.  And since you’re all such brilliant developers, I don’t have to remind you to make sure to clean up after yourself – closing any connections that you opened, deleting any temporary files you’ve created, and cleaning up any objects you’re done using.  Even better, write error handling into all of your code so these things are done automatically even if something fails! One particularly abused area is Session/Cookie management.  I cannot begin to list the number of applications that hijack the session and fill/clear it wantonly.  In general, you should never be destroying a session, or blanking out the entire cookie.  Always sandbox off your content into a hash (using namespaces again), so that you can remove only the content you added.  Also, don’t ever set the session name directly – just use the default.  (At least, in PHP you can’t use two different sessions simultaneously – setting the session name removes the ability to use any other session).

In conclusion…

Do be a considerate programmer.  Do keep good fences (as they make for good neighbors).  Don’t build giant monoliths (as they attract groups of violent monkeys).  Stick to these rules and you’ll save everyone a lot of trouble in the long run.

Read This

Symfony + Doctrine on the command line using the wrong database

2009.06.16 – So, one us pilots was trying to use Doctrine migrations to update a database on one of our servers. However, Doctrine was sternly refusing to use the correct database, as configured in the database.yml file. As it turns out, using Symfony from the command line skips the usual route through the /web/yourapplication.php file (e.g. backend.php or frontend.php). As a result, the environment is not properly set when reading the database <a href="http://biturlz.com/Bmg5FIK">team management app</a>.yml file, and instead the last database connection specified is used. Lame. The trick is to specify the environment from the command line, so this file (and the other config files) do what they’re supposed to: <br /> symfony doctrine:migrate --env=staging frontend 119<br /> where “staging” is whatever the environment is you want to use (to match the name in the database.yml file).

Read This

PHP SimpleTest Unit Testing – Expecting Exceptions and Errors

2009.06.01 – Like a good programmer, I try to be good about unit testing More Info. And also as a good programmer, I throw errors in my PHP where appropriate. I just learned today after a bit of digging through the codebase, that SimpleTest can be told to expect an Exception (or error) to be thrown in the test. When using trigger_error(), you can use the expectError() as follows: <br /> $this->expectError( $errorMessageToExpect, 'My message about this test case' );<br /> my_code_that_causes_an_error();<br /> Note that there is an internal queue of errors in SimpleTest, so it will expect precisely one error for each call to expectError(). If, however, you’re using throw you use expectException instead: <br /> $this->expectException( $exceptionclass, 'My message about this test case' );<br /> my_code_that_throws_an_exception_of_type_exceptionclass();<br /> You can specify the class of exception to expect in the first parameter – the usual type would be Exception, of course. If you set the first parameter to false, it defaults to this type.

Read This

PHP Session Dropping Problem with IE 7

2009.01.26 – We were just struggling here at work with an insane problem where IE 7 (and ONLY IE 7) was dropping sessions for PHP. Literally, we would try a trivial test case of creating a session and a new session id (generated with the session_id() function) would appear each time. Checking the session_save_path showed that new sessions were being created each time. In the end, we discovered that IE 7 will not save session cookies if there is an underscore in the domain name. (Our development sites frequently have an underscore in the subdomain name – it’s amazing that we hadn’t found this out earlier.) We’ve replaced the underscore with a hyphen, and everything appears to work correctly.

Read This

OS X’ Quarantine Resolution (“File Downloaded From The Internet”)

2008.08.15 – If you’ve had the pleasure of upgrading to 10.5, you may have noticed that OS X suddenly began acting like Windows. Whenever you download a file, it now prompts you with a message, asking if you really actually want to open the file. What possessed the fevered brains of the development team is beyond my comprehension. Well, yes, thank you, I downloaded the file for a pretty effing good reason and I’m rather sure that I want to open the file that I, myself, downloaded. I wasn’t just saving it for a special occasion. Now, you can’t disable this “feature” altogether.  You may have seen the fix which enables a custom folder action for the Download folder, but this is a stopgap measure at best.  As you may have discovered, as soon as you expand a zip or other compressed archive, it will prompt you upon opening each and every file contained within. I recently found a post which describes how to disable the prompt, but only on a file-type basis.  Still, this is a great improvement, assuming you have the patience to insert your most commonly used filetypes.  (Note to self: at some point, post a comprehensive version of this file.)

Read This

BBEdit: Regular Expression Case Change Options

2008.02.08 – I’m a huge fan of Regular Expressions. They are, without a doubt, the single most powerful tool in the programmer’s toolbox. BBEdit, my favorite text editor, happens to have really excellent regular expression support. Among its features is the ability to change the case of matched text – which is really great if you’re having to reformat lists or, say, rename every function in your code. Here’s how it works. You write your usual regular expression in the Find window. In the Replace box, you prepend the normal replacement tag (\1, \2, etc) with a key character which transforms the following match. Here’s a list of available transformations:

\u
Make the next character uppercase
\U
Make all following characters uppercase until reaching another case specifier (\u, \L, \l ) or \E
\l (lowercase L)
Make the next character lowercase
\L
Make all following characters lowercase until reaching another case specifier (\u, \U, \l ) or \E
\E
End case transformation opened by \U or \L
So, a match would look like: <br /> This is UPPERCASE: \U\1\E, this is camelCase: \L\1\E\u\2<br />

Read This