Archiv der Kategorie: Projekt P

Unfreiwilliger Lasttest

Was man nicht machen sollte:
1. Unter einer Domain „mal eben“ ein Wiki für ein Projekt aufsetzen
2. Domain und Wiki vergessen und monatelang nicht drauf schauen
3. Diese Domain dann als Testadresse für ein neues Projekt nutzen.

In den Monaten dazwischen haben offenbar hunderte von Spambots das verweiste Wiki gefunden und
fluten es seit dem mit automatischen Spameinträgen.

Ergebnis: Das Logfile meiner Testapplikation hatte in nullkommanix eine Größe von 7MB.

Alles Fehlermeldungen erzeugt von den Spambots…

Na ja, jetzt bin ich mir zumindest sicher, dass die Seite einigermaßen schnell ist.

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.

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.

Projekt P: Los geht’s

Es wird mal wieder Zeit für ein neues Projekt. Diesmal gibt es einige Besonderheiten. Normalerweile arbeite ich ja als freier Berater meistens als Projektleiter beim Kunden vor Ort. Diesmal erstelle ich für den Kunden die komplette Applikation (natürlich in Ruby on Rails) selber und arbeite im Home Office. Damit bin ich zum ersten Mal seit über 7 Jahren fast täglich zuhause.

Nach der Web-Lernbox ist das damit mein zweites RoR Projekt. Diesmal allerdings in groß …

Würde ich das Projekt klassisch kalkulieren (z.B. als J2EE Anwendung mit einem entsprechenden Team), käme ich auf Kosten von ca. 150.000 EUR Kosten. Mein Ziel ist es, das ganze für ca. 50.000 EUR zu schaffen (dabei setze ich meinen normalen Tagespreis an). Allerdings bekommen ich das Geld nicht, sondern werde mich später am Ergebnis beteiligen – aber das ist eine andere Geschichte und die soll ein anderes Mal erzählt werden.

In den nächsten Wochen wird es hier also in lockerer Folge meine Erfahrungen bei der Entwicklung einer größeren Anwendung mit Ruby On Rails geben.

Möge die Übung gelingen.