Archiv für den Monat: Oktober 2007

Projekt P. Admin Oberfläche

Die letzten Tage habe ich ja Newsletter und Benutzerverwaltung eingebaut. Was noch fehlt, ist eine Admin-Oberfläche um „mal eben“ Daten zu ändern.

Nun bin ich ja erstmal faul. Also programmiere ich das nicht selber, sondern suche mir einen schon vorhandenen Generator. Eigentlich könnte man es natürlich auch schon mit Boardmitteln machen.
script/generate scaffold Modell-Name
erzeugt schließlich die rudimentären Oberflächen, um Daten zu bearbeiten. Aber auf der einen Seite sieht das nicht sonderlich hübsch aus und darüber hinaus haben wir dann noch keine Relationen abgedeckt. Gut, dass es noch andere Generatoren gibt.

Die Kandidaten sind:
Streamlined
Active-Scaffold und
Hobo

Hobo ist allerdings zuviel des Guten, damit kann man eher komplette Anwendungen bauen. Es spielt damit in der gleichen Liga wie z.B. Goldberg.
Goldberg hatte ich tatsächlich ins Auge gefasst, da ich eh‘ auch ein wenig CMS brauche. Aber leider ist mein Design zu komplex dafür.
Wie auch immer. Gewonnen hat Active-Scaffold.

Prinzipiell nutzt man in der Railsentwicklung sehr viele Plugins und Generatoren. Da diese Generatoren normalerweise recht wenig Code erzeugen kann man das Ergebnis gut verstehen und weiterentwickeln.

Die Installation und Konfiguration von Active-Scaffold ist erschreckend simpel. Super, also weiter zum CMS.

Grüß mir die Genossen …

… ist ein alter Song von Marius Müller Westernhagen.

Die ersten Zeilen:

Neulich sechs Uhr Früh, da tritt man mir die Tür ein
Ich spring aus dem Bett, da stürmt die Polizei rein
„Los, stell’n Sie sich an die Wand! Man hat Sie erkannt.
Ein Nachbar rief uns an, Sie sind ein Symphatisant!“

Das Ende:

Eines wird mir klar, wenn irgendjemand schreit
Gesetze müssen her! dem hau ich auf die Flossen
Ja, eines ist mir sonnenklar: falls wir glauben sollten,
Terror könnt man durch Terror bremsen, dann sind wir bald wieder soweit

Warum mir der Song gerade einfällt?

Ach, ich las gerade, wie einem Paar die Flitterwochen ein wenig, ähm, spannender gestaltet wurden.

Wie ich schon vor einem Jahr schrieb. Die Terorristen haben gewonnen, wir haben verloren.

DerWesten-.de

Eigentlich wollte ich mir die neue Seite www.derwesten.de, das neue Portal der WAZ-Gruppe, anschauen. Aber wie auch schon vor einiger Zeit beim Tagesspiegel-Relaunch geht gerade nix. Damals hatte ich die Regel aufgestellt, man solle bei einem Relaunch damit kalkulieren, dass sich die Traffic am Starttag um den Faktor 2-10 erhöht.

Mitterweile sehe ich das ein wenig anders. Daher meine Regel 1A für den Launch großer Seiten:
Kündige den Launch an und mache eine Woche vorher einen Softlaunch.

Es ist technisch wie finanziell heute sehr schwierig, den Traffic am Eröffnungstag zu verkraften. Es ist nicht unmöglich, aber es ist teuer. Also lieber „heimlich“ starten. Die Nachricht darüber verbreitet sich schon schnell genug. Warum auch nicht? Wenn es bekannt wird und gut läuft kann man eine nette Pressemitteilung rausgeben: „Wir sind vor dem Plan fertig geworden und wollten unseren Kunden die Wartezeit verkürzen“ – wer kann das schon von sich behaupten.

Web 2.0 Parodie

Wie köstlich…

Ich bin ja ein bekennender Web 2.0 Fan. Nicht zuletzt deswegen, weil die Idee des User-generated-content doch eigentlich die Ursprungidee des Internet war.

Natürlich findet man zwischen allen netten Angeboten reichlich Müll. Nicht jedes aufgemotzte Web-Forum ist gleich eine millionenschwere Web2.0 Anwendung. Auch frage ich mich, wo eigentlich die ganzen Sportler herkommen sollen für die hunderte neuen Sportportale (BTW: Ich war hautnah dabei, als Becker, Neef und Co. Sportgate in den Sand gesetzt haben – auch diese Idee ist also nicht gerade neu).

