Friday, March 29, 2013

Learning Design: An Initial Curriculum

I'm a programmer, not a designer. And in the past, I've been fine with that. I'll do the programming, let the designers do the designing. But now I want to learn how to design. And by design I mean just about everything that design can mean, both things like visual, graphic design and things like usability and information architecture.

Why? What's changed? I would say two things really. First, I think I can learn design (I think anyone can learn just about anything if motivated). I used to think that it just wasn't my talent. I would tell myself that "I can make things work, I just can't make them pretty." Second, I'm curious. I want to learn design now. I have come to appreciate that design isn't just "making things pretty". I think that design is about solving the human side of a problem. Being a programmer means I can solve the technological side of a problem, but that is only half of it. The best code in the world that actually solves a real problem won't do anyone good if it isn't usable. And the more that the user interface to a system delights users the more impact that solution will have in the real world.

I also think that learning design is a better career move than, for example, learning functional programming or how to write event-driven, non-blocking web server code, or whatever the new hotness is. I don't expect to become a great designer, only a decent one. I expect I will still need to work with a "real" designer on at least some of my projects, maybe all. But being able to put together good looking prototypes, being able to communicate better with web/graphic designers, being able to produce decent initial working versions of software, being able to layout and organize displays of information in ways that are helpful and appealing, all of that makes me better able to deliver software solutions and hence make me more valuable to potential employers. Perhaps most importantly to me, as an wannabe bootstrapped entrepreneur, it means I can create more compelling applications and that I can more fully realize the applications that I see in my imagination.

So here's what I'm looking at now as resources for learning design.

Treehouse: Become a Web Designer Adventure

I like the idea of an online course. I think it will be easier to consume and stay on track. I also like that Treehouse covers theory (although maybe a little light on it by the looks of the curriculum) and also practice, how to use the tools of the trade. (But man is Photoshop expensive!)

Non-Designer's Design Book by Robin Williams

I've seen this book recommended on Hacker News and elsewhere more times than I can count. I'm including it with the hopes it will give me a good foundation in the basics of design theory (and practice).

Don't Make Me Think by Steve Krug

Another book that comes highly recommended. I realize this list is a little light on HCI type topics and perhaps I can add some more useability/user experience resources to this list, but I think Don't Make Me Think is a good place to start.

Drawing on the Right Side of the Brain by Betty Edwards

I don't think drawing will directly help me with web design, but I do think it will get the artistic juices flowing. One of the things I've read about this book is that it doesn't so much teach you how to draw as much as it teaches you how to really see. That ability to see clearly will help me to see what is good in other's design and perhaps also help me see how to make my designs better.

Design of Everyday Things by Donald Norman

Another highly recommended book, but I haven't read much about it. Looking forward to reading it.

Copying good designs

What's the saying, good artists create, great artists steal?. As part of my curriculum I'll study and copy design that I find appealing. Why do they work so well? How do they implement those designs?

I've done something like this before when I was working on learning CSS. I took a screenshot of csszengarden.com, copied the HTML and images and wrote the CSS from scratch to match the screenshot. It was a good learning exercise, not just in that I exercised applying what I had learned about CSS but after I was done I also compared what I had done to the csszengarden.com's CSS code and learned from the approaches they had taken.

Notable Mention

In my research, these resources looked interesting and I might use them, but I don't have enough time to do everything.

Sunday, March 17, 2013

Using Codea and Khan Academy to teach computer programming to my daughter

I've been teaching computer programming to my oldest daughter (who is turning 11 soon) for the past couple of years or so. We started out with Scratch and she had a blast with that. After completing a simple game that she designed and developed herself, I asked her what she wanted to do next. She said, "I want to do what you do". She knew from watching me work that the visual programming environment in Scratch is not how "real" programmers work.

So our next step was to give Python programming a try. We got the book Invent Your Own Computer Games with Python and started working through it. Unfortunately, jumping into Python from Scratch was probably a little too tough and the fact that the programs she was creating in Python were completely textual meant that it was less engaging. So I started thinking about what we could do next.

Getting nostalgic for my Atari 800XL

I thought about what computing meant for me when I was her age. Growing up I had an Atari 800XL. What a marvelously simple device compared to what we have available to us today. There were two things that made the Atari 800XL a great first computer for a kid:

  1. No internet.
  2. Simple programming environments (BASIC and Turtle graphics).

That first one is a big deal. We don't let our children use computers unattended because of the inherent dangers of the world wide web. I'm sure my parents never had any such concerns because my Atari 800XL was never networked at all. Because of that I spent a lot of time just playing around on my computer. I remember hours upon hours spent meticulously typing in computer programs from magazines such as Compute! into my 800XL.

