Gerade bastle ich an einem Wrapper für DataSources der im Umgang mit Datenbanken helfen soll (zusätzliche Statistiken, blocking bei DB Fehlern und pausieren von DB Anfragen). Dabei wrappe ich zwei Methoden getConnection() und getConnection(String, String). Nur der Aufruf der realen Methode unterscheidet sich, der restliche Code ist in beiden Methoden gleich:
Im Sinne von DRY (don't repeat yourself) ist dies aber unschön, weil der (in Realität noch komplexere) Retry code doppelt vorkommt, und ich immer beide Methoden anpassen muss. Dieses Problem kommt oft bei Frameworks vor, und nennt sich "the whole in the middle" Muster. Eine Lösung wäre:
Das funktioniert aber nur im einfachsten Fall und es verkompliziert leider den Framework code, was auch wieder der Verständlichkeit schadet.
In C# 3.0 kann man das (wie ich grade gesehen habe) mit einer Lambda Action lösen (man kann also im Prinzip anonyme Funktionsblöcke übergeben). In Java müßte man dazu ein Objekt übergeben:
Der smartConnect() code wird damit lesbarer, und man kann auch komplexere Aktivitäten injizieren (eventuell mit Argumenten zur provide() methode), aber man muss jetzt noch eine extra Klasse definieren und alles in allem wird es auch mehr Code. Bei jedem Aufruf wird ein zusätzliches Objekt erzeugt. Ich denke ich werde also eher bei dem "if" Ansatz bleiben.
Ich vermute mal der Syntaktische Zucker "Lambda Expression" erzeugt bei C# auch ein extra Call Objekt, aber es fällt wesentlich weniger zusätzlichen Code beim Aufruf an.
CODE:
public Connection getConnection(String user, String pass) ...
{
verifyState();
while(true) {
try {
Connection c = ds.getConnection(user, pass);
verifyConnection(c); // throws SQLEx
return c;
} catch (SQLException e) {
handleException(e); // throws SQLEx
}
}
}
public Connection getConnection() ...
{
verifyState();
while(true) {
try {
Connection c = ds.getConnection();
verifyConnection(c); // throws SQLEx
return c;
} catch (SQLException e) {
handleException(e); // throws SQLEx
}
}
}
Im Sinne von DRY (don't repeat yourself) ist dies aber unschön, weil der (in Realität noch komplexere) Retry code doppelt vorkommt, und ich immer beide Methoden anpassen muss. Dieses Problem kommt oft bei Frameworks vor, und nennt sich "the whole in the middle" Muster. Eine Lösung wäre:
CODE:
public Connection getConnection(String user, String pass)
{
return smartConnect(true, user, pass);
}
public Connection getConnection()
{
return smartConnect(false, null, null);
}
Connection smartConnect(boolean hasArgs, String user, String pass)
{
verifyState();
while(true) {
try {
Connection c;
// --- the whole in the middle
if (hasArgs)
c = ds.getConnection(user, pass);
else
c = ds.getConnection();
// ---
verifyConnection(c); // throws SQLEx
return c;
} catch (SQLException e) {
handleException(e);
}
}
}
Das funktioniert aber nur im einfachsten Fall und es verkompliziert leider den Framework code, was auch wieder der Verständlichkeit schadet.
In C# 3.0 kann man das (wie ich grade gesehen habe) mit einer Lambda Action lösen (man kann also im Prinzip anonyme Funktionsblöcke übergeben). In Java müßte man dazu ein Objekt übergeben:
CODE:
public Connection getConnection(String user, String pass)
{
return smartConnect(
new ConnectionProvider() {
Connection provide() { return ds.getConnection(user, pass); }});
}
public Connection getConnection()
{
return smartConnect(
new ConnectionProvider() {
Connection provide() { return ds.getConnection(); }});
}
Connection smartConnect(ConectionProvider cp)
{
verifyState();
while(true) {
try {
Connection c = cp.provide();
verifyConnection(c); // throws SQLEx
return c;
} catch (SQLException e) {
handleException(e); // throws SQLEx
}
}
}
abstract class ConnectionProvider {
Connection provide();
}
Der smartConnect() code wird damit lesbarer, und man kann auch komplexere Aktivitäten injizieren (eventuell mit Argumenten zur provide() methode), aber man muss jetzt noch eine extra Klasse definieren und alles in allem wird es auch mehr Code. Bei jedem Aufruf wird ein zusätzliches Objekt erzeugt. Ich denke ich werde also eher bei dem "if" Ansatz bleiben.
Ich vermute mal der Syntaktische Zucker "Lambda Expression" erzeugt bei C# auch ein extra Call Objekt, aber es fällt wesentlich weniger zusätzlichen Code beim Aufruf an.
In einem geschlossenen System geht keine Energie verloren. Schade dass Unternehmen kein geschlossenes System sind, denn es ist erschreckend wie viel Wissen und Erfahrung in einem Unternehmen verloren gehen kann.
Einer meiner Aufgaben ist die Beratung von Key Account Kunden bei komplexeren Projekten, um sicherzustellen dass Sie von unserer Erfahrung profitieren und natürlich um unsere Roadmap besser auf die Kundenbedürfnisse abzustimmen. Die Installation von Middleware ist meistens verknüpft mit Konsolidierungs- und Migrationsprojekten (in denen bestehende Anwendungen unterschiedlicher Hersteller auf eine neue Plattform zusammengefasst werden, ganz beliebt sind SAP Einführungen). Deswegen bekomme ich oft (am Rande) mit, wie schmerzhaft es sein kann in einem Unternehmen eine genaue Analyse der (Legacy) IST-Prozesse zu erstellen, oder für ein geplantes neues System die Mindestanforderungen zu definieren.
Ich treffe immer wieder auf die selben Muster:
Zum Glück verliefen alle Projekte die ich so kenne mehr oder weniger erfolgreich. Hilfreiche waren dabei folgende Faktoren:
Einer meiner Aufgaben ist die Beratung von Key Account Kunden bei komplexeren Projekten, um sicherzustellen dass Sie von unserer Erfahrung profitieren und natürlich um unsere Roadmap besser auf die Kundenbedürfnisse abzustimmen. Die Installation von Middleware ist meistens verknüpft mit Konsolidierungs- und Migrationsprojekten (in denen bestehende Anwendungen unterschiedlicher Hersteller auf eine neue Plattform zusammengefasst werden, ganz beliebt sind SAP Einführungen). Deswegen bekomme ich oft (am Rande) mit, wie schmerzhaft es sein kann in einem Unternehmen eine genaue Analyse der (Legacy) IST-Prozesse zu erstellen, oder für ein geplantes neues System die Mindestanforderungen zu definieren.
Ich treffe immer wieder auf die selben Muster:
- Es werden andere (neue) Mitarbeiter mit der Umsetzung der neuen Projekte betraut. Entweder weil man den alten Hasen die neue Technologie nicht zutraut, weil die bestehende Mannschaft nicht aus dem Tagesgeschäft entlassen werden solll, oder weil die Verantwortlichkeiten schleichend neu verteilt werden sollen. Egal welchen Grund es gibt die neuen Mitarbeiter haben keine Erfahrung mit dem Gesamtproblem, und die erfahrenen Mitarbeiter haben entweder keine Motivation oder Gelegenheit mehr zu helfen.
- Die Vordenker die das alte System entworfen und vor allem weiterentwickelt haben sind nicht mehr im Unternehmen. Kleine Änderungen und Pflege wird vom Stammpersonal vorgenommen, aber keiner kann die Prozesse komplett überblicken.
- Selbst die detaillierteste Systemdokumentation kann ein System (vor allem die Überlegungen bei der Umsetzung) voll beschreiben. Und selbst wenn sie es könnte, so ist sie nicht mehr vollständig erfassbar.
- Der Teufel steckt im Detail: die Projekte sind meistens so angelegt dass keine Zeit für Fehler oder Verbesserungen eingeplant werden. Das Second System muss gleich perfekt sein, auch wenn die bestehende Anwendung über Jahrzehnte gewachsen ist. Das sind unrealistische Anforderungen, im besten Fall werden im Laufe des Projektes der Umfang der Pilotprojekte immer kleiner - und damit irgendwann machbar.
- Mitarbeiter die für die Umsetzung Hauptverantwortlich sind werden so mit Fakten und Entscheidungen überschüttet, dass Verdrängungs- und Überschätzungsmechanismen einsetzen. Das Gesamtsystem aus einer anderen Sichtweise (z.B. aus Sicht des Controllings oder des Operatings, oder des Supports, oder oder) zu betrachten wird als unnötig oder zu aufwändig angesehen. Daraus ergeben sich oft Entscheidungen die sich im späteren Betrieb als sehr ineffektiv herausstellen. Oftmals werden einfach zu wenige zentrale Rollen besetzt. Keyuser und Stakeholder aus unterschiedlichen Bereichen gibt es nicht, oder werden nicht gefördert.
- Ein weiteres Problem sind knappe Deadlines und neue Technologien. Beide führen dazu dass Unternehmen externe Berater in allen Ebenen beauftragen. Das führt zu dem Effekt, dass die Überlegungen zur Umsetzung nicht immer im Besten Interesse der Firma sind, und die gemachten Erfahrungen auch mit dem Ende des Migrationsprojektes das Unternehmen wieder verlassen. Mehrere hundert Business und Technologie Consultants sind keine Seltenheit.
- Ein Problem mit dem man fertig werden muss, ist auch die Tatsache dass die funktionierenden Prozesse nicht notwendigerweise effizient sind. Bei einer genauen Analyse werden die Schwachstellen entdeckt. Oftmals wird die Entscheidung zum Re-Engeneering aber zu leichtfertig getroffen. Der Projekt-Scope weitet sich somit aus.
- Pilotprojekte werden oft auch falsch ausgesucht: zwar ist es Sinnvoll nicht mit dem Core Business als erstes auf eine neue Plattform umzuziehen, jedoch ist das bisher manuell betriebene Business einer ausländischen Zweigstelle nicht unbedingt repräsentativ. Von den Problemen wie Zeitverschiebung, kulturelle und Sprachlichen Barrieren oder fehlende Erfahrung der Stammbelegschaft ganz zu schweigen.
Zum Glück verliefen alle Projekte die ich so kenne mehr oder weniger erfolgreich. Hilfreiche waren dabei folgende Faktoren:
- Heroes die Verantwortung und Kommunikation übernehmen. Immer wieder alle Parteien an einen Tisch holen.
- Manager die Dank Sachverstand Abschätzungen hinterfragen können.
- Starke Einbindung von internen Ressourcen in allen Phasen.
- Iterative Umsetzung in kleinen Schritten.
- Die Auswahl eines Leistungsstarken und flexiblen Softwarepartners mit herausragenden Mitarbeitern (*grins*)
Geschrieben von Bernd Eckenfels
in Enterprise IT, Product Management
| Kommentar (1)
| Trackbacks (0)
In meinem letzten Artikel zum IBM Plugin für den Eclipse Memory (Dump) Analyser (MAT) hatte ich noch beschrieben, dass der Import nur mit IBM Systemdumps zurechtkommt. IBM hat jetzt nachgelegt und kann nun auch das Portable Heap Dump (PHD) Format verarbeiten.
Dabei gibt es aber Einschränkungen zu beachten. Dieses Format enthält zum Beispiel keine detaillierten Feld Inhalte und ohne Javacore Files fehlen Classloader Details.
ibm.com/developerworks/java/jdk/tools/mat.html
Das System Format sollte man bevorzugen, die Out of Memory Dumps werden aber normalerweise im PHD Format abgelegt, und diese können jetzt auch gelesen werden.
Dabei gibt es aber Einschränkungen zu beachten. Dieses Format enthält zum Beispiel keine detaillierten Feld Inhalte und ohne Javacore Files fehlen Classloader Details.
ibm.com/developerworks/java/jdk/tools/mat.html
Das System Format sollte man bevorzugen, die Out of Memory Dumps werden aber normalerweise im PHD Format abgelegt, und diese können jetzt auch gelesen werden.
Gleich zwei Termine zum Thema Java Concurrency stehen in der Region an:
Java User Group Karlsruhe - "The Secrets of Concurrency"
Mittwoch, 2009-02-11 19:15 Uhr
Dr Heinz Kabutz (PhD CompSci) Author des The Java(tm) Specialists' Newsletter
Ort: Uni Karlsruhe, ATIS, Am Fasanengarten 5, Geb. 50.34, 76131 Karlsruhe, Raum UG102
und
ObjektForum Stuttgart - Herausforderung Multikern-Systeme
Montag, 2009-02-16, 18.30 Uhr
Prof. Dr. Walter F. Tichy Universität Karlsruhe / FZI
Ort: Alte Scheuer, Degerloch
Java User Group Karlsruhe - "The Secrets of Concurrency"
Mittwoch, 2009-02-11 19:15 Uhr
Dr Heinz Kabutz (PhD CompSci) Author des The Java(tm) Specialists' Newsletter
Ort: Uni Karlsruhe, ATIS, Am Fasanengarten 5, Geb. 50.34, 76131 Karlsruhe, Raum UG102
und
ObjektForum Stuttgart - Herausforderung Multikern-Systeme
Montag, 2009-02-16, 18.30 Uhr
Prof. Dr. Walter F. Tichy Universität Karlsruhe / FZI
Ort: Alte Scheuer, Degerloch
Geschrieben von Bernd Eckenfels
in Hardware, Java Programming, Karlsruhe
| Kommentare (0)
| Trackbacks (0)
Ich bin auf der Suche nach (bezahlten) Experten im Bereich JbossMQ. Wir haben uns natürlich zuerst an RedHat gewannt mit unserer Anfrage. Die Annahme war, wir könnten uns eine Fragestunde mit einem der Entwickler kaufen (für eine spezifische 4.2 JBoss Version). Leider bietet RedHat diese Option nicht an. Deswegen haben wir uns sogar überlegt eine entsprechende Partnerschaft mit Support Vertrag abzuschliessen. Leider würde uns auch die nicht ermöglichen unsere bisherige Release Stratagie weiterzufahren, mal ganz abgesehen davon dass wir erheblichen Zusatzaufwand (Arbeit, Geld) für die Kundenlizensierung aufbringen müßten. Effektiv wäre dies ein embedded kommerzielles Produkt, was wir uns damit einhandeln würden.
Diese unflexiblen Haltung ist eine Enttäuschung für uns. Es sieht danach aus, dass RH sich für dieses Vorgehen entschieden hat aus der Angst mit bezahltem Support für Jboss.org sich das Geschäftsmodell für JBoss.com kaputt zu machen. Diese Strenge Trennung zwischen den Produkten und die Distanzierung von der Community war mir so bis dahin noch nicht bewusst geworden.
Aus dem Grund suche ich jetzt Entwickler (idealerweise Commiter) die sich mit JBossMQ auskennen (konkret geht es um das bekannte Problem dass MDBs sich aufhängen). Wir bezahlen nach Aufwand, bitte direkt Kontakt mit mir aufnehmen.
Diese unflexiblen Haltung ist eine Enttäuschung für uns. Es sieht danach aus, dass RH sich für dieses Vorgehen entschieden hat aus der Angst mit bezahltem Support für Jboss.org sich das Geschäftsmodell für JBoss.com kaputt zu machen. Diese Strenge Trennung zwischen den Produkten und die Distanzierung von der Community war mir so bis dahin noch nicht bewusst geworden.
Aus dem Grund suche ich jetzt Entwickler (idealerweise Commiter) die sich mit JBossMQ auskennen (konkret geht es um das bekannte Problem dass MDBs sich aufhängen). Wir bezahlen nach Aufwand, bitte direkt Kontakt mit mir aufnehmen.
Es ist immer wieder interessant die Analysen von Dan Dyer zu lesen. Er ist der Kopf hinter Java library uncommons-math, die insbesondere brauchbare Alternativen für Zufallszahlengeneratoren liefert.
int[] vals = new int[8];
for (int i = 0; i < 1500; i++)
vals[new Random(i).nextInt(8)]++;
System.out.println(Arrays.toString(vals));Dass dieser Code "falsch" ist weil er jeweils einen neuen PRNG erzeugt ist offensichtlich, warum es aber keinerlei vernünftig verteilte Zufallszahlen liefert (trotz den unterschiedlichen Seeds) ist eine ganz andere Sache, die er in seinem Artikel gut beschreibt.Unknown state 0. Please contact the creator of my caller ..impl.SHCInitiatorProcessor.init(SHCInitiatorProcessor.java:155) and tell her/him to please use some states that do not make me sad. This warning has no further impact.
Die IBM JVM unterscheidet sich in einigen Aspekten deutlich von der Sun JVM. Im Bereich Betrieb gibt es eine ganze Reihe von Features die im IBM Java Diagnostics Guide (5.0, 6.0) zusammengefasst sind. Einen Bereich - den Java Heapdump - möchte ich hier mal näher beleuchten:
Die IBM JVM kennt den klassischen Java Heap Dump, also einen Abzug der Java Objekte im Speicher. Diese Heap Dumps gibt es in verschiedenen Formaten. IBM unterstützt eine Textvariante und das sogenannten Portable Heap Dump Format, eingeschaltet mit -Xdump:heap. Problem ist, dass es nur von IBM Analysetools ausgewertet werden kann. Einer der besten freien Heap Dump Betrachtern ist das von der SAP gestiftete Projekt Eclipse MAT. Im Sun Umfeld sind diese Heap Dumps im HPROF Binary Format. Das Memory Analyser Tool kann deswegen Dumps von Sun, SAP und HP VM lesen. Gerade hat aber IBM ein Eclipse Pluging bereitgestellt, den IBM DTFJ Adapter. Dieses Plugin der den MAT um Import Möglichkeiten erweitert kann aber das PHD Format nicht verarbeiten.
Die Java spezifischen Heap Dumps haben ein Vorbild: die Speicherabzüge (Core Dumps) der Betriebsysteme. Core Files oder Dr.Watson Logfiles werden angelegt wenn eine Anwendung eine kritische Ausnahme verursacht (z.B. Zugriffsschutzfehler). Im Falle der IBM VM kann man solche Core Dumps aber ebenfalls für die Analyse von Java Heaps verwenden. Die von IBM genannten System Dumps werden mit der -Xdump:system option bei der VM eingeschaltet.
Wenn ein Core Dump stattfindet (entweder bei OutOfMemeoryErrors, bei Signalen, einem echten JVM Crash oder bei frei definierbaren Events) so wird dieser im System spezifischen Format in ein File geschrieben. IBM liefert ein Tool mit das sich jextract nennt (und im JRE Unterverzeichnis des SDK zu finden ist). Man muss dabei die jextract Version direkt aus dem verwendeten JRE nehmem (insbesondere auch auf dem Rechner auf dem der Coredump erzeugt wurde). Dies packt den aufbereiteten Core Dump zusammen mit systemspezifischen Details (z.B. Kopien der Symbole in den Libraries) in ein ZIP File.
Dieses bearbeitete ZIP File kann direkt in den MAT (mit IBM Update) importiert werden. Meiner Erfahrung nach klappt dies nur, wenn jextract keine Warnung oder Fehler gemeldet hat. Der Ansatz auf dem Produktivsystem den Dump vorzuverarbeiten finde ich ganz geschickt, denn nicht immer hat der Entwickler Zugriff auf ein System mit vergleichbarer Kapazität. Übrigens kann dieses ZIP auch von dem IBM Diagnose Tool Framework for Java verarbeitet werden, so kann man Analyseprogramme die den Heap durchsuchen auch direkt in Java schreiben und auf dem Produktivserver ausführen.
Die IBM JVM kennt den klassischen Java Heap Dump, also einen Abzug der Java Objekte im Speicher. Diese Heap Dumps gibt es in verschiedenen Formaten. IBM unterstützt eine Textvariante und das sogenannten Portable Heap Dump Format, eingeschaltet mit -Xdump:heap. Problem ist, dass es nur von IBM Analysetools ausgewertet werden kann. Einer der besten freien Heap Dump Betrachtern ist das von der SAP gestiftete Projekt Eclipse MAT. Im Sun Umfeld sind diese Heap Dumps im HPROF Binary Format. Das Memory Analyser Tool kann deswegen Dumps von Sun, SAP und HP VM lesen. Gerade hat aber IBM ein Eclipse Pluging bereitgestellt, den IBM DTFJ Adapter. Dieses Plugin der den MAT um Import Möglichkeiten erweitert kann aber das PHD Format nicht verarbeiten.
Die Java spezifischen Heap Dumps haben ein Vorbild: die Speicherabzüge (Core Dumps) der Betriebsysteme. Core Files oder Dr.Watson Logfiles werden angelegt wenn eine Anwendung eine kritische Ausnahme verursacht (z.B. Zugriffsschutzfehler). Im Falle der IBM VM kann man solche Core Dumps aber ebenfalls für die Analyse von Java Heaps verwenden. Die von IBM genannten System Dumps werden mit der -Xdump:system option bei der VM eingeschaltet.
Wenn ein Core Dump stattfindet (entweder bei OutOfMemeoryErrors, bei Signalen, einem echten JVM Crash oder bei frei definierbaren Events) so wird dieser im System spezifischen Format in ein File geschrieben. IBM liefert ein Tool mit das sich jextract nennt (und im JRE Unterverzeichnis des SDK zu finden ist). Man muss dabei die jextract Version direkt aus dem verwendeten JRE nehmem (insbesondere auch auf dem Rechner auf dem der Coredump erzeugt wurde). Dies packt den aufbereiteten Core Dump zusammen mit systemspezifischen Details (z.B. Kopien der Symbole in den Libraries) in ein ZIP File.
Dieses bearbeitete ZIP File kann direkt in den MAT (mit IBM Update) importiert werden. Meiner Erfahrung nach klappt dies nur, wenn jextract keine Warnung oder Fehler gemeldet hat. Der Ansatz auf dem Produktivsystem den Dump vorzuverarbeiten finde ich ganz geschickt, denn nicht immer hat der Entwickler Zugriff auf ein System mit vergleichbarer Kapazität. Übrigens kann dieses ZIP auch von dem IBM Diagnose Tool Framework for Java verarbeitet werden, so kann man Analyseprogramme die den Heap durchsuchen auch direkt in Java schreiben und auf dem Produktivserver ausführen.
Immer mal wieder erreichen mich seltsame Blindbewerbungen. Ab und zu frage ich sogar nach, woher denn die Annahme stammt, ich würde Stellen anbieten. Bisher habe ich noch nie eine Reaktion erhalten. Deswegen nehme ich mir die Freiheit das Anschreiben einer solchen Blindbewerbung hier zur Unterhaltung wiederzugeben. Zum besseren Verständnis habe ich meine Gedanken eingefügt :)
Sehr geehrte Damen und Herren,
ich bewerbe mich bei Ihnen als Java/J2EE-Entwickler. Nach jahrelangem Studium [ohne Abschluss] mit Schwerpunkten Künstliche Intelligenz und Computergrafik und mit breit angelegter Informatik-Bildung, habe ich mich entschieden, meinen Schwerpunkt einer angehenden Arbeitstätigkeit im Java-Umfeld zu suchen.
Ich bin qualifiziert, die von Ihnen [nicht] angebotene Tätigkeit auszuüben, da ich bereits während meines Studiums Erfahrungen mit der Konzeptionierung und Realisierung von Software-Projekten, in Gruppen mit jeweils mehreren Personen [Ah, da hat doch Tatsächlich jemand die Seminare und Übungen besucht] gemacht habe. [Ich habe sonst keinerlei Praxiserfahrung]
Während des Studiums habe ich immer wieder mit Java programmiert, zumeist Applets [entsprechend Umfanreich waren diese Gruppenprojekte]. Bis vor kurzem befand ich mich in einer Java-Weiterbildungsmaßnahme [denn ich muss trotz Studium mich vom Arbeitsamt aushalten lassen], um die ich mich selbst seit langem bemüht habe [in der Zeit hätte ich sonst arbeiten müssen], da zum einen in Stellenangeboten frequentiert nach Java-Programmierern nachgefragt wurde, andererseits Java eine mir leicht zur Hand gehende Programmiersprache in Erinnerung geblieben war. [Ist zwar schon Jahre her, aber wenn es sonst keine Jobs gibt...]
Ich freue mich, wenn Sie mich zu einem Vorstellungsgespräch einladen würden. Für Rückfragen - auch per E-Mail - stehe ich Ihnen gern auch kurzfristig zur Verfügung.
Mit freundlichen Grüßen
Name der Redaktion bekannt
Ich hatte ja schon öfters darüber geschrieben, dass Microsoft für die kommenden Generationen des Visual Studios und letztendlich auch für die Entwicklung auf dem .NET Stack die modellgetriebene Software Entwicklung verstärken möchte.
Dabei setzen sie auf textuelle und grafische DSL, und ein intelligentes Repository das beide verknüpft. Bei Martin Fowler (Bliki) gibt es einen Artikel (engl.), der den aktuellen Umfang von Projekt Oslo gut beschreibt.
Dabei setzen sie auf textuelle und grafische DSL, und ein intelligentes Repository das beide verknüpft. Bei Martin Fowler (Bliki) gibt es einen Artikel (engl.), der den aktuellen Umfang von Projekt Oslo gut beschreibt.
(Seite 1 von 9, insgesamt 82 Einträge)
nächste Seite »
Layout by Ricky Wilson | Serendipity Template by Carl Galloway | Login
Impressum
Bernd Eckenfels
Mörscher Str. 8
76185 Karlsruhe
bernd-10@eckenfels.net
Read More
Suche
Kategorien
Umfrage
Wirtschaftskrise
Archive
Archive
Blog abonnieren
Blogsphere
Top Referers
www.google.de (50)
www.google.es (32)
www.netvibes.com (15)
<a href='http (7)
www.google.at (5)
autocassanga.ciab.0lx.net (3)
fiatritmo.hospa.0lx.net (3)
www.raypharma.com (3)
blogs.technet.com (2)
www.google.com (2)
www.google.es (32)
www.netvibes.com (15)
<a href='http (7)
www.google.at (5)
autocassanga.ciab.0lx.net (3)
fiatritmo.hospa.0lx.net (3)
www.raypharma.com (3)
blogs.technet.com (2)
www.google.com (2)
Top Exits
www.golem.de (56)
www.heise.de (40)
www.oasis-open.org (34)
www.mela.de (30)
www.microsoft.com (25)
netzpolitik.org (24)
twitter.com (23)
www.oracle.com (23)
itblog.eckenfels.net (21)
aws.amazon.com (18)
www.heise.de (40)
www.oasis-open.org (34)
www.mela.de (30)
www.microsoft.com (25)
netzpolitik.org (24)
twitter.com (23)
www.oracle.com (23)
itblog.eckenfels.net (21)
aws.amazon.com (18)

Kommentare