Heute habe ich die erste Web 2.0 Parodie gefunden: www.zusammenzuspaet.de. Die tun so, als seien sie ein Portal welches wartende Bahnreisende zusammenbringt. Zitat:

Zusammenzuspät.de ist eine Community, in der sich Bahnreisende kennenlernen und verabreden können. Wir vermitteln Dir kostenlos Gesprächspartner während einer langen Bahnreise.

Der Brüller, oder? Ich finde das super lustig. Die Seite wirkt dabei absolut echt. Sogar das Impressum wirkt glaubwürdig. Ganz Web2.0 like ist der Betreiber natürlich eine englische Ltd. – spitze. Um glaubwürdig beta zu sein, gibt es (unter FireFox 2) einige kleine Anzeigefehler auf der Homepage – Wow, wie machen die das nur?

Früher hat man einfach mit seinem Sitznachbarn geplaudert. Und wenn das nicht ging, fand man auf jeden Fall im Bistrowagen lustigen Handelsvertreter mit dem man ein Weizen trinken konnte. Daher ist es natürlich ein wenig zu offensichtlich, dass es eine Parodie und nicht ernst gemeint ist.

Aber trotzdem echt witzig gemacht

Curryparade

Wir unterbrechen dieses Blog für einen sinnfreien Eintrag:

Google findet nichts unter dem Stichwort.
Das wollte ich ändern.

(Gerade hat ein Kandidat bei Wer wird Millionär das als Antwort gegeben und Herr Jauch hat angeregt, das mal bei Google zu suchen…)

Nachtrag:
Ich musste es einfach tun: www.curryparade.de

Projekt P: Benutzerverwaltung

Auf der Seite wird man sich als Benutzer registrieren können. Also brauche ich eine Benutzerverwaltung (Registrierung, Login, etc.).

Auch hier bin ich faul. Ich nutze einfach acts_as_authenticated.

acts_as_authenticated ist ein Generator der mir die grundlegenden Funktionen generiert. Wie schon bei der Newsletter wird es auch hier einen Registrierungscode geben, den man per Mail zugeschickt bekommt.

Das vorgegebene User-Datenmodell erweiter ich um einige Funktionen. Unter anderem kann man mehrere Adressen hinterlegen.
Also gibt es ein neues Modell namens „address“. Das Usermodell erweiter ich um den Befehl
has_many :addresses
Entsprechend kommt an das Addressenmodell:
belongs_to :user
Und schon habe ich eine saubere 1:N Beziehung definiert.
… Fast. Denn wenn ein User gelöscht wird, brauchen wir die Adressen natürlich nicht mehr. also
sieht es im Usermodell tatschlich so aus:
has_many :addressed :dependent => :destroy
Jetzt sieht es gut aus. Man könnte auch destroy_all schreiben, dann werden die Objekte sofort gelöscht. So wird vorher noch before_destroy und after_destroy für jedes Objekt aufgerufen. Es ist also langsamer. Aber die Benutzer sollen sich schließlich anmelden und nicht alle wieder löschen…

Jetzt kommt die Kür. Jeder User hat viele Adressen, aber eine Hauptadresse. Die Hauptadresse will ich einfacher finden und erweiter mein Usermodell so:
has_one :mainaddress, :class_name=>'Address', :conditions =>'addresses.primaereadresse=true'

Das Ergebnis: Auf die Hauptadresse kann ich nun in meinem Programm über User.mainaddress problemlos zugreifen. Schick, oder?

Zeitaufwand: ca. 2 Stunden. Allerdings habe ich das Design noch nicht optimiert. Aber das kommt später.

Projekt P Tag 2: Newsletter

Bei der Entwicklung der Seite werde ich die wichtigsten Funktionen zuerst entwickeln. Sollte irgendetwas gründlich schief laufen, sollen sich die Kunden zumindest schon mal als User registrieren können und eine Newsletter empfangen können.

User und Newsletter-Empfänger trenne ich dabei. Die Newsletter wird – klar – durch ein DoubleOptIn Verfahren abonniert werden. Das heißt, dass man sich auf der Seite anmeldet und anschließend einen Bestätigungslink zugeschickt bekommt. Ich brauche allerdings noch ein wenig mehr. Ich möchte neben der Mailadresse auch Name und Anschrift des Abonnenten haben (natürlich freiwillig).

