While I'm writing this, our Facebook app Status Time Capsule is in the process of migration from Amazon EC2 to a commodity web server. It's currently not working and probably won't for quite a while, and we're definitely not going to continue developing it again any time soon, so I guess it's the right time to reflect on the process of creating it :)
In the beginning was Git
At first we had this grand vision of open sourcing the app and putting it up on github. Apparently only one person in our team (Joey) knew about Git, he set up Github and everything for us... until we started implementing our deployment method and serendipitously discovered that the other 3 people (including me) were much more comfortable using Mercurial instead of Git. So then we started using Mercurial and we probably saved about 5 to 10 man-hours of learning Git.
Moral of the story: before deciding on a tool, make sure everyone in the team is comfortable with using it and there is no better obvious alternative. (Of course you don't do a systematic analysis of all version control system available on earth at this point!)
Non-PITA deployment and integration
(PITA stands for Pain In The Ass)
Since we were developing a Facebook iframe app and interfaced with its API, for the development we only had limited options: (1) create a mock server that can be run in localhost to interface with the app, or (2) do everything in a virtualized environment where all the data from Facebook is statically loaded, or (3) do everything in a public server. (1) and (2) were just added when I wrote this :P and they're kinda too complicated / error-prone anyway, so we -- and I believe most of us -- went with (3).
The disadvantage of not using localhost for deployment is too numerous but I could list the 2 most important:
- It is too easy to overwrite each other's code when 2 people are working in the same file. This happened quite a lot of time considering the size of the project and the number of programmers we have (thankfully all our team members were programmers).
- Deployment or publishing code must be as painless as possible because we do it all the time during general development and debugging.
Our workflow attempts to manage these 2 kinds of worry.
- Everything is under version control, which is a no-brainer.
- Our repository is located right in /var/www/html in the EC2 instance, so we all push to / pull from there. Now comes the fun part: when someone pushes changes to the repository in the EC2 instance, it will also update all the files in /var/www/html to the latest version. Therefore a push always updates / reverts all files in the server to the latest and greatest version.
- A nice side effect of the automatic update/revert is that we can actually debug / develop using the traditional approach of manual uploading of the files via FTP/SFTP. However when one feels that the code is ready, he will commit and push the changes to the server. If on any of these steps someone steps on another's shoes, we can easily reconcile by pull-merge-push combo.
Of course the system might take a while to get used to, but once everyone's comfortable with it, it can be a very nice productivity boost.
Writing with style
This is not as major as the other issues, but every programmer has their own style of programming. Two pieces of half-essays made by great writes do not make a great essay (if there's no coordination). From the choice of using tabs or spaces to naming of files and variables and functions, everyone does that differently. And we have 4 people cramming into a few files in PHP. Result is: ugly code.
Moral of the story: before development it might be a good idea to settle on some style guidelines such as whether to use tabs or spaces, and convention on (especially public-facing) function / class names etc.
Ever tried aiming at a moving target?
We lacked planning. Everyone roughly knows what features we would like to have in the app, but no one actually write down things like use cases or feature list. Now, I never took a software engineering course before and I hate unnecessary paperwork, but people do it for a reason: to keep everyone on the same page. I had a gut feeling that during our hack sessions each of us might not entirely understand what the other 3 guys were doing right then. With 4 people we only had 6 edges in the network and we already felt lost! Fortunately I can say that all of us were very committed and it made up for the miscommunication arising. Also due to the repository we at least do not lack coordination in deployment and integration.
Furthermore I think each of us took ownership of the code... a bit too much I would say. We added features pertaining to the area we were in charge of without actually consulting the rest of the team. (at least I felt that I did this >.<) Also it means we ignore the benefits of having 4 brains -- if someone else has a better way of implementing the feature, it will already be too late when he is made aware of the feature.
Result is feature bloat, and perhaps non-optimal allocation of resources (i.e. manpower and time). By the way, communication is also important to foster sense of belonging in the team, and although I can't say we lacked in this area, it could be done better.
Moral of the story: agree on general timeline and list of specific features to implement. When there is a desire to deviate from the plan, discuss immediately with everyone and decide.
I didn't realise I wrote quite a lot!
All in all I think our team still did it quite well. Some areas can definitely be improved, that's why we are still students :)