Codecademy Hour of Code: Minute des Grauens

Hinter der Idee, das Programmieren möglichst einer breiten Masse zu erklären und damit auch noch möglichst früh anzufangen, stehe ich uneingeschränkt. So war ich von Codecademy, wie von vielen webbasierten Lernplattformen, sehr angetan. Gerade niedrigschwellige Kurse zu Grundlagen bekannter Programmiersprachen sind in vielen Fällen heute recht gut umsetzbar und können Hemmschwellen überwinden helfen. Wenn sie wie Codecademy zudem kostenlos sind, reißen sie einige Hürden sogar regelrecht ein.

Aber gerade bei Codecademy fehlt mir nach langer Zeit dort eine stringente didaktische Linie. Ihre Kurse sind meist fahrige Unterrichtseinheiten, die keiner erkennbaren Qualitätskontrolle unterliegen. Dabei kommt dann gerade der erwünschte Lerneffekt zu kurz, wenn Aufgaben irreführend oder nicht lösbar sind. Das Team hinter Codecademy wirbt, ganz von der eigenen Stärke überzeugt, in den höchsten Tönen vom eigenen Angebot, wirklich nachvollziehen kann ich das aber nicht. Zu oft bin ich auf Codecademy mittlerweile in schlecht geschriebene Kurse und andere Sackgassen gerannt, nur um dann zu erfahren, dass diese von ihren Entwicklerinnen und Entwicklern aus der Community verlassen wurden. Codecademy selbst hält sich dann meist zurück. Das können sie gerne machen, es ist ihr Dienst, ihr kostenloses Angebot, doch sehr im Einklang mit dem eigenen Anspruch erscheint es nicht.

Mein Eindruck ist also der einer gewissen Fahrigkeit, vielleicht sogar auch Gleichgültigkeit seitens des Dienstes. Neuestes Indiz ist die kürzlich im App Store aufgeschlagene Anwendung *Codecademy: Hour of Code". Hier kulminiert das Auseinanderklaffen von eigenem Anspruch und tatsächlicher Leistung in einer winzigen App, deren didaktischer Wert sich mir nicht erschließt.

Codecademy schließt sich dem Projekt der Hour of Code an, das sich an absolute Anfängerinnen und Anfänger richtet. Das ist allemal ein ehrenwertes Ziel, da kann ich verschmerzen, dass die App eigentlich nur ein aufgehübschter Multiple-Choice-Test in fingierter Editorumgebung ist. Ein wenig statische Eingabe kann vielleicht die Furcht nehmen, ohne dann mit absoluter Freiheit zu verwirren. Was aber nicht geht, sind die vielen Ungereimtheiten und Achtlosigkeiten, die Codecademy in der App an den Tag legt. Da soll ich dann mein Alter eingeben, kann aber genauso auch beliebige Strings eingeben. Die App feiert mein Alter von "jj" Jahren trotzdem als bahnbrechenden Erfolg in meinem kometenhaften Aufstieg als Programmierer.

Diese Unachtsamkeit häufen sich in dem Kurs voll simpler Aufgaben, die wenig einsteigerfreundlich vor die Füße geworfen werden. Wirkliche Erklärungen, was dort mit meinem Dummy-Code passiert, erhalte ich nicht. Aber das wäre anscheinend auch zuviel verlangt, denn Codecademy will mich anscheinend nicht einmal damit verwirren, mir mitzuteilen, welche Sprache sie mir hier beibringen. Es passt für mich ins Bild, wenn hinter dieser App mehr der Wunsch nach Wahrnehmung der eigenen Marke als das tatsächliche Interesse an durchdachten Lernkonzepten steckt. Für mich ist das enttäuschend, denn es droht doch, dass damit dann doch manche Leute eher abgeschreckt werden. Denn sie können nicht wissen, wie wenig ihnen die App tatsächlich erklärt, so könnten sie doch die eigene Verwirrung über die App so auslegen, als wäre das alles einfach eben doch nichts für sie.

Drafts-Rezepte IX: Serverstatus bei Github

Da auch den guten Leuten von github mal die Server wegbrechen, gibt es dort eine kleine API. Es ist nur eine klitzekleine Schnittstelle, aber sie wirft raus, wie es gerade und in letzter Zeit um die Erreichbarkeit von github steht. Also basteln wir uns doch mal ein kleines Script, mit dem wir die Daten abrufen können.

from console import alert
from json import loads
from sys import exit
from urllib import urlopen, quote
import webbrowser

def error_dialog(title, message):
    '''A diaolog box for error messages.'''
    try:
        alert(title, message)
    except KeyboardInterrupt:
        pass
    webbrowser.open('drafts://')
    exit(message)

def formatdate(date):
    '''bring the date into shape'''
    return date[:-1].replace('T', ' ')