The second one, simple programming environments, is important too, but there are plenty of those to be had. Turtle graphics was particularly good because I could get the gratification of generating a visual effect of some sort. Probably the most advanced turtle graphics program I wrote (which wasn't very advanced, but I was proud of it at the time) was one where I animated a simple line drawing of a bird flapping its wings. I could control the bird's position on the screen by using a joystick. That was a lot of fun.

So this got me to thinking. Could I set up a computing environment for my daughter that would be easy for us to monitor, allow her to just waste time playing around with different ideas and approaches, and allow her to create graphical programs?

Enter Codea

I thought, what if she could have a turtle graphics like program on our iPad? She (like everyone in the family) just adores our iPad. If she could create graphical programs on the iPad, especially if they could respond to touch and what not, I thought she would get a big kick out of that.

The iPad still suffers from the problem of having unfettered access to the internet, but an app that serves as a self-contained environment would minimize the chance that she would ever even end up in Safari. Also, it's not too hard to keep an eye on her using the iPad while in the same room with her.

While Codea is a great programming environment, it's not the the best learning environment. I tried coming up with my own lessons, and I also found some Codea tutorials online, but nothing was really clicking. She did spend some time just exploring and playing with Codea, but that only goes so far.

And then we found Khan Academy

Khan Academy has video lessons and an integrated code editor. Like Codea, it offers a Processing like API. There are a few nice things about Khan Academy.

First, they have a series of tutorials that my daughter is able to watch and progress through at her own pace. The tutorials are in sync with actions in the code editor, so she can pause the tutorial and experiment with the code at any point. Also nice, the video tutorials are narrated by a woman. It might seem like a minor thing but I've noticed that my daughter has picked up on the fact that the computer programmer profession is male-dominated, so any reinforcements that, yes, girls program too, is always nice.

Second, the code editor and the graphical display are side by side. You can see the effect of your code changes as you type them. Codea requires you flip between code editing and running your code.

Third, Khan Academy has gamification! You can earn achievements and badges. You can create a "spin-off" of one of the example programs, make it cooler, and then other Khan Academy users can vote on them. Turns out this is very cool for an 11 year old!

So far, Khan Academy seems to be the most perfect environment to learn computer programming that we've found yet.

Since Khan Academy and Codea both use the Processing API, we've experimented with moving code between the two environments. There are some slight syntactic differences between JavaScript (Khan Academy) and Lua (Codea) of course. Codea also has the vertical axis flipped compared to Khan Academy. Khan Academy names some things differently and has some different API methods like:

  • strokeWeight instead of strokeWidth
  • point(x ,y)
  • triangle(x1, y1, x2, y2, x3, y3)

Here's an example of how I translated the Intro to Animation lesson into Codea (point and triangle aren't used below, but they are used in some Khan Academy programs so I'm including them here just for illustrative purposes):

-- KA-Intro to Animation

-- vim: set ts=4 sw=4 et ai filetype=lua:

function setup()
    print("Hello World!")
end

function strokeWeight(weight)
    strokeWidth(weight)
end

function point(x, y)
    line(x, y, x, y)
end

function triangle(x1, y1, x2, y2, x3, y3)
    myMesh = mesh()
    myMesh.vertices = {vec2(x1,y1),vec2(x2,y2),vec2(x3,y3)}
    myMesh:draw()
end

function initKhan()
    -- Khan Academy setup
    -- set a default stroke "weight" (codea calls this width) and color
    stroke(0, 0, 0, 255)
    strokeWeight(1)

    -- translate and scale into Khan Academy coordinate system
    translate(0, 400)
    scale(1, -1)
end

function draw()

    initKhan()
    -- this is the draw loop! everything inside this
    -- function will be run over and over again.
    background(252, 255, 214)
    noStroke()

    -- position of the car
    x = 10

    -- draw the car body
    fill(255, 0, 115)
    rect(x, 200, 100, 20)
    rect(x + 15, 178, 70, 40)

    -- draw the wheels
    fill(77, 66, 66)
    ellipse(x + 25, 221, 24, 24)
    ellipse(x + 75, 221, 24, 24)

end

So that's where we are so far. I'm hoping we can work toward a project this year, like making a mobile app game or something.

Saturday, March 09, 2013

How do you set up for multi package Python development?

Or, how do I use my models outside of a Pyramid application?

I've developed a little Pyramid app as a mobile backend version of FuelMyRoute.com. As natural, I've defined the database models inside the application. But, now I want to develop a new gas price data importer piece of code that will live outside of the Pyramid web application. This importer will need to make use of the same models as defined in the Pyramid app. So what to do?

Well, ideally I would have the models defined outside of the Pyramid app in its own package. So I would end up with three packages: the Pyramid app is a package, the models are a package, making the importer code a third package. The importer package would depend on the models package, just like the Pyramid app.

Now, in Python there are lots of mechanisms to pull this off. First we could just manipulate the sys.path in each package to pull in the needed dependencies. Second we could set a PYTHONPATH to pull in the other packages. But the way I decided to do it was to install the packages into a virtual environment. I got this idea from the Pyramid tutorial/documentation where it has you do a python setup.py develop into the virtual environment for the app. python setup.py develop is basically a way to symlink in your package into the system path of the virtual environment.

Here are the three packages. Each package name is prefixed with gptp-, which is just an codename for an earlier version of FuelMyRoute.com.

  1. gptp-models - Defines the SQLAlchemy models
  2. gptp-pyramid - The Pyramid application, depends on gptp-models
  3. gptp-importer - Gas price data importer code, depends on gptp-models

Here's the setup.py file for the gptp-models package:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from setuptools import setup, find_packages

# http://pythonhosted.org/distribute/setuptools.html#basic-use
setup(
    name='gptp-models',
    version='0.1dev',
    packages=find_packages(),
    install_requires=[
        # <0.8 includes stupid stuff like 0.8b2, so have to defensively prevent
        # alphas, betas etc. http://stackoverflow.com/a/14405269/1419499
        'SQLAlchemy<0.7.99',
        #... additional dependecies
        ]
)

This is just about as barebones as it can get for a setup.py. I believe that only name, version and packages are required. This package depends on SQLAlchmey, amongst other things, so I've included that to illustrate how to declare dependencies.

Here's the setup.py for gptp-pyramid:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import os

from setuptools import setup, find_packages

here = os.path.abspath(os.path.dirname(__file__))
README = open(os.path.join(here, 'README.txt')).read()
CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()

requires = [
    'pyramid<=1.3.99',
    'SQLAlchemy<=0.7.99',
    'transaction',
    'pyramid_tm',
    'pyramid_debugtoolbar',
    'zope.sqlalchemy',
    'waitress',
    'gptp-models',
    # .. more dependencies ..
    ]

setup(name='gptp',
      version='0.0',
      description='gptp',
      long_description=README + '\n\n' +  CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pylons",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
        ],
      author='',
      author_email='',
      url='',
      keywords='web wsgi bfg pylons pyramid',
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      test_suite='gptp',
      install_requires=requires,
      entry_points="""\
      [paste.app_factory]
      main = gptp:main
      [console_scripts]
      initialize_gptp_db = gptp.scripts.initializedb:main
      """
      )

