Architektonische Überlegungen für die Entwicklung eines Tippspiels

Der Ball ist rund

Thilo Frotscher

Die Fußball-Europameisterschaft steht vor der Tür und Millionen deutscher Nationaltrainer diskutieren, wie hoch der Sieg gegen Holland wohl ausfallen wird. Weil da jeder so seine eigene Meinung hat und man vorher eben nie genau weiß, wie’s am Ende ausgeht, sind Tippspiele so ungemein beliebt. Höchste Zeit also, endlich mal eines zu programmieren – ganz nebenbei kann man dabei eine Menge über J2EE und Patterns lernen.

Wer selbst schon einmal ein Tippspiel gestartet hat, kennt das Problem nur zu gut: Viele Teilnehmer wollen Ihre Tipps erst im letzten Moment vor einem Spieltag abgeben – es könnte ja sein, dass sich ein wichtiger Spieler noch kurz vorher verletzt. Also klingelt das Telefon des Tippspielverwalters kurz vor dem Anpfiff ununterbrochen, obwohl dieser es sich doch eigentlich schon mit Popcorn und Apfelschorle vor dem Fernseher bequem gemacht hat. Kaum ist ein Spieltag dann zu Ende, müssen die Punktzahlen der Teilnehmer ausgerechnet werden. Bei einer großen Tippgemeinschaft kann es dabei schon mal vorkommen, dass sich der Tippspielverwalter im Zahlendschungel verirrt und verrechnet. Und dann der ganze Zettelwust nein, im Zeitalter allgegenwärtiger IT muss da eine andere Lösung her.

Natürlich könnte man ein Excel-Sheet einsetzen. Dies würde Abhilfe beim Ausrechnen der Punktestände schaffen und die Zettelwirtschaft wäre auch nicht mehr notwendig, aber der Tippspielverwalter müsste weiterhin die Tipps per Telefon annehmen und kurzfristige Tippänderungen und Punktestandabfragen beantworten. Außerdem ist die Erstellung der Formeln für ein komplett automatisch auswertendes Excel-Sheet nicht unbedingt trivial. Viel besser wäre dagegen eine Webanwendung. Sie müsste so beschaffen sein, dass Mitspieler ihre Tipps bis kurz vor Anpfiff bequem mithilfe ihres Browsers eingeben oder ändern können und dass der aktuelle Punktestand jederzeit eingesehen werden kann. Die Arbeit des Tippspielverwalters beschränkt sich somit nur noch darauf, die Tippgemeinschaft und alle Mitspieler initial anzulegen, die Ergebnisse der einzelnen Spiele einzugeben und gegebenenfalls dafür zu sorgen, dass die Anwendung stabil läuft.

In einer kleinen Artikelreihe soll anhand dieses anschaulichen Beispiels erläutert werden, wie eine solche Tippspiel-Anwendung mit J2EE implementiert werden kann. Es soll dabei nicht in allen Fällen der hundertprozentig beste oder perfekte Lösungsansatz gewählt werden, sondern manchmal auch einfach der pragmatischste oder derjenige, der das beste Verhältnis zwischen Aufwand und Nutzen vorweist. Ganz so, wie in einem richtigen Projekt eben. Auf der anderen Seite sollen Features aufgenommen werden, die vielleicht gar nicht so wichtig erscheinen, aber unbedingt in der Webanwendung enthalten sein müssen, weil ein Entscheider diese Funktionalität gern haben möchte. Auch dieses Phänomen ist Entwicklern aus vielen Projekten bestens bekannt. So soll die Tippspiel-Anwendung neben einer interaktiven, browserbasierten Schnittstelle auch eine Web Service-Schnittstelle besitzen, die es zum Beispiel ermöglicht, beliebigen anderen Tippspiel-Anwendungen die eigene Geschäftslogik zur Verfügung zu stellen. Diese könnten sich dann darauf beschränken, eine eigene Benutzungsoberfläche zu entwickeln – unter Umständen etwa eine für .NET. Weiterhin soll die Webanwendung so offen gestaltet werden, dass sie später einmal dahingehend erweitert werden kann, Tippspiele für beliebige Sportwettbewerbe durchzuführen. Denn die WM 2006 ist nicht mehr fern und vielleicht möchte ja auch jemand ein Tippspiel für die Basketball-Bundesliga oder seine wöchentliche Kegelrunde einführen. Hierzu muss eine Möglichkeit geschaffen werden, mit der ein Tippspielverwalter gegebenenfalls zu allererst den Spielplan eines neuen Sportwettbewerbs eingeben kann.

Zunächst ist aber nur eine Implementierung für die Fußball-EM in diesem Jahr vorgesehen. Jedermann soll sich anmelden und eine Tippgemeinschaft gründen können. Der Gründer einer solchen Tippgemeinschaft ist dann der Tippspielverwalter für diese Gemeinschaft. Nachdem eine Tippgemeinschaft eingerichtet ist, kann der Tippspielverwalter zusätzliche Mitspieler anlegen und bestimmen, ob alle Spiele der EM getippt werden sollen oder nur eine Teilmenge. Jeder eingerichtete Mitspieler hat anschließend die Möglichkeit, für die vom Tippspielverwalter ausgewählten Spiele seinen Tipp abzugeben. Er kann sich jedoch mit der Abgabe seines Tipps auch bis kurz vor Beginn eines Spiels Zeit lassen, wenn er verhindern möchte, dass sich andere Mitspieler nach seinem Tipp richten, oder wenn er – wie eingangs erwähnt – abwarten möchte, ob sich nicht noch kurzfristig jemand verletzt. Ebenso ist es möglich, einen abgegebenen Tipp nachträglich zu ändern. Erst wenn die Anstoßzeit eines Spiels erreicht ist, können keine Änderungen am Tipp mehr vorgenommen werden. Für jedes genau richtig getippte Ergebnis erhält ein Mitspieler drei Punkte. Stimmt immerhin die Tordifferenz, werden zwei Punkte vergeben. Hat der Mitspieler dagegen nur auf den richtigen Sieger oder richtigerweise auf ein Unentschieden getippt, so erhält er einen Punkt. Gewonnen hat am Ende – klar – der Mitspieler mit den meisten Punkten.

Welche Use Cases werden für die Webanwendung benötigt? Es können zwei verschiedene Akteure identifiziert werden: Tippspielverwalter und Mitspieler. Der Tippspielverwalter muss Tippgemeinschaften verwalten (anlegen, löschen), Mitspieler verwalten (anlegen, löschen), Spielergebnisse des Wettbewerbs eingeben, sowie Wettbewerbe und Spielpläne verwalten (optional). Ein Mitspieler möchte Tipps eingeben oder editieren, den aktuellen Punktestand des Tippspiels einsehen sowie die Spielergebnisse des Wettbewerbs betrachten. Beide müssen sich grundsätzlich zuvor anmelden. Abpictureung 1 veranschaulicht diese Use Cases.

Abb. 1: Use-Cases für die Tippspiel-Web-Anwendung

Mithilfe der Use Cases lassen sich relativ einfach die Entitäten für ein Entity Relationship-Diagramm identifizieren. Abpictureung 2 zeigt einen ersten Entwurf. Dabei ist zu beachten, dass bereits eine Tabelle Wettbewerb eingefügt wurde, um eine spätere Erweiterung der Tippspiel-Anwendung auf beliebige Wettbewerbe zu erleichtern. Wie und wo der Spielplan eines Wettbewerbs abgelegt wird, soll erst später erörtert werden, wenn es daran geht, die Business-Logik der Anwendung im Detail zu durchdenken. Möglicherweise wird dann eine Erweiterung des ER-Diagramms notwendig. Weiterhin ist besonders darauf hinzuweisen, dass die Tabelle Spiel eine Spalte für Datum und Anstoßzeit enthält. Mithilfe dieser Information kann später Mitspielern die Änderung ihrer Tipps bis kurz vor Anstoß ermöglicht werden.

Abb. 2: Entity Relationship-Diagramm für das Tippspiel

Bei der Planung der Anwendungsarchitektur besteht eine wichtige Aufgabe darin, eine sinnvolle Lösung zur Unterstützung der beiden geplanten Schnittstellen (HTML-basiert und Web Services) zu finden. Da beide Schnittstellen letztlich dazu dienen sollen, die gleiche Geschäftslogik aufzurufen, muss diese auf einem einheitlichen Weg zugänglich sein und darf keine Abhängigkeiten zu einer der beiden Technologien besitzen, wenn redundante Entwicklung und unschönes Stückwerk verhindert werden sollen. So darf die Geschäftslogik beispielsweise nicht die Übergabe einer SOAP-Nachricht erfordern oder gar einen SOAP Fault erzeugen, da die browserbasierte Schnittstelle diese nicht liefern bzw. nichts damit anfangen kann. Beim Entwurf der Anwendungsarchitektur helfen eine Reihe von Patterns, die sich für die Entwicklung von J2EE-Anwendungen bewährt haben.

Stark abstrahiert hat eine typische J2EE-Anwendung den in Abpictureung 3 dargestellten Aufbau. Ein (meist) browserbasierter Client schickt HTTP Requests an ein zentrales Servlet, den so genannten Front Controller. Der Front Controller ist bereits das erste der angesprochenen Patterns. Er gehört zur Präsentationsschicht der Anwendung und dient als zentraler Einstiegspunkt für HTTP-basierte Clients, indem er alle Requests entgegennimmt und für deren Verarbeitung verantwortlich ist. Er kümmert sich gegebenenfalls um die Authentifizierung und Authorisierung, um den Aufruf der durch den Request angeforderten Geschäftslogik und um die Auswahl der Seite (oder View), auf die der Client als Reaktion auf seinen Request geleitet wird. Dadurch dass mithilfe des Front Controllers viele Entscheidungen und Kontrolllogik an zentraler Stelle versammelt werden, kann die Menge des Java-Codes in den zur Webanwendung gehörenden JSPs auf ein Minimum reduziert werden. Dies ist auch unbedingt wünschenswert, da diese ausschließlich für die reine Präsentation, also das Aussehen der Web-Anwendung verantwortlich sein sollten. Enthalten JSPs dagegen Logik in Form von Programmcode, so führt dies zu einer deutlich schlechteren Wartbarkeit der gesamten Anwendung sowie zu einer Wiederholung von Programmcode in unterschiedlichen JSPs, was dem objektorientierten Prinzip der Wiederverwendung entgegenspricht. Bei konsequenter Umsetzung des Front Controller Patterns ergibt sich quasi automatisch eine MVC-Architektur (Model-View-Controller), in welche der Front Controller die Rolle des Controllers übernimmt und die JSPs die Rolle der Views.

Zwei weitere Patterns namens Dispatcher View und Service To Worker sind sozusagen Erweiterungen des Front Controllers. In beiden wird die Entscheidung, auf welche View der Client als Reaktion auf seinen Request weiterzuleiten ist, in eine separate Komponente ausgelagert, die entweder durch ein zusätzliches Servlet oder durch eine gewöhnliche Java-Klasse realisiert werden kann. Die Verwendung eines dieser Patterns führt zu einer besseren Trennung der Zuständigkeiten innerhalb der Präsentationsschicht und damit ebenfalls zu einer besseren Wartbartkeit der Anwendung. Der Unterschied zwischen Dispatcher View und Service To Worker besteht im Wesentlichen darin, dass beim Service To Worker Pattern für die Auswahl der richtigen View als zusätzliches Kriterium die Ergebnisse der Geschäftslogik herangezogen werden können. Dieses Pattern wird beispielsweise vom Struts-Framework verwendet. Neben Front Controller, Dispatcher View und Service To Worker stehen für die Präsentationsschicht noch eine Reihe weiterer Patterns bereit, die an dieser Stelle jedoch noch nicht betrachtet werden.

Abb. 3: Typische Architektur einer J2EE-Anwendung

Für die zentrale Aufgabe des Aufrufens von Geschäftslogik ist ein weiteres Pattern von großer Bedeutung: der Business Delegate. Die Aufgabe des Business Delegate ist es, die Präsentationslogik von der Geschäftslogik zu trennen und insbesondere keine Abhängigkeiten zwischen der Präsentationslogik und der Technologie entstehen zu lassen, die für die Realisierung der Geschäftslogik verwendet wird. Hierzu stellt er eine Schnittstelle bereit, deren Methoden die Geschäftlogik der Anwendung definieren, also letztlich die Use Cases abpictureen und damit anzeigen, was die Anwendung eigentlich tut. Dabei sollte die Schnittstelle vollkommen technologieunabhängig sein, das heißt rein fachliche Parameter, Rückgabewerte und Exceptions verwenden. Am besten gewährleistet man dies, indem man die Schnittstelle des Business Delegate definiert, bevor eine Entscheidung darüber getroffen wird, welche Technologie für die Realisierung der Geschäftslogik verwendet werden soll. Der Business Delegate verwendet dann intern diese Komponenten der Geschäftslogik, und leitet Aufrufe der Präsentationslogik an sie weiter. Theoretisch ist es also auch möglich, den Business Delegate eines Tages gegen einen anderen auszutauschen, der eine vollkommen andere Technologie für die Geschäftslogik verwendet. Es wären dann im Idealfall keinerlei Änderungen an der Präsentationsschicht nötig.

Ausgehend von einer solchen, typischen J2EE-Architektur stellt sich nun die Frage, wie eine Web Service-Schnittstelle sinnvoll hinzugefügt werden kann. Die Kommunikation in einer Web Service-Anwendung erfolgt auf Basis von SOAP-Nachrichten – die SOAP-Spezifikation schreibt jedoch nicht vor, wie diese zu transportieren sind. Theoretisch sind also beliebige Transportprotokolle für die SOAP-Nachrichten denkbar. In der Praxis kommt jedoch zum momentanen Zeitpunkt in nahezu allen Anwendungsfällen HTTP als Transportprotokoll zum Einsatz. Dieses bringt zwar einige Nachteile mit sich, hat aber andererseits den großen Vorteil, dass man damit recht gut durch Firewalls hindurch kommunizieren kann.

Auf der Empfängerseite einer SOAP-Nachricht, also dort wo der Web Service installiert ist, muss es in Web Service-Anwendungen demnach eine Komponente geben, die HTTP-Requests entgegennimmt, dann die darin enthaltenen SOAP-Nachrichten auspackt und versteht, um schließlich denjenigen Web Service aufzurufen, an den die SOAP-Nachricht gerichtet war. Für den Empfang der HTTP-Requests enthalten die meisten SOAP-Frameworks für Java aus diesem Grund ein Servlet. Eines dieser SOAP-Frameworks ist Apache Axis, das für unser Tippspiel zum Einsatz kommen soll. In der Axis-Distribution ist eine Java Web-Anwendung enthalten, die in jedem servletfähigen Web Container installiert werden kann. Sie enthält unter anderem das so genannte AxisServlet, welches genau die beschriebene Funktionalität erbringt. Jedoch ruft das AxisServlet den Web Service nicht direkt auf. Stattdessen delegiert es die Verarbeitung eingegangener SOAP-Requests und den Aufruf des eigentlichen Web Service an eine Komponente namens AxisEngine weiter. Als Implementierung für den Web Services kommen bei der Verwendung von Axis verschiedene Möglichkeiten in Frage. Ein Web Service kann durch eine gewöhnliche Java-Klasse, ein Enterprise Java Bean, ein CORBA-Objekt oder sogar auch durch Programmcode realisiert werden, der in einer Scripting-Sprache erstellt wurde. Die AxisEngine ist dafür verantwortlich, die jeweilige Web Service-Implementierung aufzurufen.

Für den Fall, dass wie im Beispiel des Tippspiels eine normale Web-Anwendung um die Web Service Funktionalität von Axis erweitert werden soll, kann das AxisServlet in diese Web-Anwendung integriert werden, anstatt zwei separate Web-Anwendungen zu installieren. Unser Tippspiel enthält somit also zwei Servlets: den Front Controller für die HTML-basierte Schnittstelle, sowie das AxisServlet für die Web Service-Schnittstelle. Aufgrund der sorgfältigen Architekturplanung fällt es nun leicht, diejenige Komponente zu identifizieren, die als Web Service nach außen zur Verfügung gestellt werden soll: es ist der Business Delegate, der ja eine technologieunabhängige Schnittstelle zur Geschäftslogik der Anwendung darstellt.

Abb. 4: Architektur des Tippspiels mit Web Service-Schnittstelle

In diesem ersten Teil der Artikelreihe wurden wichtige architektonische Überlegungen für die weitere Entwicklung des Tippspiels getroffen. Offen bleiben die Fragen, welche Technologien für die Implementierung der Präsentationsschicht und der Geschäftslogik zum Einsatz kommen sollen. Für die Präsentationsschicht kommen beispielsweise verschiedene Web-Frameworks wie Struts oder Tapestry in Betracht, für die Geschäftslogik stellt sich die Frage, ob Enterprise JavaBeans verwendet werden sollen oder nicht. Und schließlich ist auch die Frage offen, auf welche Weise der Spielplan eines Wettbewerbs in der Anwendung repräsentiert und gespeichert werden soll. All diese Dinge sind Inhalt der kommenden Ausgaben. Bis dahin und nicht vergessen: Mal verliert man und mal gewinnen die anderen. (Otto Rehagel)

Thilo Frotscher ist freiberuflicher Systemarchitekt, Trainer und Berater mit den Schwerpunkten J2EE, Web Services und Softwarearchitekturen. Neben der Mitarbeit in Projekten leitet er regelmäßig Schulungen und berichtet auf Fachkonferenzen über seine Erfahrungen. Gemeinsam mit drei anderen Autoren arbeitet er gerade an einem Buch mit dem Titel Java Web Services mit Apache Axis, das im März 2004 im Software & Support Verlag erscheint. Kontakt: feedback@frotscher.com.

Links und Literatur

Geschrieben von
Thilo Frotscher
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.