Comments:"Life After PHP by D. Marshall Lemcoe Jr."
URL:http://s3.amazonaws.com/Blogger-log/index.html
As many of you know, and can easily tell from the content of this blog, I have long been a proponent of the web scripting language PHP, and more specifically, the popular PHP framework, CodeIgniter. I have made a ridiculous amount of money and made countless business connections with PHP, and owe a lot of my success to them.
It all started with an 11-year-old me buying an O’Reilly Introduction to PHP book. After being outraged that my free web host did not offer PHP or MySQL support, I just installed PHP locally and started working. Most of the book was very boring, because it showed you how to cycle through arrays, define functions, define classes, etc. These basics are great, I thought, but who cares if I cannot do anything useful with these tools? Then came the section I found most useful, the MySQL interaction chapter. Using the recently-deprecated mysql_* functions, I was learning how to make web applications that actually did things for you! The first thing I created was a todo list manager, because apparently I was not aware of the hundreds that already existed. It had no primary keys, no indexes, and I used the VARCHAR datatype for everything. And who cares that it was so poorly developed? I mean, it worked, didn’t it? At the time, web development, to me, seemed like a bunch of INSERT statements followed by some SELECTs with some CSS sprinkled in for good measure. As long as you, the user, gained some kind of benefit from it, why worry about how it was made?
For the next few years, I had nothing to do with my undeveloped, newfound skill. I spent my time learning more-advanced MySQL techniques, like using FOREIGN KEYs, JOINs, and stored procedures and understanding how to better (and more securely) deploy PHP on web servers. I got better at developing basic applications each day, and I, for the first time, felt like I could actually be learning a skill that could actually benefit me financially.
One day, I found that my school was in need of a system to manage payments for big field trips. We had a trip that 110 students were going on, and the teacher found it very difficult to mark payments off for each student, accommodate students that could not pay all at once, could not get students to pay at all, make deposit slips, and handling bounced checks. All these things took – as the teacher told me – many hours a week to deal with, and it really did not serve a goal-oriented purpose. Of course, I, the self-proclaimed web development expert, offered to try and make a system to do it. Now at the time, I felt like a real professional – making a system that the school was actually going to use and having the responsibility of handling the school’s money! I began programming this project with no plan, no framework, and absolutely no real experience with web security. To make things worse, I used absolutely no design at all; just vanilla HTML. Later, after getting some complaints that it looked ugly, I realized a new holy grail of web development when I came across Twitter Bootstrap. Now, I said, I can make websites that look half-way decent, too!
The result – which was informally named schoolPayments – actually worked very well. There was a cookie-based authentication system (which, today, I could compromise in seconds) where teachers could login, create collections, communicate with students who had paid or not paid, and see the balance less PayPal fees. On the user end, students (or their parents) clicked a link emailed out by the teacher, filled out a custom form with teacher-specified fields (such as t-shirt size), and paid with PayPal. With the first field trip, I wrote four checks totaling a little over $5200 to the school, and at that moment, I knew that I could make some real money doing projects in PHP. (My real mistake was not charging the school anything more than PayPal’s fees.)
Looking back on schoolPayments’ code, I am amazed that the system was never compromised and never experienced catastrophic database problems. There were zero SQL injection-preventing measures in place, zero FOREIGN KEY relationships outlined, and absolutely no form validation. I even made it so each collection had its own table, because I thought it would be too difficult to use a JOIN to match members of collections with the collections themselves. Either way, it worked and my ego grew to unimaginable heights. My philosophy of “if it works, what’s the problem?” was still alive and well.
The next chapter in my development career was when I took over for another developer with a startup from Pennsylvania. The scope of the project was relatively simple, for me, the expert – make an API for an iPhone application. The previous developer had used the framework CodeIgniter (along with Phil Sturgeon’s excellent RESTful API library) to begin the project, and after seeing over 4MB of files with only 40 application-specific lines of code, I dismissed the framework as useless fluff (which I still do for many modern Javascript frameworks). After doing some research, however, it was apparently very tedious to make a valid, JSON-based API, and I grudgingly visited CodeIgniter again to see what it could do for me. At first, it seemed ridiculous that I had to put database logic inside a model, load that model, and then call the function. Why could I not just perform a query, convert the result to an array, and
echo json_encode($array)
it all in a single file? In any case, I was learning how to develop web applications using (since this was an API, it was a little different) the MVC (model-view-controller) approach. My “if it works, what’s the problem?” philosophy was under attack.
After finishing that project, with some very sketchy API calls going on (for one, I used GET requests for everything, including deleting items and I used 20-character random keys for authentication), I was contracted for another project and decided to use CodeIgniter, in hopes of lessening the burdensome task of creating a multi-role authentication system. After two seconds of Googling, Tank_auth seemed like my answer. Hours later, I was up and running with a full-service, customized authentication system. I remember imagining how long something similar would have taken to write from scratch without a framework. I mean, the past authentication systems I had written just hashed a password and checked the database for a match; Tank_auth handled forgotten passwords, changed passwords, e-mail activation links, welcome e-mails.. Everything! Moreover, if I wanted to make a change or implement a new password-hashing technique, it was so easy, because I only had to change it in one place! So, I guess I liked it. It soon became the way I started all my projects – small or large. (At this time, I am actually rewriting schoolPayments to be a much more stable, secure, and feature-filled product.)
What CodeIgniter taught me was that security and scalability were the two most important things in web development. Before, I would have to load cookies onto every single page and check to see if the user was logged in. If I made a change to how the login system worked, I would have to change every single file to reflect it. This made new features and new code an absolute nightmare to implement, because there was no consistency. In other words, CodeIgniter abstracted and simplified many tasks that were, for lack of a better word, tedious,
But wait. Apparently there is something even cooler in this web development world, that would shatter my “if it works, what’s the problem?” philosophy.
PHP definitely was my first friend in web development, with CodeIgniter making it even better. However, in the past couple months, I have experimented with the rapidly-growing Python framework, Django. There is a lot to like about Django, and it seems that many modern companies are using it in production systems. The US military even uses it at some levels.
When I first installed Django and made my first project, I felt like I was using Ruby on Rails. I was basically required to use an ORM, everything had to be installed as a dependency (and those dependencies had even more dependencies), and deployment was the absolute opposite of PHP’s: difficult and hacky. That is what it felt like at first. Django also has a slightly different approach to MVC: most of the logic that I used to put into controllers is handled in the views (views.py), the routing that used to be automatically handled was put in the urls.py file, and models were models, except now I had to define the schema in the file, as opposed to creating the tables beforehand. In any case, it was doing a lot of things for me.
My first real problem with Django was the ORM. Having always approached web applications with the task of creating the database schema in something like Sequel Pro or PHPMyAdmin (arguably the best tool ever written in PHP), editing a text file to design the database was wild. Moreover, the fact that Django makes most of the decisions about how the database will be structured just baffled me – why does Django know better than me what the database should look like? Admittedly, I have grown to understand the benefits of an ORM and slowly I am leveraging the various features like in-model functions. Also, the ability to define forms at the model level saves a lot of tedious form-writing.
Next, something that is much more obvious in the various Javascript frameworks compared to other languages, is the fact that dependencies are abound. Want to use JSON? You have to install that. Want to use a third-party API? The best bet is to download their Python package, which depends on another four things, which each have more dependencies. It reminded me of my first experience with Node.js, where running the command to fetch dependencies yielded literally 54MB of files, and the app did absolutely nothing. With PHP, there were always dependencies, but rarely were they more complex than one or two PHP files that you included.
Third, and this is probably the most frustrating thing I have had to deal with coming from PHP, is the absolute nightmare it is to deploy the code. You have to always run a background process to keep it served and it is another ordeal to get it integrated into your already-configured-for-other-things nginx setup. Moreover, it seems that the CGI processors available for Python are incredibly unstable, and that given a single error or warning, it will crash and not restart. With PHP, if there was a warning, it would just log the error, and keep moving without crashing anything. FCGI would just handle it. All in all, I believe it boils down to the fact that in its early stages, Python is not yet trivial to deploy.
Side-note: I will never use a cloud-hosting solution like Heroku or AppFog to handle my applications. There is no good reason to use someone else’s pre-configured server configuration that leaves me helpless in the case of an outage. Keeping the code on my geographically-spread servers with my services gives me 100% control over how the stack is configured.
My other gripes with Django are really just subjective, because I am not nearly as proficient in Python as I am in PHP. Doing things like instantiating new objects, assembling arrays (sorry, I mean dictionaries), and converting variable types are no longer trivial. However I remember this stage with PHP, where I got confused when it came to multi-dimensional arrays. Now, many projects (and literally thousands of foreach() loops) later, I do not even think about how to use complex arrays.
I cannot say I am completely sold on this new Python-based realm of web development, but I can say that my PHP days are numbered. Django has done the same thing CodeIgniter did years ago (by abstracting tedious functions and maintaining consistency) amplified 100 times. It has given me a new excitement for web development that was much more faint with PHP. After seeing what Django makes possible, PHP just seems boring and, dare I say it, dated. However, unlike many developers that sought to bash PHP instead of just quietly moving on, I have no regrets from having spent around seven years of my life learning and implementing PHP. Not only was it a tool that I (arguably) mastered and subsequently was able to sell through my company, but it gave me a starting point for learning everything from basic web design to advanced server administration. I am certain that I would not have been exposed to so many different technologies had I not had a direct need for them. Things like Amazon Web Services, CentOS, FreeBSD, various mail, DNS, and time servers – all this knowledge and exposure came directly or indirectly from my PHP experience and made me a much more effective webmaster. Honestly, I would probably not have started a company specializing in various IT services if I had not been introduced (indirectly) to all the various technologies that power the Internet.
In conclusion, there is an incredibly good chance that I will be switching to Django from CodeIgniter in the coming months. Until then, I need to master Django and get to a point where the work I do for customers in Python is as good or better than the work I would have done in PHP. I look at this not as an ideological switch, but as simply a new toolkit for creating web-based applications that hopefully will make me more successful in the future.