Klassenkampf - Die Powersoft Foundation Classes

Werbung
Klassenkampf Die Powersoft Foundation
Classes
Dr.-Ing. Andreas Böttcher,
Dipl.-Inform. Carsten Müncheberg
Triagon Software GmbH
Die Powersoft Foundation
Classes als Basis für
Branchensoftware
Vorwort

Vermittlung praktischer Erfahrungen

kein Anspruch auf Vollständigkeit
2
Übersicht

Grundlagen des
Entscheidungsprozesses zur PFC

Thesen

konkrete Beispiele zu den Services
3
Projektsoftware vs.
Branchensoftware

Projekt - Lösungen
– spezielle Wünsche und Traditionen der
Anwender
– vorgegebene Umgebung
– Rapid Application Developement
4
Branchensoftware (1)

Allgemeine Lösung für verschiedene
Firmen der Branche

Ähnlichkeiten: Datenmodell, Semantik

Unterschiede: Gestaltung, Handhabung,
Schwerpunkte, Zusätze

Zentrale Unternehmensanwendung
5
Branchensoftware (2)

Anpassung

Modularisierung
– Erweiterungen auch lange nach Erstinstallation

Flexible Wartung
– durch die Wartungsabteilung statt der Entwickler
6
PowerBuilder und die PFC

Unterstützt PB mit PFC die
Anforderungen von Branchensoftware?
– hervorragendes Reporting
– sehr gute SQL Einbettung in PowerScript
– konsequente Objektorientierung in PowerScript
und PFC
– PFC beste Klassenbibliothek bei 4GL
7
Einsatz von PB und PFC

Wer macht
– Projektsoftware
– Branchensoftware

Wer arbeitet mit PowerBuilder
– pur
– mit den PFC
– mit einer anderen (eigenen) Library
8
Triagon Software GmbH







Gegründet 1990
Clipper-Software für Verlagsadministration
150 Installationen, ca. 800 AP
Neu: Client-Server-Appl. mit PB
30-100 AP / Installation
2 Entwickler, 2 Support/Hotline, 2 Vertrieb,
2 Admins
Entwickler: 2 MJ Vorerfahrung mit PB
9
Thesen
1. Verwende von Beginn an eine Klassenbibliothek!
2. PowerBuilder mit PFC ist für Branchensoftware
geeignet.
3. Neben der PFC benötigt man keine weiteren
Frameworks.
4. Sei bereit, der PFC bis in die Abgründe ihres
Codes zu folgen!
5. Man braucht nicht unbedingt einen zusätzlichen
Enterprise- oder Application-Layer.
10
These 1

Verwende von Beginn an eine
Klassenbibliothek.
– Schnelle funktionsfähige Prototypen mit PB
– Aber ohne Framework nur Kleinapplikationen
– Eigenentwicklung einer Library nicht nötig.
Erweitern sie ggfs. die PFC.
– Es geht nicht nachträglich!
11
These 1 (Forts.)

Höherer Aufwand - höherer Nutzen
Erhöhte Einarbeitung in die PFC
Nutzen:
 vorgefertigte sinnvolle Standardfunktionalität
 Hohe Quality Assurance durch viele Nutzer
 Dokumentation
 Offene Quellen und Erweiterbarkeit
 Vorgabe externer neutraler Standards
12
These 2
Auch Branchensoftware ist mit PFC
machbar

PFC ist Framework,
kein Application Generation Tool
– viele Services (SBA)
– aber keine vorgefertigten funktionalen Fenster
13
These 3
Du sollst keine anderen Libraries
neben der PFC haben

PFC hat fast alle originären Konzepte anderer
Libraries aufgesogen.

Hochqualifizierte Entwickler und Support

Open Source Vorteile:
– Quellcode ist frei
– weite Verbreitung
14
These 3. (Forts.)

Aufsetzende Libraries
Nachteil
• zusätzliche Vererbungschicht aller Objekte
Vorteil
• enthalten meist Objekte der Application-Schicht

Low-Level Libraries
multi-purpose function library FUNCKy
15
These 4
Folge der PFC in die Abgründe ihres
Codes

Einige Unzulänglichkeiten / Fehler

Zum Verständnis den Code befragen

Erfordert qualifizierte Entwickler
16
These 5
Nicht mehr Layer als unbedingt
erforderlich erzeugen

Enterprise Layer
– sorgt für einheitliche Gestaltung aller
Applikationen der Firma
– eigene allgemeine Basisobjekte

Application Layer
– definiert die funktionalen Basisobjekte der
Anwendung
Performance / Größe / Übersicht
17
Arbeiten mit PB & PFC

Exzellente Tools für RAD und Prototyping

Intime Kenntnisse der PFC für größere Projekte
notwendig

Hoher Lerneffekt

Definition von Standards

Mehr Probleme im PowerBuilder als in PFC
18
Arbeiten mit PB & PFC

PFC - Dokumentation
–
–
–
–

(2)
Kontextsensitive Hilfe
Analyse des Codes oft notwendig
Kommentare dürftig
Header ärgerlich
Tips:
– Scripts nicht länger als eine Seite machen
– eigenen Header definieren
19
Arbeiten mit PB & PFC

(3)
Lokalisierung
– deutsche Version mit Verzug
– neueste Version: engl. Texte z.T. hart codiert
– Änderungen im Extension-Layer

Starte mit PFC  6.0

PFC online:
www.pfcguide.com
www.pfccheatsheet.com
news://powersoft.public.powerbuilder.pfc/
20
PFC - Services & Objekte

SBA: Service Based Architectures
www.concentric.net/~Bgcastle/PAPERS/SBA/SBA_Download.shtml

Application Manager
– kapselt den Startup
– hält globale Variablen
 Vererbung ist möglich

Message Router
– Verständnis ist notwendig
– dynamischer Aufruf von Events im fokussierten Objekt
aus dem Menü
– window, fokussiertes Control, zuletzt aktives DW
21
Error Service

Von Beginn an benutzen:
– gnv_app.inv_error.of_message(...)

Erweiterungen:
– Parameter Substitution: %1, %2, ...
Vorher
nachher
– Meldungen als E-Mail
durch Nutzung des MailSend Fensters der Examples

Probleme:
– in den PFC keine konsequente Verwendung des
ErrorService
– Übersetzung des Services
22
Property Service


Services dynamisch Ein-/Ausschalten
Erzeugung der Syntax

Einschalten der Services direkt aus dem DW
– kein Scripteingriff notwendig
– DW-Design und Funktionalität gemeinsam
– Datakanja de Bruyn (PB User Meeting 9/98)
– Beispiel:
String lsRowSelect
lsRowSelect = Describe( "st_rowselect.Text" )
CHOOSE CASE
lsRowSelect
CASE '0', '1', '2' ;
of_setRowSelect(TRUE)
inv_rowSelection.of_setStyle(integer(lsRowSelect))
CASE '!'
;
// nicht vorhanden
CASE ELSE
;
// Fehlerbehandlung
END CHOOSE
23
SQL Spy Service

Debugging und Optimierung der SQLs
– in Basisklassen berücksichtigt (u_dw)

Erweiterung:
– Ausführungsplan (Sybase SQL Anywhere)
– Beispiel:
24
Menüs: Anforderungen

Vor dem Entwurf der Fenster
grundlegende Menüstruktur festlegen
 Besondere Anforderungen von
Branchensoftware:
– Nicht alle Kunden/Benutzer haben die gleiche
Funktionalität (Module) lizensiert.
– Spezielle Funktionalität darf nur für Administratoren
zugänglich sein.

Möglichst flexible Menüstruktur notwendig
25
Menüs: Welche Ansätze gibt es?

MDI mit Frame- und Sheetmenüs
(PFC-Standard)

MDI mit einzelnem Hauptmenü und
mehreren Kontextmenüs (Triagon)

Explorer-Interface
(z.B. MS-Outlook und de Bruyn)
26
Menüs: Stärken und Schwächen

komfortabler Zugang zu den Services über den
Message Router Service

ineffizient implementiert, daher wenige
Vererbungseben und wenige dynamische
Modifikationen möglich

Menüpunkte werden nicht disabled, wenn
Services abgeschaltet sind
27
MDI mit Frame- und Sheetmenus

“Two-Tier approach”
– Master-Menü erzeugen
 Kopieren von pfc_m_master nach m_xxx_master
 Nicht benötigte Menüpunkte löschen
 Eigene Menüpunkte hinzufügen
– Frame-Menü erzeugen
 m_xxx_frame ableiten von m_xxx_master
 Einzelne Menüpunkte auf disable/invisible setzen
– Sheet-Menüs erzeugen
 m_xxx_sheet_... ableiten von m_xxx_master
 Einzelne Menüpunkte auf disable/invisible setzen
 Spezielles “Action”-Menü pro Sheet hinzufügen

Nachteil: Nicht wiederverwendbar
28
MDI mit Haupt- und Kontextmenüs

Alle Fenster verwenden das gleiche Hauptmenü
– Master-Menü erzeugen
 Kopieren von Pfc_m_master nach m_xxx_master
 enthält nur Standard-Menüpunkte
– Hauptmenü-Menü erzeugen
 m_xxx_main ableiten von m_xxx_master
 enthält applikationsspezifische Menüpunkte

Menüpunkte, die nur einzelne Sheets oder DW
betreffen, werden in Kontextmenüs verbannt.
29
Kontextmenüs

In pfc_u_dw ist m_dw fest eingestellt, kann geändert werden
durch Überschreiben von event rbuttonup
// Create popup menu
// lm_dw = create m_dw (ersetzt durch)
lm_dw = create USING is_RMB_Menu

Nachteil: Keine Shortcuts, daher unergonomisch bei
Tastaturbenutzung
Windows-Standards:

– Shift+F10 aktiviert Kontextmenüs
– Wie bindet man die Win95-Menütaste ein?
30
Explorer-Interface

Ersetzt MDI-Frame

Der TreeView (Pfc_u_Tv) eignet sich zum Anwählen der
einzelnen “Sheets”, die alle in einen Explorer-Fenster
integriert sind.

Datenbankgestützter Aufbau des TreeViews sehr einfach
möglich, dadurch wird wird die geforderte Konfigugrierbarkeit
erreicht.

Da ein Teil der Navigation über den TreeView erfolgt,
vereinfacht sich der Aufbau der behäbigen Menüs.
31
Resize Service

Der Resize Service verschiebt oder skaliert alle
Controls in einem Window oder auf einer Tab-Page
individuell entsprechend ihrer Registrierung:
– FixedToRight, FixedToBottom, FixedToRight&Bottom,
Scale, ScaleToRight, ScaleToBottom,
ScaleToRight&Bottom, FixedToRight&ScaleToBottom,
FixedToBottom&ScaleToRight

Zusammen mit dem Preference Service sehr gut
für Anpassung der Applikation an unterschiedliche
Bildschirmauflösungen
32
Preference Service

Speichert Göße und Position eines Fensters sowie
Menü- und Toolbar-Einstellungen in der Registry
oder in einem INI-File.

Standard-Einstellungen sind nicht sinnvoll,
deshalb:
inv_preference.of_SetMenuItems(FALSE)
inv_preference.of_SetToolbarItemOrder(FALSE)
inv_preference.of_SetToolbarItemSpace(FALSE)
inv_preference.of_SetToolbarItemVisible(FALSE)
inv_preference.of_SetToolbarTitles(FALSE)
33
Preference Service (Forts.)

Bug: Maximized! Window-State wird nicht beachtet
(behoben in PFC 7.0)

Erweiterung: Einstellungen nicht automatisch im
Close-Event sondern nur auf Anforderung speichern
– CloseEvent überschreiben: Of_SetPreference(FALSE)
call super::close
– UserEvent: pfe_prefsave
inv_preference.Of_Save()

Wunsch: Speichern der Splitbar-Einstellungen
34
Logical Unit of Work Service

Event pfc_endtran()
Achtung: Commit / Rollback nur in Quickstart
(qckmain.pbl) implementiert

Event pfc_save
– Zu langsam bei Fenstern mit vielen Controls

Lösung:
– event pfc_saveobjects(apo_control[]) oder
– of_SetUpdateObjects(apo_control[]) und dann
event pfc_save aufrufen
35
Logical Unit of Work Service (Forts.)

Speichervorgang tunen
– Im event editchanged eine Referenz auf das
Control in einem Array ablegen
– Zum Speichern event Pfc_saveobjects aufrufen
und danach das Array rurücksetzen

Automatisches Speichern in
event rowfocuschanging einbaubar
36
Multi Table Update Service



hilfreich bei der Erstellung von DW für die effiziente
Erfassung von komplexen Datenstrukturen
Beispiel: Komplette Eingabe von Firma –
Ansprechpartner – Anschrift in einem DW.
Vorteile:
– Der Anwender muß sich bei der Eingabe nicht durch mehrere
Tab-Pages hangeln
– Die Eingaben sind vor dem Speichern vom Anwender in ihrer
Gesamtheit besser überprüfbar
– Im Falle eines DB-Fehlers kann der Anwender seine Eingaben
sofort korrigieren, eine komplizierte Routine zum Anspringen der
„fehlerhaften“ Tab-Page ist nicht notwendig
37
Multi Table Update Service (Forts.)

Problem:
– Der Service bietet keine keine Unterstützung für die
Identity-Column.
– Identity-Columns werden benötigt, wenn man mit
AutoIncrement (SQL-Anywhere) arbeitet.

Beispiel:
INSERT
SELECT
INSERT
SELECT
INSERT
INTO FIRMA ...
FIRM_KEY FROM FIRMA ( 1. Identity-Column)
INTO PARTNER SET FIRM_KEY= ....
PARTNER_KEY FROM PARTNER ( 2. Identity-Column)
INTO ANSCHRIFT SET PARTNER_KEY = ...
38
Linkage Service

Styles:
– Retrieve
– Filter
– Synchronized Scrolling

Probleme:
– Tab-Folder: Nur die DW auf der angewählten Tab-Page
sollen synchronisiert werden
– Keine AutoIncrement-Unterstützung
– Shared DW werden nicht unterstützt
39
Selection Service (n_cst_selection)

Erweiterungen
– Retrieve As Needed
– WHERE-Clause übergeben statt Retrieval-Argument
– Resizeable Response-Window:
long ll_styles
IF IsValid(inv_resize) THEN
ll_styles = GetWindowLongA(Handle(this), -16)
IF ll_styles <> 0 THEN
SetWindowLongA(Handle(this), -16, ll_styles + &
262144/*WS_THICKFRAME*/ /*+ 524288 WS_SYSMENU*/)
END IF
END IF
40
Selection Service (Forts.)


FUNCTION long GetWindowLongA(ulong whand, int
index) LIBRARY "user32.dll"
FUNCTION long SetWindowLongA(ulong whand, int
index, ulong styles) LIBRARY "user32.dll"
41
Fallen und Tricks

SaveAs mit Sonderzeichen bei .csv

Find Service: ‘&‘ nicht gefiltert

Calendar Service
– Beispiel:
42
Fallen und Tricks (2)

Sort Service: Header-Sort vs. Column Move
u_dw.EVENT clicked()
// AB: Header-ColumnMoving anschalten
IF KeyDown( KeyControl!) and row = 0 THEN
IF Pos( GetBandAtPointer(), 'header~t') = 1 THEN &
Object.Datawindow.Grid.ColumnMove = 'yes'
u_dw.EVENT lbuttoup()
// AB: Header-ColumnMoving wieder ausschalten, wenn es an ist.
IF Pos( GetBandAtPointer(), 'header~t') = 1 THEN
Object.Datawindow.Grid.ColumnMove = 'no'
END IF
43
Fallen und Tricks (3)

Sort Service: aktuelle Zeile festhalten
n_cst_dwsrv_sort.FUNCTION of_sort()
ll_row = idw_Requestor.GetRow()
IF ll_row > 0 THEN ll_rowid = idw_Requestor.GetRowIdFromRow(ll_row)
li_rc = idw_Requestor.Sort()
IF ll_rowid > 0 THEN
idw_Requestor.ScrollToRow(idw_Requestor.GetRowFromRowId(ll_rowid))
IF idw_requestor.GetRow() <> idw_requestor.GetSelectedRow(0) THEN
idw_requestor.event rowfocuschanged(idw_requestor.GetRow())
END IF
44
Tips

long varchar & timestamps beim Update
– trotz UpdateWhere= ‘Key and Modified‘
werden diese nicht in das WHERE
übernommen

Lösung:
– im SqlPreview-Event weitere Columns an das
WHERE anfügen
45
Tips (2)

ODBC: SQL-Binding
– disableBind=1
– Werte im SQL enthalten (sonst nur ‘?‘)
 sichtbar im SQL-SPY

Vorsicht: bei DisableBind=0 sind immer
ALLE updateable Columns im
UPDATE .. SET column=?, ...
enthalten!
46
Tips (3)

AncestorReturnValue
– Extended Events müssen immer den
AncestorReturnValue zurückgeben,
auch wenn nur Kommentar im Skript!

Kein PageUp/PageDown
in multiline columns
– mle-columns statt mle-controls
vorteilhaft wg. DataSharing
Lösung: pbm_dwnKey abfangen, Positionierungstasten
behandeln
47
Utilities

PFC String-Klassen
– besser: Datawindows/Datastores nutzen

FUNCKy Library
– fast unersetzlich (string Funktionen)
– PB-Interface mit kleinen Fehlern
– Verwendete Funktionen
48
Zusammenfassung

PFC verwenden!
 Erfahrungen sammeln!
– Frontend-Services sind einfach
– Backend-Services sind komplexer
49
50
51
52
string functions
token(ref string s,ref string d,int o,ref string b)
int numtoken(string s,string d)
strtran(ref string s,ref string o,ref string n,int i,int c,ref string b)
strtrani(ref string s,ref string o,ref string n,int i,int c,ref string b)
uint attoken(string s,string d,int o)
chrswap(ref string s,ref string c1,ref string c2,ulong b)
replicate(ref string s,int c,ref string b)
strextract(ref string s,ref string d,int c,ref string b
Datetime functions
fsplit(ref string f,ref string d,ref string p,ref string n,ref string e)
fgetdatef(ref string f,ref string f,ref string b)
fgettime(ref string f,ref string b)
Directory und File functions
findfirst(ref blob d,ref string f,int a,ref string b
findnext(ref blob d,ref string b)
curdir(ref string d,ref string b
boolean chdir(string d)
boolean setdrive(string d
boolean isfile(string p,int a)
Utility - Functions
getenv(ref string n,ref string b)
encrypt(ref string s,ref string k,ulong b)
decrypt(ref string s,ref string k,ulong b)
long GetWindowLongA(ulong whand, int index
long SetWindowLongA(ulong whand, int index, ulong styles
53
Herunterladen