There's more going on here, but most of the extra stuff is stuff that was auto-generated by Pyramid. The important thing is that on about line 18 the package gptp-models is listed as a required dependency.

Finally we have gptp-importer's setup.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from setuptools import setup, find_packages

# http://pythonhosted.org/distribute/setuptools.html#basic-use
setup(
    name='gptp-importer',
    version='0.1dev',
    packages=find_packages(),
    install_requires=[
        'gptp-models'
        ]
)

About what you might expect at this point.

So now with my three packages set up, I can proceed with setting up a virtual environment. I'm using Python 3.3 so I set up the virtual environment with the built in pyvenv command and install distribute and pip into it, using this script, named bootstrap-pyvenv:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/bin/sh

# Create Python virtual environment
pyvenv $1

# install distribute and pip
curl -O http://python-distribute.org/distribute_setup.py
$1/bin/python distribute_setup.py
$1/bin/easy_install pip

# Clean up
rm distribute*

So I run:

bootstrap-pyvenv gptpenv

Then, activate the environment and run python setup.py develop in each package, starting with gptp-models of course:

source gptpenv/bin/activate
cd gptp-models
python setup.py develop
cd ../gptp-importer
python setup.py develop
cd ../gptp-pyramid
python setup.py develop

Okay, so that's set up. But how do I get Pyramid to use my models that are defined in a separate package? Here's what my models.py looked like before I made my changes:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from sqlalchemy import (
    Column,
    DateTime,
    Float,
    ForeignKey,
    Integer,
    String,
    types,
    )

from sqlalchemy.ext.declarative import declarative_base

from sqlalchemy.orm import (
    relationship,
    scoped_session,
    sessionmaker,
    )

from zope.sqlalchemy import ZopeTransactionExtension

from datetime import datetime
from shapely.wkb import loads
from struct import pack, unpack

from geo.proj import ProjectedPoint, utm_projector

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()

# ... start defining my models here ...

I moved my models into gptp-models/models.py and updated the pyramid models.py to be:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import models
from sqlalchemy.orm import (
    scoped_session,
    sessionmaker,
    )

from zope.sqlalchemy import ZopeTransactionExtension

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = models.Base

The import models imports my models from the gptp-models package (could probably be namespaced better, but this suffices for now). The line

1
Base = models.Base

is just a convenience so that I can continue to import Base from the Pyramid models.py.

That's basically it. I just need to update the imports elsewhere in the app. For example, in my views.py I had

1
2
3
4
5
6
7
# ...
from .models import (
    DBSession,
    GasStation,
    GasPrice,
)
# ...

which becomes:

1
2
3
4
5
6
7
8
9
# ...
from .models import (
    DBSession,
)
from models import (
    GasStation,
    GasPrice,
)
# ...

Other Approaches to the Multiple Python Packages Problem

I asked about what people do in this situation on Twitter:

Pradeep Gowda replied with

I think that would probably be the better way to go for a larger project and multiple developers. For what I'm doing, since it's just me and a side project, the setup described above is sufficient.

Pradeep shared the following benefit of going the local pypi approach:

He also shared this link on how to set up a local PyPI.

So that's another option that is worth considering too.