Mein Name ist Ulrich Fuchs, ich unterstütze als freier Berater Anwenderunternehmen und Beratungshäuser in allem, was im Umgang mit dem ERP-System "Infor LN" und seinen Vorgängerversionen (Baan IV, Baan V) so an Aufgaben anfällt. Ich bin Projektleiter, Berater und Softwareentwickler, und weil ich alle drei Rollen tatsächlich beherrsche, bin ich der Joker immer dann, wenn's anspruchsvoll wird.

Weil Neuigkeiten, über die ich so stolpere, vielleicht auch für andere interessant sind, gibt's dieses Blog. Meine Kontaktdaten finden Sie unter
www.ulrich-fuchs.de.



Sonntag, 25. Januar 2009

Hei Teck ohne Teck is Dreck

Wie mein alter Chemielehrer zu sagen pflegte. Soll heißen, man auch des guten zu viel tun, auch in der EDV. Da hab ich jetzt bei Amazon einen neuen Staubsauger bestellt, weil mein alter nun wirklich reif für den wohlverdienten Staubsaugerhimmel ist. Und was macht Amazons "geniale" was-Sie-übrigens-auch-noch-kaufen-könnten-weil-andere-hams-auch-gekauft-Logik: Bombardiert mich seitdem auf der Amazon Startseite und seit eben auch noch per Email mit Angeboten für noch mehr Staubsauger.

Merke: Was bei CDs, Büchern und vielleicht auch bei Luftabwehrraketen funktioniert, funktioniert noch lange nicht bei Haushaltswaren.

Produktgruppenschlüssel können ja so hilfreich sein. Wie jüngst im Supermarkt, als die hübsche Kassiererin die Augen verdrehte, weil Sie für meinen Kasten deutlich alkhoholfreien Bieres eine "Altersfreigabe" in ihre Kasse tippen musste.

Mittwoch, 14. Januar 2009

Nicht tun bitte Nr 2): Globale Variablen

Wir kommen nun mal wieder zu den häufigsten Programmierfehlern, die mir so im Baan-Umfeld auffallen. Der folgende Punkt stößt mir immer besonders unangenehm auf, und zwar aus drei Gründen: Erstens, weil er so unglaublich weit verbreitet ist im Bereich des Customizings und der projektspezifichen Anpassungen. Zweitens, weil er auch noch von "gestandenen" Programmierern mit Jahren an Erfahrung gemacht wird. Und drittens weil sich gleichzeitig jeder "richtige" Programmierer (ich sag jetzt mal: So C#- und Java-Leute) an den Kopf fast, wenn er das zu Gesicht bekommt. Dass man sowas nicht macht, lernen die Jungs und Mädels schon in der Klippschule, nur bei uns im Baan-Umfeld kopiert einer diesen Unfug vom nächsten. Damit muss jetzt Schluss sein!

Genug der preliminarischen Zorns: Der Fehler heißt: Globale Variablen nutzen, ohne die zwingende Notwendigkeit dazu zu haben.

Diejenigen, die seit Jahren "sauber" programmieren, mögen jetzt bitte wegschauen. Und diejenigen, die das im folgende Beschriebene tun, mögen ihren Programmierstil bitte ändern. Und der ersten Gruppe sei gesagt: Auch wenn Ihr's nicht glaubt, die in der zweiten Gruppe san die mehran.

Also. Grundkurs Programmierung. Was ist eine globale Variable? Eine globale Variable ist eine, die im ganzen Kontext eines Programmskripts verändert und abgerufen werden kann. Vulgo: Eine Variable, die oben steht, in der declaration-Section, außerhalb einer Funktion.

Um einen ganzen Haufen globale Variablen kommt man in Baan leider nicht rum. Die typische Deklaration von Tabellen am Anfang sind genau genommen globale Variablen (sie definieren eine Variable, die so heißt wie die Tabelle, den sog. Record-Pointer). Externe Variablen, die auf Forms oder Reports benötigt werden, sind ebenfalls zwingend global. Dann gibt's noch den Fall größerer Datenstrukturen, die man mangels komplexer Datentypen in der Regel über global definierte Arrays abzubilden hat.

Niemals aber, liebe Leute, niemals aber braucht man globale Variablen, um einen Bearbeitungszustand von einer Funktion an eine andere Funktion durchzureichen.

Also, warum dann um Himmels willen finde ich in 90% aller Anpassungen und Addons solche Konstrukte:



|Mein Programm:

declaration:
table txymmm471
domain tcyesno weiter.ok

functions:
function tu.was () {
select xymmm471.*
from xymmm471
order by xymmm471._index1
selectdo
tu.was.anderes ()
if weiter.ok = tcyesno.yes then
...
endif
endselect

}

function tu.was.anderes () {
....
if irgendwas then
weiter.ok = true
endif
}



Das große Problem bei diesen Konstrukten ist, dass sie bei jedem nicht-trivialen Programm völlig unübersichtlich werden. Jemand anderes, der den Programmcode ankucken muss, blickt absolut nicht mehr durch, wo die Bedingung ist,von der die Ausführung eines bestimmten Programmteils abhängt. Weil jede beliebige Funktion im Programm die globale Variable ändern kann, sind zudem Fehler im wahrsten Sinne vorprogrammiert.

Funktionen haben Rückgabewerte. In Baan 3GL/4GL sogar mehr als einen, weil man Parameter als "Referenz" übergeben kann. Eine Funktion sollte mit ihrer Umgebung immer nur über ihre Ein- und Ausgabeparameter kommunizieren, und niemals nicht irgendwelche Dinge "außerhalb" ihrer eigenen kleinen Welt ändern. Das lässt sich nicht immer durchhalten - gerade Tabellen sind nunmal grundsätzlich global. Aber Berechnungsergebnisse und vor allem ein Rückgabestatus müssen das eben nicht sein.

Obiges Beispiel schreibt Ihr also bitte in Zukunft wie folgt:


|Mein viel schöneres Programm:

declaration:
table txymmm471

functions:
select xymmm471.*
from xymmm471
order by xymmm471._index1
selectdo
if tu.was.anderes () then
...
endif
endselect

}

function domain tcbool tu.was.anderes () {
....
if irgendwas then
return (true)
endif
return (false)
}


Also: Die Funktion tu.was.anderes wird aufgerufen, und sie gibt dem
aufrufenden if-then-Block einen Wert zurück, den dieser auswertet.