Thursday, February 25, 2016

The Fumblina Full Stack Philosophy

The Fumblina full stack philosophy is a mix of tools and ideals that I swear by in my web application projects.  The core ideals are that you should pick your own tools, make stuff for yourself, be small, and have a sense of humor.  Let's expand on that.

Pick Good Tools For Yourself

Given the choice, pick tools that work for you.  Ask yourself, "Will this make it easier for me to make good software"?  What is your situation?  What are you building and why?  For point of reference, here is my thought process for picking tools.

The Front End

HTML and Javascript are givens for web applications.  Since I'm not a web designer, Bootstrap makes it easier to put together interfaces that work on a 22 inch monitor and Android phone.  

Usually, my project is some kind of single page application.  At the time the decision was made, AngularJS looked right for this.  That might change some time in the future but, for now, it's the Javascript resource I know best.

Middle Pieces

Choices of middleware were informed by my Python 3 biases.  Flask and SQLAlchemy are the two major pieces as libraries go.  Flask makes creating JSON-based web APIs easy.  SQLAlchemy let's me use a database toolkit without being forced to use an ORM.

As application and web servers go, googling around and asking questions on Reddit helped me decide.  That's how uWSGI and Nginx ended up in the picture. uWSGI handles my Flask stuff.  Nginx plays proxy to Flask and static files.

Back End Parts

MySQL on an Ubuntu server is something I know so I stuck with it.  The rest of the pieces of my stack fit naturally in that context.  It's easy to find help online if stuck.  These were easy choices.

Working a custom tech stack generally requires a custom server setup.  Virtualization and cloud environments make sense here.  On the development side, Vagrant and Virtualbox do the job easily.  For production, Digital Ocean is a cheap no-frills service for setting up a Linux server.

For deployment, my pick is Ansible.  Knowledge of YAML plus native provisioning support in Vagrant swayed me on this one.  Ansible uses an idea called playbooks.  Playbooks used to provision a virtual machine can also work on a production server with little to no changes.

And that's how my tools were chosen.  I went with what made the most sense and asked for input when in doubt.

The Acronym

By the way, if you do pick the same tools that I do, you can make a nice acronym out of it!

FUMBLINA = Flask uWSGI MySQL Bootstrap Linux Nginx AngularJS

I made that up myself.  Kind of proud of it!

The Small and Silly Fumblina Philosophy

Here's the thing.  A full stack developer is not an unstoppable force ready to tackle any large project thrown her way.  She is not the developer equivalent of this guy.

Mr. "Full Stack" I presume?

Below is a better way of thinking about what "full stack" means.

Being A Part Of Your User Base

The best kind of product to be working on is one where you are one of the users.  For example, I am the sole user of Learning Machine.  A big user base isn't the goal.  I want to make things easier for myself when it comes to learning new things.  There are tools to build that help me in that regard.   If a user base ever did happen, great!  Having a head start as "User 0" puts me in a better position of understanding their needs.

Keeping the Feature Set Small

My favorite explanation of the "Minimal Viable Product" concept comes from Extra Credits, a Youtube show about game design.  The video emphasizes that a new game should start out with nothing but the absolute core mechanics and nothing more.  This is what you want to get right before adding all the supporting attributes.

In a recent round of commits on my Learning Machine project, everything was stripped out except for three things.  

  1. Making practice exercises.
  2. Quizzing and rating yourself on existing exercises.
  3. Reviewing a report to see where you're doing well and where you aren't.
Focusing on the core essence of a project is crucial because, as a full stack developer, there are limits to what one can do.  A full stack project for something small is challenging.  One with a huge feature set is going to spread you incredibly thin.  That's not a good thing.

Not Taking Yourself Too Seriously

Fumblina is a funny-sounding name.  It's the kind of name you give to a fairy with a lazy eye who can't quite fly straight.  When calling myself a Fumblina developer, I'm aware that I'm making fun of myself.  Laughing at oneself is a good thing and more people should do that.

Any "serious" full stack developer will have her share of stressful moments.  A sense of humor relieves stress.  Less stress leads to better judgment calls.  Better judgment calls are more likely to lead to the ultimate success of a project.  

And that's the whole Fumblina philosophy.  Or at least, that's how I like to think of it.

Tuesday, February 9, 2016

Processing Lots of Text Files with Python

Tasks involving work with text and files containing text is very common.  Python makes dealing with single files a breeze.  But what if you need to deal with LOTS of text files?  That can be a bit trickier.  Fortunately, Python is very much up to that challenge as well.

My Setup For This

The example discussed here runs on Linux Mint 17.2 64-bit.  Since we're dealing with Blender here, you can download the 64 bit version for Linux here.  The code being shown here is confirmed to run on 64 bit Python 3.4 for Linux.

The Goal In This Example

There's a piece of art software called Blender that interests me.  In Blender programming, there's an idea called "region types".  Region types help position interfaces.  My interest in is in lines that look similar to this.

bl_region_type = "WINDOW"

What region types are commonly used within the Python scripts that come packaged with Blender?  That is the question to answer here.  Answering it means scanning for info within the contents of multiple files.  There are four general steps to take in this sort of situation.
  1. Decide on what files are of interest.
  2. Decide what lines of those files are of interest.
  3. Get whatever it is you need from those lines.
  4. Act on that extracted info.
Let's break this down.

Picking Your Files

For this example, we are interested in files ending in .py within a specific set of directories.  

The walk function from the os module is very handy here.  It makes iterating through nested directories very simple.  It is also a generator.

There are two choices for dealing with generator based info.  You could use the generator to return a list of python file paths on one hand.  On the other, you could yield each of the created paths one at a time.  We're going with this second choice.  There's no reason that we need a full list of python file paths in memory all at once.  Having pyfiles as a generator is fine.

Picking The Lines

Let's assume that the line of code in question won't be broken up across multiple lines.  We'll also assume that the expression in question won't have comments on the same line.  That allows us to write naive code like what's below.

Some things to note here.  First is the usage of the with statement.  Using with in this way allows the file object's context manager to help us along.  We are dealing with dozens of files here.  Letting that context manager help close those files for us make sense.  

The second thing to note is that pick_lines is a generator too.  We don't need a full collection of file lines in memory so why have it?  

The third thing is the set up of the for loop. It is double-nested. It handles both file name collecting and file reading duties.  And yet, it is still easy to read and doesn't burden resources.  It's lazy.  It's beautiful.  It's also practical for what's being done here.

Getting What's Needed From The Lines

The goal is to get specific information from this kind of line.

bl_region_type = "WINDOW"

We want the WINDOW part and nothing else.  This only requires a few lines of straight line imperative code.  Adding more functions or generators isn't called for here.  Let's expand on our loop.

This is self-explanatory.  The important stuff comes after the equal sign.  The stuff before it doesn't matter.  Quotes and extra spaces don't count either.  All that gets tossed before throwing the desired info into a list.  And since this list is our final target, having it concretely in memory is the right thing to do.

Act On The Information

This can be whatever the situation calls for.  That could be writing info to a database or another file or whatever else you need.  Here's what I did.

This is pretty much what it looks like.  My main interest was seeing what region types were actually being used in Blender addon scripts.  Having that info and count tallies output to the console is enough.

And Finally The Completed Script

And here are the results.

UI: 78

A testament to the power of Python is what can be accomplished in barely a couple dozen lines of code.  Those few lines can parse through thousands of lines of text spread across dozens of files from various directories.  What you can do beyond that is up to your imagination.