vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Top-Preis! AP-Access-Tools-CD Volume 1  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   RSS-Feeds  | Newsletter  | Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2017
 
zurück
Rubrik: Allgemein   |   VB-Versionen: VB5, VB601.04.02
Entwurf komplexer Anwendungsoberflächen

Ein Beispiel aus der Praxis. Was wir im Rahmen dieser Dokumentation darzustellen beabsichtigen ist eine kleine, softwaretechnische Problemstellungsanalyse, die als Anregung für den Entwurf eigener Applikationen verstanden werden sollte.

Autor:  Peter A. LandauBewertung:     [ Jetzt bewerten ]Views:  13.481 

Neue Version! sevEingabe 3.0 (für VB6 und VBA)
Das Eingabe-Control der Superlative! Noch besser und noch leistungsfähiger!
Jetzt zum Einführungspreis       - Aktionspreis nur für kurze Zeit gültig -

Ein Beispiel aus der Praxis. Was wir im Rahmen dieser Dokumentation darzustellen beabsichtigen ist eine kleine, softwaretechnische Problemstellungsanalyse, die als Anregung für den Entwurf eigener Applikationen verstanden werden sollte.

1. Vorwort

Wir schreiben das Jahr 1999.

In der Abteilung eines hiesigen Großkonzerns herrscht die Goldgräberstimmung. Der Grund hierfür ist die Einführung der neuen Version des SAP-Produktes, des betriebswirtschaftlichen Software-Systems R/3 [1] für die Client/Server-Architekturen.

Ein neues Release bringt diverse Ergänzungen und Erweiterungen des Funktionsumfanges der R/3-Technologie mit sich, dies bedeutet neue Werkzeuge für den Anwender, aber auch neue Schnittstellen des Systems mit seiner Umgebung.

Zeitgleich beginnt der Wandel in den Köpfen der Anwender, insbesondere in denen der IT-Verantwortlichen.

Die Handhabung der im SAP R/3-System hinterlegten Informationen darf nun – aus der Sicht der Benutzer – anpassungsfähiger werden. Dies bedeutet hier, dass die abteilungsspezifischen Informationen fachkräftebezogener aufbereitet werden.

Zahlreiche bekannte, abteilungsinterne Geschäftsregeln der Datenauswertung und der Informationsverknüpfung müssen nun so in die EDV-Landschaft eingebetet werden, dass sie

  • rasch im System abgebildet werden, aber auch im Bedarfsfalle daraus schnell entfernt werden können
  • kostengünstiger umgesetzt werden als es bisher der Fall war
  • sich exakter umsetzen lassen
  • sich zu Simulationsanwendungen ausbauen lassen
Die an dieser Stelle auftretenden Fragen bleiben – bewusst – unbeantwortet.

Die Entscheidung für den Kauf, den Einsatz und die Erzeugung eines Software-Systems bleibt selten einer sachlichen Natur. Die bei der Entstehung der in dieser Unterlage behandelten Anwendung herrschenden politischen und soziokulturellen Aspekte wollen wir aber nicht näher betrachten.

Was wir im Rahmen dieser Dokumentation darzustellen beabsichtigen ist eine kleine, softwaretechnische Problemstellungsanalyse, die als Anregung für den Entwurf eigener Applikationen verstanden werden sollte.

2. Der Kontext – die Softwaretechnologie und die Datenverarbeitung

Das SAP R/3-System dient unserer Anwendung als primäre Datenquelle. Aus dieser Datenquelle werden definierte, abteilungsbezogene Fakten entnommen und der Datenbank [2] (Abb. 1 ) - nach dem Durchlauf von Datenprüffiltern - hinzugefügt. Diese Datenbank ist Bestandteil des in dieser Unterlage betrachtenden Systems und bildet unsere sekundäre Datenquelle.

Prinzipielle Architektur des Systems
Abb. 1: Prinzipielle Architektur des Systems

Wesentlich für die Überlegungen, die wir anstellen wollen, ist die Tatsache, dass wir mit relativ großen Datenmengen arbeiten müssen. Grossen Datenmengen im Sinne einer Visual Basic-Anwendung, die für Informationsverarbeitung dieser Intensität nicht konzipiert ist.

Das System wird täglich mit 60.000 – 80.000 Datensätzen angereichert, wobei viele davon aufgrund den zwischen ihnen fehlenden Datenbeziehungen [3] und auf sie einwirkenden Filterregeln die Datenbank nicht erreichen. Ein weiterer, wesentlicher Anteil der Datensätze bringt ausschließlich Wertänderungen [4] in der Datenbank unseres Systems mit sich, sodass wir nie mit einem Datenzuwachs dieser Größenordnung direkt in unserer sekundären Datenquelle zu rechnen haben.

Aufgrund der beim Aufbau dieses Systems gemachten Erfahrungen – Datenverarbeitungszeiten im Netzwerkbetrieb von ca. 8 Stunden – lässt sich behaupten, dass wir uns quasi am Rande des mit VB Machbaren bewegen und an die Grenzbereiche einer schlichten EDV-Anwendung stoßen.

Die Kopplung unseres Systems an die sekundäre Datenquelle – die Datenbank – erfolgt mittels ADO-Technologie, wie aus der Abb. 1 ersichtlich.

Wie zu Beginn bereits erwähnt, wollen wir mit Hilfe unserer Software den Wünschen der Anwender gerecht werden, dies geschieht hier, indem wir eine Datenauswertungseinheit mit einem mächtigen Filter ausstatten, der die – für den jeweiligen Benutzer - relevanten Informationen der Datenbank durchsiebt.

2.1 Die Problematik – der prototypische Softwareentwurf vs. Komplexität

Die Filtereinheit der Anwendung soll die Anforderungen diverser Berufsgruppen der Firma an die Datenauswertung erfüllen, d.h., die Datenabfrageeinheit der Software muss ihnen ein breites Spektrum an Suchoptionen anbieten.

Hintergrundinformationen: die Abb. 2 zeigt die Maske eines Datenabfragefilters der Anwendung. Das System baut auf einer fortgeschrittenen Stufe der Datenbanktechnologie auf.

Hierbei werden die Daten aus einem Informationsbehälter mit bereits für die Datenabfragen optimierten Angaben gelesen. Dieser Informationsbehälter stellt nicht mehr eine Datenbank dar.

Dabei ist es möglich – und wurde im Rahmen der hier analysierten Anwendung praktisch umgesetzt – die Spalteninhalte des Informationsbehälters VOR der erfolgten Datenabfrage in die Auswahlfelder der Filtermaske einzulesen, damit der Benutzer alle in der Datenbank gesammelten Daten einer Spalte bereits VOR seiner zu initiierenden Abfrage sichten kann.

Der Benutzer kann also – bevor er eine bestimmte Datenselektion im Filter formuliert – ein Auswahlfeld "ausklappen" und darin eine bestimmte Information markieren, wohlwissend, dass diese von ihm markierte Angabe auf jeden Fall in der Datenquelle vorhanden ist.

Zusammengefasst: in einer gewöhnlichen Datenbankanwendung gibt der Benutzer ein Suchkriterium vor, ohne zu wissen, ob dieses jemals erfüllt sein wird, d.h. es besteht die Möglichkeit, dass die Datenabfrage kein Ergebnis liefert.

In unserer Anwendung weiß der Benutzer bereits nach dem "ausklappen" eines Auswahlfeldes, welche Daten in der Datenquelle vorhanden sind, weil die im Auswahlfeld aufgelisteten Werte alle Werte einer Spalte der Datenquelle darstellen.

Auf diese Art und Weise kann das Vorhandensein einzelner Informationen in der Datenablage einfacher geprüft werden. Dies ist extrem nützlich in Fällen, in denen der Benutzer weiß, dass ein Datensatz mit bestimmten Merkmalen in der Datenquelle verfügbar sein muss.

Aufbau des Datenabfragefilters
Abb. 2: Aufbau des Datenabfragefilters

Ein breites Spektrum an Suchoptionen für den Anwender - was heißt das für den Systementwickler?

Es müssen diverse, zum Teil sehr umfangreiche Datenabfrageanweisungen (SQL) realisiert werden, da wir i.d.R. mehrere Tabellen der Datenbank gleichzeitig ansprechen und analysieren müssen. Dabei werden die Datenabfrageanweisungen vom Anwender mit - über die Filtereinheit (siehe Abb. 2) gesetzten – Parametern versehen.

Vorspann: mit dem Aufbau des Datenfilters für unsere Anwendung befinden wir uns mitten in einem prototypischen Entwicklungsprozess. Prototypisch [5], da die Software aufgrund von Erfahrungen, die mit den einzelnen Versionen des Systems gemacht worden sind und den sich aus ihnen ergebenden neuen Fragestellungen für die Praxis fortentwickelt wird. Prototypisch bedeutet hier, dass die Entwicklung des Filters nicht auf eine exakt festgelegte Anwendungslogik aufbaut, die vom Kern – der vorhandenen Logik des Programms – bis hin zur Schale - der Anwendungsoberfläche - führt, sondern hier die entgegengesetzte Richtung einschlägt.

Zuerst entsteht – in Absprache mit den Endanwendern – die Systemschale, die Anwendungsoberfläche (siehe Abb. 2 ), die den Anforderungen der Benutzer entspricht. Anschließend wird mittels Analyse der sich daraus ergebenden Anforderungen an das System die Datenabfrage für die Datenbank und die Logik der Anwendung definiert.

Ein breites Spektrum an Suchoptionen dem Benutzer anbieten zu wollen bedeutet für uns in erster Linie den Aufbau einer anwenderorientierten, kompakten und somit auch komplexen Benutzerschnittstelle (vgl. Abb. 7).

In einem prototypischen Entwicklungsprozess wird das Programm quasi zu einem Experiment, womit sich unkompliziert in die Bereiche vorstoßen lässt, die bei der Planung nicht berücksichtigt werden konnten, da sie nicht bekannt und/oder vollständig ergründet worden sind.

Prototypischer Softwareentwicklungsprozess bedeutet ggf. aber auch, dass vorhandene Softwarebestandteile aufgrund neuerer Erkenntnisse verworfen werden. Ein enormes Maß an Weitblick wird benötigt, um die zu realisierenden Programmbausteine so allgemein zu gestalten, dass sie auch nach der Erlangung neuester Erkenntnisse über den (hier wirtschaftlichen) Bereich – obgleich abgewandelt – weiterverwendet werden können.

Die hieraus resultierenden Konsequenzen?

Wir befassen uns einerseits mit der Gestaltung einer komplexen Benutzerschnittstelle, die gemäß den Anforderungen der Anwender definiert worden ist. Andererseits müssen wir uns wiederum mit dem Gedanken anfreunden, dass u.U. „nichts bleibt, wie es ist“. Der mögliche Wandel der Systemlogik und der Form der Systemoberfläche bleibt stets - aufgrund des prototypischen Entwicklungsprozesses - zu berücksichtigen.

An dieser Stelle an die Objektorientierung zu denken könnte sich als utopisch erweisen. Warum? Die Grundlage für eine objektorientierte Softwareentwicklung bildet i.A. ein durchdachtes, objektorientiertes Schema, z.B. ein UML-Diagramm, setzt aber voraus, dass die Grenzen des Systems bereits festgelegt und bindend sind. Wenn wir davon ausgehen, dass der Programmierer und der System-Designer wie in diesem Falle dieselbe Person sind und annehmen, dass unser Software-Prototyp permanent weiterentwickelt wird, stellen wir schnell fest, dass der Verwaltungsaufwand, ein bereits vorhandenes UML-Diagramm zu restrukturieren, enorm hoch ist.

Den Aufwand, den wir anstellen müssen, um stets „up to date“ zu sein, steht nicht in einem ökonomisch sinnvollen Verhältnis zu unserer eigentlichen Programmierarbeit.

Wie groß ist die Wahrscheinlichkeit, dass das momentan erzeugte Dokumentationsdiagramm in einigen Minuten, Stunden oder Tagen wieder verworfen wird? Die Chancen für die vollständige Erhaltung des Diagramms in unserem prototypischen Entwicklungsprozess sind gering. Aus diesem Grunde befassen wir uns an dieser Stelle mit einem nicht-objektorientierten Softwareentwurf.

Für die Profis: natürlich ist dieser Argumentationsgang einseitig
Es ist das Ziel, das uns die Vorgehensweise und die hierbei anzuwendenden Mittel vorschreibt.

Für den Fachmann einer Softwareentwicklungsabteilung wäre vermutlich die Wiederverwendbarkeit der Software das oberste Ziel. Unsere Anwendung entsteht jedoch in einem Abteilungskontext, d.h. sie ist streng spezifisch und abteilungsbezogen. Das Ziel unseres Entwurfs ist ein schnelles Herbeischaffen einer funktionierenden, den Praktiker unterstützenden Softwarelösung.

3 Die Mittel gegen die Komplexität der Aufgabenstellung

In einem Block unterhalb der Tabulatorseiten des Filters (siehe Abb. 2 ) finden wir fünf Tasten (Leistung, Umsatz,... Tag,...) die der Auswahl von mehreren logischen Informationsquellen dienen (vgl. Abb. 3 ). Diese Informationsquellen sind physikalisch innerhalb der Datenquelle hinterlegt.

Wir bezeichnen ab jetzt die fünf Tasten als den Datenquellenschalter. Welchem Zweck dient er?

In der Abb. 3 wurde die Datenquelle mit dem Datenbanksymbol versinnbildlicht. Sie beinhaltet sechs voneinander getrennte jedoch sich inhaltlich überschneidende Informationsmengen – die sechs gelben Balken in der Darstellung sollen die sechs möglichen Schalterstellungen andeuten. Jede dieser Informationsmengen enthält Spalten – ähnlich der[a1] einer Tabelle - die mit den Auswahlfeldern unseres Filters (Abb. 2 ) korrespondieren, d.h. mit diesen verknüpft sind.

Ein Auswahlfeld bezieht sich dabei nicht nur auf eine, sondern auf mehrere dieser Informationsmengen.

Aktiviert nun der Anwender eine Auswahlliste in der Maske, um darin einen Wert für die Datenabfrage auszuwählen, „weiß“ das System nicht, auf welche dieser sechs Informationsmengen sich die Suchabfrage zu beziehen hat. Aus diesem Grunde wählt der Benutzer über den Datenquellenschalter (Abb. 3 ) zuvor die entsprechende Informationsmenge aus.

Modellierung eines Datenquellenschalters
Abb. 3: Modellierung eines Datenquellenschalters

Die Oberfläche des Filters - Abb. 2 – besteht nicht nur aus einer, sondern, wie an den Tabulatorlaschen erkennbar, aus mehreren Seiten. Die Informationsmengen sind daher mit mehreren Tabulatorseiten des Filters verknüpft.

Wird eine bestimmte Informationsmenge ausgewählt, so werden die in dieser Menge vorhandenen Spalten mit den entsprechenden Auswahlfeldern des Filters verbunden.

Verschiedene Mengen enthalten ggf. verschiedene Informationsspalten, so dass nicht alle Auswahlfelder auf einmal mit Informationen verbunden sein müssen. Werden sie nicht verbunden, so bieten sie dem Benutzer keine Daten zur Auswahl an. Damit der Anwender durch ein datenloses Auswahlfeld nicht verwirrt wird, wird das Feld deaktiviert [6].

Sechs Informationsmengen stehen uns zur Verfügung, folglich gibt es sechs Muster, nach denen die Felder ein-/ausgeblendet werden.

Wir befinden uns mitten in einem prototypischen Entwicklungsprozess, daher können wir nicht davon ausgehen, dass wir

  • künftig keine weiteren Regeln für das Ein-/Ausblenden der Felder hinzufügen werden
  • mit der jetzigen Form und Komplexität des Filters [a1] seine bereits höchstmögliche Ausbaustufe erreicht haben, d.h., dass wir ggf. eine Steigerung der Komplexität zu erwarten haben

3.1 Die Visualisierung

Irgendwann kommen wir bei der gegebenen Aufgabenstellung an einen Punkt, an dem wir zwar die Anforderungen erfasst haben, aber nicht wissen, WIE wir die Komplexität der Zusammenhänge zwischen den einzelnen Teilaufgaben organisieren sollen.

IRGENDWIE als Leitwort bei der Realisierung der Software erweist sich spätestens dann als eine Einbahnstrasse, wenn wir die Korrektheit unserer Vorgehensweise beweisen müssen, bzw. das System erweitert werden soll. Wie also können wir uns selbst helfen?

"Bei jeder geistigen Arbeit braucht man irgendwann Papier und Bleistift [...] sonst verlieren wir den Überblick"

"Wir erfassen beim ersten ‚Hindenken’ in aller Regel nicht den Grundstein des zu errichtenden Gedankengebäudes, wir beginnen bei den Gedankengebäuden nicht mit dem Fundament, sondern vielleicht mit dem dritten Stock des Westflügels." [Weiler, 39 ff.]

Der Schlüssel hierzu kann die Visualisierung (vgl. Abb. 4) und die ggf. darauf beruhende Modellbildung sein.

Eine Arbeitsskizze
Abb. 4: Eine Arbeitsskizze

Es bietet sich an, Hilfskonstruktionen aufzubauen, die die Gesamtheit aller denkbaren Merkmale des Problems auf die wesentlichen Merkmale reduzieren. „Dabei wird das Originalsystem einer Systemanalyse unterzogen, bei der die wesentlichen Elemente des Systems, ihre Beziehungen zueinander und ihr Verhalten bestimmt wird. "Anschließend ist sicherzustellen, „dass das Modell in der Lage ist, das interessierende Verhalten des Originalsystems hinreichend genau wiederzugeben. Welche Abbildung geeignet ist, hängt maßgeblich vom Untersuchungszweck ab." [Sauerbier, 7]

3.2 Das Modell im Modell

Die wissenschaftliche Methode zur Bekämpfung der Komplexität führt zur Modellbildung.

Ein Datenbank-Modell oder ein Klassen-Modell in der objektorientierten Softwareentwicklung sind beide erprobte, wissenschaftliche Mittel einer organisierten, strukturierten Vorgehensweise bei der Erzeugung von Software.

Wir haben uns bewusst gegen die objektorientierte Methode – die Klassenmodellbildung - entschieden, benötigen aber dennoch ein Modell, um der Komplexität der Aufgabenstellung zu begegnen. Wir möchten an dieser Stelle eine Nachbildung der Filtermaske kreieren, ein Filtermodell erschaffen, um die Aufgabe – mit Methode – zu lösen. Mit Methode heißt, dass wir planmäßig vorgehen wollen, d.h. wiederum, dass wir sicherstellen wollen, dass wir auch in der Lage sind, die Ergebnisse unserer Vorgehensweise zu prüfen.

Eine Überprüfung unserer Vorgehensweise wird spätestens dann vonnöten sein, wenn wir unseren Software-Prototypen erweitern müssen.

Ein Modell im Modell
Abb. 5: Ein Modell im Modell

Gemäß der Abb. 5 wollen wir ein logisches Gebilde erschaffen, eine „Zwischenschicht“ unserer Filter-Anwendung, die ein Modell der Filter-Oberfläche darstellt.

Wie sieht die Modellbildung im Falle des Filters aus?

Abbildung der Softwareoberflächen auf ein logisches Modell. Prinzip.
Abb. 6: Abbildung der Softwareoberflächen auf ein logisches Modell. Prinzip.

Vergegenwärtigt man sich, dass der Anwendung ein Datenbankmodell zugrunde liegt, das die Zusammenhänge zwischen den (rohen SAP R/3 -) Daten zum Ausdruck bringt und dass die Filtereinheit ein weiteres Modell darstellt, nämlich eines, das eine weitere Abstraktion der Daten für den Benutzer vornimmt – der Anwender bekommt ja diverse Zusammenfassungen der Spalteninformationen, die im Hintergrund geschehen nicht mit – so möchten wir die dritte Modellebene im Rahmen dieser Dokumentation erörtern.

Aus der Abb. 7 lässt sich erkennen, dass die Tabulatorseiten des Filters zwar größtenteils aus den Auswahlfeldern (ComboBox-Objekte) bestehen, diese aber logisch unterschiedlich gruppiert und angeordnet sind. Zusätzlich finden wir einige in die Filtermaske integrierte Kontrollkästchen (CheckBox-Objekte).

Abbildung der Oberfläche auf ein Modell. Weitere Filterformulare.
Abb. 7: Abbildung der Oberfläche auf ein Modell. Weitere Filterformulare.

Das Ziel unseres Modells – das wir nun konzipieren wollen - ist eine Vereinheitlichung der Objektgruppen im Hinblick auf die Eigenschaft Ein-/Ausblenden [7]. Wir möchten die Gruppen an Objekten über einen gewählten Index ansprechen dürfen. Warum?

Wie bereits erläutert, wählt der User über den Datenquellenschalter eine der sechs Informationsmengen aus. Jeder dieser Mengen wird dabei ein Ein-/Ausblendmuster für die Feldaktivierung zugeordnet. Das System soll die Auswahlfelder, die keine Informationen enthalten werden, ausblenden. Dabei kann es auch vorkommen, dass Felder, die Informationen anbieten, bewusst dem Benutzer vorenthalten werden – eine Feldaktivierungslogik muss her.

Wie werden die Objektgruppen bestimmt?

Eine Objektgruppe wird über einen Rahmen [8] logisch zusammengefasst (vgl. Abb. 6 , Termine und Statusfelder) und/oder zusätzlich über einen Begriff neben dem Feld (Abb. 7) zum Ausdruck gebracht.

Die roten dreidimensionalen Punkte in den Abbildungen sollen verdeutlichen, dass wir entweder bestimmte Feldergruppen – die Auswahl eines bestimmten Datums im Bereich von – bis, soll entweder als Einheit dem Anwender zur Verfügung gestellt werden oder gar nicht – oder aber einzelne Objekte verallgemeinern wollen.

Anschließend sollen uns alle Objektgruppen als gleiche logische Einheiten im Rahmen des Programms zur Verfügung stehen (Abb. 8), da wir nicht ständig zwischen Auswahlfeld, Kontrollkästchen, Anzahl 1 oder Menge 2 unterscheiden möchten.

Die Indizierung der Objektgruppen unseres Modells erfolgt hierbei mittels Konstanten oder der sog. "benannten Konstanten", die über die Enum-Anweisung definiert werden. Wie aus der Abb. 8 ersichtlich werden die Namen für die einzelnen Konstanten entsprechend den jeweiligen Gruppennamen gewählt, so dass wir über den, hinter der Bezeichnung einer Konstanten stehenden Wert, die Gruppe, die wir ansprechen möchten, gezielt auswählen können.

Demnach wird der Aufruf von DoDatumAktiv(efBLT [9], True) den ersten Datumsblock bestehend aus zwei Auswahlfeldern aktivieren – siehe Enum in der Abbildung. Die genauere Definition des Moduls folgt in Kap. 4.

Mit der Definition der benannten Konstanten (Abb. 8) haben wir uns für eine bestimmte Vorgehensweise entschlossen - nämlich die, der Erstellung eines Modells, das auf einem über Enum definierten Index basiert.

Damit unser System normiert - ein einmal festgelegter Weg wird konsequent über alle Komponenten hinweg beibehalten - aufgebaut wird, definieren wir eine weitere benannte Konstante, die diesmal die Tabulator-Laschen konsequent abbildet (Abb. 9).

Anwendungsoberfläche – Modell - Index
Abb. 8: Anwendungsoberfläche – Modell - Index

Ein Tabulatorobjekt [10] verfügt zwar bereits über eine Index-Eigenschaft, unser Ziel ist aber die Schaffung einer Einheitlichkeit im Rahmen unseres Systems. Die Ordnung stellt für uns das Mittel zur Bezwingung der Komplexität dar.

Alle relevanten Filterkomponenten sollen mittels selbstdefinierter Index-Angaben angesteuert werden dürfen.

Abbildung der Tabulatorobjekte auf eine Aufzählung zwecks Indizierung
Abb. 9: Abbildung der Tabulatorobjekte auf eine Aufzählung zwecks Indizierung