def request(method):
    '''a request to github's status API.'''
    api_url_base = 'https://status.github.com/api/{method}'
    try:
        response = urlopen(api_url_base.format(method=method))
    except IOError:
        error_dialog('Connection Error', 'Unable to perform request.')
    if response.getcode() != 200:
        error_dialog('Error', 'Status code: {0} - Message: {1}'.format(response.getcode(), response.read()))
    return loads(response.read())

def github_status():
    '''get information and admin messages for github servers.'''
    status = request('status.json')
    messages = request('messages.json')
    output = '''
GITHUB STATUS
================
{date}: {status}

Last messages:
    '''.format(date=formatdate(status['last_updated']),
               status=status['status'])
    for item in messages:
        output += '\n{date}: {status}\n{comment}\n'.format(date=formatdate(item['created_on']),
                                                             status=item['status'],
                                                             comment=item['body'])
    output += '\nFor further information: https://status.github.com/'
    webbrowser.open('drafts://x-callback-url/create?text={0}'.format(quote(output)))

if __name__ == '__main__':
    github_status()

Gist

Die Action in Drafts ist auch keine Neuerung mehr.

pythonista://githubstatus?action=run

Import-Link

Seitdem Drafts auch Actions ausführt, wenn ein Draft keine Zeichen enthält, muss auch nur die Action gefeuert werden. Daraufhin rödelt Pythonista etwas rum, wirft dann aber das Ergebnis als Text in einen neuen Draft aus. Darin stehen dann in knapper Form die Informationen.

Gistacular: Ein mobiles Zuhause für Gist

Was für eine prächtige Ergänzung das kleine Gistacular zu iOctocat ist. Zwar kann ich Gists auch dort ansehen, aber nicht bearbeiten. Gistacular schließt diese Lücke auf einfache Weise.

Die App ist ein stromlinienförmiger Client für Gists. Alles ist übersichtlich angeordnet. Ich kann Favoriten verwalten, Skripte anderer Leute durchforsten, neben den eigenen Skripten natürlich. Der Texteditor ist spartanisch, aber ausreichend. Aber Gistacular zeigt in der Vorschau auch Syntax-Highlighting.

Ich sehe langsam, dass ich meine Desktoprechner nur noch für wirklich umfassende Schreibarbeiten oder eben Spiele brauchen werde. Alles andere kann ich immer besser auch von mobilen Geräten erledigen.

Übrigens, der Quellcode von Gistacular ist freundlicherweise auch auf Github.

Bilder: iTunes

Drafts-Rezepte V: Wetterdaten mit OpenWeatherMap

Ich habe mir wieder ein kleines Skript (current_weather.py) gebastelt, mit dem ich für einen beliebigen Ort die aktuelle Temperatur und Luftfeuchtigkeit erhalte. Als Datenquelle dient die API von OpenWeatherMap, abgerufen wird es wieder über Pythonista. Das Skript sieht folgendermaßen aus:

# -*- coding: utf-8 -*-
import clipboard
from console import alert
from json import loads
from sys import argv, exit
from urllib import urlopen, quote
import webbrowser

def error_dialog(title, message):
  '''A diaolog box for error messages.'''
	try:
		alert(title, message)
	except KeyboardInterrupt:
		pass
	webbrowser.open('drafts://')
	exit(message)

def filter_data(data):
	'''create output string from response'''
	weather = loads(data)
	temperature = weather['main']['temp']
	humidity = weather['main']['humidity']
	output = 'Temperatur: {0} Celsius\nLuftfeuchtigkeit: {1}%'.format(temperature, humidity)
	return output

def get_current_weather_in(data):
	'''get current weather data'''
	api_url_base = 'http://api.openweathermap.org/data/2.5/weather?q={0}&units=metric&lang=de'
	try:
		response = urlopen(api_url_base.format(data))
	except IOError:
		error_dialog('Connection Error', 'Unable to perform request.')
	if response.getcode() == 200:
		weather_data = filter_data(response.read())
		webbrowser.open('drafts://x-callback-url/create?text={0}'.format(quote(weather_data)))
	else:
		error_dialog('Error', 'Status code: {0} - Message: {1}'.format(response.getcode(), response.read()))

if __name__ == '__main__':
	get_current_weather_in(argv[1])

Gist

Das Skript kann dann über die Drafts-Action ausgeführt werden:

pythonista://current_weather?action=run&argv=[[draft]]

Import-Link

Im Grunde war das auch schon alles. In Drafts muss dann in einer neuen Notiz nur der Name der Stadt eingegeben werden. Gegebenenfalls sollte sicherheitshalber noch das Land hinzugefügt werden. So würde Hamburg, de mir die aktuelle Temperatur und Luftfeuchtigkeit für Hamburg geben.