Also sieht mein Prozess so aus:
1. Kunde trägt seine Mailadresse auf der Seite ein
2. Kunde bekommt eine Mail mti einem Bestätigungslink
3. Kunde ruft den Link auf und gibt anschließend weitere Daten ein
4. Datensatz wird aktiviert.

Ok, wir brauchen also zuerst eine Tabelle um die Daten abzulegen.
script/generate modell subscriber

Jetzt schnell die Attribute definiert:
CreateSubscribers < ActiveRecord::Migration def self.up create_table :subscribers do |t| t.column :name, :string t.column :vorname, :string t.column :strasse, :string t.column :plz:string t.column :ort:string t.column :mail, :string t.column :created_at, :date t.column :updated_at, :date t.column :activation_code, :string, :limit => 40
t.column :activated_at, :datetime
end
end

def self.down
drop_table :subscribers
end
end

Und die Tabelle anlegen:
rake db:migrate

created_at und updated_at sind besondere Fehler. Rails wir diese Felder selbstständig füllen.

Um sein Abo zu aktivieren, braucht der Kunde einen Aktivierungslink. Wir brauchen also einen Schlüssel, den wir in den Link einbauen. Das machen wir in der Klasse Subscriber so:
class Subscriber < ActiveRecord::Base
before_create :make_activation_code

def make_activation_code

self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
end
(...)
end

So, jetzt kann ich den controller erzeugen und mir die notwendigen Methoden bauen. Diese sind:
– activate (hier frage ich den weiteren Kundendaten)
– activate_step2 (hier speichern wir die Daten)

Und schon bin ich fertig.

Ach, mist. Da habe ich doch glatt etwas vergessen. Ich möchte dem Abonnenten die Möglichkeit geben, sich durch einen einfachen Link wieder abzumelden. Dazu muss ich aber eine Schlüssel speichern aus dem ich den Link erzeuge (also wie der activation_code, den ich dem Kunden schicke. Unter Ruby on Rails ist das aber kein Ding:
script/generate migration subscriber_deactivationcode
erzeugt mir eine neue Migrationsdatei.

Die nur schnell ausfüllen:
class Subscribers3Deactivationcode < ActiveRecord::Migration def self.up add_column :subscribers, :deactivation_code, :string, :limit => 40
end
def self.down
remove_column :subscribers, :deactivation_code
end
end

Ok, eigentlich müsste die die vorhandenen Datensätze updaten. Aber ich habe ja nur Spieldaten, also was soll’s. Jetzt noch schnell make_activation_code erweitern:
self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )

Fertig!

Ich habe natürlich nicht alles beschrieben. Der Kunde bekommt natürlich einige Mails zugeschickt. Das ist aber nicht sonderlich spektakulär. Außerdem habe ich einige Tests geschrieben, um meine Entwicklung zu überprüfen.

Zeitaufwand für das Feature? 1/2 Tag.
Geschwindigkeitsvorteil gegenüber normaler (J2EE) Entwicklung: Gering, in Jave würde man es ähnlich machen. Allerdings musste ich nicht ständig meine Arbeit übersetzen und auf einen Testserver deployen, sondern konnte direkt aus der Entwicklungsumgebung (netbeans 6) „run file“ aufrufen und habe dadurch sehr schnell meine Entwicklung testen können.

Projekt P Tag 1: Design und HTML

Auch nach vielen Jahren bei verschiedenen Web-Agenturen haben sich meine zeichnerischen Fähigkeiten nicht wirklich verbessert. Ich hatte schon in der Schule eine 3- in Kunst. Bilde mir zwar ein, Design beurteilen zu können. Aber damit muss ich es sja noch lange nicht selber können.

Also gebe ich das Design an eine externe Agentur. Auf der erstellten Grafiken werden dann die HTML Template gebaut. Das könnte ich zwar eigentlich einigermaßen selber. Aber die Zeit drängt. Daher wird die initiale Erstellung durch einen externen HTML’er durchgeführt. Dies nutze ich dann zusammen mit masterview als Basis meiner Entwicklung.

