Anmelden

View Full Version : Proceduren / Serviceprogramm / BIND-Verzeichnis



olbe
10-08-10, 12:50
Hi,
wenn wir aktuell in einem Programm Proceduren verwenden, sind diese auch in dem jeweiligen Programm definiert und komplett vorhanden (in den D-Bestimmungen definiert und am jeweiligen Programmende der entsprechende Code für die Procedure).
Durch diese Vorgehensweise hat man unter Umständen die gleiche Procedure dann in x-Programmen immer wieder definiert, was nicht wirklich sinnvoll ist.

Mehr Sinn macht es ja, diese regelmäßig verwendeten Proceduren an einer Stelle zusammenzufassen / zu verwalten und bei Bedarf mehr oder weniger automatisch im jeweiligen Programm zur Verfügung zu haben.

Da ich bisher nicht wirklich Ahnung von Serviceprogrammen, BIND-Verzeichnissen, ... habe, musste ich ein wenig ausprobieren und bin dann auf folgende Vorgehensweise gekommen:

In der Source MYLIB/QRPGLESRC/PR_TOOLS01 definiere ich mir z.B. die Proceduren:
*
H NOMAIN
*
************************************************** *************
*
D calc01 PR 9S 3
D in_wert01 9S 0 value
D in_wert02 9S 0 value
*
D calc02 PR 9S 3
D in_wert01 9S 0 value
D in_wert02 9S 0 value
*
************************************************** *************
*
P calc01 B export
D calc01 PI 9S 3
D in_wert01 9S 0 value
D in_wert02 9S 0 value
*
D out_wert S 9S 3
*
C eval out_wert = in_wert01 * in_wert02
C return out_wert
P E
************************************************** *************
*
P calc02 B export
D calc02 PI 9S 3
D in_wert01 9S 0 value
D in_wert02 9S 0 value
*
D out_wert S 9S 3
*
C eval out_wert = in_wert01 / in_wert02
C return out_wert
P E
************************************************** *************
Diese Source wandele ich dann mit CRTRPGMOD MODULE MYLIB/PR_TOOLS01) SRCFILE(MYLIB/QRPGLESRC) um.

In der Source MYLIB/QSRVSRC/PR_TOOLS01 führe ich dann die Sourcen auf, die
exportiert werden sollen:
STRPGMEXP
EXPORT SYMBOL(calc01)
EXPORT SYMBOL(calc02)
ENDPGMEXP

Das wird dann mit CRTSRVPGM SRVPGM(MYLIB/PR_TOOLS01) EXPORT(*SRCFILE) SRCFILE(MYLIB/QSRVSRC) umgewandelt.

Im Anschluss daran habe ich mir dann ein BIND-Verzeichnis erstellt, wo ich dann das Serviceprogramm PR_TOOLS01 hinzugefügt habe:
CRTBNDDIR MYLIB/PR_TOOLS01
ADDBNDDIRE BNDDIR(MYLIB/PR_TOOLS01) OBJ((PR_TOOLS01))

In dem jeweiligen RPG-Programm schreibe ich dann in die H-Bestimmungen BNDDIR('PR_TOOLS01'), so dass mir die Prozeduren dann im Programm zur Verfügung stehen.

Das funktioniert soweit, nur würde ich gerne wissen, ob dies ein halbwegs vernüftiger Weg ist, oder ob ich mir das Leben unnötig schwer mache?

Danke schonmal.

BenderD
10-08-10, 13:10
Gechmacksache sagte der Affe und biss in die Seife

- die Binder Language kannst du dir schenken, export(*ALL) tuts ebenfalls (ohne Binder Language kannst du nicht mit Signaturen spielen und bekommst bei Änderungen an den Service Programmen einen rebind, aber das tut der Stabilität gut).

- statt Binderverzeichnis kann man auch die benötigten Module beim Compile angeben. Letzteres setzt natürlich voraus, dass man ein Change Management System einsetzt (oder minimal die Compile Befehle in der Source ablegt und durch einen Pre Prozessor ausführen lässt - CRTCPP gibts auf meiner Open Source Seite)

D*B

andreaspr@aon.at
10-08-10, 13:28
Mehr Sinn macht es ja, diese regelmäßig verwendeten Proceduren an einer Stelle zusammenzufassen / zu verwalten und bei Bedarf mehr oder weniger automatisch im jeweiligen Programm zur Verfügung zu haben.

Für die Prototypes solltest du ein Copy-File verwenden. Dort hast du dann ein einziges mal deine Definitionen und in allen anderen Modulen bindest du das Copy-File ein.
Wenn du im Copy-File was ändern solltest musst du dann natürlich die Module neu erstellen damit die Änderung wirksam wird.

olbe
10-08-10, 14:44
Danke.

Das mit der Copystrecke hört sich gut an. Werde ich dann mal ausprobieren.

@Bender:
Wie geht das den ohne die BIND-Verzeichnis Geschichte?

BenderD
10-08-10, 15:06
.. so sieht das z.B.: in meinen Quellen aus

D*B CRTRPGMOD JDBCGATE
D*B+ DBGVIEW(*SOURCE)
D*B+ REPLACE(*YES)
D*B CRTPGM JDBCGATE
D*B+ BNDDIR(QC2LE)
D*B+ ACTGRP(JDBCGATE)
D*B+ BNDSRVPGM(JVAGATE)
D*B+ DETAIL(*FULL)
unter BNDSRVPGM kann man die benötigten zu bindenden Module aufzählen. Das verwendete BNDDIR QC2LE wird für das einbinden von C und LE Routinen benötigt (wenn man denn solche verwendet) und gehört zum Betriebssystem dazu.

und damit man die beiden Commands nicht immer wieder eintippen muss und alles immer reproduzierbar ist, gibt es einen kleinen Preprozessor, der das aus der Quelle ausliest und abdüst.
Das mit den Copy Strecken ist natürlich ebenfalls richtig, Ich lege die in einer QRPGLEH ab, dann kann ich die Teildateien gleich nennen und verbruzzele keinen Buchstaben für ein Suffix, 10 reichen eh nur für stammelnde Namen.

D*B

olbe
10-08-10, 15:26
Danke!
Probiere ich dann mal aus.

B.Hauser
11-08-10, 06:45
Da gibt es unterschiedliche Ansätze:

Bei uns werden die (exportierten) Prozeduren nach Funktionalität in Teildateien geordnet.

Aus jeder Teildatei, die i.d.R. mehrere Prozeduren beinhaltet wird zunächst ein Modul und anschließend aus dem Modul ein Service-Programm erstellt. Das Modul wird anschließend sofort gelöscht.
Für jede Teildatei gibt es ein Copy-Member mit dem gleichen Namen in einer eigenen Source File QPROLESRC, in der die Prototypen für die exportierten Prozeduren hinterlegt sind. (Für die Faulen haben wir noch ein Copy-Member, indem die einzelnen Prototyp-Copymember über Copy zusammengefasst sind. Damit muss man nur eine Copy-Strecke angeben. Allerdings bei vielen vielen Prototypen, kann dabei aus einem 3 Zeiler Programm durchaus eine 300 seitige Umwandlungsliste entstehen). Ich bevorzuge allerdings die einzelnen Prototypen-Copystrecken, dann sehe ich gleich am Source Code was verwendet wurde.
Ebenso gibt es für jede Teildatei eine Binderquelle in der die exportierten Prozeduren eingetragen sind.
Alle Service-Programme werde in ein einziges Binderverzeichnis eingetragen.
Dieses Binderverzeichnis wird jeweils beim Erstellen eines Service-Programs oder eines Programms angegeben.
In allen Programmen wird das Binder-Verzeichnis wie folgt in den H-Bestimmungen hinterlegt. Dadurch wird das Binder-Verzeichnis mit jeder Compilierung über 14=Umwandeln (oder CRTBNDRPG) gezogen, ohne dass der Compile-Befehl geändert werden muss. Damit können alle Programme wie bisher mit Auswahl 14=Umwandeln (oder CRTBNDRPG) erstellt werden.


/If Defined (*CRTBNDRPG)
H DftActGrP(*No) BndDir('QC2LE': 'MYBNDDIR')
/EndIf

Um das Ganze zu vereinfachen habe ich bereits vor Jahren (inzwischen schon zum 3. Mal - nach 2 Firmenwecheln) einen Compile-Befehl geschrieben, der mir die ganze Arbeit, also Erstellen Modul, Erstellen oder Aktualisieren Bindersprache, Erstellen des Service-Programs, Hinzufügen des Service-Programs in das Binder-Verzeichnis und Löschen des Moduls abnimmt. Damit kann ich jedes Service-Programm einfach über PDM compilieren. Die einzige Voraussetzung ist, dass jeweils nur eine Quelle in ein Service-Program (oder Programm) gebunden wird und die neuen exportierten Prozeduren am Ende des Source Codes eingefügt werden.

(eigentlich wollte mein Chef diesen Command mal zum freien Download zur Verfügung stellen, ist aber bis dato noch nicht passiert :( )

Birgitta

BenderD
11-08-10, 07:38
... so unterschiedlich scheint mir das garnicht.
- die Copystrecken für die Prototypen sind wohl überall gängig.
- der eine löscht die Module, der andere nicht.
- ein Modul = 1 Serviceprogramm scheint sich ebenfalls durchgesetzt zu haben
- bei dem zentralen Binderverzeichnis muss man sicherstellen, dass die Procedures alle eindeutig benamt sind und bleiben (meistens werden die dann mit dem Modulnamen als prefix versehen, entweder schon im Interface, oder im Prototyp umbenannt - ich mache das im Prototyp) (was mich von dem zentralen Binderverzeichnis abhält: das Ding vermüllt, weil keiner aufräumt und der größte Chaot im Team hat den größten EInfluss auf das Binderverzeichnis...)

--- die Unterschiede reduzieren sich in letzter Konsequenz darauf, ob man Binderlanguage verwendet oder schlicht EXPORT(*ALL) sagt. Bei der Verwendung von Binderlanguage (wenn man es denn richtig macht), kann man sich rebinds sparen; verwendet man export(*all) kriegt man in der Regel eine Signature Änderung, sodass verwendende Programme sofort beim Aufruf abschmieren, wenn sie nicht neu gebunden wurden. Habe ich lauter Birgittas, oder Thomas, oder Mihaels, oder Barbaras im Team, oder einer von denen hat die anderen unter der Knute geht das gut, bei einigen Gesichtern, die ich gerade vor mir sehe, eben nicht. (</off topic>nebenbei bemerkt: beim statischen binden mehrerer Module in ein Service Programm ist Binder Language unverzictbar</off topic>)
- Compile aus dem PDM ist kein Hexenwerk, da bastelt sich jeder seinen Command - es sei denn, man setzt Change Management Software ein, was sicherlich die bessere Lösung wäre.

D*B

Da gibt es unterschiedliche Ansätze:

Bei uns werden die (exportierten) Prozeduren nach Funktionalität in Teildateien geordnet.

Aus jeder Teildatei, die i.d.R. mehrere Prozeduren beinhaltet wird zunächst ein Modul und anschließend aus dem Modul ein Service-Programm erstellt. Das Modul wird anschließend sofort gelöscht.
Für jede Teildatei gibt es ein Copy-Member mit dem gleichen Namen in einer eigenen Source File QPROLESRC, in der die Prototypen für die exportierten Prozeduren hinterlegt sind. (Für die Faulen haben wir noch ein Copy-Member, indem die einzelnen Prototyp-Copymember über Copy zusammengefasst sind. Damit muss man nur eine Copy-Strecke angeben. Allerdings bei vielen vielen Prototypen, kann dabei aus einem 3 Zeiler Programm durchaus eine 300 seitige Umwandlungsliste entstehen). Ich bevorzuge allerdings die einzelnen Prototypen-Copystrecken, dann sehe ich gleich am Source Code was verwendet wurde.
Ebenso gibt es für jede Teildatei eine Binderquelle in der die exportierten Prozeduren eingetragen sind.
Alle Service-Programme werde in ein einziges Binderverzeichnis eingetragen.
Dieses Binderverzeichnis wird jeweils beim Erstellen eines Service-Programs oder eines Programms angegeben.
In allen Programmen wird das Binder-Verzeichnis wie folgt in den H-Bestimmungen hinterlegt. Dadurch wird das Binder-Verzeichnis mit jeder Compilierung über 14=Umwandeln (oder CRTBNDRPG) gezogen, ohne dass der Compile-Befehl geändert werden muss. Damit können alle Programme wie bisher mit Auswahl 14=Umwandeln (oder CRTBNDRPG) erstellt werden.


/If Defined (*CRTBNDRPG)
H DftActGrP(*No) BndDir('QC2LE': 'MYBNDDIR')
/EndIf

Um das Ganze zu vereinfachen habe ich bereits vor Jahren (inzwischen schon zum 3. Mal - nach 2 Firmenwecheln) einen Compile-Befehl geschrieben, der mir die ganze Arbeit, also Erstellen Modul, Erstellen oder Aktualisieren Bindersprache, Erstellen des Service-Programs, Hinzufügen des Service-Programs in das Binder-Verzeichnis und Löschen des Moduls abnimmt. Damit kann ich jedes Service-Programm einfach über PDM compilieren. Die einzige Voraussetzung ist, dass jeweils nur eine Quelle in ein Service-Program (oder Programm) gebunden wird und die neuen exportierten Prozeduren am Ende des Source Codes eingefügt werden.

(eigentlich wollte mein Chef diesen Command mal zum freien Download zur Verfügung stellen, ist aber bis dato noch nicht passiert :( )

Birgitta

B.Hauser
11-08-10, 08:23
- der eine löscht die Module, der andere nicht.

Das Problem mit den stehengelassenen Modulen fängt dann an, wenn die Spezialisten Module in das Binderverzeichnis stellen (weil sie mehrere Module in Service-Programme oder Programme binden wollen). Damit sind Module und Service-Programme mit den gleichen Prozeduren im gleichen Binderverzeichnis. Das gibt zwar ein Problem beim Binden (per Default sind doppelte Prozedur-Namen nicht erlaubt). Aber die Spezialisten sind ja nicht dumm. Es gibt ja zum Glück die Option *DUPROC in den Binderbefehlen (die doppelte Prozedurnamen zulässt), die man ja angeben kann ...

... und juhu fallera, Module werden gebunden statt Service-Programme. Beim nächsten Update des Service-Programms rufen die (Service-)Programme, in denen das Modul (anstatt des Service-Programms) gebunden wurde, weiterhin den alten Schrott auf!

... und dann viel Spass beim Suchen!
... sch........ööööööööönes ILE!

Birgitta