Einzelnen Beitrag anzeigen

Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#1

Anwendungs-Startup -- Konzepte?!

  Alt 27. Dez 2011, 23:56
Guten Abend zusammen,

ich stehe gerade vor dem Problem, wie genau man eine Anwendung hochfahren lassen kann und welche Punkte dies denn alles betrifft. Im allgemeinen frage ich hier nach Ideen von euch und will auch über eine Idee von mir diskutieren. Ziel des Ganzen soll es dann irgendwann mal sein, ein einheitliches Framework zu basteln, welches für nachzu alle Anwendungstypen (VCl-Anwendung, Konsolenanwendung, Service etc.) anwendbar ist -- in so fern das überhaupt möglich ist.

Zu klären wäre zuvor noch der Zustand "vollständig gestartet": ich stelle mir bei einer normalen VCL-Anwendung den Zustand vor, in dem der Benutzer das Hauptformular sieht, d.h. bezogen auf z.B. die Delphi IDE, eben das IDE-Fenster, oder bei Microsoft Word auch das Eingabe-Fenster mit der Ribbonleiste. Ebenso kann man dies auf Konsolenanwendungen und Dienste übertragen: der Zustand, bei dem die erste Eingabe möglich ist bzw. die erste Aufgabe, für die die Anwendung erstellt wurde, abgearbeitet wird. Natürlich kann man das hier noch sehr weit fassen, aber ich denke, dass nun in etwa klar ist, um was es geht. Solltet ihr hierzu Anmerkungen haben, so lasst es mich gerne wissen.

Welche Sachen fallen nun an, bis sich die Anwendung im "vollständig gestarteten Zustand" befindet? Bitte vervollständigt diese Liste, wenn euch dazu noch etwas einfällt!
  • SplashScreen ein- und ausblenden: Hierzu hat sakura einen Thread geliefert, der sehr interessant ist. Ich hatte das bisher immer so gelöst, dass ich im Hauptthread den SplashScreen angezeigt und in weiteren Threads den Startup gehandelt habe.
  • Log-Komponente einrichten
  • Allgemeine Konfigurationen laden (Registriy, INI, DB, XML etc.): Ich lagere die Konfiguration in eine separate Klasse, die als Datenhalter agiert und von Factories und sonstigen Klassen abgefragt werden kann.
  • DB-Verbindung aufbauen: Hier versuche ich eine Verbindung zur Datenbank aufzubauen, scheitert dies versuche ich dies mit Hilfe des Users zu fixen, z.B. falsch eingegebene Zugangsdaten, oder bringe eine entsprechende Fehlermeldung.
  • Basis-Daten aus der DB laden: Hierunter ist zu verstehen, dass ich quasi bei der Anzeige des SplashScreens schon mal das aufwendige Laden von Daten abhandeln will, sonst muss ich dem Nutzer nochmals einen Ladebildschirm zumuten.
  • DLLs/Plugins laden
Diese Sachen tauchen bei meinen Anwendungen jedenfalls andauernd auf. Daraus leite ich ab, dass ich teilweise aufeinandere aufbauende Teile laden muss. Daraus entstand dann die Idee, dass ich einen allgemeinen CommandProcessor baue, der beim Start lediglich Commands ausführt. Jedes Modul bekommt dann, in so fern es für den Start relevant ist, eine Command-Klasse "zugewiesen". Ein Beispiel:
  • SplashScreenShowCommand
  • LoadConfigurationCommand
  • ConnectToDatabaseCommand
  • LoadDataFromDataBaseCommand
  • CloseSplashScreenCommand
Ich habe schon bewusst auf die Reihenfolge geachtet, allerdings nicht auf mögliche Parallelität. Und zwar müssen die Commands ja in einer sinnvollen Reihenfolge ausgeführt werden, da die DB-Verbindung ja Einstellungen benötigen könnte, die vom Konfigurationsobjekt kommen, ebenso kann ich den SplashScreen erst nach erfolgreicher Beendigung des letzten Commands ausführen. Auf der anderen Seite können aber auch manche Module parallel geladen werden -- leider fällt mir hierzu gerade kein Beispiel ein

Daraus resultiert jedenfalls, dass ich zwischen den Commands Abhängigkeiten einbauen muss, sodass der CommandProcessor das entsprechend beachten und automatisch parallel ablaufende Commands erzeugen kann. Hierzu fällt mir nur ein, dass jede Command-Klasse eine ID und eine "required Commands"-Eigenschaft erhält -- Eventuell kann man dies auch über Klassen-Attribute erledigen. Über diese Eigenschaften steuert der CommandProcessor dann alles.

Nun, wie aber läuft das mit der Registrierung der Command-Klassen/-Instanzen beim Processor ab? Hier brachte mich Stefan Glienke auf die ganz nette Idee, das ganze vollautomatisch über Klassen-Attribute laufen zu lassen und so via RTTI alle Klassen und deren Attribute auszulesen. Ist eine Klasse von einem speziellen Typ (z.B. TStartupCommand) abgeleitet oder wird ein gewisses Interface (z.B. IStartupCommand) implementiert und wird ein spezielles Attribute verwendet, so ist dies eine Command-Klasse, welche beim Start instanziiert und ausgeführt werden muss -- das einzige, was der Entwickler hier noch machen muss, ist die "Execute"-Methode der Command-Klasse zu implementieren. Über die Attribute sollen sich dann auch noch diverse Einstellungen der Commands steuern lassen -- Beispiel: Ein Command-Klasse muss zwei mal instanziiert werden, mit jeweils unterschiedlichen Einstellungen.

Ich hoffe, dass ihr nun ein Bild davon habt, was ich mir unter einem Start einer Anwendung so vorstelle. Natürlich ist das Konzept darauf ausgelegt, komplexe Starts sinnvoll zu managen, weshalb dieses für kleinere Projekte eher flach fällt, aber auch genutzt werden können soll -- daher so viel (beinflussbarer) Automatismus wie möglich.

So, spätestens an dieser Stelle würde mich interessieren, wie ihr dieses Konzept findet UND wie ihr eure Starts organisiert? Habt ihr Verbesserungsideen? Oder gibt es einen Punkt, den ich gar nicht beachtet habe und der das Konzept schon im Kern scheitern lässt?
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat