Is modern learning a dis-service to our youth?

Quick background — one of my day jobs is being a ski instructor in the winter and in the process of getting my certifications have learned a bit about the teaching model and ways people learn.  Thus ended up having this interesting realization the other day while chatting with my brother.

People learn in three primary ways (the Fleming VAK model):

  • Visual — see it written, slides
  • Auditory —  lecture, discussion
  • Kinesthetic — move it, touch it, do it

Without going into blending, or some other theories of learning, since I’m preferential to VAK and how it relates to ski instruction (another topic another day).  The big thought that I had was that the big change in recent years (last 10) is that teachers are teaching with powerpoint.

Why do I feel that powerpoint is bad?  Lets think about this for a second, if we subscribe to the VAK model of learning.  That means that to successfully retain something you need to do one or more of the VAK steps to imprint the learning into your memory.  If your instructor hands you a deck of slides, now instead of coping the key points of the lecture you’re just reading them.  Which to a kinesthetic learning is a loss.

To a visual learner, this might be a boon, but at the same time I personally doubt that a visual learner has a photographic memory.  The process of a professor writing things down is going to give the visual learner some time to process the input given rather than potentially memorize a slide.

Finally the auditory learner, at one side probably no change, but at the other, since a PPT deck is so structured in flow there is no tangents or discussion that’s quickly available.  So, if somebody asks a question, instead of going with “lets cover this now” it’s hold that though and in five slides we’ll touch on it, if you still have questions ask then.

Generally, too much structure doesn’t allow for the process of discovery and the ability to reinforce material through multiple means of learning styles (VAK).

Django + Tornado = Chat

Just finished up a quick one day project…  Was curious about Torando and since I’ve been playing with Django wondered about mixing the two…   Of course at one level there isn’t much reason to put django and tornado together since django has a “fine” webserver built in and Torando is all about async.

Thus you need to invent an app that requires async, traditional http chat with long polling is the trick.  So, pulling a demo from the NodeJS land and building a bunch of glue work I ended up with a working Django+Torando = Chat application.  Sorry there is no demo, since it looks and works pretty much like the NodeJS chat application (borrowed their UI and JS).

However if you want to check out the code take a look at this:

http://github.com/koblas/django-on-tornado

The key part that’s interesting is this ability to add asyn requests to a django handler:

from django_tornado.decorator import asynchronous

@asynchronous
def recv(request, handler) :
    response = {}

    if 'since' not in request.GET :
        return ChatResponseError('Must supply since parameter')
    if 'id' not in request.GET :
        return ChatResponseError('Must supply id parameter')

    id = request.GET['id']
    session = Session.get(id)
    if session :
        session.poke()

    since = int(request.GET['since'])

    def on_new_messages(messages) :
        if handler.request.connection.stream.closed():
            return
        handler.finish({ 'messages': messages, 'rss' : channel.size() })

    channel.query(handler.async_callback(on_new_messages), since)

Python wierdness

Just frustrated, why the output is

Broken = 2 and Wierd = 3 at one level make no sense, since after all you would think that if you referenced a member variable it’s context would remain the same…

class Foo :
    BROKEN = 1
    WIERD  = 1

    def __init__(self) :
        print('Before broken=%d weird=%d' %( self.BROKEN, self.WIERD))
        self.BROKEN += 1
        self.__class__.WIERD += 1
        print('after  broken=%d weird=%d' %( self.BROKEN, self.WIERD))

Foo()
Foo()

# Output is :
# Before broken=1 weird=1
# after  broken=2 weird=2
# Before broken=1 weird=2
# after  broken=2 weird=3
Tagged

Customers are your assets

I’ve been wrangling with use registration for years, partly because it’s an interesting time sink.  Partly because it’s annoying when it’s wrong.  Plus, usually when you start building any application in this day and age you need some form of user registration.  The basic systems these days are:

  • Username and Password  (e.g. yahoo, google)
    • Key signup form elements: Username, Email, Password, Captcha
  • Email address and Password (e.g. facebook, linkedin)
    • Key signup form elements: Email, Password, Capthca
  • Pure Facebook Connect (or Google Connect, etc.)
    • Key signup form elements: Big Facebook button
  • Hybrid systems
    • ..topic of discussion…

Fundamentally username+password and email+password are just variants of themselves, really coming down to how you are known on the system (unique handle “johndoe77″ vs. real name “John Doe”).  Both systems typically will send you and email asking you to confirm your email and they always have a Captcha since the spammers are going to bully you into submission if you don’t. It’s really hard to innoviate in this space it’s just getting the implementation right, but I’ve build four or fourty of these in the past.

The new kid on the block is the Facebook Connent, Google Connect, OAuth/OpenID systems.  The happy part is that as sites start implementing these systems we can stop having to type our passwords into site after site after site — do you really make unique passwords?!?.   The challenge is that as a service you still want to have connection with your user.  Things I’ve noticed:

  • Google gives you email address _easily_ (thanks guys)
  • Facebook gives you a handle to email address and prompts for permission (so, so)
  • LinkedIn you’re just a pain in this front, I want a relationship with your user, not just some handle to use your funked up messaging platform.
  • Twitter/Yahoo – data exchange is a pain.

Back to owning our user!  It’s easy to own the user if they type a password, it gets progressively harder when we start using the Open provider marketplace to have the user.

Why should you care? Because users are your biggest asset!  If you don’t realize that you’re not thinking hard enough.  The cost of customer acquisition is $X in this day and age the cost of marketing to a known user is a fraction of $X (say 1/10th).  Which means that if you have a service and spent $100 on Google ad words to find customers the cost to market a new product to them is $10 rather than $100 — plus you don’t have to re-train them hopefully so your support costs are lower.

