der kl@mmeraffe | ruby. java. development.

a developers guide to the world of code

Friday, December 23, 2005

Ruby on Rails

I have translated this article in english here

(this is an older article in german, you can find new articles here

Ruby on Rails ist ein streng auf MVC basierendes Web-Framework, geschrieben und erweiterbar in und mit Ruby. Es baut sehr stark auf einem Generator-Ansatz auf, die komplette Verzeichnisstruktur und die Vorlagen für Models, Views und Controller können generiert werden. Durch den weitesgehenden Verzicht auf Konfigurationsfiles ist es auch für Menschen mit Abneigungen gegenüber Administrationsübungen (Der Autor schließt sich hier ausdrücklich ein) wunderbar geeignet.
Es entfallen sinnentleerte Mapping-Dateien (Klasse Angebot -> Tabelle Angebot), da Ruby anhand von Namensgleichheit zwischen der R- und O-Welt die Objekte und Attribute auf die Datenbank mappt.

Um das ganze auch mal anhand eines Beispiels zu testen, hier eine kleine, praktische Anwendung: Eine Todo-Listen-Verwaltung. Hier sollen Todo-Listen nebst einzelnen Todos angelegt, geändert, gelöscht und angesehen werden können.

Aber kommen wir zuerst zur Technik. Um mit Rails arbeiten zu können brauchen wir zuerst Ruby, das bekommen wir auf der Ruby-Homepage. Um eine Datenbankanwendung entwickeln zu können, benötigen wir ausserdem ein Datenbanksystem. Typischerweise verwenden wir hier das (mittlerweile) auch einfach zu bedienende MySQL, hier im Beispiel in der Version 4.1. Nebst dem kostenlosen MySQL Administrator 1.1. Beides auf der MySQL-Homepage zu beziehen.

Nach der Installation können wir in per Kommandozeile mit dem bei Ruby mitgelieferten Package Manager Rails installieren.
gem install rails --include-dependencies

Nun erstellen wir das Projekt "Todo":
rails todo

Dadurch wird der komplette Verzeichnisbaum generiert. In dem Unterverzeichnis "app" landen später die views, models und controller.

Als nächstes erstellen wir eine neue Datenbank (Schema) unter MySQL mit Namen "todo" inklusive zwei Tabellen:
lists (id, name, bezeichnung)
todos (id, name, txt, list_id)

So, jetzt editieren wir im Verzeichnis todo/config die Datei database.yml und passen sowohl die Entwicklungs-, Produktions- und Testdatenbankeinstellungen entsprechend unserer Umgebung ein.

Starten wir nun den Web-Server:
ruby script/server

Mit einem Klick auf http://localhost:3000 bekommen wir den erfolgreichen Start bescheinigt.

Lassen wir Rails nun seine Stärken ausspielen. Durch die Benennung der Listen-Tabelle in "lists", schließt Rails darauf, dass eine Komponente "List" in unserer Anwendung auf sie mappt. Rails ist hierbei (im Englischen) sehr Clever, mappt auch von "Entries" auf "Entry". Hier erkennen wir zum ersten Mal den von den Entwicklern und dem Autor vertretenen Vorsatz "Konvention über Konfiguration". Zwar ist der Code Konventionen unterlegen, dafür sind Deployment-Deskriptoren und Mapping-Files passe.

Generieren wir nun model und controller der Komponente "List":
ruby script\generate model List

ruby script\generate controller List

Erneut generiert Rails die Stubs für uns, inklusive Helper-Klassen und Unit-Tests.

Editieren wir nun unter app/controller die Datei list_controller.rb und schreiben innerhalb der Klasse
scaffold :list

Ein Klick auf http://localhost:3000/list/new zeigt uns, was wirkliches Prototyping ist. Die CRUD (Create, Remove, Update, Destroy) Funktionalität ist komplett vorhanden. Und das mit nur einer Zeile Code im Controller.

Mehr hierzu demnächst.

add this article to del.icio.us

add to del.icio.us | submit to digg | submit to reddit

Thursday, December 22, 2005

News: AJAX-Framework als Apache-Projekt vorgeschlagen

Hm, brauchen wir AJAX? Mal überlegen, was war mein erster Gedanke? A steht für Asynchronous. Das ist ok. J für JavaScript. Autsch. JavaScript als Bestandteil eines neuen Hypes? AJ - And XML. Spätestens seit zu großen build-Files diverser Ant-Jünger und zerklüffteten 2.1er EJB-Deployment-Deskriptoren auch lieber nicht.
Da hofft man also, dass der Endandwender sich mit dem Response/Request Zyklus abgefunden hat bis modernere Technologien Abhilfe schaffen, da findet doch einer raus, dass man über ein XMLHTTPRequest-Objekt per JavaScript Abfragen auf den Server machen kann. Jetzt auch bei Apache.
Nun, JSP sorgte dafür, dass man per Tags keinen serverseitigen Skriptcode mehr benötigt, jetzt haben wir wieder den Clientseitigen.
Wems gefällt. Mehr dazu hier:
artikel@golem.de

add to del.icio.us | submit to digg | submit to reddit

Wednesday, December 21, 2005

Picocontainer

Picocontainer ist ein sogenannter IOC-Container. IOC steht für Inversion of Control und wurde (soweit ich informiert bin) von Martin Fowler vor einiger Zeit auf den Begriff Dependency Injection konkretisiert. Grundsätzlich bedeutet IOC, dass die Kontrolle für die Erstellung von abhängigen Objekten nicht mehr explizit sondern implizit gesteuert wird.

Beispiel:
public class KundeDAO {
[..]
Database db = new OracleDatabaseImpl();
[..]
}

In dieser Klasse ist die Verknüpfung zur Datenbankimplementierung fest, eine Wiederverwendung der Klasse wäre unter eines Deploys auf einem MSSQLServer problematisch. Falls eine Vielzahl kleiner Objekte viele Beziehungen zueinander aufbauen ist von einer losen Koppelung kaum noch zu sprechen.

Vereinfachend gehe ich jetzt nur auf zwei Arten von Dependency Injection ein

Möglichkeit 1:
Setter Injection

public class KundeDAO {
[..]
Database db;

public void setDatabase(Database db) {
this.db = db;
}
[..]
}


Möglichkeit 2:
Constructor Injection

public class KundeDAO {
[..]
Database db;

public KundeDAO(Database db) {
this.db = db;
}
[..]
}

Schauen wir uns in erster Linie Möglichkeit 2 an. Die Beziehungen (hier vereinfacht nur die Datenbank) werden übergeben, durch die Abstraktion zum Interface Database kann jede Form von Datenbank übergeben werden. Damit bleiben die Objekte lose gekoppelt und die Wiederverwendbarkeit steigt enorm.

Mit einem IOC-Container wie Picocontainer entfällt die direkte Verwaltung und Zuordnung der Beziehungen und die platz- und zeitraubende Instanzierung abhängiger Objekte, da der Container die Abhängigkeiten "injiziert" (daher Dependency Injection) und die Klassen selbst nicht mehr für die Erstellung verantwortlich sind.

Um das auf obiges Beispiel anzuwenden, würde ein Code-Snippet folgendermaßen aussehen:

MutablePicoContainer pico = new DefaultPicoContainer();
pico.registerComponentImplementation(OracleDatabaseImpl.class);
pico.registerComponentImplementation(KundeDAO.class);
KundeDAO kunde = (KundeDAO) pico.getComponentInstance(KundeDAO.class);

Hier werden einem neu erstellten PicoContainer die einzusetzenden Klassen übergeben und anschließend eine Instanz der KundeDAO-Klasse erstellt. Per Hand würde man das folgendermaßen abbilden:

Database database = new OracleDatabaseImpl();
KundeDAO kunde = new KundeDAO(database);

Bei einem so trivialen Beispiel wie hier macht das eher wenig Sinn. Wenn allerdings viele Klassen viele Abhängigkeiten untereinander haben ermöglicht Pico eine weniger starre Kopplung.

Soviel zur Einführung. Pico bietet auch Lifecycle-Support an und wirkt sehr sauber entwickelt (Test-First). Mehr Infos gibt es hier:

Picocontainer Homepage
Pico 5-Minuten Einführung

add to del.icio.us | submit to digg | submit to reddit

CSS - Einführung Teil 1

Wer schon einmal eine Homepage erstellt hat, kennt das Problem: Der Code wird spätestens bei den Designanpassungen (Schriften, Hintergrundbilder,...) unübersichtlich und vor allem schwer wartbar. Das kommt daher, weil das "Was?" (Was wird angezeigt?) und das "Wie?" (Wie wird es angezeigt?) im HTML vermischt vorliegen.
Die Lösung aus der Misere: Cascading Style Sheets, von Freunden "CSS" genannt.

Ein Beispiel. Nachfolgend eine Demonstrationsseite (das unter CSS-Jüngern alseits bekannte "CSS Zen Garden Projekt") in reinem HTML.

Demo-Seite

Hier ist lediglich das "Was?" hinterlegt. Da CSS extern das "Wie?" übernehmen kann, können mit zwei unterschiedlichen CSS-Dateien ein und die selbe HTML auf vollkommen unterschiedlichen Wegen interpretiert werden.

Beispiel 1
Beispiel 2


Diese Beispiele haben beide ein und dieselbe HTML-Datei, die Texte sind identisch, aber durch CSS wird da Layout vollkommen anders dargestellt.

Ein erster Schritt:

Nehmen wir einmal folgenden HTMLcode zur Grundlage:

<html>
<head>
</head>
<body>
<h3>Ein erster Test</h3>
Mit ein kleinwenig Text
</body>
</html>

Zeigt man diesen Code im Browser an, wird einfach eine Überschrift mit etwas Text abgebildet:


Ein erster Test


Mit ein kleinwenig Text


Langweilig, oder? Passen wir doch ein wenig die Schrift an. Wir schreiben eine Datei test.css:

body {
font: normal 10px/1.6em "Lucida Grande", "Verdana", sans-serif;
}

h3 {
color: red;
}

Dem aufmerksamen Betrachter fällt auf, dass vor den {}-Klammern jeweils ein HTML-Tag steht. In den Klammern werden dann Anpassungen für diesen Tag implementiert. Wenn wir also wollen, dass sämtliche h3-Überschriften auf unserer Website rot sind, müssen wir lediglich das obenstehende css-File einbinden.
Hierfür müssen wir im <head>-Abschnitt folgenden Code hinzufügen:

<link rel="stylesheet" type="text/css" href="test.css" />


Das Ergebnis mit CSS:
hier klicken

Demnächst mehr!

add to del.icio.us | submit to digg | submit to reddit