540 likes | 790 Views
Spring.NET Einführung und Überblick. 22. April 2008 Gerhard Schlemm. E-Mail: gerhard.schlemm@comma-soft.com Website: http://www.comma-soft.com XING: https://www.xing.com/profile/Gerhard_Schlemm. Agenda. Spring.NET Überblick über das Framework Anwendungskonfiguration mit dem Spring.NET
E N D
Spring.NETEinführung und Überblick 22. April 2008 Gerhard Schlemm E-Mail:gerhard.schlemm@comma-soft.com Website:http://www.comma-soft.com XING:https://www.xing.com/profile/Gerhard_Schlemm
Agenda • Spring.NET • Überblick über das Framework • Anwendungskonfiguration mit dem Spring.NET • Theorie • Praxis (Demo) Zum Thema "Aspect Orientated Programming"(AOP) mit Spring.NET wird es einen weiterenVortrag geben!
Was ist Spring.NET? • In einem Satz: • "Spring.NET is an application framework that provides comprehensive infrastructural support for developing enterprise .NET applications." • Also eines von vielen Frameworks mitden üblichen Zielen: • Entwicklung und Administration vereinfachen • Testbarkeit fördern und unterstützen • Konsistenz • etc.
"Core Value Propositions" • Wo kann man mit Spring.NET besonders profitieren? • Anwendungskonfiguration mit Spring.NET • Zusammensteckung einer Anwendung aus normalen .NET-Objekten (Plain Objects – POs) zur Laufzeit (IoC-Container) • "Aspect Orientated Programming" (AOP) • Paradigma, das anstrebt, bestimmte Aspekte einer Anwendung getrennt von der Kernfunktionalität zu entwickeln und diese später zur Gesamtanwendung zusammenzuführen.
Historie und Status • Historie: Spring ist ein Framework aus der J2EE-Welt(begonnen 2003) und in der Praxis stark erprobt • "Philosophische" Portierung auf .NET begonnen 2004 • Aktuelle Version: Spring.NET 1.1.1 (April 2008)für .NET Framework 1.0, 1.1 und 2.0 • Open Source unter Apache License 2.0 • Interface21 ist die Firma hinter Spring(.Java und .NET),die auch Support und Education kommerziell anbietet
Framework-Philosophie (I) • Die Module von Spring.NET ... • sind in der Regel den üblichen Tiers und funktionalen Schichten der Anwendung zugeordnet • Data Access Layer, Business Object Layer, Presentation Layer, Service Layer, etc. • können aber auch einzeln eingesetzt werden • Zahlreiche Hilfsmodule laden dazu ein, auch ohne Verwendung der Spring.NET- Kernfunktionalität eingesetzt werden zu können
Framework-Philosophie (II) • Zu bestehenden .NET Technologien • Abstraktionen einführen • Komfortfunktionen ergänzen • aufgespürte Lücken füllen • Zusätzlich ermöglichen, daß .NET-Konzeptemit den Spring.NET-Kernfunktionalitäten harmonieren und von ihnen profitieren.
Module - Spring.NET Core • Zentral: "Inversion of Control"-Container • Nimmt der Anwendung die Aufgabe des Erzeugens, der Konfiguration und der Verdrahtung kollaborierender Komponenten (POs) ab • Unabhängige Hilfsmodule für den Container • Abstraktion des Zugriffs auf Ressourcen, • Expression Evaluation etc. • Zentral: "Aspect Orientated Programming" (AOP)
"Inversion of Control" (I) • Zitat aus GoF-Buch (1995) zurAbgrenzung zwischen Toolkit und Framework • "When you use a toolkit, you write the main body of the application and call the code you want to reuse. When you use a framework, you reuse the main body and write the code it calls."
"Inversion of Control" (II) • Beispiel: Der Eingabe eines Werts soll eineBerechnung folgen, dann Ausgabe • Toolkit: Schreibe Code zur Werteingabe und anschließender Durchführung der Berechnung • Framework: Schreibe Code, der ein Formular zusammenstellt+Code zur Durchführung der Berechnung.Dann wird der Kontrollfluß an Formular bzw. Framework übergeben, und dieses ruft die Berechnung auf. • Aus diesem Kontext stammt der Begriff"Inversion of (Flow) Control" (IoC)
"Inversion of Control" (III) Toolbox Framework X main body main body E B A E B A
"Inversion of Control" (IV) • Beispiel: NUnit (und Verwandte) • Methoden werden als [SetUp], [TearDown], [Test] annotiert • Der Kontrollfluß wird durch das NUnit-Framework gesteuert • Verallgemeinerung:"Don't call us, we call you"
IoC bezüglich Dependencies (I) • IoC wird häufig stark verallgemeinert und somit unspezifisch verwendet • Unser Szenario (Anwendungskonfiguration): • POs erbringen lose gekoppelt gemeinsam eine Funktion • Hierzu existieren notwendige Abhängigkeiten (Dependencies) zwischen diesen POs • Das Auflösen dieser Abhängigkeiten wird der Kontrolle der POs entzogen (IoC – "Don't call us, we call you")
IoC bezüglich Dependencies (II) • Dependency Injection (DI) • POs werden transparent mit allen notwendigen Dependencies versehen • POs haben kein Wissen (keine Abhängigkeit) zu der externen Komponente die Dependencies auflöst • Diese Komponente wird als Container bezeichnet • mehr zum Container später • DI führt idealerweise zu • einer losen Kopplung der POs • und zu besserer Testbarkeit
IoC bezüglich Dependencies (III) • Dependency Lookup • Andere Namen: Service Locator, Registry • Unklare Definition: • selten DI zugeordnet, meistens nicht • häufig als Spielart von IoC aufgefaßt • Wesentlicher Unterschied zu Dependency Injection:Dependency Lookup beinhaltet Abhängigkeit der POszur einer Form von Registry • Beachte: Die Implementierung und Mächtigkeit einer solchen Registry kann aber der eines IoC-Containerssehr ähnlich sein
IoC-Container (I) • IoC-Container • Externe, generische Factory-Implementierung • Instantiierung und Konfiguration der POs • Auflösen der Abhängigkeiten zwischen POs • Konfiguration dieser generischen Factoryerfolgt deklarativ in Form einer Konfigurationsdatei • Änderung der Konfiguration erfordert keine Neukompilierung
IoC-Container (II) • IoC-Container • Ist ein guter Punkt, um weitere Infrastruktur-Funktionalität aufzuhängen • Beispiel: AOP-InfrastrukturDa der Container verantwortlich für die Instantiierung von Objekten ist, kann er auch dafür sorgen, daß die Aspekte indie POs eingemischt werden • Der Kern von Spring.NET ist ein solcher IoC-Container
IoC-Container – klassische Factory • Vergleich • Klassische, nicht-generische (Abstract) Factory • fester Fundus von Produkten (der Factory) und Implementierungen im Code • IoC-Container als generische Factory • flexibler Fundus von Produkten und Implementierung, festgelegt durch Konfigurationsdatei
IoC-Container • Argumente für den Einsatz eines IoC-Container • (Re-)Konfiguration ohne Neukompilieren • dadurch einfachere Anpaßbarkeit(z.B. Austausch von Implementierungen)und Erweiterbarkeit • Von eingebauten Patterns profitieren (Singleton) • Komfort-Funktionen wie automatische Injektion von Dependencies "by name" oder "by type" • Stichwort autowire (s.u.) • Aufwand von eigenen, oftmals redundante Factory-Implementierungen vermeiden
IoC-Container – klassische Factory • Argumente für den Einsatz eines IoC-Container • Testbarkeit durch DI • Besonders wichtig: im Container als zentralem Punkt der Objekterzeugung aufgehängte Zusatzfunktionen • Lifecycle-Management • Object Pooling • Infrastruktur für "Aspect Orientated Programming" • etc.
IoC-Container – Silver Bullet? • Vorsicht! • Der Container-Ansatz ist nicht pauschal der bessere • In vielen Fällen reicht eine klassische Factory aus • Priorität liegt nicht immer auf Wiederverwendbarkeit und Erweiterbarkeit! • Der Container wird auch das "new" im Codenicht ersetzen • POs werden stets mit Hilfsobjekten arbeiten, für die es keine Notwendigkeit gibt, daß der Container sie erzeugt und injiziert oder überhaupt kennt!
IoC-Container – Silver Bullet? • Vorsicht! • Wenn man sich für einen Container entscheidet:sehr genau überlegen müssen, welche POs man dem Container "überläßt" und welche nicht • "Sollbruchstellen" der Anwendung • an denen Austauschbarkeit der Implementierungvorhersehbar ist • an denen zum Testen Mocks eingeklinkt werdensollen
Container Gewichtsklassen • Schwergewichtige Container • Schwergewichtige Container verfolgen einenholistischen Ansatz • J2EE-Container muß in der Lage sein, mit Servlets, EJBs, JMS, JTA, ... umzugehen, damit er sich so nennen darf • Auch der COM+-Container verfügt über sehr viel Funktionalität (siehe auch Enterprise Services)
Container Gewichtsklassen • Leichtgewichtige Container • Fokussiert auf bestimmte Funktionalität -> "leicht" • Gilt als der moderne Ansatz! • Beispiele: Spring.NET und viele andere (s.u.) • Bei Spring.NET gibt es aber die Tendenz, mehr und mehr Funktionalität anzubieten • In welche Rubrik fällt die .NET CLR ;-)?
Demo Szenario • MVP-Pattern: Die kollaborierenden Komponenten sind Model, View und Presenter • Die MVP-Komponenten enthalten keine Abhängigkeiten von Spring.NET: POs • Anwendung verwendet MVP-Komponenten • Model, View und Controller werden mit Spring.NET erzeugt, konfiguriert und verbunden • Anwendung hat Abhängigkeit zu Spring.NET
Demo Model-View-Presenter
"Quickstart" – Rückblick • Wir haben ... • Mit Hilfe einer XML-Konfigurationsdatei unsere Spring.NET-ObjectFactory für die "Produkte" Model, View und Presenter konfiguriert • Festgelegt, wie diese drei Produkte miteinander zu verdrahten sind, hier zwei Initialisierungsvarianten • "Setter Injection" – Properties belegen • "Constructor Injection" – Konstruktor mit Argumenten aufrufen • Eine einfache Main-Methode geschrieben,die mit Hilfe der Spring.NET ObjectFactory dieMVP-getriebene GUI startet
Creational Patterns • Wie oft erzeugen? • Singleton (default, singleton="true") oder • Prototype (singleton="false"); • Wie erzeugen? • Direkt über seinen Konstruktor • Über das FactoryMethod-Pattern • Rückgabewert statische Methode (factory-method="...") • Durch ein anderes Factory-Objekt • Rückgabewert Funktionsaufruf (factory-method="...") der Factory (factory-object="...")
Demo: Creational Patterns
Typkonvertierung • POs werden nicht nur mit Referenzen auf andere Spring.NET-kontrollierte POs initialisiert • Die Spring.NET ObjectFactory kennt zur Laufzeit • den value-String in der XML-Datei • den Typ der Property / des Konstruktorarguments • Mechanismus zur Konvertierung des Stringsdurch TypeConverter • Spring.NET baut auf die .NET-Mechanismen auf und bringt weitere TypeConverter mit • Eigene TypeConverter können ergänzt werden
Aufzählungstypen • Auch Aufzählungstypen können zurconstructor injection und setter injectionverwendet werden: • <list>... • <set>... • <dictionary>... • <name-values>...
Demo: TypeConverter
Lifecycle-Methoden • <object ... init-method="..."> • Initialisierung des Objekts programmatisch abschließen • Methodenwahl ohne Neukompilieren änderbar • Nach Erzeugung und Zuweisen der Properties aufgerufen • <object ... destroy-method="..."> • Spring.NET ObjectFactory implementiert IDisposable • Für die POs im Container wird IDisposable. Dispose aufgerufen, wenn implementiert • Daraufhin wird die per Anwendungskonfiguration festgelegte destroy-method aufgerufen • Auch für Objekte, die nicht IDisposable implementieren
Erzeugungsstrategie (I) • Default: Erzeugen aller deklarierten Objektebeim Erzeugen der Spring.NET Object Factory • Ausnahme: Nicht-Singletons (Prototype, s.o.) • Vorteil: Viele Fehler in der Konfigurationwerden sofort erkannt • fehlende Objekte, Konstruktoren, Typen, Properties • unzutreffende Konstruktor/Property – Signaturen • zyklische Abhängigkeiten • Nachteil: lange Startup-Zeit der Anwendung
Erzeugungsstrategie (II) • Feinsteuerung möglich • Default für alle Objekte <objects ... default-lazy-init="true|false"> • Pro Objekt<object ... lazy-init="true|false"> • Vermutung: Sehr genau darüber nachdenken, wann man welche Strategie benötigt • In welchem Teil der Anwendung • In welcher Phase (Entwicklung/Test/Produktiv)
Komfortfunktionen • autowire-Funktion • Abhängige Objekte automatisch nach Name oder Typermitteln (für Properties und Konstruktoren) • Mit Vorsicht einzusetzen – kleine Änderungen habensonst massive, unerwartete Auswirkungen • Konfigurationsvererbung • unabhängig von PO-Vererbungshierarchie können auch Konfigurationshierarchien gebildet werden • Dann werden mehrere <object ...>-Konfigurationen nacheinander auf demselben PO angewandt • analog zu Konstruktoren in einer Vererbungshierarchie
Weitere Konfigurationsvarianten • Zuweisungen (setter/constructor) mit ... • bisher gesehen: Referenzen auf Objekte im Container und "Werten" ( -> TypeConverter) • zusätzlich stehen bei der Initialisierung zur Verfügung • Ergebnis eines Methodenaufrufes auf Objekte, • Field- oder Property-Wert eines Objekts, • Warum gibt es so viele Varianten? • Der Container hat den Anspruch, auch ältere POs, die nicht geändert werden können/sollen, deklarativ verdrahten zu können! • Vermutlich klappt es nicht immer
Demo: Property-Wert injizieren
Dependency Lookup • Objekte können im Code Funktionen des Containers nutzen (container-aware) • Z.B. zur Laufzeit den Container auffordern, ein Objekt "by name" zu instantiieren • Beispiel: Order-Klasse muß zur Laufzeit mehrere Instanzen von OrderItem erzeugen (auch DI einer Factory lösbar) • Dann sind die Objekte jedoch vom Container abhängig • Die Zusammenstellungs-Anwendung selbst wird stets von Spring.NET abhängig sein • siehe 04_Anwendung.csproj im Beispielcode
Framework-Philosophie • Zu bestehenden .NET Technologien • Abstraktionen einführen • Komfortfunktionen ergänzen • aufgespürte Lücken füllen • Zusätzlich ermöglichen, daß .NET-Konzeptemit den Spring.NET-Kernfunktionalitäten harmonieren und von ihnen profitieren.
Weitere Module (I) • Module der "Middle Tier" • Transaktionen • Vereinheitlichtes Programmiermodell über Transaktionen • Deklaratives Transaktionsmanagement • Data Access Object (DAO) • Vereinheitlichte Exceptions • Konsistente Verwendung von ADO.NET / NHibernatedurch geeignete Basisklassen für DAOs • ADO.NET Komfort-Funktionen • Factory für DbProvider • etc. • ORM – NHibernate-Integration
Weitere Module (II) • Services • Ziel: Ein PO ohne spezielle Basisklasseim verteilten Szenario nutzbar machenund dabei DI und AOP ermöglichen • Ein PO kann exportiert werden als • .NET Remoting • .NET Enterprise Services • Web Services • [WCF-Integration in Planung]
Weitere Module (III) • Web • IoC-Kontext automatisch und Page-lebenszyklusübergreifend bereitstellen • DI für ASP.NET-Seiten • jedem <object ...> kann ein Scope (Request, Session, Application zugeordnet werden) • Bidirektionales DataBinding • Einige kleinere Erweiterungen / Features • AJAX Extensions • POs konfigurieren, mit AOP anreichern und als Web-Service exportieren (keine Basisklasse/Attribute notwendig) • z.B. für den Client-seiten Zugriff aus JavaScript
Kritische Betrachtungen (I) • Generell zur deklarativen Anwendungskonfiguration und Instantiierung zur Laufzeit: • Den "sicheren Hafen" der vom Compilersichergestellten Typsicherheit verlassen • Fehler zur Laufzeit • Übersichtlichkeit der Konfiguration problematisch • Spring.NET • Qualität der Fehlermeldungen nur befriedigend • API-Design: .NET 2.0 Generics werden zwar unterstützt, aber man merkt, daß das Framework für .NET 1.1 entwickelt wurde
Kritische Betrachtungen (II) • Fehlende IDE-Unterstützung in Visual Studio • Derzeit nur XML-Schema • Inhaltliche Validierung der Anwendungsdefinition fehlt • Wunschliste: spezielles Intellisense, Goto Definition, Unterstützung bei Refactoring / Rename, ... • Objektgraphen visualisieren • Eclipse für Spring(.Java) bietet hier mehr! • OpenSource Spring.NET IDE für SharpDevelop und Visual Studio wurde 2008 ins Leben gerufen
Zusammenfassung • Spring.NET ist ein leichtgewichtiges Frameworkfur Enterprise Application Development • IoC-Container • Generische Factory mit deklarative Konfiguration,Auswertung zur Laufzeit • Dependency Injection • Infrastruktur für "Aspect Orientated Programming" • Code für Aspekte seperate von der Kernfunktionalität der POs entwickeln und sie bei der Erzeugung einmischen • Weitere Module für verschiedene Tiers / funktionale Layers
Andere IoC-Container für .NET • Castle Windsor (altbewährt) • http://www.castleproject.org/container/index.html • Microsoft Patterns & Practises:Unity Application Block (nun Beta) • http://codeplex.com/unity • AutoFac (C#3.0/.NET 3.5) • http://code.google.com/p/autofac/ • Weitere siehe Auflistung bei Scott Hanselman • http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx
Links • MSDN-Artikel zu DI • http://msdn2.microsoft.com/en-us/magazine/cc163739(printer).aspx • Artikel zu IoC/Di von Martin Fowler • http://martinfowler.com/articles/injection.html • http://martinfowler.com/bliki/InversionOfControl.html • Spring.NET Download + Doku + Material • http://www.springframework.net/ • Artikel "DI with Spring.NET" (David Consdorf) • http://www.developer.com/net/csharp/article.php/10918_3722931_1 • Übersicht .NET Ioc-Container von Scott Hanselman • http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx