Lade...
 

Programmierrichtlinien

AppsWH Programmierrichtlinien


1 Arbeitsmittel

Modul-Editor VSCode mit InstantView plug-in (empfohlen)
Versionsverwaltung Perforce (empfohlen)
Hilfe TikiWiki
Hilfegenerator Zugriff über den AppsWarehouse Browser
Modulgenerator Zugriff über den AppsWarehouse Browser

 

2 Modul Erstellung

Bei der Erstellung von neuen Modulen oder Apps empfiehlt es sich mit den ClassiX® -Modulgeneratoren auf die Grundschablonen für AppsWH-Apps zurückzugreifen. Die Generatoren werden in der AppsWarehouse App zur Verfügung gestellt.
In der Regel entsteht ein Viergestirn in der Form Providermodul mit Editier-, Listen- und Selektionsapp, deren Dateinamen sich an der darin hauptsächlich bearbeiteten Klasse ausrichten. Auch die Namen der in den Apps verwandten Messages sollte sich an den angesprochenen Klassen orientieren.

 

2.1 ClassiX® Konventionen

  • Grundsätzliches
    • InstantView® -Skripte sind (in der Regel) in Dateien organisiert, an deren Beginn das statement Module() steht. Der Oberbegriff aller Dateien ist daher "Modul". Anhand der Endung werden Module folgendermaßen unterschieden (s.a. weiter unten "Code Organisation"):
      • .mod - Provider
      • .app - App
      • .cxp - App Suite
      • .lod - include Datei mit speziellen Prozeduren für das Laden von Objekten aus externen Dateien 
      • .gen - Modulgenerator Schablone
    • Englisch ist Hauptsprache der Programmierung: Modul-, App-, Variablen- Messages Namen, Kommentare, etc. sind auf englisch anzugeben. (Wenn ein englischer Begriff nicht bekannt ist, dann muss er nachgeschlagen werden.)
    • Für Programmierung im DACH Bereich ist Deutsch die zweite in den multi-lingualen Texten anzugebende Sprache.
    • Beim Programmieren und bei der Erstellung von neuen Modulen und Apps sind die Basisrichtlinien (vorgegeben durch die Modulgenerator-Schablonen (*.gen)) zu berücksichtigen.
       
  • Namenskonvention Dateinamen
    • Der erste Buchstabe eines Datennamens ist immer klein. Setzt sich der Name aus mehreren Wörtern zusammen, dann beginnen die folgenden Wörter jeweils mit einem großen Buchstaben (camelCase).
    • Provider Module für Klassen werden wie die Klasse selbst benannt (z.B. cxPerson.mod oder cxSalesInvoice.mod)) und haben die Dateiendung ".mod". Allgemeine Provider Module (z.B. fileTools.mod oder query.mod) beschreiben ihre Funktion.
    • Module mit Dialog-Masken oder Module, an die eine Nachricht gesendet werden kann werden als App bezeichnet und haben die Dateiendung ".app". Die Hauptnachricht an die App beginnt mit der Funktion der App, also EDIT_ für eine Bearbeitungsmaske, LIST_ für eine Liste und SELECT_ für einen Selektionsdialog. Im Namen der App befindet sich diese Funktion immer am Ende, also Nachricht EDIT_PERSON geht an personEdit.app, LIST_PERSON an personList.app und SELECT_PERSON an personSelect.app.
    • Apps für Editierzwecke (xxxEdit.app) beinhalten im Standard eine Zeile in der Form ' #include ?xxxEdit.lod? '. Diese .lod Dateien dienen dazu - ohne Ableitung - solche Prozeduren einzubinden, die das erstmalige Laden von Daten beim Neu-Hochfahren eines Systems ermöglichen. Nach Hochfahren eines Systems sind diese Prozeduren - und damit diese Dateien - obsolet und können später gelöscht werden.
       
  • Namenskonvention Variablen
    • Der erste Buchstabe eines Variablennamens ist immer klein, der von Widget-Namen und von Prozeduren immer groß zu schreiben. Setzt sich der Name aus mehreren Wörtern zusammen, dann beginnen die folgenden Wörter jeweils mit einem großen Buchstaben (camelCase für Variablen, CamelCase für Prozeduren).
    • Variablennamen sollten so weit als möglich selbsterklärend sein (ggf. durch mehrere Worte).
    • Klassennamen und Messages werden durchgängig in Großbuchstaben geschrieben. Sind diese aus mehreren Wörtern zusammengesetzt, dann erfolgt die Trennung durch Unterstriche (underscore).
    • Slots, die aus einem technischen Hintergrund eingeführt wurden, beginnen mit einem Unterstrich. (Bspw. "_ivCode")
       
  • Definitionen
    • Vor der Definition neuer Pseudo-Klassen (classix.odb) muss dieses mit dem Leiter des AppsWH Entwicklerteams abgestimmt werden. Pseudo-Klassen sind als Substantive zu verstehen (reale Objekte oder Begriffe).
    • Vor der Definition neuer Datenfelder (classix.dic) muss dies mit dem Leiter des AppsWH Entwicklerteams abgestimmt werden. Einzelne Datenfelder sind als Substantive (pointer, collections) oder Verben zu verstehen.
    • Vor der Definition neuer specifier (classix.dic) muss dies mit dem Leiter des AppsWH Entwicklerteams abgestimmt werden. Specifier sind als Adjektive oder Adverbe der definierten Datenfelder (Substantive oder Verben) zu verstehen.
    • Messages
      • Messages werden grundsätzlich in der classix.msg deklariert.
      • Messages werden nach dem Schema EDIT_xx, LIST_xx, SELECT_xx und xx_SELECTED, xx_CREATED, xx_CHANGED, xx_DELETED gebildet, wobei xx für z.B.einen Klassennamen steht.
      • Kundenspezifische Messages bilden hierzu eine Ausnahme, diese sollten in der Kunden.ext zusammen mit den Kundenspezifischen Modulen oder Ableitungen deklariert werden.
         
  • Code Organisation mittels von Modulen
    • Module werden hauptsächlich unterschieden in Provider(module) (Endung .mod) und Anwendung(smodule) (Endung .app).
    • Provider
      • Jeder REP Klasse ist ein Provider Modul mit folgender Namenskonvention zugeordnet: z.B. Klasse CX_CUSTOMER -> Provider cxCustomer.mod.
      • Provider enthalten in sich gekapselte Prozeduren und stellen quasi eine Erweiterung des Methodeninterfaces einer Klasse dar.
      • Darüberhinaus gibt es auch Anwendungsspezifische Provider (z.B. projectSetup.mod) mit allgemein gültigen, Klassen übergreifenden Prozeduren.
      • Provider sollten über StaticVar helfen, globale Variablen zu vermeiden.
      • Provider Module dürfen keine Messages empfangen.
    • App
      • Eine App stellt eine ganz bestimmte funktionale Einheit, eine ganz bestimmte, aus Prozess orientierten und ergonomischen Gesichtspunkten aufgebaute Applikation dar.
      • Entitäten- bzw. Klassenorientierte Apps (z.B. Pflegemaske von Kunden (CX_CUSTOMER)) können von deren Klassen-Providern (z.B.cxCustomer.mod) abgeleitet sein.
      • Eine App "sollte" jeweils nur eine Maske enthalten oder nur Masken, die in direktem Zusammenhang stehen und bei denen eine Auslagerung keine mögliche, anderweitige Wiederverwendung erkennen lässt.
         
  • Codierung
    • Einrückungen
      • Die Makrodefinition und das Semikolon am Ende des Makros wird grundsätzlich um 4 Leerzeichen eingerückt. Der Inhalt des Makros wird um weitere 2 Zeichen eingerückt.
      • bei geschweiften/eckigen Klammern, bei jeder Schleife und in allen case-Anweisungen werden die eingeschlossen Anweisungen um 2 Zeichen eingerückt.
    • Messages dienen in der Regel der Kommunikation zwischen Modulen oder einzelnen Fenstern und nur in Ausnahmefällen nur innerhalb eines Fensters.
    • Direktes Ansprechen eines Widgets in einem anderen Fenster sollte vermieden werden und über Messages geschehen.
    • Das Aussehen und die Funktionalität von Identifikationsfeldern (z.B. uniqueID) sollte grundsätzlich von entsprechenden Zählern und FString-Feldern gesteuert werden.
    • Makro SetAllTxnManagers in Beleg-Modulen im INITIALIZE-Block aufrufen (und nicht bei jedem Verbuchen neu); in allen Kundenprojekten sollen die REP-Collections CX_TXN_DESCRIPTOR indiziert werden.
    • In erster Linie sollte "iterate" mit dem Zusatz (UNSAFE) versehen werden, da dies eine starke positive Wirkung für die Performance hat. Es ist dabei zu beachten, dass die collection - über die iteriert wird - selbst nicht verändert werden darf, d.h. keine Elemente aus der colelction entfernt noch Element in die collection eingefügt werden dürfen (dieses wird vom System überprüft).
    • Contains sollte nicht auf eine Collection(LIST) aufgerufen werden. Wenn möglich, die Collection(LIST) mit einer Collection(SET) ersetzen. Dies wirkt sich positiv auf die Performance aus.
    • Maßeinheiten dürfen nie alleine im Code stehen, sondern immer an eine Ziffer grenzen (1kg und nicht 1 kg). Sprachabhängigkeit von Maßeinheiten ist hierbei zu beachten: 1pieces anstatt 1Stück verwenden.
    • Wird die globale Variable "user" verwendet, muss mit einer Dup-if Anweisung überprüft werden, ob diese Variable gefüllt ist.
    • Innerhalb einer Procedure sollen in der Regel lokale Variablen (LocalVar) verwendet werden. Bei der Verarbeitung von Messages können lokale Variablen mit der Verwendung einer anonymen Prozedur ( "{}" )  definiert werden.
    • Dateien aus ClassiX sollten immer im UTF8-Format geschrieben werden: hierfür das CX_ASCII_FILE Objekt mit dem Funktionsaufruf Call(UTF8Code) initialisieren.
    • Wenn eine Message direkt an ein Widget/Fenster gesendet werden soll, muss vorher mit Call(IsOpen) geprüft werden, ob das Widget/Fenster geöffnet ist. Ausnahme: Die Message wird vom selben Fenster gesendet oder die Message wird getriggerd.
    • Die Query-Parameter von Find und FindFirst müssen mit einer Klammer umschlossen werden, falls es mehr als einen Parameter gibt. (Beispiel: "(!?processed.date) & (!?cancelled.date)" Find(CX_INVENTORY) ).
       
  • Änderungsdienst
    • Werden Änderungen in einem Modul vorgenommen, müssen parallel dazu alle Kundenspezifischen Ableitungen dieses Moduls sofort mitbeachtet und gegebenenfalls geändert und getestet werden.
    • Dienen Änderungen im Quelltext dazu, etwas lokal auszuprobieren und sollen so nicht eingecheckt werden, sind sie in Analogie zu Remove-Before-Flight-Tags mit einem Kommentar
      // DONTSUBMIT <some notes what to do here>

      zu versehen. Dieser kann vom Versionskontrollsystem gefunden werden, welches einen etwaigen Eincheckvorgang abbricht.
    • Kundenspezifische Änderungen
      • Kundenspezifisch abgeleitete Module enden mit einem Kundenkürzel (z.B. custoedt_eva.mod).
      • Kundenspezifische Module, die nicht von einem Standard-Modul abgeleitet sind, beginnen mit dem Kundenkürzel (z.B. eva_newModule.mod).
      • Kundenspezifische Pseudo-Klassen beginnen mit dem Kundenkürzel (z.B. EVA_MY_PSEUDO_CLASS).
      • Unterhalb des Kundenordners ...\classix\AppsWH\Kundenordner kann noch der Ordner "dev" angelegt werden, um mit den dort eingecheckten Modulen die Lauffähigkeit in unserer lokalen Benutzerumgebung zu gewährleisten.
        In der Start-Batch muss der Ordner dann mit aufgenommen werden. Entsprechend ist darauf zu achten, dass dieser Ordner beim manuellen Austausch nicht zum Kunden gelangt. Bei Diff-Erstellung wird dieser Ordner ignoriert.
         
  • Fehler handling
    • Kann Code nur durch einen workaround zum Laufen gebracht werden, muss im Code an der entsprechenden Stelle ein Kommentar zum workaround eingetragen werden. Dieser ist folgendermaßen einzutragen:
      • // FIXME [Kürzel des Programmieres] [Datum] [RFC-RFC-Nummer (ohne führende Nullen)] [Kommentar]
      • Beispiel: "// FIXME SB 8.3.2016 BUG-3456 Widget flackert bei Anzeige" (für ein Ticket) oder "// FIXME SB 8.3.2016 RFC-102345 schlechte performance" (für eine Anfrage).
      • Aus dem Kommentar muss ersichtlich werden, welcher Code für den Workaround geschrieben wurde und wie der Workaround aus dem Code entfernt werden kann.
      • Wurde das Ticket/die Anfrage als erledigt zurückgemeldet, muss der Bearbeiter seine FIXMEs im Code überprüfen und anpassen.
         
  • Aufbau ini-Dateien & Co.
    • Die ini-Datei besteht, wie hier beschrieben aus zwei Sektionen: Dictionary und MetaInfo.
    • Die Sektion Dictionary wird komplett in einer dic-Datei eingefasst.
    • Die classix.dic definiert hierbei die grundlegenden Einträge. Diese können überschrieben werden, indem die classix.dic von einer spezifischen dic-Datei inkludiert wird.
    • In der ini-Datei folgt nach dem Include der dic-Datei mit dem Schlüsselwort MetaInfo dessen Sektion. Die nachfolgenden Statements werden in der ini-Datei selbst angegeben, da sie sehr projektspezifisch sind.
      • AutoLayer
      • Database
      • DLLs
      • Icon
      • IndexCopy
      • SystemDB
      • WinEditor
    • Innerhalb dieser Sektion wird die odb-Datei inkludiert, die analog zur dic-Datei mit einer projektspezifischen Variante überschrieben worden sein kann.
      Ini Include

 

2.2 ClassiX® Konventionen für die GUI

  • Oberflächenfelder (Widgets)
    • Alle Widgets müssen mit einem Namen versehen werden.
    • Der Name von Ein- und Ausgabefeldern ist im Regelfall der direkte Zugriffsausdruck (inkl. der Klasse) für das entsprechende Datenfeld. (z.B. CX_CUSTOMER::partner.name).
    • Komplexe Zugriffsausdrücke, d.h. Zugriffsausdrücke mit Funktions- und/oder Prozeduraufrufen müssen mit Alias Namen versehen werden, die immer mit einem Großbuchstaben beginnen.
    • Widgets ohne Bindung an ein Datenfeld müssen gemäß der allgemeinen Namenskonvention benannt werden (s.o. bzw. 1.Buchstabe groß, danach camel case).
    • Alle Datenfelder (Ein- oder Ausgabefeld) müssen - grundsätzlich - einen diesen beschreibenden Text haben. Dieser Text ist so zu gestalten, dass er - z.B. auch wenn vorgelesen - das Datenfeld ausreichend genau beschreibt (Barrierefreiheit). Im Regelfall werden hierfür die Prompt-Felder eingesetzt. Ist ein Prompt für den Aufbau der Maske "zu mächtig/eigentlich unnötig, da ein Prompt mehrere Felder beschreibt", kann mit dem Flag LABEL("deutsch", "englisch") im Datenfeld-Widget der beschreibende Text angegeben werden. Auch kann der beschreibende Text als TOOLTIP angegeben werden.  Eine LABEL Angabe übersteuert hierbei einen Prompt, ein Prompt übersteuert eine TOOLTIP Angabe.
    • Die für ein Ein- oder Ausgabefeld zugehörigen Promptfelder sind mit dem Zusatz "Pmt", ein zugehöriger Button mit "Btn", eine Checkbox mit "Chk" und ein Radio Button mit "Rdo" zu versehen, wobei der erste Buchstabe immer groß geschrieben wird, Punkte im Zugriffsausdruck weggelassen und dafür der nächste Buchstabe ebenfalls groß zu schreiben ist (s.a. Unterpunkt "Barrierefreiheit"). Der Zusatz "Qry" ist für diese Eingabefelder reserviert, mit denen man ein Datenfeld direkt suchen kann. Der Name des dieses Eingabefeld beschreibenden Prompt-Feldes hat am Ende anstatt des "Qry" ein "Pmt".
    • Alle Widgets müssen in einer funktional logischen und auch ergonomischen Reihenfolge angezeigt werden. Die Felder müssen in dieser Reihenfolge auch über die Tab Taste entsprechend ansteuerbar sein. (s.a. Unterpunkt "Barrierefreiheit")
    • Buttons
      • Normale Buttons und die Buttons in der Toolbar sollen nicht aus- und eingeblendet (Hide, Show) werden, sondern mit Lock, Unlock deaktiviert bzw. aktiviert werden.
      • Aus Gründen einer klaren Bedienerführung sind Buttons für Speichern, Neu, etc. mit unterstüzenden Tooltip Angaben durchaus erlaubt und wünschenswert.
    • Short cuts
      • Buttons können mittels Eingabe von "Alt + Buchstabe" direkt angesteuert werden.
      • Hierzu ist im Namen des Buttons/Menüeintrags dem für den short cut zu verwendenden Buchstaben ein "&" voranzustellen.
        • Folgende Buchstaben sind ausschließlich zu verwenden:
          Taste Button Beschriftung Beschreibung
          B &Buchen/&Book (Im Internet Explorer nicht einsetzbar, da man mit Alt+B das "Bearbeiten"-Menü öffnet.)
          C   Der Buchstabe "C" ist mehrfach belegt, führt aber immer zum Schließen eines Fensters.
          C Abbre&chen/&Cancel wenn nur eine Aktion in einer Maske möglich: z.B. Auswählen Objekt.
          C S&chließen/&Close normales Schließen einer Anwendung/App.
          C Zurü&ck/Ba&ck Schließen einer (Teil-)Anwendung und Rückkehr zu einer (Haupt-)Anwendung.
          E B&earbeiten/&Edit (Im Internet Explorer nicht einsetzbar, da man mit Alt+E in das URL Eingabefeld springt.)
          I E&infügen/&Insert Einfügen eines Objekts in eine Liste (s. Entfe&rnen/&Remove)
          L &Löschen/De&lete Löschen eines Objekts
          N &Neu/&New Neues Objekt anlegen (Bearbeitungsmaske wird geleert)
          O &Ok/&Ok Automatisches Speichern und Schließen eines Bearbeitungsfensters oder eine Auswahl in einem Auswahlfenster treffen und das Auswahlfenster schließen.
          P Drucken (&P)/&Print Aufruf Drucken
          R Entfe&rnen/&Remove Entfernen eines Objekts aus eine Liste (s. E&infügen/&Insert)
          S &Speichern/&Save Speichern der Eingaben für ein Objekt
          T Wei&ter/Nex&t Nächsten Arbeitsschritt aufrufen (z.B. nächste Position bearbeiten)
    • Tooltips
      • Eine detailliertere Beschreibung von Ein- und Ausgabefeldern kann/sollte über TOOLTIP vorgenommen werden. (s.a. Unterpunkt "Barrierefreiheit")
      • Button Widgets mit Bildern müssen über TOOLTIP detailliert beschrieben werden. (s.a. Unterpunkt "Barrierefreiheit")
    • Feste Texte
      • Fenster (inkl. Notebook Tabs) und Gruppen Header Texte , Prompt-, Button Texte usw. sollten auf einer Maske immer nur einmal erscheinen, d.h. alle festen Texte einer Maske sollten zueinander unterschiedlich sein.
      • Prompt Texte zu Pflichfeldern müssen am Ende mit einem Stern (*) versehen werden.
    • Aktionslisten im Hinblick auf MorphIT
      • Es sollte vermieden bei Checkboxen und Radiobuttons einen SELECT-Event zu definieren der nur den aktuellen Zusatnd des Widgets abbildet. Dieser sollte beim Speichern oder beim Aufruf der Suche erst aus dem Widget ermittelt werden, z.B.:

         

        FALSCH SELECT WRONG
        RICHTIG SELECT RIGHT

         

  • Layout
    • Alle Felder müssen immer in Gruppen (Group oder Composite) definiert werden, um eine inhaltliche und Layout bezogene Strukturierung zu gewährleisten.
    • Mittels von Attach Anweisungen muss ein responsive design nachgebildet werden. (z.Zt in MorphIT besser möglich, daher unter MorphIT testen.)
    • Der Abstand zweier Zeilen sollte immer 11 mc betragen
      • Die y-Koordinate von Prompts sollten z. Bsp. wie folgt hoch gezählt werden: 11, 22, 33, 44, 55,...
    • Der Abstand zwischen Widget und zugehörigen "..."-Knopf beträgt 10 mc
    • Der vertikale Abstand zwischen Gruppen ist auf 11 mc festgelegt
      • Damit ergibt sich der y Wert aus folgenden Werten der Vorgängergruppe: y +h + 11
        • Beispiel: siehe Bild: 2 + 44 +11 = 57
          Group(GFull, 5, 2, 1515, 44, ...) -> Group(GLeft, 5, 57, 740, 44, ...)
      • Beinhaltet die Vorgängergruppe selbst noch eine Gruppe, muss nochmal 11 addiert werden, um die korrekte Darstellung im Web zu gewährleisten.
    • Die Gruppenhöhe ist fest definiert über die Anzahl der vertiakl angeordneten Widget: Anzahl Widget * 11 + 11
      • Beispiel 4 Widgets: 4*11+11=55
      • Bei der Berechnung wird davon ausgegangen, dass nur einfache Widgets mit einen Abstand von 11 mc vorkommen.
        Bei Verwendung von Listen, Textboxen usw. muss man natürlich deren Höhe mit berücksichtigen
    • Ausrichtung der Elemente in Spalten wie in einem Formular. Es sollte versucht werden,
      • das die Elemente in einer Flucht zu einander liegen,
      • dass nicht zu viele unterschiedliche Fluchtpunkte vorkommen,
      • Spalten sollten mind. 50 mc voneinander entfernt liegen (Abstand zwischen Ende eines Felder einer Spalte bis zum Beginn eines Feldes der nächsten Spalte)
    • Verwendung einer ObjectComboBox
      • Eine ObjectComboBox als Eingabefeld sollte immer aus einem Prompt, der Box und einen Button rechts neben der Box bestehen (bitte Namensgebung beachten!).
      •     Prompt(CustomerPmt, 15, 11, T("Kunde", "Customer"))
           
        ObjectCombobox(CX_COMPOUND_TXN::customer, AUTO_POSITION, ENTIRE, ACCEPT_DROP, NULL_ELEMENT, 250, 11451, 150)
            Button(CustomerBtn, TOOLTIP("Kunden auswählen", "Select customer"), 695, 11, 30, 7, T("...", "..."))

            Attach(CustomerBtn, RIGHT, 15)
            Attach(customer, CustomerBtn, OPPOSITE, STRETCH, RIGHT, 10

      • In den SetFormat Anweisungen sollte eine Farbgebung nur sehr spärlich vorgenommen werden (Standardfarbe ist schwarz)
    • Hinweis
      Sollte die Webdarstellung verzerrt sein, so muss man ein Composite als erstes Element über das Fenster legen.

 

Layout Oberflaeche
(Quelle: ..\..\..\data\ppt\Layout_Oberfläche.pptx)

 
  • Statusleiste
    • Wegen der Scrollfähigkeit bei Browser Anwendungen sollte von einer Nutzung der Statusleiste Abstand genommen werden.
       
  • Listen
    • SetFormat-Anweisungen für eine Objektliste sollten normalerweise im INITIALIZE-Block definiert werden, weil sie die Formatbeschreibung der Liste erweitern.
    • ObjectListView Widgets sollten mit dem Flag OPTIMIZE deklariert werden, wobei darauf zu achten ist, ob Zugriffsausdrücke über wrapper überschrieben sind (siehe utilpurc.mod::SetPurchaseAgreementListBox).
    • In den SetFormat Anweisungen sollte eine Farbgebung nur sehr spärlich vorgenommen werden (Standardfarbe ist schwarz).
    • Für Buttons im Umfeld von ObjectListView Widgets sind folgende Punkte zu beachten:
      • Buttons sollten rechtsbündig per Attach an die ObjectListView angedockt werden: Attach(InsertBtn, RIGHT, 15)
      • Dabei sollten Buttons, die häufiger verwendet werden weiter rechts erscheinen als Buttons, die weniger verwendet werden.
      • Der Abstand zwischen den Buttons sollte 10mc betragen.
      • Oberhalb der Liste sollten Buttons stehen, die Elemente hinzufügen - unterhalb solche, die Elemente manipulieren oder entfernen.
      • Sind auf der rechten Seite der Liste Pfeil-Buttons zum Verschieben von Elementen vorhanden, verschieben sich auch die Buttons parallel mit der Liste nach links.
  • Barrierefreiheit
    • Um ClassiX Anwendungen Barreierefrei zu gestalten, müssen - zusätzlich zu den bereits aufgeführten Richtlinien - bestimmte weitere Richtlinien beachtet werden:
      • Bilder müssen Alternativtexte haben: hierzu können mit der App des Präsentationsmanagers Texte hinterlegt werden.
      • Falls Hintergrundgrafiken in Fenstern eingesetzt werden, dürfen diese keine Informationsinhalte aufweisen. Wenn überhaupt könnte man z.B. das Logo eines Kunden als Hintergrundbild nehmen.
      • Falls Audioinformationen hinterlegt sein sollten, müssen zu diesen Alternativtexte hinterlegt sein.
      • Falls Farben eingesetzt werden (Farbe von Spalten in Listen, von Prompts, in Bildern, um eventuell speziell auf einen bestimmten Zustand hinweisen zu wollen) dürfen diese nicht einziger Informationsträger sein: hier muss man mit TOOLTIP (statisch) bzw. mit "Widget Call(SetTooltip)" (dynamisch) weitere Informationen hinterlegen.
      • Schriftgrafiken dürfen nicht eingesetzt werden.
      • Falls eine Bedienung zeitabhängig sein muss (um z.B. eine Schreib-Transaktion nicht zu lange offen halten zu müssen), muss ein klarer Hinweis erfolgen, warum diese Transaktion abgebrochen wurde.
      • Alle Spalten einer Liste müssen eine Überschrft haben.
      • Falls Abkürzungen verwendet werden, müssen diese auf den Hilfeseiten erklärt sein.

 

2.3 Transaktionshandling

Alle Transaktionen, welche auf die Datenbank zugreifen, machen automatisch eine Schreibtransaktion auf. Dies bedeutet, dass die Daten, auf welche zugegriffen wird, für die Dauer der Transaktion gesperrt sind. Für den Instantview Programmierer bedeutet dies folgendes:

  • Kann in einer Transaktion sichergestellt werden, dass auf Daten nur lesend und nicht schreibend zugegriffen wird, so ist eine Lese-Transaktion über EndTXN BeginTXN(READ) zu starten. Eine bereits bestehende Transaktion würde das BeginTXN(READ) überlesen, daher ist es wichtig, dass mit EndTXN die eventuell bestehende Transaktion geschlossen wird.
  • Für lange Transaktionen ist zu prüfen, ob diese in zwei Schritten (einem lesendem Teil und einem schreibendem) ausgeführt werden können.
  • Benutzerabfragen sind zu Begin der Transaktion durchzuführen. Hierbei muss sichergestellt werden, dass möglicherweise zu diesem Zeitpunkt bereits schreibende Transaktionen geschlossen werden. (Natürlich nur, wenn bis dato noch keine Daten geschrieben worden sind.) Für den Fall, dass eine Transaktion vor einer Benutzerabfrage nicht geschlossen werden kann, ist das Makro G_AskYesNo o. ä. zu nutzen. Dieses Makro lässt dem Benutzer eine definierte Zeit für die Beantwortung der Abfrage. Die Transaktion wird abgebrochen, wenn diese Zeit verstreicht.
  • Wird eine Transaktion durch ein Event (SELECT, DOUBLE_CLICK, ...) eines Widgets lesend durch "EndTXN BeginTXN(READ)" gestartet, so ist vorher zu überprüfen, ob die Message durch ein "SendMsg(..., DIRECT)" aus einer bestehenden Transaktion heraus ebenfalls getriggert wird.
  • Eine Abbruch sollte immer mit einer verständlichen Fehlermeldung erfolgen. Dabei ist der Befehl Attention(AbortTXN, ERROR) cancel zu verwenden. Der Parameter AbortTXN und der Befehl cancel lösen einen Rollback aus, so dass die Daten, die eventuell geändert wurden, wieder auf den Stand gesetzt werden, den sie vor der Transaktion hatten.
  • Das Gültigkeitsdatum darf nur über die Message SET_VALIDITY_DATE geändert werden, ansonsten kann man bei einem Abbruch der Transaktion nicht den Status des Gültigkeitsdatum erkennen. Achtung, hier ist nicht die Gültigkeit von Objekten gemeint.

 

2.4 Transaktionsbeschreibungen und Workflows

Transaktionsbeschreibungen und Workflows sind alle im Verzeichnis appswh\\data\TXN-WF gespeichert und eingecheckt. Dies bedeutet, dass nach jeder Änderung die Transaktionsbeschreibung / der Workflow ausgecheckt, exportiert und wieder mit eingecheckt werden muss. So bekommt der Kunde bei einem Diff automatisch den letzten Stand mit ausgeliefert, egal wie viele Änderungen bis zum letzten Stand nötig waren. Es ist aufgrund der neuen Import Routine der Geschäftsprozesse nicht mehr notwendig, den Kunden die Änderungen an den Zuständen oder Übergangsbedingungen zu überlassen. Man kann einfach den exportierten Geschäftsprozess als Textdatei ausliefern, welchen der Kunde nur noch importieren muss.

Wichtig!
Bevor man etwas an einem Geschäftsprozess oder einer Transaktionsbeschreibung ändert, liest man diese vorher aus dem eingecheckten Stand ein! Sonst checkt man nachher noch seinen uralten angepassten Stand ein, was natürlich nicht geht! Übrigens, Transaktionsbeschreibungen muss man vor dem Importieren löschen!
Tipp dazu:
Ist man  nicht sicher, ob der eingecheckte Stand wirklich aktueller ist, als der aus der Datenbank, die man gerade vom Kunden mitgebracht hat, so kann man einfach den entsprechenden Geschäftsprozess/Transaktionsbeschreibung auschecken, einmal exportieren und über Perforce's "Diff file against depot" vergleichen. Sind deutliche Unterschiede erkennbar, so ist zu klären, welcher der aktuellere Stand ist. Dieser sollte dann vor der eigentlichen Änderung eingecheckt werden, damit die Revisionshistorie nachher nur die wirklich geänderten Stellen markiert.

Und noch mal zur Erinnerung:
Transaktionsbeschreibungen werden mit der Endung .txn, Geschäftsprozesse mit der Endung .wfl exportiert. Transaktionsbeschreibungen sind paarweise zu exportieren. (incl. rückgängig).
Es gibt ein paar Ausnahmen, bei denen man nicht so genau bestimmen kann, ob und wie sie zusammen gehören, (nicht mit der Kombination _BACK). In diesen Fällen bitte jeweils anhand der eingecheckten Datei prüfen, welche Transaktionsbeschreibungen enthalten sind und auch genau so exportieren!

Richtlinien: 

Wer Transaktionsbeschreibungen anfasst, der beschreibt diese bitte gleich nach folgendem Schema:

Beschreibung_TXN.jpg

Sprich:

Im Kurztext wird beschrieben, um welche Änderungen es sich handelt.

In der Beschreibung wird dann die Vorbedingung in Worte gefasst, sodass man nicht jedes mal erst 'ne Viertelstunde analysieren muss, wann hier was wo passiert.

Dies ist noch ein ziemlich einfaches Beispiel, aber wenn es dann um komplexe Bedingungen geht, ist es eine wirkliche Vereinfachung.

Falls dies gegen eine vorher festgelegte aber unausgesprochene Richtlinie der Verwendung des Beschreibungsfeldes geht, bitte Info an mich. In diesem Fall könnten wir später die Beschreibung noch ergänzen, es ist aber trotzdem zwingend erforderlich, damit sofort anzufangen!

2.5 Programmiervorgaben

s. ausgewählte Programmbeispiele.

2.6 Tipps und Tricks

  • Nach Möglichkeit 'vector | -> vector' durch 'vector Insert' ersetzen (z.B. bei garbageVector)

3 Einchecken

  • Der eingecheckte Stand muss immer lauffähig und somit auch beim Kunden jederzeit austauschbar sein.
    Dies bedeutet nicht, dass es verboten ist Zwischenstände einzuchecken, sofern diese keine Syntaxfehler etc. erzeugen. Beim Einchecken von Zwischenständen sollte überlegt werden, ob die neue Funktionalität vorerst gesperrt werden sollte. (NON_SELECTABLE im Menü oder "Noch nicht freigegeben" Attention(AbortTXN) cancel)

  • Relevante Informationen sind immer in der Changelist einzutragen nicht in dem Job. Ist ein Reorg etc. notwendig, so sollte dies nicht in einem Nebensatz erwähnt werden. Diese Information sollte in der Changebeschreibung einen eigenen Block bekommen, der durch #-Zeichen oder sonstigen Warnung durchaus hervorgehoben werden kann.
     

    Beispiel:

    #############################ACHTUNG####################################

     

             Reorg XYZ muss im Modul XYZ ausgeführt werden

     

    ########################################################################

  • Beim Einchecken sollte der Changelist auch eine dem Anwender begreifliche Beschreibung der Änderung beigefügt werden.

  • Sollte es notwendig sein gewisse Personen oder Abteilungen zu informieren, so ist auch diese Information der Changelist beizufügen.

3.1 Icons einchecken

Aktuell müssen icons jeweils im BMP und Icons Ordner eingecheckt werden. In der Regel sind die Icons 16x16 Pixel groß.
Im BMP Ordner wird dabei noch zwischen Listen und Toolbar Icons unterschieden. Die Toolbar Icons haben einen grauen Hintergrund und die Listenicons im Unterordner einen weißen.
Im Icons Ordner werden die Icons als PNGs mit transparenten Hintergrund eingecheckt.

Im Quellcode wird in Toolbars und bei Knöpfen der Bitmapname mit Dateiendung eingetragen. Alternativ oder für Listenbitmaps werden Bitmaps über die Prozedur iconTools::GetIconByBaseName registriert, dabei wird der Bitmapname als String ohne Dateiendung übergeben und zusätzlich noch der Unterordner per Stack (16 oder 0) definiert:
16 "component_simple"      iconTools::GetIconByBaseName -> componentSimpleBitmap

Zusätzlich müssen die neuen Icons imageMap.json Datei im Systemordner eingetragen werden. Sind die Umgebungsvariablen CX_BITMAP (Icons-Ordner) und CX_BITMAP2 (BMP-Ordner) vorhanden wird dann statt dem BMP das PNG dargestellt.
In der Json-Datei müssen die Namen alle klein geschrieben werden.

4 Dokumentation

Module müssen stets sofort - und im günstigsten Fall sogar vor der eigentlichen Programmierung - beschrieben werden. Das sofortige Erstellen der Dokumentation dient dazu, das was programmiert wird im Gesamt-Kontext der gewollten Funktionalität zu betrachten. Fest verdrahtete Logik im Programm, sollte, - soweit rein technischer Natur im Modul - ansonsten aber immer in der AppsWarehouse-Dokumentation für den Benutzer der Software nachvollziehbar sein.

    4.1 Dokumentation des Moduls im Quellcode

  • Prozeduren, Messages und Module werden im InstantView-Quellcode mit Doc-Kommentaren im Stil von JavaDoc, JSDoc bzw. Doxygen versehen. Diese unterscheiden sich von herkömmlichen Mehrzeilenkommentaren insofern, dass sie mit zwei Sternen beginnen:
    /** * this is the description of the module moduleName. It can also span mutliple * lines and contain the keyword class to describe which classes are worked on: * @class CX_CLASS, CX_INTEGER */ Module(moduleName) [ /** * converts a value into another one. After dot the long text is beginning * new row long text - "*" will not show in documentation * @param {CX_CLASS} obj - an object which is needed by this procedure * @optional {INTEGER} id - class of this object (may or may not be on the stack) * @return {CX_CLASS|STRING} result - the result of this procedure */ Define(ConvertAValue) LocalVar(obj, id) -> obj Depth if { -> id } id if { id obj Inherited if { "It inherits" return } } obj ; /** * even messages can have a doc-comment. It can contain the same keywords * as a procedure does: * @param {CX_PERSON} person - person to edit * @return {BOOLEAN} whether editing was successful */ EDIT_PERSON: { LocalVar(person) -> person CX_PERSON person ConvertAValue Dup is(STRING) if { person Put(comment) TRUE } else { Drop FALSE } } ]
    • Die Beschreibung wird in Englisch geschrieben.
    • Die Beschreibung beginnt mit einer Kurzbeschreibung, welche mit einem Verb beginnt und mit einem Punkt abgeschlossen wird (in diesem Beispiel. „converts a value into another one.“). Anschließend folgt ein beliebig langer Fließtext. Danach folgen beliebig viele Tags, welche weitere Informationen in formaler Weise dokumentieren.
    • Tags beginnen stets mit einem @-Zeichen. Es existieren die folgenden Tags:
      • @param: Für Prozeduren und Messages können hierüber die eingehenden Werte auf dem Stack beschrieben werden. Das erste @param-Tag beschreibt den Wert Top, der zweite Top-1 etc.
      • @optional: Parameter, welche übergeben werden können, aber nicht übergeben werden müssen, werden als optional bezeichnet.
      • @return: Für Prozeduren können hierüber die ausgehenden Werte auf dem Stack beschrieben werden. Das erste @return-Tag beschreibt den Wert Top, der zweite Top-1 etc.
      • @class: Für Module können mit Komma getrennt Klassen angegeben werden, welche durch das Modul editiert werden. Diese sind aktuell in der AppsWarehouse-Dokumentation unter AppsWH_module#Klassen zu finden.
      • @security: Für Messages kann hierüber angegeben werden, was gesperrt wird, wenn man die Message deaktiviert. Dies ist aktuell in der AppsWarehouse-Dokumentation unter AppsWH_module#Security in der Spalte Security eingetragen.
    • @param, @optional und @return sind in der folgenden Syntax anzugeben:
      1. In geschweiften Klammern die verschiedenen Typen, von denen ein Parameter sein kann.
        • Können verschiedene Typen genutzt werden, sind diese mithilfe des Zeichens | zu trennen.
          Beispiel:
          @param {STRING|INVALID} name - may be a name or invalid
        • Ist ein beliebiger Typ möglich, ist * zu verwenden.
          Beispiel:
          @param {*} variableName - use anything you want.
        • Neben Klassen können auch native Typen wie STRING, BOOLEAN, VECTOR, NULL oder INVALID genutzt werden.
        • Für die Typen VECTOR und COLLECTION kann mithilfe von spitzen Klammern angegeben werden, welchen Typ die Elemente haben.
          Beispiel:
          @param {VECTOR>} vector of collections of integers
      2. Ein Bezeichner für diesen Parameter. Wird der Parameter innerhalb der Prozedur/Message in einer Variablen abgelegt, so muss dieser mit dem im Kommentar angegebenen Bezeichner übereinstimmen.
      3. Nach einem Bindestrich folgt eine Beschreibung des Parameters
      4. Hinweis:
        Typ und Bezeichner können weggelassen werden.
    • Diese Kommentare werden genutzt um eine technische Dokumentation zu generieren.
  • Synopsis und Dictionary sollten die Funktion des Moduls ausreichend dokumentieren. Einer der Dictionary-Begriffe sollte auf den Geschäftsbereich verweisen für den das Modul im wesentlichen gedacht ist (z.B. Finanzbuchhaltung, Einkauf, etc.)
  • Kommentare
    • werden in englischer Sprache erfasst
    • Komplexe Programmbereiche sollten insbesondere dahingehend dokumentiert sein, warum das Programm die nachfolgenden Codezeilen benötigt
    • "Gefährliche" Codestellen, d.h. Codebereiche, die auf keinen Fall oder nur unter größter Sorgfalt geändert werden dürfen, sollten spezifische Hinweise erhalten

    4.2 Dokumentation des Moduls in der AppsWarehouse-Dokumentation

  • Jedes Modul muss dokumentiert werden.
    Im Modul selbst wird der Name der Hilfe Datei definiert: Module(delinedt, HELP("delinote")): delinote
    In den Fenstern wird dann auf den jeweiligen Anker verwiesen: Window(EditWin, HELP("#EditWin"),...

    Neben einer genauen Beschreibung der Benutzerschnittstelle (auch die Logik hinter Datenfelder und Buttons) ist auch darauf zu achten, das Modul allgemein bezgl. seiner beabsichtigten Aufgabenerfüllung und in seinem Kontext zu anderen Modulen zu beschreiben. Entsprechende, gegenseitige Links sind zu erfassen.

    Achtung:
    Die Verlinkung muss über die "Custom URL" (Beispiel: de_AppsWH_delinote) erfolgen, da ansonsten der Link bei Umbenennung der verlinkten Seite nicht mehr funktioniert.
    Wird im Modul der Name der Hilfe Datei abgeändert, muss auch die Custom URL aktualisiert werden (Beispiel: de_AppsWH_cxDeliveryNote). Auch sollte der TikiWiki-Administrator darüber informiert werden, damit die Links auf die Seite in der Datenbank aktualisiert werden können. Diese interne Kommunikation ist auch wichtig, da die manuell durch den Administrator ausgeführte Änderungsübersetzung nicht die Custom URL bzw. die Überschrift der englischen Seite aktualisiert.
  • Hat das Modul seinen HELP-Eintrag, gelangt man per F1-Hilfe zur erforderlichen Hilfeseite und kann diese anlegen bzw. bearbeiten.
  • Bei Beschreibung von Masken Feldern muss angegeben werden, was mit dem Inhalt dieses Feldes wo wie steuert. Ist das Feld nur nachrichtlich, sollte dieses auch so angegeben werden, es sei denn, das Feld ist allgemein bekannt (z.B. der Vorname einer Person).

 

5 Qualitätssicherung

Die Qualität der Module ist durch umfangreiche Tests - unter Erstellung von Test Frameworks - zu gewährleisten. Insbesondere ist zu darauf zu achten, inwieweit sich Änderungen in einem Modul sich auf Kundenspezifische Ableitungen dieses Moduls auswirken.

Bei Tests und auch im laufenden Betrieb der Kunden sind die Logfiles auf Warnungen oder sonstige Hinweise hin zu überprüfen.

 

6 Fehlerbehebung

Zur Behebung von Fehlern bedarf es zunächst einer sehr sorgfältigen Analyse, weshalb überhaupt ein Fehler auftreten konnte. Dazu ist es auch erforderlich die Anwendung, in der ein Fehler aufgetreten ist, im Ablauf und seiner Logik sehr genau zu verstehen. Ein schnelles "Wegmachen" eines Fehlers birgt die Gefahr, andere Fehler neu einzubauen.

Zum Verständnis des Ablaufs und der Logik einer Anwendung ist immer die AppsWarehouse-Dokumentation zu Rate zu ziehen. Lücken in der Dokumentation müssen vor der eigentlichen Fehlerbehebung geschlossen werden.

Es ist grundsätzlich immer davon auszugehen, dass ein Programm fehlerfrei ist. Daher muss man sehr genau erklären können, warum dennoch ein Fehler aufgetreten ist.

    6.1. Fehlereingrenzung

  • Nachlesen in der AppsWarehouse-Dokumentation, was die Anwendung grundsätzlich leisten soll
  • Nachstellen des Fehlers
  • Identifikation der Fehlerstelle im Modul
  • Historie des Moduls untersuchen, wann und von wem dieses geändert wurde: eventuell diesen letzten Bearbeiter des Codes hinzuziehen (nur "wesentliche" Änderungen sind zu beachten)

    6.2. Fehlerbearbeitung

    Treten in ClassiX® Fehler auf, so können einige dieser Fehler sofort bestimmten Ursachen zugeordnet werden. Hier ist eine Liste mit bekannten Fehlern, ihren Ursachen und Lösungsansätzen.

    Sollten sich umfangreichere Umbauten abzeichnen, muss der für den Fachbereich zuständige Mitarbeiter Fachbereich zuständige Mitarbeiter --> hinzugezogen werden.

    Können Fehler im Modul nicht behoben werden (z.B. wegen Fehlern in der Basis oder Datenbank), dann ist folgende Kennzeichnung anzugeben:  // FIXME „Fehlernummer“ „Kürzel des Programmierers“ „Datum“ „erklärender Kommentar“

 

7 Weiterentwicklung

    Änderungen sind beim Einchecken der Module im jeweilig genutzten Archiv-System (z.B. Perforce) durch ausreichende Kommentare genau zu beschreiben