Tips and Best Practices
If you're only dealing with a simple Web site that you develop and deploy in one iteration, you may never have to worry about updating it, or you may be able to get away with hot fixes, straight to the live site. However, once you start dealing with a project of considerable complexity, and one with multiple development iterations, there's no way around some sort of tiered system for update deployment—unless you write perfect code, in which case you should stop reading my blog and go make a million dollars.
The trouble of course is that as you're developing a new feature, you make changes or additions to the existing code of your application. But let's say you can't always write perfect code, and can't predict the effects of your new code. If something breaks, any of the people using your system will see the wreck, all of a sudden. For the users, it would be like trying to drive a car while a service technician is working on the transmission: very difficult, and very annoying.
So, don't do work on the live (production) site—only update it when you're 99% certain that your updates are working properly. A few technicalities arise:
- If you can't work in the Production environment, where do you work? And how can your working environment (Development) be as similar as possible to Production?
- How do you move code (and data, and other components) between Development and Production? How do you make sure that you're working off of current Production data? How do you deploy an update to Production smoothly (without taking forever, without missing a file/update)?
- How do you design your application so that it can be shoved around (from Production to Staging, to Development) without breaking paths, database connections.
The good news is that, with a little work and foresight, all these considerations can be easily managed.
Development and Staging
Your development tiers will depend on the size and complexity if your project. For instance, if there is only one developer, you can get away with a single development environment where you do your work before updating.
As soon as there are multiple developers working on the same project, it becomes desirable for each person or team to have a "sandbox," where one can mess around while building new functionality. And once there are multiple components being built at a time, it becomes necessary to have another type of workspace (typically called a Staging environment) where all of the separate components can be tested together, before they are released to Production.
So how do you make a development environment?
Creating the Development Environment
Some people have the luxury of working with Virtual Servers, where it's trivial to "clone" the Production server, giving you an exact copy to fool around with. In this case, there are fewer considerations in obtaining a development environment.
If you aren't working with virtual servers, you might have to manually make a copy of Production. In this case, it's easier to ensure congruence between Development and Production if Development can run on the same server as Production. This is likely not feasible for large projects, since Production will need all available resources to serve clients.
Transferring Code and Data
In any case, working without a virtual server requires some manual copying, so the key is automate.
Write a script that copies the production databases to a new test version. With MySQL (if you have the right permissions), you can just copy the database folder in /var/lib/mysql (or wherever your database files are kept).
In my case, I check out code from a version control repository to start a fresh development environment, but the repository doesn't track every single thing that the application needs to run. For all those extra things, add them to some kind of shell script so that you can get set up right away.
Speaking of version control, I've found this to be a huge help in managing code between Development and Production. I'm not sure if this is an accepted best practice, but it's working for me. Using git, I keep Production managed under its own repository. When I want to start a fresh development server, I check out (clone) the Production code. As I work, I commit any changes to my development repository. Then, when I'm ready to release the new features to Production, I use git's
pull command to fetch updates from Development and apply them to Production. The big advantage I find here is that I don't have to keep track of what I've changed; as long as I commit the changes, git knows what to update.
Note that even if you were sure that your code worked, you wouldn't want to use
pull to update Production unless you were certain that there wouldn't be any conflicts when merging the new code with the old code. This isn't usually a problem with a small number of developers, but with multiple branches of code, conflicts may arise that need to be manually sorted out.
Obviously proper testing standards fit into the updating process, but that's another topic for another time.
To make development server setup as quick as possible (and many other maintenance tasks), any global, server-specific variables or configuration should be specified in a separate configuration file: database connection information, server path, base URL for the Web site, debug settings. I keep these settings in a file that isn't even tracked by version control. That way (if I'm really smart), I can write a script that will copy all the production code, data, etc., and create the configuration file with all the appropriate test database connection info and all the paths to wherever my development server is installed.
With all server-specific settings isolated, it's easy to copy your code between servers, because you know it will be grabbing the right path and connection information from the respective configuration file.
With good design and a little work, starting a fresh, up-to-date development environment will be a command away at the shell prompt. Wow! Almost makes you want to write that next login screen!