That brings me to my last world view of customer registration — hybrid registration.  No I don’t have a quick example deployed at the moment (currently in alpha).  The basic premise is that you ask for the basics up front:

  • Username
  • Password
  • Email address

But now instead of the classic “captcha” page you hit them with the Facebook Connect/Google Auth page to confirm their account.  The complexity of getting this working is slightly higher than the Captcha, but the advantage is that in addtion to having about the same barrier as a Captcha from a spam protection standpoint you also now have a secondary form of authentication and potentially access to very useful data about your customer.

  • Friends/Contacts
  • Full Name
  • …etc…

While you’re probably a smart service and don’t hit the customer over the head with “spam your friends” what you can do is save this away for later use, like when “Sally Smith” joins you notice that “Tom Jones” is a friend of hers and you can point this out in “Suggested Friends”.  Sally just thinks that you’re a smart service — maybe goes “how did they know that” — but you’re really  using the information for their own good.

The second benifit is that since you’re still running a user through a classic registration flow, you’ve got an email address to conduct future marketing to.   But not just that you’ve also now got a guaranteed second touch with the customer.  Why’s that important?

  • Your first touch was getting them to signup and confirm their account, because they connected a social network to their account we’ve got a high confidence that it’s a real user.
  • Your second touch is the confirmation email, which the user will now open 30 minutes to a day later.  Where you can remind them of all the cool things they should be doing with your service.
  • Your third touch is the message you send in three to seven days thanking them for signing up for your service and potentially looking at some of their recent behaviors on the site to determine some simple bucketing of their behavior to help send an appropriate message.

If you feel like I jumped from Hybrid authentication to customer contact, you’re right.  But, fundamentally as I’ve played with user authentication and buit a variety of systems and looked at the long term value of that customer.  My mindset has evolved into these tenets:

  • Own your user — don’t give them away
  • Enable them to login with a variety of system — lower the barriers
  • Keep the lifetime value of your user in mind

Hybrid authentication is the way to go!

Tagged , , ,

Zendesk and Django integration

Part of this post is the gratuitous, gosh that was easy to integrate!  Of course part is a small point that I would like developers to think about.

First off here’s the code snippet, which owes it’s history to:

Zendesk Remote Authentication with Django and Unicode Names and Zendesk remote authenticatin with Djnago (the original posting)

def authorize(request):
    if not request.user.is_active :
        return HttpResponseRedirect(reverse('openauth:signin'))

    try:
        timestamp = request.GET['timestamp']
    except KeyError:
        raise Http404

    u = request.user

    data = ''.join((u.profile.name(), u.email, u.username, settings.ZENDESK_TOKEN, timestamp))
    hash = md5(data.encode('UTF-8')).hexdigest()

    url = "%s/access/remote/?%s" % (settings.ZENDESK_URL, urllib.urlencode({
                'name'        : u.profile.name(),
                'email'       : u.email,
                'external_id' : u.username,
                'timestamp'   : timestamp,
                'hash'        : hash,
            }))

    return HttpResponseRedirect(url)

What’s different — or why am I making this post:

  • Use u.get_full_name() rather than the appends with the spaces, in my case I’ve got another object hanging out (profile) which contains the users name.
  • Use the django username as the external_id — I though about using user.id, but since username should be unique and fairly inflexible that’s a good approximation.
  • Use a join rather than a whole bunch of “%s%s%s%s” no formatting needed…

Finally, the big rant the original code used a bunch of formatted prints to build the URL argument.  If you’ve been handed a language with libraries like python and a framework like django, you don’t think about cross site scripting or other breakages (& in the username) which is going to cause problems…. It’s trivial to use urlencode to avoid these problems.

Time for Money (business 101)

I just read a post talking about the “Does your startup pass The Sleep Test“, in principal the idea is sound it’s a little simplistic.

Fifteen years ago I worked as a consultant, the money was good but the problem I quickly realized is that fundamentally I was just trading time for money.  We can all see how a construction worker trades time for money — $15/hour here I come I’ll hammer and pour concrete all day.  Being a ski instructor is the same way, just like any trade job you’re just on the work for X hours get Y dollars, but you have to wake up and do it all again…  What’s funny is there are a lot of white collar jobs that are the same way, Lawyer is being a great example — hence why many people are slaving away on the partner path — then at least they get the benefit of their co-workers time.

Fundamentally, you need to build a business that for every hour you put in yields a % gain in a core asset.  That asset can then be realized in a few different ways.

  • A blog — you post frequently — have a regular readership that grows and advertising to support it.  This passes the sleep test, people read while you’re asleep, but at some point to grow you need to be a publisher (e.g. TechCrunch) because if you don’t and go on vacation your asset will decrease in value.
  • A piece of software — you or a small team builds a piece of software and sell it, you potentially can sell the software for many times the cost of development.  If done right you can build service contracts and upgrades that yield long term revenue on your customers post sale.
  • Software as Service — similar to above, but now you can charge on a reoccurring basis, though fundamentally this is really just shrink wrapped software with the support side built into the monthly charges.  Variants on this are advertising supported web apps. etc. etc.
  • Secondary assets — you build a widget give it away for free, but fundamentally you’re building a secondary asset that you hope to either data mine or sell directly.   When you signup for that free car at the mall, the offer is the car, but the company is now getting access to your contact information to both sell you a timeshare but also now they’ve got Name/Address/Phone/Email all in a nice neat package..  Plus as a “Are you interested in a Timeshare” phone call you can verify all of the information.

Once a business has an asset, Readers/Customers/Core Asset it now has something to grow and foster.  This is asset is then what the business should be organized around the care of.