Unsere Datenquelle enthält drei Sorten an Daten, die jeweils als einzelne Datensätze (Einzelwerte) und kumuliert unter dem Gesichtspunkt Tagesdatum (Tag) zur Verfügung stehen.

Wie eingangs bereits angedeutet, baut die Anwendung, aus der die Filterkomponente entstammt, auf einer fortgeschrittenen Form der Datenbanktechnologie auf, in der die Faktenredundanz gewollt und beabsichtigt ist, weil andere Aspekte der Datenverarbeitung – wie z. B. die Auswertungsgeschwindigkeit der Daten - im Vordergrund stehen.

Aus der Abb. 3 erkennen wir, dass unsere genormte Vorgehensweise – der Einsatz von Definitionen der benannten Konstanten – konsequent weiterverfolgt wird, obgleich dort in einer fortgeschrittenen Variante. Bei 3 Datensorten zu je 2 Dimensionen ergeben sich kombinatorisch (3x2=) 6 Auswahlmöglichkeiten der Knopfbetätigung, diese werden als Konstanten zur Selektion der Informationsquelle innerhalb einer neuen Enum-Definition verankert.

Wir möchten im Rahmen dieser Dokumentation jedoch nicht näher auf die Einzelheiten der Anwendung zugrundeliegenden Datenwelt eingehen, sondern widmen uns – wie bisher – dem Filtermodell.

Wenn wir in einem Abstraktionsvorgang – gemäß der Abb. 8 – die logischen Gruppen von Objekten der Anwendungsoberfläche als logische Einheiten – die roten dreidimensionalen Punkte in den Graphiken – betrachten, können wir diese mit Hilfe eines Index gezielt selektieren.

Index des Modells
Abb. 10: Index des Modells

Die Abb. 10 zeigt, nach welchen Kriterien die Zuordnung der Enum-Konstanten zu den Objekten der Anwendungsoberfläche erfolgt.

Was geschieht hier?
Zum einen werden alle Objekte oder Objektgruppen einer bestimmten Konstanten innerhalb der Enum zugeordnet, womit ein Index für den Zugriff auf die Objekte/Objektgruppen entsteht. Zum anderen erfolgt eine logische Unterteilung [11] der Enum-Konstanten in Untermengen, die sich auf diverse Objektarten oder Objektgruppen beziehen.

Somit sind z.B. die Konstanten efBLT bis efFAKTDATUM den logischen Gruppen zugeordnet, die sich auf die Datumsauswahl beziehen und somit aus je zwei Auswahlfeldern bestehen. Die Konstantenmenge eff bis efP bilden den Index für den Zugriff auf die Statusfelder, die in der Filteroberfläche durch ein CheckBox-Objekt realisiert werden, usw.

Bis hierhin haben wir eine Menge mentaler Arbeit im Abstraktionsprozess geleistet.

Wir haben erkannt, dass wir mit Objekten/Objektgruppen – wie sie auch definiert sein mögen – arbeiten wollen, daher haben wir uns die logischen Einheiten – 3D-Punkte in den Abbildungen – erdacht. Diese Objektgruppen – logische Einheiten - möchten wir gezielt ansprechen dürfen, womit die Definition eines Index – der Konstanten – sinnvoll wurde.

Innerhalb des Index bzw. direkt an der Anwendungsoberfläche haben wir diverse Gruppen gleicher Objekttypen identifiziert (vgl. erneut Abb. 10 ) und somit eine Grundlage für die Definition des Modells unseres Filters geschaffen.

Eine Grundlage für die Definition des Modells?

Das Modell wird nun auf der Basis unserer bisherigen Erkenntnisse definiert, d.h. in eine Datenstruktur überführt. Die Abb. 11 liefert die Zusammenfassung dieser Informationen in einer graphischen Darstellung [12].

Das Filtermodell
Abb. 11: Das Filtermodell

Von links nach rechts in der Graphik angedeutet entsteht somit ein Datensatz mit fünf Feldern. Die ersten drei Felder beinhalten – von oben nach unten betrachtet - drei Arrays [13] von denen wiederum das erste und das dritte Array Datensätze mit je zwei Feldern führen. In diesen Feldern befinden sich Verweise auf die Auswahlfelder der Maske (die extrem neugierigen schauen – bitte - unter Code 2 nach).

Das zweite Array von oben besteht aus Verweisen auf die Oberflächenobjekte vom Datentyp CheckBox.

Das vierte Feld wird von einem Datensatz gebildet, das zwei CheckBox-Objekte speichert, und das fünfte Feld ist ebenfalls ein Array, diesmal aber bestehend aus den gespeicherten Verweisen auf die Auswahlfelder.

Für den Zugriff auf die Arrays des soeben definierten Modells nutzen wir den hierzu über Enum erzeugten Index (Abb. 10). Wie der Zugriff über den Index auf die Array-Felder des Modells erfolgt, demonstriert die Abb. 12 .

Das Zusammenspiel: Index – Modell
Abb. 12: Das Zusammenspiel: Index – Modell

Bis hierhin haben wir ein Filter-Datenmodell kreiert, um die Verweise auf die Filteroberflächenobjekte darin zu speichern.

Wir möchten die Objekte der Maske – wie bereits angekündigt – gezielt ein-/ausblenden und dies mit dem Hintergedanken, dass:

  • wir die Filterdaten aus sechs voneinander getrennten Informationsquellen beziehen
  • der Anwender VOR der Auswahl der Daten eines Auswahlfeldes, eine dieser sechs Informationsquellen über den Datenquellenschalter gezielt auswählt und somit bestimmte Felder der Filtermaske aktiviert
Die Betätigung des Datenquellenschalters führt zur Auswahl einer Informationsquelle und dem dieser Informationsquelle zugeordneten Ein-/Ausblendmuster für die Aktivierung der Felder unseres Filters, vgl. Abb. 13.

Ein-/Ausblendmusterauswahl. Anwendungsprinzip
Abb. 13: Ein-/Ausblendmusterauswahl. Anwendungsprinzip

Die Datenstruktur, die für die Codierung der Ein-/Ausblendmusterinformationen herangezogen wird, könnte ein 2-dimensionales Array sein. In dem Falle ist es aber ein Array von Arrays, gem. Abb. 14 . Die Ursache hierfür war eine bestimmte Vorstellung, die sich bei mir eingestellt hat, das Bild einer „Perlenschnur“ - waagerecht, rot - an der die codierte „Logik“ für das Ein-/Ausblenden von Maskenobjekten – senkrecht, blau – wie an einer Halskette herunterhängt.

Ein-/Ausblendmuster. Schema der Datenstruktur und die Indexkonstanten
Abb. 14: Ein-/Ausblendmuster. Schema der Datenstruktur und die Indexkonstanten

Wir nutzen die bereits zuvor besprochenen Enum-Mengen zur Indizierung der Arrays, die Informationen darüber enthalten sollen, OB das Objekt, das die Arrays modellieren, ein- oder ausgeblendet wird. Folglich ist der den Arrays zugrundeliegende Datentyp der Sorte Boolean.

Was nun passieren muss ist folgendes:

  1. Codieren der Ein-/Ausblendmuster in der Datenstruktur, gem. Abb. 14, Code 4
  2. Zuweisen der Oberflächenobjekte dem Filtermodell, gem. Abb. 11, Code 6
  3. Synchronisation der Ein-/Ausblend-Muster mit dem Filtermodell, vgl. Code 7
    Dies geschieht stets nach dem Start der Anwendung und nach der Auswahl einer bestimmten Informationsquelle mittels Datenquellenschalters, gem. Abb. 13
Damit beenden wir den analytischen Teil der Dokumentation und widmen uns der Implementation des Modells.

4. Die Realisierung - Visual Basic 6.0

Die Ideen dürften sich problemlos in eine beliebige Programmiersprache übertragen lassen, da die Ansätze allgemeingültig sind.

Die benannten Konstanten - Enum - finden ihre Anwendung sowohl in Visual Basic, als auch in Pascal, C++, C#, VB.NET, etc.

Private Enum eFILTERBLATT
  eTERMIN
  eKUNDE
  eANDERE
  eINFORMATION
  eVERSION
End Enum
 
Public Enum eWObinICH
  eAE_Tag ' 0
  eAE_Einzel
  eLE_Tag
  eLE_Einzel
  eUM_Tag
  eUM_Einzel
  eUNKNOWN ' Filter aus
End Enum
 
Private Enum eFAeinzel ' ALLE !
  efBLT
  efLIEFIST
  efPLANstart
  efISTstart
  efPLANende
  efEROEFF
  efAE
  efFAKTDATUM
  eff
  efV
  efU
  efL
  efP
  efAUFTRGEB
  efREGUL
  efREMPF
  efIN
  efAUS
  efKURZBZCHN
  efVERTRIEB
  efBRANCHE
  efDISPON
  efTECHN
  efLAGEN
  efGRP
  efMASLAM
  efWIDERST
  efVERKBELEG
  efFAKTART
  efPPSAUFTRNR
  efSDAUFTRNR
  efMATNR
End Enum

Code 1: Konstantendeklarationen

Code 1 zeigt noch einmal die Definitionen der besprochenen Konstanten der Abb. 9 und der mehrfach zum Einsatz kommenden Enum für die Indizierung der Objekte/Objektgruppen der Filtermaske eFAeinzel.

Die besondere Aufmerksamkeit gilt der Konstanten eUNKNOWN deklariert als Public Enum eWObinICH.

Im Rahmen der Implementierung wird u.a. eine Variable vom Typ eWObinICH definiert, die die aktuelle Auswahl des Benutzers mittels des Datenquelleschalters aufnimmt. Für die Zahlenwertvariablen in Visual Basic gilt, dass sie nach dem Start des Systems automatisch mit einer 0 initialisiert werden – was in vielen anderen Programmiersprachen nicht unbedingt der Fall sein muss und im Falle einer Enum-Variablen in VB auch nicht der Fall ist. Dies bedeutet, dass der Initialisierungszustand einer Enum-Variablen mit dem ersten Wert der Enum-Menge angedeutet wird, d.h., unsere Enum-Variable wird mit dem Wert eWObinICH.eAE_Tag initialisiert.

Wir wollen aber mit Hilfe der Enum-Werte die sechs möglichen Benutzerentscheidungen – Auswahl der Informationsquelle 1 bis 6 – eindeutig kennzeichnen. Mit der automatischen Initialisierung unserer Variablen gibt das VB-Entwicklungssystem uns einen Wert vor, der nicht unbedingt der Benutzerauswahl entspricht.

Versuchen wir nun das System im Debugger-Modus zu analysieren, so stoßen wir auf die vom VB-System "verfälschten" Informationen – verfälscht im Sinne einer unerwarteten Initialisierung der Enum-Variablen.

Um dieser Problematik bewusst entgegenzuwirken, deklarieren wir eine weitere Konstante eWObinICH.eUNKNOWN, mit der wir auch – absichtlich – die Variable nach dem Start des Systems initialisieren.

Auf diese Weise können wir die Systemzustände vollends kontrollieren und während der Analyse im Debugger-Modus auch sinnvoll darstellen.

Private Type tDATUMBEREICH
  VON As ComboBox
  BIS As ComboBox
End Type
 
Private Type tARRDATA
  BZCHN As ComboBox
  NR As ComboBox
End Type
 
Private Type tLANDDATA
  IN As CheckBox
  AUS As CheckBox
End Type
 
Private Type tFILTER ' Modell des GESAMTEN Filters !
  DATUM(eFAeinzel.efBLT To eFAeinzel.efFAKTDATUM) As tDATUMBEREICH
  STAT(eFAeinzel.eff To eFAeinzel.efP) As CheckBox
  ARR(eFAeinzel.efAUFTRGEB To eFAeinzel.efREMPF) As tARRDATA
  LAND As tLANDDATA
  DATA(eFAeinzel.efKURZBZCHN To eFAeinzel.efMATNR) As ComboBox
End Type
 
Private Type tDATAART ' Modell der Ein-/Ausblendmuster
  DATENART(eFAeinzel.efBLT To eFAeinzel.efMATNR) As Boolean
End Type
 
Private FILTER As tFILTER
Private FILTERREGELN(eWObinICH.eAE_Tag To eWObinICH.eUM_Einzel) As tDATAART
' Globale Abbildung der Filterregeln !

Code 2: Datentypdefinitionen und Variablendeklarationen

Im Abschnitt des Code 2 erfolgen die Definitionen der Datentypen für die Modellierung der Datensätze des Filtermodells, gem. Abb. 11, wie auch die Definition der Struktur des Modells selbst.

Der Datentyp tDATUMBEREICH fasst die Referenzen – die Zeiger – auf zwei ComboBox-Felder der Filteroberfläche. Die Variablen VON und BIS in diesem Datensatz modellieren ein Pärchen an Auswahlfeldern, die der Anwender zur Festlegung eines Datumsbereiches in der Maske selektieren kann.

Dieser Datensatz ist Bestandteil des ersten Arrays in der Abb. 11 und wird ebenfalls im Datenmodell, dem Datentyp tFILTER - Code 2 – als erstes Array abgebildet.

DATUM(eFAeinzel.efBLT To eFAeinzel.efFAKTDATUM) As tDATUMBEREICH zeigt die Modellierung des gesamten Arrays. Dabei sind eFAeinzel.efBLT bis eFAeinzel.efFAKTDATUM die Indexwerte aus dem Enum eFAeinzel (Code 1), die benutzt werden, um die einzelnen Felder des Arrays zu erreichen.

Auf analoge Art erfolgt die Abbildung weiterer Arrays und deren Datensätze im Modell unseres Filters.

Der Datentyp tDATAART kapselt ein Array, das im Zusammenhang mit der Variablen Private FILTERREGELN(eWObinICH.eAE_Tag To eWObinICH.eUM_Einzel) As tDATAART, die "Logik" für das Ein-/Ausblenden der Oberflächenobjekte des Filters beinhaltet. Die Konstantenwerte eWObinICH.eAE_Tag bis eWObinICH.eUM_Einzel entsprechen hierbei den sechs Positionen, die den Anwender über den Datenquellenschalter erreichen kann – angedeutet in der Abb. 14 über die waagerecht angeordneten, roten Quadrate. Die Werte des Enum eWObinICH geben die Antwort auf die Frage "wo bin ich?".

Der Benutzer soll dem System "erklären", wo er sich befindet, d.h. in dem Zusammenhang, mitteilen, welche der sechs Datenquellen angesteuert wird und welches der sechs Ein-/Ausblendmustern für die Aktivierung der Filterobjekte zu nutzen ist. Wir initiieren hier quasi den Benutzerlauschangriff "von unten", vom Innern des Systems.

DATENART(eFAeinzel.efBLT To eFAeinzel.efMATNR) As Boolean – der Datentyp tDATAART ergibt die in der Abb. 15 senkrecht angeordneten, blauen Objekte, die für alle Objektgruppen an der Oberfläche des Filters stehen sollen. Zur Laufzeit des Programms wird diese Variable in einer Schleife von oben nach unter durchlaufen, womit überprüft wird – die Werte der Variablen sind vom Typ boolean – OB die jeweilige Gruppe an Objekten in der Maske des Filters angezeigt werden muss oder auch nicht.

Gesamtbetrachtung, Regeln - Modell
Abb. 15: Gesamtbetrachtung, Regeln - Modell

Private FILTER As tFILTER definiert letztlich unter der Bezeichnung FILTER unser Filtermodell.

Private Sub DoInitFilterMaske()
  DoInitArrayFilter ' Filterlogik ins Array eintragen...
  ' DoFilterRegelnProtokoll ' Fürs debuggen !
  ' ------------------------------------------------------
  ' Reale Objekte an das Filter-Modell zuweisen !
  DoInitFilterDatum
  ' Die realen Objekte an das Modell der Maske zuweisen !
  DoInitFilterRest
  ' ------------------------------------------------------
  DoFilterLogikArrayToModel eLE_Tag ' default beim Start!
  ' Abbildung Array => Model
End Sub

Code 3: Das Initialisierungsmodul

Das Initialisierungsmodul gem. Code 3 ruft nacheinander alle für eine sinnvolle Vorbelegung der Modelle – Filter und Ein-/Ausblendmuster - benötigten Quellcode-Einheiten auf.

Zuerst wird die in Code 4 erläuterte Prozedur DoInitArrayFilter ausgeführt, mit der die sechs Ein-/Ausblendmuster mit Werten entsprechend der Auftraggeberanforderung vorbelegt werden. Danach wird die – im Bedarfsfalle einzusetzende – Prozedur DoFilterRegelnProtokoll wirksam. Sie dient der Ausgabe von Inhalten der Ein-/Ausblendlogik. Eine Erläuterung der Funktionsweise folgt in Kürze.

Die Module DoInitFilterDatum und DoInitFilterRest dienen der Zuweisung der realen Objekte der Filteroberfläche unserem definierten Filtermodell.

Schließlich übernimmt die Prozedur DoFilterLogikArrayToModel die Synchronisation der Ein-/Ausblend-logik mit dem Modell des Filter.

' Festhalten der Filterregeln im Array!
' Anschließend aktualisieren gemäß dieser Inhalte 
Private Sub DoInitFilterRegeln(ByVal ART As eWObinICH)
  With FILTERREGELN(ART)
    Select Case ART
      Case eWObinICH.eAE_Einzel
        .DATENART(eFAeinzel.efBLT) = True
        .DATENART(eFAeinzel.efLIEFIST) = False
        .DATENART(eFAeinzel.efPLANstart) = False
        .DATENART(eFAeinzel.efISTstart) = False
        .DATENART(eFAeinzel.efPLANende) = False
        .DATENART(eFAeinzel.efEROEFF) = False
        .DATENART(eFAeinzel.efAE) = True
        .DATENART(eFAeinzel.efFAKTDATUM) = False
        ' -------------
        .DATENART(eFAeinzel.eff) = True
        .DATENART(eFAeinzel.efV) = True
        .DATENART(eFAeinzel.efU) = True
        .DATENART(eFAeinzel.efL) = True
        .DATENART(eFAeinzel.efP) = True
        ' ------------- Seite 2
        .DATENART(eFAeinzel.efAUFTRGEB) = True
        .DATENART(eFAeinzel.efREGUL) = False
        .DATENART(eFAeinzel.efREMPF) = False
        .DATENART(eFAeinzel.efKURZBZCHN) = False
        ' .DATENART(eFAeinzel.efIN) = True
        ' .DATENART(eFAeinzel.efAUS) = True
        .DATENART(eFAeinzel.efVERTRIEB) = True
        .DATENART(eFAeinzel.efBRANCHE) = True
        .DATENART(eFAeinzel.efIN) = False
        .DATENART(eFAeinzel.efAUS) = False
        .DATENART(eFAeinzel.efVERTRIEB) = True
        .DATENART(eFAeinzel.efBRANCHE) = False
        .DATENART(eFAeinzel.efDISPON) = True
        ' ------------- Seite 3
        .DATENART(eFAeinzel.efTECHN) = True
        .DATENART(eFAeinzel.efLAGEN) = True
        .DATENART(eFAeinzel.efGRP) = True
        .DATENART(eFAeinzel.efMASLAM) = True
        .DATENART(eFAeinzel.efWIDERST) = True
        .DATENART(eFAeinzel.efVERKBELEG) = True
        .DATENART(eFAeinzel.efFAKTART) = False
        .DATENART(eFAeinzel.efPPSAUFTRNR) = True
        .DATENART(eFAeinzel.efSDAUFTRNR) = True
        .DATENART(eFAeinzel.efMATNR) = True
      Case eWObinICH.eAE_Tag [...]
      Case eWObinICH.eLE_Einzel [...]
      Case eWObinICH.eLE_Tag [...]
      Case eWObinICH.eUM_Einzel [...]
      Case eWObinICH.eUM_Tag [...]
    End Select
  End With
End Sub

Code 4: Initialisierung der Ein-/Ausblendregeln

In der Prozedur DoInitArrayFilter - Code 4 - wird eine Variable vom Enum-Typ eWObinICH deklariert. Sie dient als Iterationsvariable, um über die sechs möglichen, vom Benutzer festlegbaren Zustände zu iterieren, sie zu durchlaufen. Mit jedem Aufruf von DoInitFilterRegeln ii erfolgt eine Inkrementierung (Hochzählen) der Variablen . Dadurch wird das Modul DoInitFilterRegeln(ByVal ART As eWObinICH) sechs mal aufgerufen, jedes Mal mit einem anderen Variableninhalt, um jedes Mal einen anderen Zustand der Ein-/Ausblendlogik zu initialisieren.

In der Prozedur DoInitFilterRegeln erfolgt der Zugriff auf die FILTERREGELN() einer bestimmten Art.

In Abhängigkeit von der Art der Regeln - Select Case ART ­– wird entschieden, ob eine Objektgruppe für den Benutzer sichtbar bleibt - .DATENART(eFAeinzel.efBLT) = True – oder ausgeblendet sein soll - .DATENART(eFAeinzel.efLIEFIST) = False.

Aufgrund der sprechenden Namensgebung für die benannten Konstanten, können wir dem Quellcode relativ leicht entnehmen, um welche Objektgruppen es sich hierbei handelt. Die Konstante efBLT steht für die Gruppe der Objekte, die sich auf den BLT-Termin [14] beziehen, wie aus der Abb. 15 ersichtlich.

Die unter Code 5 dargestellte Code-Einheit DoFilterRegelnProtokoll dient uns als Testeinheit für die bereits im Logik-Modell mittels DoInitFilterRegeln hinterlegte Ein-/Ausblendlogik. Die Ausgabe der Ein-/Ausblendlogik-Informationen erfolgt dabei im Debug-Fenster, gem. Abb. 16.

Private Sub DoFilterRegelnProtokoll() ' Test-Modul !
  Dim ii As eWObinICH
  Dim nn As eFAeinzel
 
  For ii = eWObinICH.eAE_Tag To eWObinICH.eUM_Einzel
    Select Case ii
      Case eWObinICH.eAE_Einzel: Debug.Print "AE einzeln"
      Case eWObinICH.eAE_Tag: Debug.Print "AE tag"
      Case eWObinICH.eLE_Einzel: Debug.Print "LE einzeln"
      Case eWObinICH.eLE_Tag: Debug.Print "LE tag"
      Case eWObinICH.eUM_Einzel: Debug.Print "UM einzeln"
      Case eWObinICH.eUM_Tag: Debug.Print "UM tag"
    End Select
 
    For nn = eFAeinzel.efBLT To eFAeinzel.efMATNR
      With FILTERREGELN(ii)
        Select Case nn
          Case efBLT
            Debug.Print "  -BLT => " & .DATENART(nn)
          Case efLIEFIST
            Debug.Print "  -LiefIST => " & .DATENART(nn)
          Case efPLANstart
            Debug.Print "  -PLANstart => " & .DATENART(nn)
          Case efISTstart
            Debug.Print "  -ISTstart => " & .DATENART(nn)
          Case efPLANende
            Debug.Print "  -PLANende => " & .DATENART(nn)
          Case efEROEFF
            Debug.Print "  -EROEFF => " & .DATENART(nn)
          Case efAE
            Debug.Print "  -AE => " & .DATENART(nn)
          Case efFAKTDATUM
            Debug.Print "  -FAKTDATUM => " & .DATENART(nn)
          Case eff
            Debug.Print "  -F => " & .DATENART(nn)
          Case efP
            Debug.Print "  -P => " & .DATENART(nn)
          Case efV
            Debug.Print "  -V => " & .DATENART(nn)
          Case efU
            Debug.Print "  -U => " & .DATENART(nn)
          Case efL
            Debug.Print "  -L => " & .DATENART(nn)
          Case efAUFTRGEB
            Debug.Print "  -AuftrGeb => " & .DATENART(nn)
          Case efREGUL
            Debug.Print "  -Regul => " & .DATENART(nn)
          Case efREMPF
            Debug.Print "  -Rempf => " & .DATENART(nn)
 
          [...]
 
          Case efFAKTART
            Debug.Print "  -FaktArt => " & .DATENART(nn)
          Case efMATNR
            Debug.Print "  -MatNR => " & .DATENART(nn)
        End Select
      End With
    Next nn
  Next ii
End Sub

Code 5: Logik-Testmodul

Dabei erzeugen wir – für jeden der sechs Zustände der Enum eWObinICH:

  • eine Hauptüberschrift – in der Abb. 16, die Information "AE tag" - um im Debug-Fenster die Angaben darüber zu hinterlassen, wo wir uns momentan befinden
  • je eine Ausgabe pro FILTERREGELN(ii)– in der Abb. 16, die Information "-BLT => Falsch" etc. - um alle Zustände die Ein-/Ausblendlogik auszugeben
Das "Durchwandern" der Werte der eWObinICH-Konstante entspricht dem Durchlaufen der in der Abb. 14 waagerecht eingezeichneten, roten Objekte. Die Iteration über FILTERREGELN(ii), die Werte der eFAeinzel-Konstante, dem Durchlaufen der in der Abb. 14 senkrecht eingezeichneten, blauen Objekte.

Ausschnitt der vom Testmodul erzeugten Ausgabe
Abb. 16: Ausschnitt der vom Testmodul erzeugten Ausgabe

Wieso benötige ich ein Testmodul?
Zur eigenen Sicherheit und der Sicherstellung, dass die "Logik" korrekt codiert wurde und somit die Filterobjekte wunschgemäß auf der Oberfläche der Filtermaske angezeigt werden. Wir müssen dabei bedenken, dass wir nicht an einer Spielanwendung arbeiten, sondern an einem System, das mehrere Fachkräfte in ihrer täglichen Arbeit unterstützen soll. Ein Hilfsmittel ist nur dann eine Hilfe, wenn es sachlich korrekt ist.

Alternativ lässt sich die Information direkt dem Quellcode entnehmen. Wir müssen hierbei aber bedenken, dass wir uns im prototypischen Entwicklungsprozess befinden, in dem sich die Situation schnell ändern kann. Dementsprechend sollten wir in der Lage sein, die aktuelle Situation schnell zu erfassen und rasch zu dokumentieren. Indem wir die Ausgabe des Testmoduls in eine Datei statt an das Debug-Fenster umleiten, können wir die gespeicherten Logik-Zustände mit wenig Aufwand in einer dokumentierenden Unterlage bereitstellen.

' Verweise auf die Origilalobjekte sammeln
' => Zugriff über das Modell auf das Original
Private Sub DoInitFilterDatum()
  With FILTER.DATUM(eFAeinzel.efBLT)
     Set .VON = Me.FldTERMBLTvon
     Set .BIS = Me.FldTERMBLTbis
  End With
  With FILTER.DATUM(eFAeinzel.efLIEFIST)
    Set .VON = Me.FldTERMLIEFISTvon
    Set .BIS = Me.FldTERMLIEFISTbis
  End With
 
  [...]
 
  With FILTER.DATUM(eFAeinzel.efFAKTDATUM)
    Set .VON = Me.FldTERMFAKTURAvon
    Set .BIS = Me.FldTERMFAKTURAbis
  End With
End Sub
 
' Verweise auf die Origilalobjekte sammeln
' => Zugriff über das Modell auf das Original
Private Sub DoInitFilterRest()
  With FILTER
    Set .STAT(eFAeinzel.eff) = Me.FldTERMStatusForecast
    Set .STAT(eFAeinzel.efP) = Me.FldTERMStatusPlan
    Set .STAT(eFAeinzel.efV) = Me.FldTERMStatusVorgabe
 
    [...]
 
    Set .DATA(eFAeinzel.efFAKTART) = Me.FldSONFAKTURAART
    Set .DATA(eFAeinzel.efMATNR) = Me.FldSONMatNr
  End With
End Sub

Code 6: Sammeln der Originalobjekte

In den Prozeduren DoInitFilterDatum und DoInitFilterRest erfolgt die Zuweisung der Filterobjekte der Maske an das von uns definierte Filtermodell.

' Art mittels Knopfkombination bestimmt !
Private Sub DoFilterLogikArrayToModel(ByVal ART As eWObinICH)
  Dim ii As eFAeinzel
 
  With FILTERREGELN(ART) ' Art der Filterlogik !
    For ii = eFAeinzel.efBLT To eFAeinzel.efMATNR
      Select Case ii ' Absteigend...
        Case eFAeinzel.efBLT To eFAeinzel.efFAKTDATUM
          DoDatumAktiv ii, .DATENART(ii)
        Case eFAeinzel.eff To eFAeinzel.efP
          DoStatusAktiv ii, .DATENART(ii)
        Case eFAeinzel.efAUFTRGEB To eFAeinzel.efREMPF
          DoArrAktiv ii, .DATENART(ii)
        Case eFAeinzel.efIN
          DoLandAktiv .DATENART(ii)
        Case eFAeinzel.efKURZBZCHN To eFAeinzel.efMATNR
          DoDataAktiv ii, .DATENART(ii)
      End Select
    Next ii
  End With
End Sub

Code 7: Synchronisationsmodul - Ein-/Ausblendlogik – Filtermodell

DoFilterLogikArrayToModel bezieht sich auf die Übertragung der Ein-/Ausblendlogik auf das Filtermodell. Die Situation lässt sich aus der Abb. 15 entnehmen.

Wir iterieren hierbei über die Logik-Arrays von oben nach unten – blau im Bild – und gleichen die Informationen mit den Modelldaten ab. Der Informationsabgleich erfolgt hierbei nur für einen bestimmten Fall, einen Fall, den der Benutzer durch die Betätigung des Datenquellenschalters bestimmt hat – Parameter ART, vom Typ des Enum eWObinICH. Für diesen speziellen Fall greifen wir auf die FILTERREGELN(ART) zu, und laufen alle Objektgruppen For ii = eFAeinzel.efBLT To eFAeinzel.efMATNR und die dort zuvor definierten Enum-Untermengen (vgl. Abb. 10 und das Filtermodell im Code 2) durch.

Für jede Objektgruppe wird dabei eine Prozedur aufgerufen, die die Objekte der Oberfläche ein-/ausblendet, wobei als Parameter beim Aufruf die Informationen

  • welche Objektgruppe?
  • ein- oder ausblenden?
übermittelt werden. Demnach wird mittels DoDatumAktiv ii, .DATENART(ii), die Datum-Objektgruppe angesprochen, ii übergibt hierbei den aktuellen Enum-Wert, d.h. den exakten Index der Gruppe oder des Objektes, das de-/aktiviert wird. Der Parameter FILTERREGELN(ART).DATENART(ii) übergibt für das Gruppenobjekt mit dem Index ii den Ein-/Ausblendwert aus dem zugehörigen Ein-/Ausblendmuster.

' Aktivierung inkl. Farbformatierung !
Private Sub DoDatumAktiv(ByVal Index As eFAeinzel, _
  ByVal AKTIV As Boolean)
 
  With FILTER.DATUM(Index)
    .VON.Enabled = AKTIV
    .VON.Text = cALLE
    .BIS.Enabled = AKTIV
    .BIS = cALLE
    .VON.BackColor = IIf(.VON.Enabled, eFARBE.eGELB, _
       eFARBE.eGRAU)
    .BIS.BackColor = IIf(.BIS.Enabled, eFARBE.eGELB, _
      eFARBE.eGRAU)
  End With
End Sub
 
Private Sub DoStatusAktiv(ByVal Index As eFAeinzel, _
  ByVal AKTIV As Boolean)
 
  With FILTER.STAT(Index)
    .Enabled = AKTIV
  End With
End Sub
 
' Aktivierung inkl. Farbformatierung und zurücksetzen!
Private Sub DoArrAktiv(ByVal Index As eFAeinzel, _
  ByVal AKTIV As Boolean)
 
  With FILTER.ARR(Index)
    .BZCHN.Enabled = AKTIV
    .BZCHN.Text = cALLE
    .NR.Enabled = AKTIV
    .NR.Text = cALLE
    .BZCHN.BackColor = IIf(.BZCHN.Enabled, _
      eFARBE.eGELB, eFARBE.eGRAU)
    .NR.BackColor = IIf(.NR.Enabled, _
      eFARBE.eGELB, eFARBE.eGRAU)
  End With
End Sub
 
Private Sub DoLandAktiv(ByVal AKTIV As Boolean)
  With FILTER.LAND
    .IN.Enabled = AKTIV
    .AUS.Enabled = AKTIV
  End With
End Sub
 
' Aktivierung inkl. Farbformatierung!
Private Sub DoDataAktiv(ByVal Index As eFAeinzel, _
  ByVal AKTIV As Boolean)
 
  With FILTER.DATA(Index)
    .Enabled = AKTIV
    .Text = cALLE:
    .BackColor = IIf(.Enabled, _
      eFARBE.eGELB, eFARBE.eGRAU):
  End With
End Sub

Code 8: Ein-/Ausblendmodule

Code 8 listet alle Module auf, die die Aktivierung der Filterobjekte bewirken.

Die Prozedur DoDatumAktiv bezieht sich auf die Gruppe der Datumsobjekte, die unter FILTER.DATUM(Index) im Filtermodell gespeichert werden.

Der Parameter .DATENART(ii) übergibt einen Boolean-Wert an die Prozedur. Dieser Wert wird über den Parameter AKTIV an die Eigenschaft .Enabled weitergereicht: .VON.Enabled = AKTIV.

Ist der Inhalt des Parameters .DATENART(ii) in seinem Wert WAHR - somit auch AKTIV WAHR - so wird die Objektgruppe in der Filtermaske aktiviert, analoges gilt für das Gegenteil.

Die Auswahlfelder sollen einen Standardwert anzeigen, dieser wird mittels .VON.Text = cALLE gesetzt, wobei cALLE eine Konstante mit dem Inhalt "Alle" andeutet.

Leider werden beim Deaktivieren der Felder nicht die Hintergrundfarben der Auswahlfelder geändert, so dass der Anwender u.U. nicht gleich merkt, ob ihm eine Auswahl zur Verfügung steht oder nicht. Um unnötigen Problemen aus dem Weg zu gehen, bietet es sich an, bei der Deaktivierung eines Auswahlfeldes auch seine Hintergrundfarbe zu ändern. Dies soll die folgende If-Abfrage und Zuweisung bewirken:

.VON.BackColor = IIf(.VON.Enabled, eFARBE.eGELB, eFARBE.eGRAU)

Demnach wird der Wahrheitswert von .VON.Enabled abgefragt. Ist das Feld sichtbar (=TRUE), behält es seine eFARBE.eGELB. Ist es nicht mehr erreichbar, ist seine eFARBE.eGRAU. Diese Farbwerte wurden zuvor mit dem Eigenschaften-Editor ermittelt und unter einer weiteren benannten Konstanten eFARBE abgelegt.

Analoge Betrachtungen gelten für weitere Objektgruppen-Aktivierungsmodule aus Code 8.

5. Nachwort – Szenenwechsel - 3D-Dokumentation

"Die Zukunft gehört hier Web-basierten Kataloglösungen, die alle erforderlichen Daten zentral auf einem Rechner speichern. Über Handy und Laptop gelangen diese Daten zu den Servicetechnikern vor Ort. [...] Über dreidimensionale Kataloge können sie 3D-Modelle erstellen, bei denen alle Bauteile klar identifizierbar sind. Mit einem Mausklick wird das Modell herangezoomt, gedreht oder geöffnet, so dass sich die einzelnen Baugruppen auf dem Bildschirm zeigen. Geräte lassen sich realitätsgetreu in sämtliche Bestandteile zerlegen [...].

3D-Animation auf dem Display eines PDA
Abb. 17: 3D-Animation auf dem Display eines PDA

Durch das Einbinden von Animationen lassen sich Ein- und Ausbaupfade nachverfolgen. [Industrielle Informationstechnik, 6-7 2001, H. Petters, S. 40]

6. Literatur - Anregung

  • Theorie und Praxis von Simulationssystemen - T. Sauerbier; Vieweg; ISBN 3-528-03866-7
  • Produktinnovation - J. Gausemeier, P. Ebbesmeyer, F. Kallmeyer, Hanser; ISBN 3-446-21631-6
  • Künstliche Intelligenz - G. F. Luger; Addison-Wesley; ISBN 3-8272-7002-7
  • SAP R/3 Kompendium - R. Möhrlen, F. Kokot; Markt & Technik; ISBN 3-8272-5313-6
  • Kreativitätstraining – P. Weiler; Südwest; ISBN 3-517-07551-5

Kritik, Anregungen...

Kritik, Anregungen und Kommentare zu diesem Artikel richten Sie bitte direkt an den Autor Peter A. Landau.

Kontakt:   Peter A. Landau


[1] Für die nachfolgenden Ausführungen im Rahmen dieser Dokumentation werden wir das SAP R/3-System gedanklich reduzieren. Abstrahiert betrachtet ist es für uns eine sehr umfangreiche Datenbank mit ausgedehnten Datenanalysemöglichkeiten.

[2] Methodisch gesehen verbirgt sich dahinter eine Weiterentwicklung der Datenbanktechnologie - die wir jedoch an dieser Stelle nicht studieren wollen. Aus der logischen Perspektive hingegen betrachtet, handelt es sich hier um ein Datensammlungsobjekt, hier als Datenbank bezeichnet. Für die Analyse, die wir im Rahmen dieser Dokumentation anstellen wollen, sind diese Unterschiede aber unbedeutend.

[3] Kein passender Primärschlüssel zum Fremdschlüssel vorhanden.

[4] Eine SQL-UPDATE-Anweisung wird wirksam.

[5] Prototypisch ist nicht mit unsachkundig gleichzusetzen. Viele Anwendungen aus dem Bereich der Expertensysteme werden auf diese Weise entworfen: "Expertensysteme werden durch fortschreitende Annäherungen an das fertige System erstellt [...]. Dieser Vorgang des Testens und Korrigierens von Entwürfen ist allen Entwicklungen von Expertensystemen gemein und steht im Gegen-satz zu hierarchischen Entwicklungsprozessen, wie dem Top-Down-Entwurf." [Luger, 285]

[6] Deaktiviert im Sinne von: Visible = FALSE.

[7] Enabled = TRUE, FALSE. Ein-/Ausblenden im Sinne von Visible = TRUE würde den Anwender unnötig verwirren, da er die ihm bekannten Auswahlfelder plötzlich nicht mehr erreicht, sie verschwinden an der Oberfläche der Software. Bei vielen auszublendenden Feldern pro Tabulatorseite entstünde somit der Eindruck der Leere in der Maske und könnte somit als ein undurchdachtes Design missdeutet werden.

[8] Frame - Objekte

[9] "e" und "f" im efBLT sind aufgrund einer internen Vereinbarung, einer Konvention entstanden. "e" steht für Enum im Datentyp, "f" hingegen bezieht sich auf ein Feld.

[10] SSTab

[11] Natürlich lassen sich auch mehrere Enums statt Untermengen direkt definieren.

[12] Die Anzahl der Array-Elemente im Bild stimmt nicht mit der Anzahl der zu speichernden Elemente überein. Es ist nur ein visuelles Hilfsmittel.

[13] Die Wahl des Datentyps soll - wie der gesamte Inhalt der Dokumentation - als Vorschlag und Anregung verstanden werden. Auch die Collection oder eine Klasse, etc. wären denkbar - je nach Absicht, die mit der Modellierung verfolgt wird.

[14] Enabled = TRUE, FALSE. Ein-/Ausblenden im Sinne von Visible = TRUE würde den Anwender unnötig verwirren, da er die ihm bekannten Auswahlfelder plötzlich nicht mehr erreicht, sie verschwinden an der Oberfläche der Software. Bei vielen auszublendenden Feldern pro Tabulatorseite entstünde somit der Eindruck der Leere in der Maske und könnte somit als ein undurchdachtes Design missdeutet werden.

Dieser Workshop wurde bereits 13.481 mal aufgerufen.

Über diesen Workshop im Forum diskutieren
Haben Sie Fragen oder Anregungen zu diesem Workshop, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

Neue Diskussion eröffnen

nach obenzurück


Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Workshops finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
   

Druckansicht Druckansicht Copyright ©2000-2017 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel