Don’t forget the other kind of WTF

Sometimes, the code looks good, but it doesn't mean that the whole project in itself is good.

First, a project should be simple to install. The install documentation should exist and always be up to date. I encounter too many projects where "inside knowledge" is required to install the application, and you don't know if it doesn't work because you didn't install it right or it just doesn't work. There should be a single command (makefiles or shell scripts are here for that) for a single task. It should not require weird system settings (this is very annoying with PHP when a lot of the language is customizable through php.ini).

On a similar note, the architecture should be simple to comprehend. When it feels too much like "magic", when a simple action has too many unsaid consequences, something is wrong. There should not be hundreds of classes and inheritances when an option would be enough (this is an idea found at least in Python and Symfony 1.4 that I quite like). Names should be readable and short, not everyone has or likes using auto-completion.

I'm not sure what creates this kind of WTF. Inexperienced but talented programmers? Programmers who think too high of themselves? Programmers that are not lazy enough?

Share:
  • del.icio.us
  • Twitter
  • Reddit
  • Digg
  • Facebook
  • Google Bookmarks
  • DZone
  • LinkedIn
  • Wikio
  • Identi.ca
Posted in PHP, Symfony | Tagged | 1 Comment

chmod 777 is evil

Well, chmod 666 is the true evil obviously, but people who use the chmod 777 trick really don't want to bother with the different signification of x for files and folders, so they mark all files as executables. This makes ls in my terminal quite ugly, and is what motivated me to write yet another rant!

Traditionally, the web server runs with a special, underprivileged user. Now, this is totally fine — I'll get back to that later. However, when a developer starts a project, he naturally does it with his own account. This is fine, too. When he wants to test it, he installs a web server (let's say Apache and mod_php1), and tells the web server to use the project directory. However, the web server's user can't read, or at least can't write in the directory. And here, our web developers asking for help gets recommended to "chmod 777". Symfony even has a command for doing it, and it is a real shame.

It will work. It will also make an ugly git commit, and an ugly ls. Il will create files owned by the web server, and the developer is likely to use sudo before every command to work around the problems that will ensue, and it just gets insane.

Separation of privileges is what makes UNIX systems great. Let's understand them and use them, please.

The obvious solution here is to run your development server under the development user. There is no need to separate when it's for your own usage. There is a even better solution, embraced by almost every language but PHP: a way to start a web server on demand. I believe it was started by Ruby on Rails with WEBrick, and now every non-PHP framework has it. Python, by using WSGI makes it very easy. I simulated this feature for Symfony by writing symfttpd. It's actually simpler for the developer as there is no configuration or installation at all.

Enough about developers; it's not their job to setup daemons and manage UNIX systems. Let's talk about the real accomplices of the Devil: system administrators.

Yes, there are system administrators that don't use permissions properly. And they are legion. I've seen horrors, up to "sudo svn up" on the production server, because half the files ended being owned by root. And then "chmod 777" on millions of files.

There are many solutions there; group inheritance with the setgid bit, forcing the users to su as the web server user, or a deployment script (I've used the three of them for different situations).

Why is this important? Because it is often useful to separate users (one should not have access to the other's projects in reading or writing), or to separate projects for security (one hacked project should not give access to the others).

I've seen it… done wrong:

  • safe_mode for PHP. It doesn't work and will disappear in newer versions anyway.
  • Only allowing FTP access to users, who can still upload a PHP script which will have access to everything (if run through the web server). Oh, and FTP sucks. Same issue with SSH and chroot.
  • Add the users to the group the web server is running as. Allows SSH access. Nice, but the PHP script trick will, again, defeat it.

There is only one solution: use the "group" solution, but run a different PHP instance for each user. It is quite rarely used because the convenience of Apache and mod_php. But running PHP in the same process as the web server feels quite dangerous for me too. I think mod_php is an abomination.

I've done it for years with Lighttpd, PHP and FastCGI with a few alterations to Gentoo's spawn-fgci init script (which is now able to handle multiple configurations without any alteration since a few months). My setup is very similar to that one.

Note that while I mention PHP, this issue is not strictly related to PHP, yet seems widespread in PHP communities.

  1. I don't like much both of them, but more on that later []
Share:
  • del.icio.us
  • Twitter
  • Reddit
  • Digg
  • Facebook
  • Google Bookmarks
  • DZone
  • LinkedIn
  • Wikio
  • Identi.ca
Posted in PHP, Symfony, Sysadmin | 2 Comments

Exceptions

I see on a lot of projects stuff like this:

 
function getStuff()
{
  try
  {
    return $this->retrieveStuff()
  }
  catch (Exception $e)
  {
    return null;
  }
}
 

The issue, in this example, is not that we silence an error. It should be logged, but there could be a legitimate use for this. For instance, it requires a connection to a remote server we have no control over, and we still want to serve the rest of the content to the user, as the information is not vital.

No, my issue it that we catch all errors, when the aim was to catch only one error (for instance "unable to connect to that remote server"). Imagine now there is a real bug in retrieveStuff(), it would still be interpreted by developers as a connection errors.

The solution is to have one exception type per error type (it sounds obvious said that way, doesn't it?), and only catch the specific error, for instance ConnectionError.

PHP's error handling is historically bad, and even though new features use exceptions, the legacy ones don't. Or sometimes functions should trigger a fatal error but it is only a warning, and the code continues, which can trigger unwanted and hard-to-debug results. There are amazing plugins for Symfony that convert errors to exceptions (and warnings seem to be handled properly, i.e. they are logged and don't cause the page to fail). It's a start.

However, even when you get exceptions, you can't always filter them easily. For instance, in Symfony, there are many different errors that would throw the same class. Symfony has a handful of exceptions, Doctrine has a bit more (though they can be quite meaningless!). Overall, there are defined "by module" than "by error".

Comparatively, Python's handling of exceptions is exceptional1. There are exceptions for everything, and most of the time errors are handled by only checking the class and not the contents of the exception. It is probably the feature I love the most about Python. With the else, finally, and with statements, it is almost a pleasure to handle errors.

  1. sorry []
Share:
  • del.icio.us
  • Twitter
  • Reddit
  • Digg
  • Facebook
  • Google Bookmarks
  • DZone
  • LinkedIn
  • Wikio
  • Identi.ca
Posted in PHP, Python, Symfony | Leave a comment
Bear