Tuesday, 10 September 2013

So, python web apps are not that hard after all

So, I was saying earlier that writing web apps with Python is hard ...

I was sorely mistaken... Obviously, I am not using any frameworks to facilitate my project - which is a huge mistake, but a learning exercise for me (I'm  fairly new to python). When not using a framework, you are exposed to the internals of how CGI and Python all meld together, as well as how to use the FieldStorage object to respond to Ajax requests.

It's only hard if you do it the "wrong" way

Writing a web app with Python 3 is only hard if you do it the wrong way. I come from a background of coding C++ code using the most bleeding edge coding techniques - OOP, TDD, Templates, Multiple inheritance, Polymorphism, insert bleeding edge coding technique here, etc.

Now, this is all good and well when using a language like C++ where you only face the OS endpoints (Windows API, stdlib etc) at certain points in your code. But these techniques do not work too well when using a high level scripting language like Python. I started off by churning out dozens of classes which has get and set methods for any data members. I also tried to abstract away the basic Python functionality by writing classes which dealt with IO and repeated function calls...in short I ended up trying to write a framework on top of Python. This is all good, as awesome Python frameworks exist, but it was detracting from my main purpose - to get on with writing the app.

It gets even harder when you just write what you need

By this I mean that I stopped writing my framework when I realized my folly, but then had to start over by only writing the code I needed. This is the hardest part of coding - writing the least amount of code to accomplish the highest level of functionality. This is the zen of coding, and it took me a while to find my sweet spot.

Of course, you need Database wrappers, you don't want to instantiate a SQLite3 console in the middle of iterating through your FieldStorage object to find URL parameters ... but you do want to have a handy function on hand so that you can take those parameters and do something useful during that loop.

Getting it "just right"

I finally hit my stride when I had my fancy UML diagram all spec'd out and I was able to write only the classes I needed. Those classes, in turn, contained only the functions I needed, and after ironing out some kinks in my way of thinking about Python classes, I was able to bang out a decent web app in about 80 hours. Of course, I did not have the luxury of spending days on end adding classes all willy nilly, I had to squeeze in odd hours here and there to get it done.

The main thing I learned is that Python is awesomely powerful when it comes to manipulating data. Python 3 comes with a slew of features which allows one to have a working Ajax request handler in about 20 lines of code. I also learned that the true strength of Python shows through when you have finished your self-inflicted torture ie: "learning curve" and simply get on with the business of writing your app.

Python frameworks are there to abstract away the drudgery of having to code a "find key in dataset" algorithm for the 20th time, they save you from yourself when you do not know enough about the language to step around common pitfalls.

The current trend is micro-frameworks

Todays developers have gotten slightly lazy in that they all rely on some framework. These days micro-frameworks are all the rage, and developers become burnt out after spending maybe an hour trying to digest the documentation for the latest and greatest framework. I prefer to stay away from all that because these frameworks fall into disuse and are forgotten and if you have gone 98% of the way into building a business using one of these forgotten frameworks then you either have to hire rockstar developers to save you from the framework, or you have to add improvements and workarounds for the last version of the framework on the planet.

These options are not really too usable for startups, and I can see why many startups bank on either technologies which have already found a firm footing, or on creating their own frameworks and platforms on which they can build their latest and greatest product.

I'm not saying it's wrong to use a new micro-framework, just that you should really weigh your options when deciding on your development strategy. I spent about 4 hours searching the net and becoming aware of the "abandonment trend", which causes developers to furiously write code using a new library, only to become frustrated when something doesn't work the way they guessed ... and the documentation has not quite caught up to all the new features - developers write code, great developers write code which documents itself, the greatest developers don't write code - they write documentation which executes at runtime. Chew on that for a second.

Optional ranting

During my foray into writing my first web app, I discovered that many would-be Pythonistas are doing "the right thing" by writing everything themselves - excluding the kitchen sink. During their development they hit inevitable snags which could be solved by adding something to the language itself - like a way to say FieldStorage.findkey('key') ... which may or may not actually exist. But, the great part of these flaws is that patterns emerge, tried and tested functions become public knowledge after a developer bangs his head on his desk while solving a "simple" problem.

I ended up needing to send emails to users of my web app, I wanted a way to send the email, store it in the database, and store the resulting message off-site ... I spent a few hours trolling messageboards to find a solution when it suddenly hit me, like a slice of lemon wrapped around a brick - use gmail, which promptly led me down the rabbit hole in search of a way to send email... About an hour later I hit upon this little script, which must be the simplest way to send email which I have found: http://kutuma.blogspot.com/2007/08/sending-emails-via-gmail-with-python.html

If you have copied the script and are now frantically struggling to get the interpreter to recognize your efforts, bear in mind that things have been reorganised in Python 3, by replacing the import statements with these statements, you should be able to get up and running in no time:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email import encoders
That little slice of code should save you lots of time when working with Python 3 and struggling to understand why seemingly innocuous import statements don't want to work..

Well, that's enough of my ranting, my web app should go live within the next month or so - at which time I will make it available for public use. Until then, happy coding...