Jong Nederland Innovatie Incompetentie
on June 30, 2007Zojuist kwam ik langs een artikel van Robert Gaal genaamd Hoe kweken we echte startups. Robert kaart zeer juist een probleem aan: “Waarom produceren onze scholen werknemers, en geen ondernemers?”.
de Ingenieur in Opleiding
Als afgestudeerde ingenieur kan ik mij goed identificeren met die opmerking. Ik heb mijn HBO redelijk snel afgerond en ben nu een 21 jarige afgestudeerde die voor vier werkgevers in de IT heeft gewerkt. De Technische Informatica opleiding - de hoogst scorende HBO variant in NL - die ik heb gekozen heeft mij de volgende dingen geleerd:
- Jaar 1, verantwoordelijkheid ontduiken met Prince 2
- Jaar 2, Java is de taal voor het bedrijfsleven, websites bouwen is voor MBO-ers
- Jaar 3, met de test aanpak TMAP kan je testplannen schrijven waar Sogeti een ton voor vraagt bij de klant (oh en dat alles zonder daadwerkelijk software te testen!)
- Jaar 4, wil je je HBO halen, besteed dan 60% van je tijd aan daadwerkelijk 'iets doen' en achter leraren aanzetten
Begrijp me niet verkeerd, ik heb ook wel echt dingen geleerd op de HvA. De dingen die ik heb geleerd waren veelal dingen van leraren die ik echt respecteer en ik heb vooral van die leraren geleerd door een actieve eigen interesse te tonen. Ook heb ik nog het oude systeem (cafetaria-vakken) mee kunnen maken waarbij ik mijn eigen interesses goed kon ontwikkelen (en mij hebben klaargestoomd voor een meer flexibele zelf).
Ik ben ook uitermate tevreden met ons sociale systeem en de extreme zorg voor studenten. Maar er moet toch wel wat veranderen hier.
de Werkende Ingenieur
Vanaf de middelbare school ben ik part time werkende geweest in de IT sector. Dit heeft me een grote voorsprong gegeven op mede studenten en is een van de redenen geweest dat ik een half jaar van m'n studie kon snijden. Ik heb ook een redelijke cijferlijst waaronder negens voor beide stages.
Kortom, ik was een redelijk presterende student die veel in de praktijk ernaast deed. Vol met zelfvertrouwen ging ik dan ook op zoek naar een baan. Aangezien ik nogal into Japan ben leek dat mij wel een leuke uitdaging. Inmiddels werk ik bij een Amerikaans-Japans bedrijf dat met een web-startup project bezig is. Deze young professional is daar toch wel even tegen de lamp gelopen. Werken in een buiten-europees bedrijf is toch wel andere koek. Koek? Ontbijtkoek? Nee, geen tijd voor, werken jij!
De werk ervaring die ik nu op doe heeft mij duidelijk gemaakt hoe onder-competent de Nederlandse starters kunnen zijn. Nou is het natuurlijk niet fair om met zo'n Amerikaans kadaverdiscipline bedrijf te gaan vergelijken, maar het zegt wel iets over de huidige stand van zaken.
Ik denk dat de gemiddelde Nederlandse student zodanig in de watten wordt gelegd door het gefinancierde studentenleven en aangelokt wordt door 'sociale zekerheid' dat er rond de 28ste niks meer overblijft dan een behoefte aan een nieuwbouwwoning in Almere, een goed-verzekerde leaseauto en een gazon om te maaien.
Als beginnende/pogende web-ondernemer heb ik dan ook erg veel moeite met soortgelijke mensen te vinden. Laat staan soortgelijke afgestudeerden te vinden..
to be continued
Detecting atom/rss Feeds in Ruby
on June 22, 2007In the current SNS - Social Networking Site - boom it is becoming increasingly important to deal with usability. People have accounts for many different websites and it's getting more and more tiring to register for a new account. This is one of the main reasons why Confabio.com doesn't require you to signup and login. And it's also one of the main reasons why websites like Wakoopa.com make their registration as painless as possible. A colleague of mine was even experimenting with the idea of omitting the username/email requirement at all. Also, OpenID is yet too young and Sun's Liberty Alliance is just too corporate and slow.
But for most social networking sites it's pretty simple: they just need people to enter information. So let's make that as easy for the user as possible.
Entering Syndication Feeds
For one of my projects I have to let users enter information about themselves. This is so they can build up their own profile. What I really like about some of the new sites is that they aggregate your blog's contents and your FlickR pictures.
One of such websites is the Tokyo based Social Networking Site Asooboo.com. After signing up you can enter your blog feed and FlickR username and it will keep track of all your stories and pictures. I think that's really cool and it's one of the first steps in making the web more ubiquitous. You can later change your Feed URL in your 'edit my profile':
Entering Links instead of Feeds
Entering feeds is nice, but to users that are not tech-savy 'Feed, RSS and Atom' might raise question marks. Therefore I think it would be nice if the users wouldn't have to worry about feeds, but instead can just enter their links like:
My Websites and Profiles:
- http://blog.dominiek.com/
- http://www.flickr.com/photos/dominiekterheide/
- http://del.icio.us/dominiekth
It would then show a fancy spinner and convert it to 'My Blog', 'My Pictures' and 'My Links'. All content will be automatically aggregated if it can detect any RSS feeds on those pages.
Detecting RSS feeds
When you use a proper browser like Mozilla Firefox you will see a syndication icon every time you visit a website that has RSS feeds:
It does this by reading certain HTML tags.
After a quick search I couldn't find any code to do this in my own project, so I wrote a little piece of code for it with a RubyOnRails integration test.
You can use it like this:
FeedDetector.fetch_feed_url('http://blog.dominiek.com/')
=> "http://blog.dominiek.com/feed/atom.xml"
FeedDetector.fetch_feed_url('http://blog.dominiek.com/feed/atom.xml')
=> "http://blog.dominiek.com/feed/atom.xml"
FeedDetector.fetch_feed_url('http://www.flickr.com/photos/dominiekterheide/', :rss)
=> "http://api.flickr.com/services/feeds/photos_public.gne?id=71386598@N00&lang=en-us&format=rss_200"
# alternatively you can parse HTML with FeedDetector.get_feed_path(html_data)
# see integration test for more examples
FeedDetector + Test
Excuse my quick mash code. The FeedDetector (lib/feed_detector.rb):
require 'net/http'
class FeedDetector
##
# return the feed url for a url
# for example: http://blog.dominiek.com/ => http://blog.dominiek.com/feed/atom.xml
# only_detect can force detection of :rss or :atom
def self.fetch_feed_url(page_url, only_detect=nil)
url = URI.parse(page_url)
host_with_port = url.host
host_with_port << ":#{url.port}" unless url.port == 80
req = Net::HTTP::Get.new(url.path)
# something fishy going on with URI.host
res = Net::HTTP.start(url.host.gsub(/:[0-9]+/, ''), url.port) {|http|
http.request(req)
}
feed_url = self.get_feed_path(res.body, only_detect)
feed_url = "http://#{host_with_port}/#{feed_url.gsub(/^\//, '')}" unless !feed_url || feed_url =~ /^http:\/\//
feed_url || page_url
end
##
# get the feed href from an HTML document
# for example:
# ...
# <link href="/feed/atom.xml" rel="alternate" type="application/atom+xml" />
# ...
# => /feed/atom.xml
# only_detect can force detection of :rss or :atom
def self.get_feed_path(html, only_detect=nil)
unless only_detect && only_detect != :atom
md ||= /<link.*href=['"]*([^\s'"]+)['"]*.*application\/atom\+xml.*>/.match(html)
md ||= /<link.*application\/atom\+xml.*href=['"]*([^\s'"]+)['"]*.*>/.match(html)
end
unless only_detect && only_detect != :rss
md ||= /<link.*href=['"]*([^\s'"]+)['"]*.*application\/rss\+xml.*>/.match(html)
md ||= /<link.*application\/rss\+xml.*href=['"]*([^\s'"]+)['"]*.*>/.match(html)
end
md && md[1]
end
end
The integration test (test/integration/feed detector test.rb:
require "#{File.dirname(__FILE__)}/../test_helper"
class FeedDetectorTest < ActionController::IntegrationTest
def test_fetch_feed_url
return # uncomment me to test HTTP fetching
# test mephisto
feed_url = FeedDetector.fetch_feed_url('http://blog.dominiek.com/')
assert_equal('http://blog.dominiek.com/feed/atom.xml', feed_url)
# test wordpress
feed_url = FeedDetector.fetch_feed_url('http://digigen.nl/')
assert_equal('http://digigen.nl/feed/', feed_url)
# test non conventional port
feed_url = FeedDetector.fetch_feed_url('http://blog.dominiek.com:8000/')
assert_equal('http://blog.dominiek.com:8000/feed/atom.xml', feed_url)
# test only_detect rss/atom on flickr
feed_url = FeedDetector.fetch_feed_url('http://www.flickr.com/photos/dominiekterheide/', :atom)
assert_equal('http://api.flickr.com/services/feeds/photos_public.gne?id=71386598@N00&lang=en-us&format=atom', feed_url)
feed_url = FeedDetector.fetch_feed_url('http://www.flickr.com/photos/dominiekterheide/', :rss)
assert_equal('http://api.flickr.com/services/feeds/photos_public.gne?id=71386598@N00&lang=en-us&format=rss_200', feed_url)
# make sure that feeds return themselves
feed_url = FeedDetector.fetch_feed_url('http://blog.dominiek.com/feed/atom.xml')
assert_equal('http://blog.dominiek.com/feed/atom.xml', feed_url)
feed_url = FeedDetector.fetch_feed_url('http://digigen.nl/feed/')
assert_equal('http://digigen.nl/feed/', feed_url)
end
def test_get_feed_path
body = []
body << ' <html>'
body << ' <head>'
body << ' <link href="/super.css" rel="alternate" type="text/css"/>'
body << ' <link href="/feed/atom.xml" rel="alternate" type="application/atom+xml" />'
body << ' </head>'
body << ' </html>'
# Mephisto
feed_path = FeedDetector.get_feed_path(body.join("\n"))
assert_equal('/feed/atom.xml', feed_path)
body[3] = ' <link href=\'/feed/atom.xml\' rel="alternate" type="application/atom+xml" />'
feed_path = FeedDetector.get_feed_path(body.join("\n"))
assert_equal('/feed/atom.xml', feed_path)
# FlickR
body[3] = '<link rel="alternate" type="application/atom+xml" title="Flickr: Photos from dominiekth Atom feed" href="http://api.flickr.com/services/feeds/photos_public.gne?id=71386598@N00&lang=en-us&format=atom">'
feed_path = FeedDetector.get_feed_path(body.join("\n"))
assert_equal('http://api.flickr.com/services/feeds/photos_public.gne?id=71386598@N00&lang=en-us&format=atom', feed_path)
body[4] = '<link rel="alternate" type="application/rss+xml" title="Flickr: Photos from dominiekth RSS feed" href="http://api.flickr.com/services/feeds/photos_public.gne?id=71386598@N00&lang=en-us&format=rss_200">'
feed_path = FeedDetector.get_feed_path(body.join("\n"))
assert_equal('http://api.flickr.com/services/feeds/photos_public.gne?id=71386598@N00&lang=en-us&format=atom', feed_path)
feed_path = FeedDetector.get_feed_path(body.join("\n"), :rss)
assert_equal('http://api.flickr.com/services/feeds/photos_public.gne?id=71386598@N00&lang=en-us&format=rss_200', feed_path)
# Wordpress
body[3] = '<link rel="alternate" type="application/rss+xml" title="Digigen RSS Feed" href="http://digigen.nl/feed/" />'
body[4] = ' </head>'
feed_path = FeedDetector.get_feed_path(body.join("\n"), :atom)
assert_equal(nil, feed_path)
feed_path = FeedDetector.get_feed_path(body.join("\n"), :rss)
assert_equal('http://digigen.nl/feed/', feed_path)
end
end
I'm sure this might be useful to some people so Enjoy!
Second the Haque web 2.0 Borrel
on June 17, 2007Yesterday I've attended a borrel - a gathering for drinks (のみかい) in the beautiful city of the Haque. About twenty Dutch web entrepreneurs met up in the appropriate venue Ondernemerscafe (entrepreneur cafe). There were a lot of interesting people and the food was quite nice. I'm not quite sure who made the free beers possible, but thanks a lot!
The following projects are both domestically and internationally interesting:
- fleck.com adding collaborative notes to web pages
- wakoopa.com community software usage
- roomware project physical world meets virtual self
And I'm happy to anounce that people we're quite excited about:
Friday I released the first version of confabio.com and it's running quietly now. This version is just to offer a sneak preview like I did at the meeting yesterday. Plug in your cam and check it out: confabio.com!
RubyEnRails 2007
on June 12, 2007
Last Thursday was the second RubyOnRails conference in the Netherlands. Conveniently, it was four minutes walking from my apartment in Amsterdam. RubyEnRails was organized and sponsored by recruitment companies that have RubyOnRails fever. The main sponsor was Adnexus the company by Brett Dawkins, a very active Dutch RoR scener.
Conference day
The conference was opened by Dr Nic Williams who gave two nice lectures that day. I knew Dr Nic because he has a nice blog and made nice comments about my Shuriken script. It appears Dr Nic is very fond of extending the syntax of Ruby by using 'magic' tricks like methodmissing or constmissing.
There were about 200 people at the conference. There was a mixed audience of PHP developers, Java developers and Sysop gothics. Also there was a fair percentage of recruiters, some of them with no clue. What really surprised me was the low amount of people that had actual production experience with rails. I suspect there weren't more than 20. During the lunch break, Dr Nic even admitted that he codes Java for a living.
Interesting cases
There were two interesting real-life cases nonetheless:
- Wakoopa.com, a 'what software do you use' social networking site by Robert Gaal (blueace.nl)
- Nedap's MovesOnRails, a health-care planning application by the Dutch Devices Factory Corp (Nederlandse Apparatenfabriek).
Also, I had a fruitful conversation with the director of Nedforce, someone who really does have a clue.
Noted techniques
These are some things that I heard and are more or less new to me:
- BackgrounDRB a distrubuted ruby job scheduler for rails
- Asset Packager a rails plugin that compresses your CSS/JavaScript
- multi-page (MovesOnRails) They invented this thing that allows you to navigate your layouts like a book. Still waiting for some code though.
Noted tools
- monit server monitoring tool
- munin server monitoring tool
- pingdom.com server monitoring tool 2.0, with SMS notification which is nice for in Europe
- mailroom a webapp that facilitates mail interaction with team and customers (not quite sure what it is yet, but people like it)
