Saturday, June 9, 2007

Model-View-Presenter (MVP) und seine Geschmacksrichtungen

Neulich hat Jeremy D. Miller in seinem Blog die verschiedenen Ausprägungen des Model-View-Presenter Patterns erörtert. Hier ein kurze Zusammenfassung dessen was mir wichtig erscheint:

Dem MVP liegen im allgemeinen folgende Definitionen zu Grunde:
  • Model ist eine Abbildung dessen was dargestellt wird.
  • View ist die Darstellung.
  • Presenter bringt das Model auf der View zur Darstellung und aktualisiert das Model aufgrund von Benutzereingaben.

The Autonomous View

Das 'Anti-Pattern'. Model-View-Presenter sind in einer Klasse vereint.

Supervising Controller
  • Presenter: Übergibt das Model (oder Teile davon) der View zur Darstellung. Der Presenter wird von der View aufgerufen um auf Benutzereingaben zu reagieren.
  • View: bringt das vom Presenter an die View übergebenen Model zur Darstellung (z.B mit Databinding). Leitet Benutzereingaben an den Presenter weiter.

Die View ist somit direkt vom Modell abhängig.

Passive View
  • Presenter: Kapselt das Model gegenüber der View. Übernimmt das Databinding indem die dargestellten Werte (nicht das Model) explizit der View zur Darstellung übergeben werden. Der Presenter wird von der View aufgerufen um auf Benutzereingaben zu reagieren.
  • View: Stellt die vom Presenter übermittelten Werte dar und leitet Benutzereingaben an den Presenter weiter.

Gegenüber dem Supervising Controller Pattern hängt die View hier nicht vom Modell ab.

Presentation Model
  • Presentation Model: Das Model und der Presenter sind hier zusammengeführt. Das Presentation Model zeigt gegenüber der View die darzustellenden Werte und reagiert falls ein solcher Wert verändert wird. Das Presentation Model wird von der View aufgerufen um auf Benutzereingaben zu reagieren.
  • View: Bindet das Presentation Model direkt für die Darstellung.

Für die Kommunikation zwischen View und Presenter gibt es bei allen Pattern zwei Möglichkeiten:

  1. Direkt: Die View ruft den Presenter direkt und explizit via Methoden auf (z.B im Eventhandler in der View).
  2. Indirekt: Der Presenter abonniert Events welche die View zur Verfügung stellt.

Zur Zeit verwende ich meistens das Passiv View Pattern um eine höchstmögliche Testabdeckung in den Unittests zu erreichen.

Thursday, June 7, 2007

LinqToSql vs. NHibernate

Im folgenden vergleiche ich 'LINQ to SQL' mit NHibernate und Stelle die Unterschiede und Gemeinsamkeiten dieser beiden O/R-Mapper dar.

Sessions
Was in 'LINQ to SQL' der DataContext ist in NHibernate die Session. Beide Implementationen realisieren UnitOfWork und IdentityMap was uns ein sicheres und bequemes Arbeiten mit einem DomainModel ermöglicht.


Transaktionen und Locking
Da beide O/R-Mapper UnitOfWork implementieren, unterstützen uns beide auf ähnliche Weise beim optimistischen Locking. Beide O/R-Mapper halten den für das optimistische Locking nötigen Ursprungszustand der Objekte intern, also im DataContext oder in der Session.

Für das pessimistische Locking ermöglichen beide O/R-Mapper den Zugriff auf die Transaktion auf welcher der Transaktionsbeginn und -ende, sowie der Isolationslevel gesteuert werden kann.


Persistence Ignorance (PI)
Nur NHibernate ermöglicht das Persistieren von beliebigen Objekten. Bei 'LINQ to SQL' (in Orcas Beta1) muss INotifyPropertyChanging und INotifyPropertyChanged implementiert werden. In 'LINQ to SQL' kann wahlweise die Mapping-Information auf der Klasse als Attribute oder in einem externen XML abgelegt werden.

Eliminierung O/R Impedance-Mismatch
Hier zeigt sicher der größte Unterschied zwischen den beiden O/R-Mappern. Folgende nicht abgeschlossene Liste zeigt Features welche NHibernate unterstützt, 'LINQ to SQL' aber nicht:

  1. Abfragen berücksichtigen unpersistierte Änderungen
  2. Unterstützung mehrerer Abbildungsarten für die Vererbung ( table-per-class / table-per-subclasss / table-per-concrete-class )
  3. Mapping von n-m Beziehung

Da 'LINQ to SQL' den Punkt 1. nicht unterstützt müsste zum Beispiel mit Aggregates (Eric Evans: Domain Driven Design) gearbeitet werden. Diese würden die unpersistierten Änderungen in ihrem Aggregate berücksichtigen und verwalten.

Abfragesprache
'LINQ to SQL' ist mit der Abfragesprache LINQ zur Zeit hier im Vorteil. Eine LINQ-Implementation für NHibernate ist aber in Bearbeitung und danach wird es unter diesem Punkte keine nennenswerte Unterschiede geben.


Wartung
Hier sehe ich keine grossen Unterschiede, da das Warten der Mapping-Informationen immer eine mühsame Angelegenheit ist. Mit dem 'LINQ to SQL' -Designer (Beta1) kann sehr schnell eine erste Version eines Mapping-Schemas erstellen werden. Die Wartung und Pflege des Schemas erfolgt danach aber manuell.

Falls jemand schon praktische Erfahrungen in einem grösseren Projekt mit 'LINQ to SQL' hat, würde ich mich über einen Erfahrungsbericht sehr freuen.

So nun muss ich mir noch LINQ To Entities anschauen!