Das führt uns zu der Frage: wann delegieren, wann selber machen? Viele Menschen haben Probleme, Aufgaben zu delegieren. Das hat einen einfachen Grund: Entweder man kann die Aufgabe selber nicht durchführen. In dem Fall kann man auch die Qualität der Arbeit schlecht bewerten. Man kann das Ergebnis zwar beurteilen. Aber vielleicht hätte man es noch besser oder schneller machen können. Leider kann man es nicht beurteilen.
Oder man ist bei dem Thema selber gut. In dem Fall geht viele Leute ihren Mitarbeitern auf die Nerven, weil diese die Aufgabe scheinbar nicht gut genug erfüllen. Wie auch, wenn der Chef ihnen das immer wieder weg nimmt …
Gerne hört man das Sprüche wie „Das kann sonst niemand richtig“, „Wenn ich es nicht selber mache, herrscht hier das Chaos“ usw. usw.

Es gibt auf der anderen Seite z.B. die Regel, dass Leiter von Entwicklungsteams ab einer Teamgröße von 7 Personen nicht mehr selber programmieren sollten. Auch das halte ich mittlerweile für zu einfach formuliert. Warum sollte man nicht selber in die Tasten greifen, solange das Team nicht auseinanderfällt?

In meinem aktuellen Fall gibt es zwei einfache Parameter: Zeit und Geld. Ich habe ein sehr geringes Budet (vor allem ist es mein eigenes Geld …) und ich habe feste Zeitvorgaben. Daraus will ich eine möglichst hohe Qualität holen – also ein Aufgabe aus dem Bereich der linearen Optimierung :-)

Allgemein würde ich folgende Regel aufstellen: Es ist einfacher, Aufgaben nachträglich wieder an sich zu ziehen als nachträglich abzugeben. Also sollte so viel wie möglich abgeben und sich auf die Qualitätssicherung konzentrieren.

Ich werde die Telefonfirmen wegen Terrorunterstützung anzeigen

So, Obermann und Co., zieht euch schon mal warm an. Wobei, in Guatanamo ist es ja eher warm. Jetzt geht es euch an den Kragen!

Über eure Telefonleitungen werden Verbrechen geplant. Terroristen verabreden sich zu echt schlimmen Dingen. Und nicht nur das: Täglich werden per Telefon Menschen bedrohnt und beleidigt. Darüber hinaus fördert ihr illegale Webeanrufe (Cold-Calls) da ihr diese nicht filtern. Ich werde euch verklagen und ihr müsst solche Telefonate filtern!

Was? Wie? Das ist doch schwachsinn? Nur weil sie die Transportwege zur Verfügung stellen, trifft sie keine Schuld? Sie können doch gar nicht alle Inhalte filtern, auch wenn das vielleicht bei einigen unseriösen Call-Centern klappen könnte?

Ja und? Beim Internet wird es doch auch so gemacht. Deutsche Gerichte prüfen gerade, ob Internetprovider Angebote wie YouPorn filtern müssen. Das Telmediengesetz sieht zwar den Übermitter von Inhalten eigentlich nicht in der Verantwortung für die Inhalte. Aber scheinbar ist das Gesetz nicht 100% eindeutig formuliert. Wenn ich es richtig verstehe, gibt es vor Gericht wohl einen Unterschied zwischen „Verantwortung“ und „Haftung“.

Sollten diese Abmahnungen vor Gericht tatsächlich Bestand haben, müsste man aus meiner Sicht mit gleicher Logik von der Telekom verlangen, bekannte unseriöse Call-Center abzuklemmen. Das wird lustig…

Spam vom tourismus-bayern.com

Huch, da bekomme ich eine Spam Mail mit der Überschrift Newsletter Tourismus-Bayern der
Systemmarketing.de.

Selbstverständlich habe ich sowas nicht angefordert. Der Spammer weiß es aber besser. Unter der Mail findet sich (wie in vielen anderen Mails dieser Art auch):
„Sie bekommen diesen Newsletter, da Sie sich als Empfänger beim Newsletter
von tourismus-bayern.com und/oder tourismus-tirol.com eingetragen haben.
Wenn Sie den Newsletter nicht mehr erhalten wollen, klicken Sie hier“

Jetzt könnte ich da denke, ok, habe ich mal nicht aufgepasst.

Dumm nur, dass die Mail an eine Adresse geht, welche ich ausschließlich im Usenet verwende (und die
bezeichnenderweise auch noch usenetspam@(…) heißt.

Ich habe den Freunden mal ein T5F geschickt. Zuerst per Mail. Sollte das nicht klappen, gibt es ein Fax.