Das Notes Forum

Lotus Notes / Domino Sonstiges => Projekt Bereich => Thema gestartet von: Marinero Atlántico am 13.12.04 - 19:30:05

Titel: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 13.12.04 - 19:30:05
Hi,

das wäre eine gute Idee. Ich hab momentan wirklich wenig Zeit.
Head First Design Patterns hat in Sachen einfachen Beispielen wirklich Standards gesetzt und man könnte dann auch sehen, wo eben die Nachteile von LotusScript OO liegen.
Werde drüber nachdenken sobald ich Zeit habe.
Ab nächste Woche sollte es ein wenig ruhiger werden.

Jemand Interesse. Jens, Thomas, Matthias?

Nicht nur ich halte GoF bezüglich OO für mehr als wichtig.
Würd nach den Kapiteln von Head First Design Patterns vorgehen.
Und die Beispiele sehr sehr einfach halten. Also gar nicht mehr Ansichten und Dokumente referenzieren, sondern rein in einer ScriptLib bleiben.
Als Daten können dann Types oder Arrays oder Lists dienen.
Ähnliche "schwachsinnige" Beispiele wie in HF DP (Truthähne, die sich als Enten verkleiden, etc.)

Gruß Axel
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Semeaphoros am 13.12.04 - 19:46:49
Die Idee finde ich gut. Kannst Du uns noch Links oder Literatur angeben? Danke
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 13.12.04 - 20:03:47
http://c2.com/cgi/wiki?DesignPatterns *
und eben Head First Design Pattern (hab ich im Java Forum stehen.

Bruce Eckel schreibt auch seit ca. 25 Jahren an seiner Version:
http://mindview.net/Books/TIPatterns/

Die ganze Bewegung begann sich ca. 1995 mit dem berühmten GoF Buch zu verdichten. (s. sicher c2.com wiki). Nur ist das wirklich sehr, sehr schwer nachzuvollziehen.

http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=9&t=002907

Gruß Axel

* Das ist btw. der erste Wiki oder "the only wiki that matters" :-)
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: TMC am 13.12.04 - 20:35:40
Gute Idee, ich bin sehr interessiert   :D
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: animate am 13.12.04 - 21:30:03
das ist eine gute Idee. Habe ich schonmal angefangen, weil ich es auch für eine gute Idee hielt. Ich habe dann aber aufgegeben, weil es ziemlich langweilig war.

Viel interessanter fände ich, wie du schon mal vorgeschlagen hast, Axel, LotusNotes DP zu finden und zu beschreiben.

Jetzt sagt bestimmt jemand, haben wir doch schon mit den BP-Postings hier im Forum.
Das ist natürlich korrekt und die Dinger sind auch klasse. Nur sind die mir viel zu detailliert. Ich denke eher an Pattern, die das DB Design betreffen.

Leider fällt mir grad kein gescheites Beispiel ein (bin wohl schon zu lange raus aus der Sache. Wobei, das von Thomas Schulte gerade vielleich sowas wär, also nicht sein spezielles Problem, eher so die Schichtenproblmatik, wohin mit meinen Logikfunktionen. Naja, vielleich fällt mir, oder euch ja noch mal was ein).

Nichtsdestotrotz, ich würde schon das ein oder andere Pattern nach LS übersetzen (wenns übersetzbar ist). Du musst aber die Arbeitspakete schnüren, Axel, als Projektleiter.
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: TMC am 13.12.04 - 22:08:21
noch 2 Links:

Design Patterns erklärt inkl. Muster nach GoF mit Beispielen:
http://de.wikipedia.org/wiki/Entwurfsmuster

Design Patterns nach GoF mit UML-Diagrammen und C# Quellcodes:
http://www.dofactory.com/Patterns/Patterns.aspx
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: animate am 13.12.04 - 22:13:56
ihr wollt Links? Ihr bekommt Links

http://www.cetus-links.org/oo_patterns.html
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 14.12.04 - 10:35:23
Ich versuche die Beispiele sehr, sehr einfach zu halten.
Werd das erstmal selber mit Strategy, Abstract Factory oder so versuchen. Wenn das funktioniert können andere ja weitere Patterns übernehmen.

@Thomas: Ich glaube Lotus Notes DPs zu finden ist eine wesentlich schwierigere Aufgabe. Muss man erstmal überlegen auf welchem scope Level man suchen muß. Ziemliche Pionierarbeit. Hohe Frustrationsgefahr.
Ob der Übertrag der GoF auf LoNo langweilig ist, werde ich sehen.  ;)

Ich besitze so ziemlich alle Design Pattern Einführungsbücher für Java. Als Einstiegsbuch in dieses Thema ist "Head First Design Patterns", von den Freemans, Sierra/Bates sowie Johannes de Jong, Jason Menard et. al. als technical reviewer eindeutig das beste Buch (egal ob man visuell, blau oder rot-weiss kariert ist).
Quasi alle Leute sagen, dass dieses Thema komplexer/abstrakter ist als wie zuerst von ihnen angenommen.

Zitat
Originally posted by Ilja Preuss:
[QB]
 
Well, yes. I'd say that is because software development is harder than it looks, though.  ;)
 
Seriously, in my experience OO doesn't have some of the benefits many people expect: "better matches human thinking", "understandable to customers", "easier to model the real world" etc. pp.
 
What it does is giving you additional tools to manage dependencies between software modules, most importantly polymorphism.
 
It's not easy to get that right - it took me personally several years to grok it (if we assume that I do today  ;)  ).
 
On the other hand, it's not easier with procedural development - after all, the main difference is that procedural languages are missing polymorphism, which, again, is a tool to manage dependencies.[/QB]

 
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Semeaphoros am 14.12.04 - 10:49:39
Das ist ein seehr, seehr gutes Zitat, Axel, das Du da gebracht hast, jemand, der die Sache praxisnah und nicht religiös sieht. Danke
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: animate am 14.12.04 - 10:57:12
für AbstractFactory habe ich hier schon mal ein Beispiel gepostet:
lotusgeek (http://www.lotusgeek.com/SapphireOak/LotusGeekBlog.nsf/plinks/ROLR-5UV6YM)

ist kein witziges Beispiel, eher praktisch. Und ich bin damals etwas mit copy und paste durcheinander gekommen, aber das dürfte vernachlässigbar sein
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 14.12.04 - 11:34:16
Das ist ein seehr, seehr gutes Zitat, Axel, das Du da gebracht hast, jemand, der die Sache praxisnah und nicht religiös sieht. Danke

Ilja ist definitiv einer der top 10 Gurus von Javaranch.
Ich glaub der hat einfach alle OO-Bücher der letzten 10 Jahre gelesen, kennt den c2-wiki auswendig, setzt das ganze praktisch um und denkt darüber nach.
http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=recent_user_posts&u=00016595

98.9% der >100-Posting-Rancher sehen die Dinge nicht-religiös, praxisnah. Ilja ist aber ein Spezialfall, weil er einfach wirklich sehr kompetent ist.

@Thomas: Das Beispiel ist sicher gut. Ich will für meinen Versuch aber nicht so viel Infrastruktur, Ressourcen und praxisnähe. Das ist dann weniger Arbeit. Mal schaun, ob das gangbar ist.
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 16.12.04 - 20:49:33
vor dem 30.12. nix zu erwarten.
Hab da aber jetzt sozusagen beruflich mit zu tun (LoNo und coding von OO-Design).
Also Motivation ist da.

Gruß Axel 
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: TMC am 16.12.04 - 21:05:16
OK, prima.
Hast Du eine Idee womit man starten könnte?

Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: -Michael- am 19.12.04 - 21:41:58
Hi,

ich hatte vor einigen Wochen den OO-Thread von TMC verfolgt (http://www.atnotes.de/index.php?topic=16422.0) und daraus eine einfache Klasse erstellt:
http://www.atnotes.de/index.php?topic=18601.0

Bei OpenNTF hatte ich das in der CodeBin auch veröffentlicht:
http://www.openntf.org/Projects/codebin/codebin.nsf/CodeByDate/71E930683C3401A3C1256F2F00611BAA

Alain H Romedenne schreibt dort, dass das ganze nach Design Patterns schreit:
Zitat
History class sample is paving way to "Observer" & "Command" design patterns enablement:

Er meint wohl die GOF-Patterns, und wenn ich mir GOF so ansehe, dann klingt es auch sinnvoll, hier diese Patterns zu verwenden. Allerdings fehlt mir da der Skill.

Aber vielleicht ist das für Euch eine Anregung, diese Patterns anhand einem konkreten Beispiel umzusetzen.

Michael
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 20.12.04 - 10:03:10
Es ist einfach so, dass in den letzten Jahren Anforderungen für sauberes OO-Programmieren aufgestellt und Techniken vorgeschlagen worden sind, um diese Anforderungen zu erfüllen. Dabei bilden die GoF-Pattern eine ausser jeder Diskussion stehenden unverzichtbaren Gundlage.
Ich hab z.Zt. z.B. ein Projekt, wo - wie Paul Breitner sagen würde - ziemlich vogelwild OO programmiert wurde. Sucks bigtime.
Dieses ganze Theorie-OO Zeugs, das von Gamma, Fowler, Ward Cunningham, Larman uvam. produziert wird sind nicht irgendwelche schöngeistigen Consulting-Ideen sondern verdichtete Erfahrung von Praktikern.
Das Zeugs ist komplex. Aber imho effektiver und interessanter als der Featurismus von Lotus, wo sich Anwendungsprogrammierer wie ich ständig neuen "einfachen" Produkten gegenübersehen,  deren Schwächen nicht diskutiert werden (DWF, LEI, Domino Workspace, XML, etc.)
Jens Augustiny (Semaphoros) hatte hier teilweise für mich Anzeichen einer Argumentationslinie, dass OO eigentlich ganz einfach und natürlich ist und das man es mit LotusScript Kenntnissen eigentlich schon "kann". Das widerspricht völlig meinen Erfahrungen.
Desweiteren besteht ein gewisser Zielkonflikt zwischen "konkret" und "vielseitig verwendbar".
Um aber hier meinen Versuch zu starten brauche ich mehr Zeit als ich momentan habe.
Die IT-Krise in der westlichen Welt hat dazu geführt, dass die User von openSource Seiten heute deutlich kritischer gegenüber dem code sind als zur Zeit des oh-supi-open-source (2001).
Ohne seine Aussage geprüft zu haben, habe ich somit eine gewisse Sympathie für die Kritik von Alain H Romedenne.

Gruß Axel
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Semeaphoros am 20.12.04 - 12:25:48
Jens Augustiny (Semaphoros) hatte hier teilweise für mich Anzeichen einer Argumentationslinie, dass OO eigentlich ganz einfach und natürlich ist und das man es mit LotusScript Kenntnissen eigentlich schon "kann".

Da hast Du mich aber wirklich nicht verstanden. Meine Argumentation ist vor allem, das Nehmen von Angst gegenüber OO, welche ich bei vielen LS-Codern/Designern feststellen kann. Da Notes/Domino selber OOrientiert ist, ist dem LS-Gewandten die ganze Sache nicht fremd, und mit etwas Auseinandersetzung mit dem Domino Objekt Modell lässt sich sehr gut OO-Praktiken aus den Domino-Gegebenheiten ableiten. Sprich, der LS-Gewandte muss nicht bei Null anfangen, wenn man ihm den richtigen Weg zeigt. Mehr ist in meinen Aussagen nicht drin und meine diesbezüglichen Vorträgen (der nächste an der Lotusphere 2005 nächsten Januar) zielen genau darauf hin, dem LS-Programmierer hier Hilfestellung auf dem Weg zu OO zu geben. OO liegt nicht primär in LS, sondern im Produkt Notes/Domino, man muss den Leuten vor allem zeigen, wo sie das finden, und viel wichtiger: es ist ein Umstellen der Denkweise. Zentrale Aussage in meinem Vortrag nächsten Monat: ein OO-Projekt funktioniert nur, wenn man durchgängig von der Analyse bis zur Realisation in OO-Mustern denkt, dieses Denken muss her, die Grundlagen und Muster kann Domino/Notes selber liefern (das ist wohld as, was Du als "natürlich" interpretiert hast). IBM selber vergisst, die gegenwärtigen "treuen" Entwickler dort abzuholen, wo sie jetzt stehen und damit sehen all diese Sachen, in die sie die Lotus-Leute bewegen wollen, für diese wie völliges Neuland aus, kein Wunder, dass sich der durchschnittliche Lotus-Entwickler dagegen wehrt, alles Neue wird meistens erst einmal abgelehnt.
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 20.12.04 - 16:35:19
Ist für meinen Geschmack zu "yellow".
Man braucht nur auf das "brilliant" Domino Objekt Modell zu schauen, einen "konsequenten" OO Analyse/Design-Prozess zu haben und alles wird gut...
Ich hab hier ein Projekt übernommen mit OO-in-LS-code, wo ich nur sagen kann, dass die brilliant geniuses, die das verzapft haben, deutlich zu wenig und nicht zu viel Angst vor OO haben.
Werde diesen GoF Thread weitermachen to teach you fear, angst and terror.  ;D
 

Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Semeaphoros am 20.12.04 - 16:51:48
Eben, Axel, wenn Du in meinem Post zwischen den Zeilen lesen würdest, genau so verliert man die Leute, wenn man sie nicht dort abholt, wo sie sind. Sprich, wenn die Leute gelb sind, dann musst Du sie gelb abholen und mit der Zeit dann halt umfärben. Sonst laufen sie davon.
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 20.12.04 - 21:20:27
Das folgende ist keine Wahrheit, sondern ein Internet Thread. Für Wahrheiten, bitte Bücher kaufen.

Warum gibt es OO?
Hauptgrund ist wohl die leichtere Anpassung des codes an sich wandelnde Anforderungen. Bei sich ständig wandelnden Anforderungen ist es einfach zu zeitaufwendig, in mehr oder wenig gut funktional dekomponierten Funktionen mit Tonnen von if-thens nach der entscheidenden Stelle zu suchen, wo man was ändern muß.
Man glaubt deshalb, dass es übersichtlicher ist Programmlogik in sogenannte Klassen zu packen. Klassen sind Blaupausen für Objekte. Klassen haben Methoden und mehr oder weniger temporäre Variablen (die nennt man Eigenschaften).
Klassen behandeln am besten genau einen Aufgabenbereich der Programmlogik. Sie kappseln sozusagen diesen Aufgabenbereich. Wenn sich die Anforderungen an diesen Aufgabenbereich ändern, muß man nur die Klasse ändern und nicht tagelang im code nach den entsprechenden Stellen suchen. Es kann natürlich auch vorkommen, dass eine Änderung der Anforderung in mehreren Klassen code-Änderungen erfordert. Das läßt sich nicht immer vermeiden, ist aber nicht so gut.

In der Frühphase von OO (frühe 90er Jahre) gab es alle möglichen einfachen Argumente für OO, von denen aber viele nicht so toll sind.
Heute glaubt man, dass es irgendwie scheissendreck-kompliziert aber händelbar ist und Sinn macht. Und das man besser wird, je tiefer man sich mit dem Zeugs einlässt.
Wichtig sind v.a. die sogenannten GoF Design Patterns, die gute OO-Design-Praxis in vereinfachten Beispielen "verdichten".
Die Design Patterns sollen eine Hilfe sein, um die sogenannten OO-Prinzipien zu erfüllen.
Die OO-Prinzipien sind:
- Kappsele das, was sich ändern wird (um auf Änderungen in den Anforderungen an einer Stelle zu reagieren)
- Komposition ist total oft besser als Vererbung (was Komposition ist, wird später noch klar)
- Programmiere gegen Interfaces und nicht gegen Implementierungen (was das ist, wird später noch klar)
- strebe nach lose gekoppelten Designs zwischen interagierenden Objekten (was das ist, wird später noch klar) 
- Klassen sollten offen sein für Erweiterungen, aber geschlossen für Veränderungen (man sollte möglichst nicht in bestehenden code rumhacken. Um Funktionalität zu erweitern/ggbfls zu verändern sollte es möglich sein, einfach eine neue Klasse hinzuzufügen).
- Mach deine Klassen besser immer nur von Abstraktionen abhängig und nicht von konkreten Klassen (was das ist, wird später noch klar)
- Sprech nur zu deinen Freunden (also besser nicht barocke Gebilde der Art wie ship.getRoomNumber(room.getNumber()).getRenterId().getName(); )
- Don't call us, we'll call you. (wenn du deinen LotusScript Bob in sowas wie querySave ablässt, dann wird das ja auch nicht aus der Maske explizit aufgerufen, sondern der User speichert das Dokument und dann wird der code im QuerySave von Notes automatisch aufgerufen. So ungefähr, wird aber noch genauer erläutert).
- Eine Klasse soll nur einen Grund haben, um verändert werden zu müssen (geht wieder in die Richtung, dass möglichst wenig an bestehenden code geändert werden soll, wenn sich die Anforderungen ändern).

In der Folge sollen hier die sogenannten GoF Patterns als Lotus Script implementiert werden. Dabei soll gezeigt werden, inwieweit diese total berühmten GoF Patterns die oben genannten Anforderungen erfüllen und was an diesen eigentlich so toll ist.

Gruß Axel
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 20.12.04 - 22:32:37
Kappseln, Kompisition, Interfaces, Implementierung, lose gekoppelt, interagierende Objekte, Abstraktionen, GoF Patterns.
Lots of confusing stuff  ???
Tonnen von Fremdwörtern  ;D

In der Folge versuche ich die garantiert sinnfreien Beispiel aus HF Design Patterns von Java nach Lotus Script zu portieren.
Ich versuche dann zu beschreiben, wie sich diese komischen Design Pattern mit den noch seltsameren OO Prinzipien (s.o.) in Verbindung stehen.
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: koehlerbv am 20.12.04 - 22:53:00
Nicht labern, Axel, sondern machen! Ich bin wirklich an diesem Thread äusserst interessiert und beileibe nicht so "gelb", wie Du vielleicht denken magst. Gerade, weil Du diesen Thread führen möchtest, bin ich an Deiner non-pure-yellow-Sicht sehr interessiert und würde mich gerne beteiligen (sicherlich vorrangig lernend).

Mein Dank schleicht Dir jedenfalls schon voraus.

Bernhard
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 22.12.04 - 17:59:35
Erste konkrete Postings sind so zwischen Weihnachten und Neujahr zu erwarten, da ich zur Zeit einfach zu viel Arbeit habe, weil zum Jahresabschluss von Kundenseite mein natürlicher Feind (konkrete Ergebnisse) leider total hip sind.  ::)

@All: Meine Motivation wird es extrem steigern, wenn Fragen gepostet werden. Also so mehr aktives Lernen.
Mein mir vorschwebender Ansatz ist grade, dass ich sehr einfache Notes-Implementierung der gof Patterns schreibe und die Hintergründe eben gerade nicht aufschreibe. Bei meiner Paranoia alles "richtig" zu beschreiben würde das eh ziemlich langweilig.
Ich bin (noch) kein Weltmeister in LotusScript OO, weil ich da einfach noch nicht viel gemacht habe, werde es sicher aber schnell werden. Auf Fehler meinerseits bitte schonend aufmerksam machen. Nicht so unverschämt, wie ich das immer mache.

sincerely yours

a sinner
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: animate am 22.12.04 - 21:03:23
- Kappsele das, was sich ändern wird

Falls es jemanden interessiert - dieser kleine, unbedeutende und vielleicht sowieso logisch erscheinende Satz ist für mich (un sicher nicht nur für mich) der Schlüsselsatz überhaupt. Wenn du den kapiert hast und befolgst, dann bist du eigentlich schon ein guter Designer :)
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: koehlerbv am 22.12.04 - 21:32:19
Absolute Zustimmung, Thomas. Und diese Stellen muss man erkennen (können). Ob man das dann DPs nennt oder anders oder ... sowas gehört zur absoluten Basis-Überlegung. Wird aber selten befolgt. Ich stolpere ja manchmal über Altlasten, und das schmerzt extrem. Schon der (ggf. Selbst-)Zwang zu "Ich schreibe das nur EINMAL !!!" zwingt schon zu extremen Verbesserungen.
Wie gesagt: Ich wäre gern dabei bei dieser Sache und bin fest überzeugt, dass ich da noch eine Menge lernen kann (wofür man ja nie zu alt wird, wenn die Sichtweise stimmt  ;) )

Einer der DP-Kenner sollte aber mal den Anfang setzen. Bei mir heisst das  gedanklich vielleicht nur alles anders, aber ...

Bernhard

PS: Dein Posting beim LotusGeek fand ich übrigens hochinteressant, Thomas. Ich mache sowas recht ähnlich, sollte aber noch mehr abstrahieren. Ob das dann DP heisst oder wie auch immer ... der theoretische Unterbau könnte / sollte bei mir durchaus dem aktuellen "Sprech" angepasst werden und natürlich mit BPs / DPs erweitert werden. Ich lerne gerne.
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: TMC am 22.12.04 - 21:34:04
Nicht labern, Axel, sondern machen!
Also ich finde auch Theorie sehr interessant, so z.B. Axel's Posting #18 hier.
Irgendwann sollte es dann aber in die Praxis gehen  :)


Zitat
- Kappsele das, was sich ändern wird

Thomas / Axel:

Frage: heißt es nicht umgekehrt auch: "Kapsele das was sich *nicht* ändern wird" ?
(also typischescherweise in der LS-Programmierung die Auslagerung von immer wiederkehrenden Functions/Subs in ScriptLibs. Oder speziell bei der LS-Klassenprogrammierung die Auslagerung in Methoden. Typisch z.B.: das 1000ste ReplaceSubstring, eine Sort-Routine, etc. etc. Ich denke sowas wird man - sobald es mal steht - nur noch sehr selten ändern).
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: koehlerbv am 22.12.04 - 22:28:23
Matthias, natürlich gehört alles gekapselt, was irgendwann wiederkehren wird. Also sehr, sehr viel.

Ich habe dafür ScriptLibs wie
- BasicLib: Was jede DB braucht. Ich habe mir mittlerweile abgewöhnt, hier scheinbar "unnötige" Routinen pro App zu entfernen. BasicLib ist BasicLib, und fertig.
- ReportRoutines: Routines für das Logging (wenn erforderlich)
- AgentTools: Some tricky routines to manipulate the agent settings  ;D
- CommonAppLib (was die Klasse von Apps - so vorhanden - immer braucht)
- CommonAppUILib (was die Klasse von Apps - so vorhanden - immer braucht)

Und dann kommen SpecialAppLib, SpecialAppUILib etc.

Die Libs (ausser den Special...Lib) werden per %INCLUDE eingelesen. Wenn sich also eine neue Erkenntnis ergibt, ist überall Neukompilierung (und ggf. Anpassung) erforderlich, was ja bei den Basics nun überhaupt nicht schadet und dazu zwingt, "ein für allemal" gründlich zu programmieren.

Das war jetzt ein bisschen BP, aber nicht DP. Und es zwingt von vornherein dazu, wie man Libs sinnvol laufbaut (nicht, dass LibA LibB aufruft, diese dann LibC und diese wiederum LibA, was gerechterweise tierisch knallt und Kopfschmerzen bereitet, weil man 'ne Menge falsch gemacht hat).

Bernhard
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 23.12.04 - 20:28:56
O.k. die Idee dieses Threads besteht gerade darin, praktischen code zu produzieren und dann daraus Theorie, Terminologie, Konzepte, Klassifizierungen, etc. abzuleiten.
Nur dafür brauche ich eben mehr Ruhe, die ich ja auch bald bekomme (trotz extra gig am 28. + evtl. 29. inklusive real existierender Vorbereitung).
Aber noch ein paar Theorieschnippsel, weil ich das zufällig gestern abend noch im GoF Buch gelesen habe:

Zitat
- BasicLib: Was jede DB braucht. Ich habe mir mittlerweile abgewöhnt, hier scheinbar "unnötige" Routinen pro App zu entfernen. BasicLib ist BasicLib, und fertig.
- ReportRoutines: Routines für das Logging (wenn erforderlich)
- AgentTools: Some tricky routines to manipulate the agent settings  Grin
- CommonAppLib (was die Klasse von Apps - so vorhanden - immer braucht)
- CommonAppUILib (was die Klasse von Apps - so vorhanden - immer braucht)
Wie noch zu sehen sein wird, sind Patterns etwas anderes (soll sich dann aus den Beispielen erschliessen und es wie ihr wisst, geht es nicht um besser oder schlechter). 
Das weitestgehend sich auf c++ beziehende GoF Buch von 1995 bezeichnet solche wiederverwendkehrenden Libraries als
a) Toolkits
b) Frameworks
Patterns sind etwas explizit anderes.
Toolkits sind dabei wiederverwendbare Funktionsbibliotheken, die ein breites Anwendungsspektrum für einen Haufen an Stellen in einer Menge von Anwendungen haben, z.B. eine IO-Library oder eben sowas wie die beiden CommonAppxxx Libraries.
Frameworks haben ein enger definiertes Anwendungsspektrum. Z.B. ein Framework um alle möglichen verschiedenen Graphen zu erzeugen, oder pdf Dokumente, oder eben Agenten-Settings zu manipulieren (Notes) oder für Logging. 

In Java sind die Toolkits (und die Frameworks, etwa für Regular Expressions) Bestandteil der "core Library". Deshalb sind da so viele Klassen.

Patterns sind etwas weniger konkretes und code ist immer nur ein Beispiel für die Implementierung eines Patterns. Ausserdem sind sie "kleiner". Ein Toolkit oder ein Framework kann immer aus mehreren Pattern bestehen aber ein Pattern nie aus einem Toolkit oder Framework.

Hört sich erstmal esoterisch an, aber die Perspektive ist eben anders. Es ist noch nicht mal kompliziert.
 
Macht euch nicht so einen Kopf und wartet auf die Beispiele.

Patterns sind ausserdem für die Programmierpraxis etwas sehr konkretes. Gerade Einsteiger-OO Bücher stellen OO in aller Regel zunächst immer aus der Analyse-Perspektive da. Ein Aufgabenbereich wird als Klassen/Objekte wiedergegeben, die miteinander in Beziehung stehen, bzw. miteinander interagieren. Diese Klassen/Objete sind Repräsentationen von der realen Welt (Als Beispiel: Student, Kurs, Raum).
Wirklicher Code wird dann aber aus dieser Ananlyse-Perspektive in eine Design-Perspektive übertragen, woraus dann der code entsteht. Die Anwendung aus dieser viel code-näheren Design Perspektive sieht dann ganz anders aus. Eine Menge an Klassen sind einfach keine Repräsentationen von Objekten in der Realen Welt, sondern mehr so Dinge, die die Anwendung zusammenhalten. (s. Bilder: Eclipse screen shot ist code, was unmittelbar aus Design folgt. Anzahlmässig viel mehr Klassen als in Analyse.)
Und um herauszufinden, welche Klassen man braucht und wie man diese zusammensetzt, um eine Analyse umzusetzen, braucht es eben diese Pattern.
Und es gibt auch nur 23 GoF Pattern (sind aus OO-Sicht die fundamentalsten, die es gibt). Und die sind noch nicht mal gleich "wichtig". Und ausserdem ähneln sie sich teilweise sehr.

wenn das euch verwirrt, tut es als schöngeistiges Gequatsche ab

Axel

Beispiele folgen
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 04.01.05 - 13:08:35
1.   Es gibt code.
2. Gof Design Patterns sind nicht irgendwelche „genialen“ Bibliotheken, sondern im-ersten-Blick-nicht-sehr-offensichtliche-echt wertvolle Hinweise zur Erstellung von flexibel anpassbaren OO-Code. Das Thema besitzt starke Abhängigkeiten zu anderen Teilen der OO-Theorie, so dass ich die erst mal versuche einfach darzulegen, wie ich diese sehe. Und zwar anhand von konkreten Code.

Ich habe beschlossen, die Designpatterns in eine Art Konsoleninfrastruktur mit LogDatenbank zu tun.
Dafür gibt es in Domino das Alog4.ntf template:.
Also bitte:
1.   Neue Datenbank erstellen
2.   Erweiterte Templates anhaken (show advanced templates)
3.   Agent Log auswählen (filename: alog4.ntf)
4.   Als Filename habe ich genommen HF_DP\ALog.nsf, als Name „Alog for HF_DP code“ (die krude Mischung aus Englisch und Deutsch ist so). Ihr könnt auch etwas anderes nehmen. Besser lokal installieren.


Als Datenbank für den Designpatterns code gibt es die Datenbank HF_DP.nsf (s. Attachment, im Administrator unterzeichnen ist immer eine gute Idee). Diese irgendwo besser im lokalen NotesData anlegen (z.B. im Verzeichnis HF_DP).
Wenn ihr die Datenbank auf eurem Rechner habt, geht ihr zur Ansicht Konfiguration. Da gibt es einen „Erzeugen/Konfiguration Logger“ Aktionsbutton. Das Dokument ist aber schon da. Dieses bitte bearbeiten. Ggbfls den Speicherort der Ressource LogDatenbank, die ihr eben erzeugt habt anpassen.

Die Werte sind:
Server:     (im Sinne von <leer>
Datenbankpfad: HF_DP\Alog.nsf
Default Identifier: DEFAULT (eigentlich egal)

Nun befinden sich in der Datenbank HF_DB 2 Skriptlibraries, in denen je eine Klasse das Auslesen des Konfigurationsdokument und die Kommunikation mit dem NotesLog-Objekt unterstützen (Designer öffnen und Überblick, nicht Durchblick verschaffen).
Dabei benutzt ein Objekt der Klasse Logger ein Objekt der Klasse ConfigDocWrapper (s. code).
Jede dieser Klassen hat 1, eine, una, one Aufgabe:
-    Logger regelt das mit dem Logging
-   ConfigDocWrapper kann Konfigurationsdokumente auslesen.

Gemäss objektorientierter Analyse sollen Klassen kohäsiv sein. D.h. sie sollen 1 thematische Aufgabe übernehmen. Manchmal ist es nicht so einfach herauszufinden, was nun sinnvollerweise 1 thematische Aufgabe darstellt. Oft ist es einfach.

Hier habe ich schon viel Unsinn in bestehenden code gesehen. Ich mein, man muss wirklich kein mega-guru sein, um auf die Idee zu kommen, dass eine Konstruktion mit zwei Klassen wo eine Klasse, die gleichzeitig xml schreibt, LSA Konfiguration ausliest, weitere Dateien erzeugt mit einer Klasse kommuniziert, die Notes Konfiguration ausliest und durch eine NotesView iteriert möglicherweise nicht so besonders gut thematisch gegliedert ist. 
Das aber nur am Rande, da es hier mehr um OO-Design gehen soll.

Ansonsten sind die beiden Klassen in den SkriptLibs in HF_DP.nsf von einem OO Standpunkt aus fragwürdig. Der Programmierer dieser Klassen besitzt vielleicht einen gewissen tragischen, möglicherweise genetisch bedingten Hang zur chronischen Underperformance. Gerade diese Schwächen können aber im weiteren Verlauf des Threads ganz nett sein, um OO-Design-Problematiken aufzuzeigen. Es wäre ganz gut, wenn die hier anwesenden Leute sagen könnten, wo aus ihrer Sicht die Schwächen liegen.

Diese beiden Klassen werden von den Agenten genutzt, in denen die Klassen für die weiteren Erörterungen drin sind. Erst mal ist dort der Agent DecoyDucksDontFly_Start mit den Klassen Duck, RedHeadDuck und MallardDuck. Es ist ein Entensimmulationsprogramm. Im Initialize des Agenten ist code, der Objekte der Klassen erzeugt und diese quasi als client nutzt.. Ihr könnt das erst mal ausprobieren, indem ihr diesem Agenten aus dem Notes Menü Agenten startet. Evtl. im Debugger anschauen was passiert.
Falls alles richtig läuft, werden ein paar Einträge in die Log-Datenbank geschrieben.

Logger benutzt ConfigDocWrapper, um die Log-Db zu finden.
Die Duck-Klassen in dem Agenten „DecoyDucksDontFly_Start benutzen Logger.
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 04.01.05 - 13:14:31
Ich stelle hier erst mal kurz die beiden Klassen wie sie in der Datenbank benutzt werden als UML Klassendiagramm dar. Damit kann man am ganz gut ein paar OO-Grundlagen erklären.
Statische Sicht (UML-Klassendiagramm):
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 04.01.05 - 13:15:23
Dieses Diagramm ist nicht so schwer zu lesen.
In den lustigen Karteikarten sind 3-teilige Dinger drin.
Oben in den 3-teiligen Dingern stehen Buchstabenfolgen drin, die extrem an die Namen der Klassen erinnern, von denen so eben die Rede war und die darüber hinaus auch noch im code der Datenbank stehen. Die 3-teiligen Dinger sind also Klassen.
Die sind in den Karteikarten drin und –aha- auf den Karteikarten stehen die Namen der SkriptLibs und Agenten, wo die Klassen drin sind.
Oben sind dann noch bekannte Domino Klassen.
Die Karteikarten heissen in UML packages. Die Notes-Klassen sind in einer –sagen wir – speziellen Art von packages namens Subsystem. So wichtig ist die Unterscheidung hier nicht.
Packages sind eine Art Container. Etwas, wo man was reintut. ScriptLibs und Agenten sind ja auch etwas, wo man Klassen reintut. Also passt dieses UML-Element wirklich sehr gut.

Die meisten Leser sollten schon mal gehört haben, dass Klassen Eigenschaften und Methoden haben. Im zweiten Teil der Klassen stehen die Eigenschaften und im 3. Teil die Methoden.
Das minus-Zeichen vor den Eigenschaften steht für den Zugriffs-Modifizierer private
Das plus-Zeichen vor den Methoden steht für den Zugriffs-Modifizierer public.
Was das genau ist, wird noch erklärt. Hier sind alle Eigenschaften private und alle Methoden public. Das ist nicht zwangsläufig so. Was es mit diesen Zugriffsmodifizierern auf sich hat, wird noch erklärt.
Die Domino-Klassen haben überhaupt keine Eigenschaften und Methoden eingetragen. Das ist aber nur, weil man in UML Teile weglassen kann. Die interessieren hier nicht und stehen sowieso in der Notes Hilfe.
Es interessiert mich nur, dass in den selbstgeschriebenen Klassen diese Domino-Klassen benutzt werden.

Zwischen den Klassen gibt es eine Menge Pfeile. An manchen steht <<is-a>>, aber an den meisten <<has-a>>. Wo <<is-a>> steht, sieht das Pfeilende anders aus als die wo <<has-a>> steht.
Normalerweise würde man in einem UML Diagramm nicht <<has-a>> und <<is-a>> reinschreiben, weil das in UML schon durch genau diese Formen der Pfeilenden ausgedrückt wird. Ich habs nur zur besseren Klarheit da reingeschrieben.

Beginnen wir mit den <<has-a>> Pfeilen.
Schaut euch die Klasse ConfigDocWrapper in der ScriptLib Configuration an.
Was steht dort oben:

   Private vw As NotesView
   Private docConfig As NotesDocument
   Private keyConfig As String

Und wohin gehen die has-a Pfeile von Configuration im UML-Bild??
Zu NotesView und zu NotesDocument.
Und was steht da oben??
DocConfig as NotesDocument und vw As NotesView.

In den anderen Klassen finden sich im Code die <<has-a>> Beziehungen auch in den Attributen wieder. Ist auch logisch. <<has-a>> im Sinne von „hat-ein“ ist vom normalen Sprachgebrauch so was wie eine Eigenschaft.
Ob man eine Eigenschaft im code in UML als has-a Beziehung oder als Eigenschaft (2. Teil von Klasse) modelliert, befindet sich sowieso im Ermessen des Modellierers. Es gibt gewisse Argumente, warum bestimmte Eigenschaften als has-A Beziehungen dargestellt werden, aber das ist hier kein UML-Kurs und erst mal nicht so wichtig.
Has-A Beziehungen werden auch als Composition bezeichnet. Ein wichtiges Motto der GoF ist: Favour Composition over Inheritance. Ihr müsst das jetzt nicht verstehen. Wird später erklärt. Einfach im Unterbewusstsein aufnehmen. Wenn ihr den Thread zu Ende gelesen habt, wacht ihr als C#.NET Programmierer auf 
Und die anderen Pfeile? Die is-a Pfeile?
Die stehen für Vererbungsbeziehungen (Inheritance).
A RedHeadDuck is a Duck.
A MallardDuck is a Duck.
Klingt logisch.
Und sieht man das auch im code?
Ja.
Public Class Duck
Public Class RedHeadDuck As Duck
Public Class MallardDuck As Duck

Das LS Schlüsselwort As steht für Vererbung oder anders ausgedrückt is-a Beziehungen.

In der nächsten Folge wird genauer die exakten technischen Wirkungen dieser Vererbung anhand des laufenden Codes erklärt (phate Debugger-Session). Diese sind in allen OO-Sprachen sehr ähnlich. Ihr könnt den Agenten starten und es euch schon mal im Debugger und der Log-DB anschauen. Vorweg schon mal das: (hab ich grad bei dem Microsoft Autor Jesse Liberty gelesen): Es gibt durch Vererbung aus Design-Sicht 2 Effekte:
-   tendentiell schon mal problematische code inheritance
-   als zweiten und wichtigeren Effekt Polymorphismus.

Danach wird der Code des Entensimulationsprogramms erweitert. Da wird deutlich, was an Vererbung problematisch ist und warum die GoF Autoren „Favor composition over inheritance“ für eine gute Idee halten. Das Dilemma des Entensimulationsprogramms wird durch das Strategy Pattern angegangen. Das wird die erste Anwendung eines Patterns sein. 

Tipp für Logger/ConfigDocWrapper-Bashing: Schaut auf die Abhängigkeiten. Die has-a Pfeile sind Abhängigkeiten. Welche konkreten weiteren Anforderungen können an diese Klassen gestellt werden (z.B. bei Wiederverwendung in einem konkreten anderen Kontext). Verbesserungsvorschläge?
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: animate am 05.01.05 - 11:00:26
Welche konkreten weiteren Anforderungen können an diese Klassen gestellt werden (z.B. bei Wiederverwendung in einem konkreten anderen Kontext). Verbesserungsvorschläge?

Also nix konkretes und nix was du nicht wüsstest, aber evtl. musst du mal deine Konfiguration woanders herholen oder/und dein Log woanders hinschreiben.
Verbesserungsvorschlag? Da das hier ja auch etwas eine Lehrveranstaltung ist, denke ich dass sich die, die was lernen möchten, dazu Gedanken machen und die Gedanken veröffentlichen sollten.  ;D
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: animate am 05.01.05 - 13:15:05
Welche konkreten weiteren Anforderungen können an diese Klassen gestellt werden (z.B. bei Wiederverwendung in einem konkreten anderen Kontext). Verbesserungsvorschläge?

Hmm, vielleicht doch besser was konkretes. Der Benutzer soll in der Datenbank konfigurieren können, ob er in eine DB oder in ein Textfile loggen will. Außerdem sind in Zukunft noch weitere Log-Formate geplant.
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: TMC am 05.01.05 - 13:17:43
Verbesserungsvorschläge?

OK, wir haben hier mehrere Enten, die nach und nach ein paar Dinge machen sollen wie eben quacken oder schwimmen.
Beim Blick auf den Code fällt auf, dass
jeweils über die ConfigDocWrapper - Klasse das Setup-Dok auslesen lässt.
Also View suchen, Dokument finden, Felder auslesen, etc.

Wenn man jetzt aber nun mit vielleicht 100 verschiedenen Enten zu tun hat, ist das performancemäßig wohl nicht das beste.

<Offtopic>
Im Code steht öfter If Bedingung Then Error 999.
Lt Help sollten sich user-defined Error in der Range zw. 1000 und 1999 befinden. Ist aber jetzt wirklich eine absolute Kleinigkeit, ist mir halt nur aufgefallen ;-)
</Offtopic>

Matthias
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 05.01.05 - 15:53:36
Dies sind 2 sehr gute Punkte.
Thomas hat auf die coupling Problematik aufmerksam gemacht, auf die ich noch weiter eingehen werde. Jedes der Objekte kümmert sich um sein Spezialgebiet (Logging und Konfigurationsdokument auslesen) und - was Sinn macht - sie kooperieren miteinander.
Trotzdem ist diese Kooperation irgendwie zu fest verdrahtet. V.a. benötigt man für die Konfigurations-Klasse in der Datenbank zwingend eine Ansicht "Configuration", was auch eine ziemlich mutige Voraussetzung ist (vielleicht existiert in einer bestehenden Datenbank schon eine Ansicht mit diesem Namen).
Die Klassen aber flexibler zu machen, hat einen Preis. Nämlich, dass die Klassen in der Benutzung ein bischen komplizierter werden. Dazu später mehr. Es wird in moderner OO-Design Literatur immer wieder darauf hingewiesen, dass man nicht Flexibilität um ihrer selbst willen einfügen soll, nur weil man das programmieren kann. Die Flexibilität hat immer den Preis, dass die Klassen etwas schwerer zu benutzen sind. Das ist also ein Abwägen nach dem Gesichtspunkt, wo Wandel der Requirements zu erwarten ist. Dort ist es dann sinnvoll, Flexibilität für etwas mehr Komplexität "einzukaufen".
Mathias sein Punkt war nicht unbedingt zu erwarten und deshalb sehr gut. Ich hab das aber auch so gesehen, als ich die Klassen programmiert habe. In anderen Programmierumgebungen wie z.B. C# würde man solche für alle Enten wiederverwendbare Objekte (nicht Klassen) entweder in einer static-Variable halten oder über eine Singleton-Factory erstellen (wird noch erklärt und die braucht auch dieses static-feature). Ich mach mal ein Java Beispiel mit Lazy Static Initialisierung, damit es klar wird, wie static eigentlich funktioniert. Ich find das durch solche Vergleiche LS OO klarer und nicht unklarer wird.
Wie man Objekte shareable zwischen mehreren Client-Objekten (in diesem Fall Enten) macht, halte ich z.Zt. für ein Problem, dass irgendwie gelöst werden muss. Es ist in der Tat eine Ressourcenverschwendung, dort jedesmal ein Objekt mit den einzelnen Properties zu initialisieren!!!
Eine Herausgeberin des Buches, von dem dieser Thread inspiriert ist (Head First Design Patterns), wird übrigens heftig von Domino Bloggern gelobhudelt. Sie ist übrigens auch Mitbegründerin...  :-X
http://hostit1.connectria.com/twduff/home.nsf/plinks/TDUF-68B2TR 
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Mark³ am 05.01.05 - 18:10:17
1. super interessante Artikelliste (Thread), ich werde am Ball bleiben

2. Ich finde Design Pattern und echte OO-Programmierung sehr interessant, habe bisher aber noch keine Notesentwicklung gesehen, wo sich das wirklich auszahlt. Zumal Klassen im Notes-Designer grundsätzlich total unübersichtlich sind, da sie nicht übersichtlich dargestellt werden. Benutzt ihr im echten Leben auch sowas in LS oder ist das nur Spielkram, weil ihr aus der Java bzw. C++-Ecke stammt?
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 05.01.05 - 18:48:55
habe bisher aber noch keine Notesentwicklung gesehen, wo sich das wirklich auszahlt.
Ich schon. Und zwar an verschiedenen Orten. Selbst ganz früher 1999/2000 bei Kasten haben wir Klassen benutzt. Z.B. für Tabellen-Sortierung und Dokument-Locking. 

Zumal Klassen im Notes-Designer grundsätzlich total unübersichtlich sind, da sie nicht übersichtlich dargestellt werden.
Was am schmerzlichsten fehlt ist auto-code completion. Ich tipp den Objektnamen rein einen Punkt und dann Strg-Alt und hab alle erreichbaren Methoden und Properties der Klasse.
Ansonsten finde ich es übersichtlicher als Skript ohne OO. Eclipse (meine Lieblings Java-IDE) macht natürlich vieles übersichtlicher.

Das ist das aber ein Mitmach-Thread und kein Bewunder-Thread.

Benutzt ihr im echten Leben auch sowas in LS oder ist das nur Spielkram, weil ihr aus der Java bzw. C++-Ecke stammt?
Ja. Logo. Ich programmiere Java/J2EE, Lotus Notes und bin .NET Selbstlernen.
Ich find den Begriff Spielkram auch nicht so treffend. Programmiersprachen sind nicht so wichtig. In Java/C++ gibt es natürlich mehr Möglichkeiten und man begreift da auch bestimmte Sachen, die es unter Lotus Notes nicht gibt.
Aber ich kenne sehr gute Lotus Programmierer und schlechte Java Programmierer.

Axel
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Semeaphoros am 05.01.05 - 20:10:35
Kann mich dem von Axel hier nur anschliessen, auch ich benutze OO in LS, würde wohl sonst nicht die Mühe auf mich nehmen, an der Lotusphere genau dazu einen Vortrag zu machen.
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: koehlerbv am 05.01.05 - 20:47:06
Jo, an OOP ärgert mich auch nur eines (abgesehen von der mangelnden Unterstützung durch die Notes Designer IDE): Und zwar immer, wenn ich feststelle, dass ich hinterher erkennen muss, dass ein scheinbar brauchbarer prozeduraler Ansatz sich hinterher wegen dem Verzicht auf OOP zum Klotz am Bein wird. Dann könnte mich mich immer in den Hintern beissen, dass ich es nicht gleich richtig gemacht habe.

Um den zwar drastisch sinkenden Anteil solcher Fälle weiter zu minimieren, hoffe ich darauf, bald etwas Zeit zu haben, um mir auch in diesem Thread weitere Anregungen holen zu können.

Auf jeden Fall: Danke, Axel, für Deine Mühen !

Bernhard
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 05.01.05 - 21:38:38
... wichtig ist v.a. den source code zu verfolgen. Da steckt meine Hauptarbeit drin. Wg. ansonsten viel Arbeit wird dies auch nicht wahnsinnig schnell aber stetig vorangehen.
Ich gewinne durch die Diskussion einige Ideen.

thx Axel

Z.B. muss das von Mathias wiederentdeckte "no-static-to-share-dependant-objects" anti-pattern von LotusScript dringend angegangen werden durch einen Workaround in eigenen code.

Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 11.01.05 - 10:47:11
Nun sollen erst einmal auf einige typische OO-Vererbungsphänomene anhand des eigentlichen codes aufgezeigt werden. Es geht um ein paar wichtige Details der Implementierung von OO in die Sprache selbst. Diese Implementierung ist übrigens in allen Sprachen gleich. Wer das jetzt versteht, hat direkt ein paar Punkte für C#, VB.NET und Java-Zertifizierungen im Sack.

Schauen wir uns zunächst die Resultate des Durchlauf des Agenten in der Log-DB an.
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 11.01.05 - 10:47:52
Mit der großen roten 1 im Bild gekennzeichnet fällt auf, dass Duck:New 3 mal aufgerufen wird. RedHeadDuck.New und MallardDuck.New() werden aber nur 1 mal aufgerufen. Komisch. Komisch. 
Wer sich das nicht direkt erklären kann, schaut sich den Ablauf des codes am besten direkt mal im Debugger an.
Direkt bei den ersten steps!
Und was passiert dort im Debugger?
Richtig. Wir rufen.
Code
Set myRHDuck = New RedHeadDuck()
auf und es wird erst der Konstruktor von Duck aufgerufen und dann erst der Konstruktor von RedHeadDuck.
Das gleiche Phänomen ist bei dem Aufruf von MallardDuck zu beobachten.
Deshalb gibt es im Logger 3 Einträge von Duck.New pro Durchlauf. Schliesslich wird er – wie zu erwarten – noch mal bei new Duck() aufgerufen (letztes Code-Segment im Agenten.Initialize).

Die Methode new ist, wie bereits erwähnt, eine spezielle Methode. Ein Konstruktor, um genau zu sein. Konstruktoren von Klassen in einer Vererbungshierarchie werden also scheinbar bei der Objektintiierung in einer Art Hierarchie aufgerufen.
Und zwar als erstes der Konstruktor der oberste Hierarchie und zum Schluss der unterste in der Vererbungshierarchie (der initiierte Typ).
Konstruktoren dienen der Initiierung von Instanzvariablen. MallardDuck is-a Duck und deshalb muss auch der Konstruktor von Duck aufgerufen werden (oberste in der Hierarchie) und dann RedHeadDuck (eigentlicher Typ der erzeugt wird und erbt direkt von Duck).
Würde Ducks eine Oberklasse Birds haben und RedheadDuck von Duck erben, würde zunächst der Konstruktor von Birds aufgerufen, dann Duck und dann RedHeadDuck.   

Eine Schwäche von LotusScript OO gegenüber anderen OO-Sprachen ist, dass die Konstruktoren von Klassen in einer Vererbungshierarchie die gleichen Parameter übergeben werden m.ü.s.s.e.n. Bei dem Entenbeispiel fällt das nicht weiter auf, weil alle new Methoden (Konstruktoren) keine Parameter haben.
Sobald aber z.B. das new von MallardDuck ein Parameter übergeben wird (z.B.
Code
New (name as String) 
muss auch Duck einen Konstruktor mit einem String-Parameter haben.
Den Konstruktor auf keine Parameter belassen würde dazu führen, dass die Klasse nicht kompiliert mit einer entsprechenden aussagekräftigen Fehlermeldung im Designer.

In Java ist man da ein bischen freier.

Als erste Zeile im Konstruktor kann man das Schlüsselwort super benutzen, um dem unmittelbar aufgerufenen Parent-Konstruktor andere Parameter zu übergeben (In Java heissen Konstruktoren nicht new sondern haben immer den Namen der Klasse. Der Konstruktor von Duck heisst also in Java nicht new sondern Duck. Das ist aber nur syntaktischer Zucker, heisst: unwichtig:

Code
class Duck {
   public Duck () {}
}


class MallardDuck extends Duck {
  public MallardDuck(String name) {
    super();
 }
}
Dieses super muss aber in der ersten Zeile des Konstruktors der Kind-Klasse stehen.
Sieht aus wie ein normaler Aufruf, muss aber an erster Stelle stehen. Das kann Anfänger verwirren. 

C#.NET ist vielleicht in seiner erst mal merkwürdig aussehenden Syntax ein bischen deutlicher: (Vorsicht ungetester Code)
Code
class Duck {
 Duck () {}
}

public class MallardDuck : Duck {  
// der Doppelpunkt steht für Vererbung wie „extends“ in Java oder „as“ in LotusScript
 public MallardDuck (String name): base() {

 }
}
: base() steht für die Parameter-Übergabe an den  Parent-Constructor.

Wir sehen, dass die is-a Beziehung (Vererbung) eine sehr enge Kopplung von 2 Klassen verursacht. Tatsächlich ist RedHeadDuck eine Duck, weil eben der Konstruktor von Duck aufgerufen wird, wenn man RedHeadDuck erzeugt.

Was ist eigentlich, wenn man keine Lust hat oder vergisst einen Konstruktor zu schreiben?
Dann erzeugt der Compiler in LotusScript, Java und .NET einen leeren Default-Konstruktor ohne Parameter. Ihr könnt spasseshalber den new() Konstruktor von MallardDuck ausremen (mit %rem %end rem) und sehen was passiert, wenn ihr dann den Agenten laufen lässt. Dort ist auf jeden Fall ein Konstruktor. Dieser Compiler-generierte Konstruktor sieht so aus:
Code
Public sub new

End sub
Er steht nur nicht im code, wohl aber in der kompilierten Klasse.
Schwerwiegendere Auswirgungen hat das ausremen des Konstruktors von Duck. Die Klassen kompilieren zwar, dafür terminiert aber eine Runtime Exception „Object Variable Not Set“ den Programmablauf. Das ist so, weil der Konstruktor von Duck die wichtige Aufgabe hat, die Variable myLogger zu initialisieren. Remt man den vorhandenen Konstruktor aus, wo diese Variable inititalisiert wird und benutzt statt dessen den Default-Konstruktor, wo diese Variable nicht initialisiert wird, weil da keine Anweisungen wie die wichtige
Code
		Set myLogger = New Logger()
fehlt, ist diese Instanzvariable im weiteren Programmverlauf nicht gesetzt und es passiert in der Zeile
Code
Call myLogger.setIdentifier("DecoyDucksDontFly_Start::RedHeadDuck")
genau diese „Object Variable not Exception“.


Kommen wir zum nächsten Punkt. Das heisst Moment.
Warum stehen eigentlich in der Log-Datenbank die beiden Duck:new(), die über den Aufruf new MallardDuck() bzw. new RedHeadDuck aufgerufen worden sind unter der Sektion:
DecoyDucksDontFly_Start::Duck
und nicht unter DecoyDucksDontFly_Start::MallardDuck bzw. DecoyDucksDontFly_Start::RedHeadDuck?
Das ist nicht gut.
Nochmal. Was passiert genau bei dem Aufruf von new RedHeadDuck?
1.   RedHeadDuck.new() wird aufgerufen.
2.   Notes sieht, dass diese Klasse eine Superklasse Duck hat.
3.   Notes leitet den Aufruf auf Duck.new() weiter
4.   Im new() von Duck wird ein neues Logger-Objekt wird initialisiert und der Instanzvariable myLogger der Klasse Duck wird dieses Logger Objekt zugewiesen Set myLogger = New Logger()
5.   Die Methode .setIdentifier der Klasse Logger wird mit dem Parameter "DecoyDucksDontFly_Start::Duck" aufgerufen.
6.   In der Methode setIdentifier von Logger wird die Eigenschaft „Programname“ unseres NotesLog-Objekts geändert. Diese manipuliert die „Sektion“ in der Ansicht der Log-Datenbank (nähere Details zu Programname s. Noteshilfe)
7.   Es wird die Methode log("Info:Duck::New terminates") von Logger aufgerufen. Die Sektion steht auf "DecoyDucksDontFly_Start::Duck".
8.   Der Konstruktor new() der Superklasse Duck ist abgearbeitet und nun wird der Konstruktor der eigentlichen Klasse abgearbeitet (RedHeadDuck.new().
9.   In dem Konstruktor new() von RedHeadDuck wird wieder die Methode setIdentifier der Klasse Logger aufgerufen. Nun wird dieser Methode aber ein anderer Parameter übergeben. ("DecoyDucksDontFly_Start::RedHeadDuck").
10.   Wieder wird die Eigenschaft Programname unseres NotesLog-Objekts geändert in myLogger.setIdentifier. Der übergebene Parameter heisst aber nun "DecoyDucksDontFly_Start::RedHeadDuck" und nicht wie im Konstruktor von Duck "DecoyDucksDontFly_Start::Duck".
11.   Die Methode log von myLogger wird mit dem Parameter ("Info:RedHeadDuck.New called" aufgerufen. Das steht nun aber unter der neuen Sektion (Auswirkung von Punkt 10).

Mir gefällt das Verhalten nicht, dass die Logging-Section sich während eines new Aufrufs aus initialize (dem Client code) ändert. Welcher poofy wanker hat das programmiert? Ich weiss, dass auch ich einmal angefangen habe mit Object Orientation, aber muss man so code veröffentlichen? Ich werde das bald so umschreiben, dass das Logger Objekt im Agenten erzeugt wird und den Konstruktoren der Klasse als Parameter übergeben wird.
Oder irgendwie anders. Jedenfalls ist das eine ganz gute Diskussionsgrundlage für OO-Designpraktiken. 
Das initialisieren von myLogger im Konstruktoren in der Basis-Klasse war keine gute Idee!
To strong a coupling. Leider hat Igor z.Zt. wegen IBM.486 Vorbereitung meinen Larman, aber ich bin mir ziemlich sicher, dass sich dort klarere theoretische Fundierungen finden, warum das jetzt dazu führte, dass die Klassen redesigned werden müssen.
Code
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 11.01.05 - 17:25:58
Themenwechsel: Ein bischen seltsam mag vielleicht auch erscheinen, warum in der Klasse RedHeadDuck überhaupt Methoden der Eigenschaft myLogger aufgerufen werden können. Schliesslich hat diese Klasse überhaupt keine Eigenschaft myLogger.  Nur die SuperKlasse hat eine solche Eigenschaft:
Code
Private myLogger As Logger
Offenbar kann aber die Kind-Klasse RedHeadDuck diese Eigenschaft der Elternklasse Duck mitbenutzen. Genau das ist ein Aspekt der Vererbung. Kindklassen tragen die Eigenschaften und Methoden ihrer Elternklasse in sich. Oft zumindest.
Mich hat das an LotusScript erst ein bischen verwirrt. In Java werden Eigenschaften mit dem Zugriffs-Modifier private nicht an child-Klassen vererbt.

In Java sieht es so aus:
Code
public class Parent {
	Parent() {
		System.out.println("****In Parent Konstruktor *******");
		System.out.println(publicMember);
		System.out.println(protectedMember);
		System.out.println(packagePrivateMember);
		System.out.println(privMember); // hier kann im Gegensatz von Child auf privMember zugegriffen werden!!!
		
		 

	}
	// nur innerhalb der Klasse sichtbar. Von Child aus kein Zugriff. 
	private String privMember = "privMember ist da.";
	// vor der nächsten Eigenschaft oder Membervariable steht kein Access-Modifier
	// aber auch der leere Access Modifier setzt bestimmte Regeln. 
	// Solche Variablen sind nur innerhalb des Pakets sichtbar. 
	// wir haben hier oben in dieser Klasse kein package Statement.
	// Deshalb landet die Klasse im default package. Ausserhalb von solchen 
	// mini-Demo Anwendungen schreibe ich keine Klassen ohne package. 
	String packagePrivateMember = "packagePrivateMember ist da.";
	// protected: wie packagePrivate (also sichtbar innerhalb des gleichen Pakets) und zusätzlich
	// alle Klassen, die von dieser Klasse erben und in einem anderen Paket sind. 
	protected String protectedMember = "protectedMember ist da.";
	// public: Vollzugriff. Aus allen Klassen kann auf diese Instanzvariable zugegriffen werden. 
	public String publicMember = "publicMember ist da.";
}

public class Child extends Parent {

	Child() {
		System.out.println("****In Child Konstruktor *******");
		System.out.println(publicMember);
		System.out.println(protectedMember);
		System.out.println(packagePrivateMember);
		//System.out.println(privMember); 
		//Lässt compiler nicht zu. 
		//Auf private members kann nur in der Klasse selbst zugegriffen werden. 
	}
	public static void main(String[] args) {
		new Child();
	}
}

Zwar kennen sowohl Java als auch LS Zugriffs-Modifier, jedoch heisst private in beiden Sprachen offenbar etwas leicht anderes. Das ist völlig normal. Auch bei C++/C# und Java gibt es jeweils leicht andere Zugriffs-Modifier. Die grundsätzliche Idee von private ist aber überall gleich. Es ist der Zugriffs-Modifier mit der höchsten Kappselungsstufe. Also der, der am restriktivsten Zugriffe von aussen einschränkt.
Wenn aber nun private Eigenschaften in Lotus-Script fröhlich von anderen Klassen aufgerufen werden können, vielleicht haben die LotusScript Programmierer einfach vergessen oder keine Zeit mehr gehabt das zu programmieren.
Doch es gibt einen Schutz.
Wenn ich am Ende des codes in Initialize des Agenten die Zeile:
Code
myShouldNotBeInitializedDuck.myLogger
Erhalte ich die Meldung: Not a public member MyLogger.
Auf private Member habe ich also aus anderen Modulen keinen Zugriff.
Wenn ich die Doku richtig verstanden habe, dann heisst private in LotusScript:
private für das gleiche Modul. Ich werde das aber noch genauer prüfen.
Wenn die Klassen in derselben Declaration-Section stehen können sie gegenseitig auf private Members zugreifen. Sobald sie in anderen Declaration Sections stehen oder der aufrufende Code im Initialize gibt es keinen Zugriff (ungeprüfte Hypothese, mein Verständnis der doku).

Auf jeden Fall bleibt die Tatsache, dass der code ausserhalb des Moduls, nämlich im Initialize des Agenten etwas anderes sieht als der code innerhalb der Klasse.
Genau dieses Phänomen ist der Kern von Kappselung. Aus OO-Sicht bezeichnet man alle Methdoden und Eigenschaften eines Objekts, auf die im jeweiligen Kontext zugegriffen werden kann als Interface. Dieses Interface aus OO-Sicht hat nur über 2 Ecken etwas mit dem Java-Schlüsselwort „Interface“ zu tun. Insgesamt ist es ein Synonym (je nach Kontext eine unterschiedliche Bedeutung). Auch LotusScript Klassen haben ein Interface. Sogar – wie alle OO-Klassen – direkt mehrere. Nämlich je nach Kontext. Für Aufrufe innerhalb der Klasse oder des Moduls gibt es ein private-Interface (Methoden und Eigenschaften mit public oder private Modifier) und ein public Interface (für Zugriffe von aussen, etwa aus dem Initialize eines Agenten wie im Beispiel). Dieses public Interface besteht nur aus den Methoden und Eigenschaften mit public modifier. Die mit private sind verborgen (hidden).
Dies hat extrem wichtige Auswirkungen, die noch später näher erläutert werden sollen.

Frage: Es gibt aber auch Eigenschaften und Methoden ohne public oder private Zugriffs Modifier. Hat das vielleicht in LotusScript auch eine spezielle Bedeutung wie in Java?
Nein. Hat es nicht. Der Compiler fügt den Eigenschaften ohne Zugriffs-Modifier automatisch ein private hinzu und den Methoden automatisch ein public.

Frage: Warum ist das für beide verschieden? Wäre es nicht einfacher, wenn sowohl Methoden als auch Eigenschaften public wären oder private. Zumindest alle einheitlich?
Eigentlich nicht. Nach normaler OO-Praxis sind Methoden eher, aber nicht immer public und Eigenschaften eher, aber nicht immer private.
Das ist mehr als eine Konvention. Aber das versuche ich später zu erklären. Da muss erst mal ein bischen über public und private Interfaces geredet werden.

Als nächstes wird
-   das Redesign durchgeführt (kann wegen mir auch wer anders machen, ist aber egal)
-   sich mal angeschaut was es mit dieser merkwürdigen delete() Methode auf sich hat, die es zwar in der Klasse gibt und gemäss dem Ergebnis in der Log-DB irgendwie aufgerufen wird. Wer sich den code genau anschaut, sieht das im code diese Aufrufe nicht stattfinden.
-   Der Frage nachgegangen, dass zwar der Konstruktor von RedHeadDuck den parent-Constructor aufruft, die in Duck definierte Methode swim() aus RedHeadDuck aufgerufen wird. Bei der Methode display(), die es sowohl in den Eltern als auch in den Kind Klassen gibt, aber nur die display() Methode des jeweiligen Objekts aufgerufen wird (beim Konstruktor werden ja beide aufgerufen). Alles ein bischen verwirrend, vielleicht.
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Semeaphoros am 11.01.05 - 17:41:02
Axel, Du hast das mit Private schon richtig interpretiert, hat aber nix mit OO zu tun, sondern "übergeordnet" mit LS: die kleinste Scope-Einheit ist gemäss LS-Definition das Modul und nicht die Class oder whatever in einem Modul sonst noch granularer sein könnte .... irgendwo hatte ich das mal sogar ausdrücklich gelesen, weiss nur nicht mehr wo (wahrscheinlich im LS-Programmer Guide)
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Mark³ am 11.01.05 - 18:15:57

-   Der Frage nachgegangen, dass zwar der Konstruktor von RedHeadDuck den parent-Constructor aufruft, die in Duck definierte Methode swim() aus RedHeadDuck aufgerufen wird. Bei der Methode display(), die es sowohl in den Eltern als auch in den Kind Klassen gibt, aber nur die display() Methode des jeweiligen Objekts aufgerufen wird (beim Konstruktor werden ja beide aufgerufen). Alles ein bischen verwirrend, vielleicht.


um mir das Gefühl des Mitmachens zu geben: Die display() Methode wird nur vom jeweiligen Objekt aufgerufen, weil sie überladen ist (geht in LS hier, weil alle display() die gleichen Parameter erwarten, nämlich keinen) . Wobei der Sinn der Überladung darin liegt dass man   mit dem gleichen Interface sowohl Eltern-Objekte als auch Kind-Objekte ansprechen kann  ::)    ???
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 11.01.05 - 19:03:32
Axel, Du hast das mit Private schon richtig interpretiert, hat aber nix mit OO zu tun, sondern "übergeordnet" mit LS: die kleinste Scope-Einheit ist gemäss LS-Definition das Modul und nicht die Class oder whatever in einem Modul sonst noch granularer sein könnte .... irgendwo hatte ich das mal sogar ausdrücklich gelesen, weiss nur nicht mehr wo (wahrscheinlich im LS-Programmer Guide)

So etwas ähnliches schwirrte in meinem Kopf auch rum.
Und ja sicher: Private gibt es auch für Funktionen und Subs.
Ich finds nicht so schlimm. Das echte Problem für "modernes"-GoF OO sind die fehlenden abstrakten Klassen und das fehlende static.

Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 11.01.05 - 19:17:25
um mir das Gefühl des Mitmachens zu geben: Die display() Methode wird nur vom jeweiligen Objekt aufgerufen, weil sie überladen ist (geht in LS hier, weil alle display() die gleichen Parameter erwarten, nämlich keinen) .
Typisch Microsoft-Programmierer  ;D(Scherz. Ich hab nix gegen Microsoft). s. dein codestore Kommentar zum neuesten Eintrag.  ;D
Du verwechselst gerade überschreiben mit überladen.
overwriting: beide Klassen haben eine display Methode mit gleicher Parameterliste. Man spricht hier auch von gleicher "Signatur" der Methode. Wenn ich mich recht erinnere gehört der Rückgabetyp zur Signatur. .
Overwriting funktioniert in LotusScript wie in Java oder C#.

overloading (überladen) ist, wenn 2 Methoden in einer Klasse den gleichen Namen aber unterschiedliche Parameterlisten haben. Das geht in LotusScript nicht. 
zb:
public display()
und
public display (name As String)
Overwriting hat ziemlich viel mit OO zu tun. Overloading gab es aber schon stark in prozeduralen Sprachen. In LotusScript aber nicht in den UserDefined Funktionen. In den von Lotus zur Verfügung gestellten Funktionen und Routinen gibt es - wie Jens oder Bernhard sehr richtig angemerkt hat - Funktionen/Routinen mit unterschiedlichen Parameterlisten, also overloading.
z.B. mir fällt dazu ein, dass messagebox sowohl:
messagebox "a message"
als auch:
messagebox "a message", intNumber, "aTitle"
aufgerufen werden kann.
Variierende Parameterlisten für Methoden mit gleichen Namen geht nicht für eigene Funktionen.

 
Hab mal so prep Fragen zu c# certi gesehen. Da wird auf diesen Begriffen (ähnlich wie bei Java) ziemlich drauf rumgeritten. Es gibt aber nur die 2: overloading und overwriting.   
Meine deutsche Begrifflichkeit ist aber auch manchmal nicht so toll.
Wobei der Sinn der Überladung darin liegt dass man   mit dem gleichen Interface sowohl Eltern-Objekte als auch Kind-Objekte ansprechen kann  ::)    ???
Im Prinzip ist das richtig (überschreiben nicht überladen). Das geht in Richtung Interface-Inheritance statt code Inheritance, Polymorphismus und Late Binding. Begriffe, die ich noch Versuche klar zu machen. Euer Autor Jesse Liberty kann das übrigens ziemlich gut darstellen.  8)

Gruß Axel
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Semeaphoros am 11.01.05 - 20:59:43
Private gibt es auch für Funktionen und Subs.
Ich finds nicht so schlimm. Das echte Problem für "modernes"-GoF OO sind die fehlenden abstrakten Klassen und das fehlende static.

Genau, daher, dass es Private und Public auch im sonstigen LS gibt, kommt diese Scope-"Problematik" auch zustande, und einverstanden, das ist nicht wirklich tragisch, da muss man einfach dran denken. Fehlende abstrakte Definitionen und fehlendes Static (bzw. eingeschränktes) ist wirklich eine echte Einschränkung.
Titel: Re: Gang Of Four (GoF) Design Patterns für LotusScript on OO nachprogrammieren?
Beitrag von: Marinero Atlántico am 20.01.05 - 19:13:22
Falls das jemand nachvollziehen will: Unten ist eine nsf mit Agenten angehängt. Bitte den Agenten in die schon bestehende Datenbank kopieren und den laufen lassen. Am besten auch im Debugger.

So was ist nicht so gut mit dem jetzigen Code?

1.   Jede Testklasse erzeugt ihr EIGENES Logger-Objekt, dass wiederum mehrere kostpielige Notes-Operationen durchführt, die eigentlich nur einmal nötig sind. Lägen die Notesdatenbanken auf dem Server gingen sie über das Netzwerk (noch kostspieliger). Im Prinzip ist das egal.
Performance? Egal? Ach du heilige Kaffeetasse.
Dieser Code ist ausreichend schnell, für was er tut.
Zu frühes Optimieren kann schnell zu unübersichtlichen Code führen. 
Wobei man meiner Meinung nach schon ein bischen über Performance nachdenken sollte.
Oft verursachen aber nur kleine Stellen im Code wirklich Performance-Probleme. Um diese aufzuspüren helfen sogenannte Profiler.
Würden wir die Datenbank auf einen Server legen wäre die Initialisierung eines Loggers schon kostspieliger, weil die Lookups gegen das Konfigurationsdokument Remote Calls sind.

2.   Ausserdem und schlimmer haben wir bei der Vererbung das Problem, dass die Superklasse ihr eigenes setIdentifier aufruft, so dass Log-Nachrichten von 1 call durch den Client in 2 Kategorien landen (Duck und MallardDuck bzw. RedHeadDuck).

Wir müssen das irgendwie umschreiben.
Leider hat Igor wie gesagt meinen Larman, d.h. ich muss das später noch mal überarbeiten.
Aber im Grunde sehe ich hier ein echtes Problem von HighCoupling. Wir wissen schon, dass Klassen kohäsiv sein soll, d.h. sie sollen 1 Thema aus der realen Welt behandeln.
Deshalb haben wir 1 Klasse für das Konfigurationsdokument, 1 für den Logger und jeweils eine für jeden Typ Ente und die Superklasse, die lieber abstrakt wäre, aber IBM bastelt lieber an Workplace rum.
Das war cohesion. Jetzt gibt es noch coupling. Es heisst high cohesion. Low coupling. Coupling heisst die Abhängigkeit zwischen den Klassen. Natürlich muss es da Abhängigkeiten geben, weil die Objekte ja irgendwie zusammenarbeiten sollen. Nur sollte jede einen gewissen Freiraum haben. Möglichst viel sogar. Damit sie unabhängig von den anderen eingesetzt werden kann und ausserdem haben wir eben durch den doppelten-setIdentifier-in-den Konstruktoren einen ärgerlichen Seiteneffekt von Vererbung.

Es gibt verschiedene Stufen von Kopplung und Larman hat das gut beschrieben.
Die höchste Stufe ist, wenn 1 Objekt Creator eines anderen Objekts ist. Duck creates Logger, weil es new Logger() aufruft.
Was können wir machen?
Wir können Logger ausserhalb von Duck erstellen und diesen Logger dann jeder Ente übergeben. Dann können wir den Logger auch wiederverwenden. Der Logger ist unabhängiger von der Ente.

Ist das umsonst?
Nein.
Der Client-Code wird ein wenig komplizierter. Client code ist das, was im Initialize des Agenten steht. Die Enten sind also ein bischen schwerer zu bedienen.

Code
Rem gibt’s auch im beigefügten .nsf
Dim theLogger As Logger 
	' client muss Logger erstellen. 
	Set theLogger = New Logger()
	
	Dim myRHDuck As RedHeadDuck
	Dim myMDuck As MallardDuck
	Dim myShouldNotBeInitializedDuck As Duck
	
	'Logger setzt pro Objekt eine neue Kategorie
	Call theLogger.setIdentifier("DecoyDucksDontFly_StartBetter::RedHeadDuck")
		' Operationen mit RedHeadDuck
	Set myRHDuck = New RedHeadDuck(theLogger)
	Call myRHDuck.swim()
	Call myRHDuck.quack()
	Call myRHDuck.display()
	
	‘das gleiche Logger-Objekt manipulieren, um es für die MallardDuck zu benutzen
	Call theLogger.setIdentifier("DecoyDucksDontFly_StartBetter::MallardDuck")
	' Operationen mit RedHeadDuck

	Set myMDuck = New MallardDuck(theLogger)
	Call myMDuck.swim()
	Call myMDuck.quack()
	Call myMDuck.display()
	
	‘das gleiche Logger-Objekt manipulieren, um es für die Duck zu benutzen
	Call theLogger.setIdentifier("DecoyDucksDontFly_StartBetter::DuckBetter")
	
	Set myShouldNotBeInitializedDuck = New Duck(theLogger)
	Call myShouldNotBeInitializedDuck.swim()
	Call myShouldNotBeInitializedDuck.quack()
	Call myShouldNotBeInitializedDuck.display()
	
	'PASS BY REFERENCE!!!
‘ VORSICHT: WILD
	theLogger.setIdentifier("DecoyDucksDontFly_StartBetter::BigDuckMassacer")
	
Logger ist wie gesagt deutlich unabhängiger von den Enten, wenn wir das Objekt dem Konstruktor übergeben und es nicht mehr im Konstruktor erzeugen!

Lasst das erst mal laufen und schaut euch das Ergebnis in der Log-DB an.

Interessant ist v.a. die letzte Zeile und die Auswirkungen in der Log-DB:

Code
theLogger.setIdentifier("DecoyDucksDontFly_StartBetter::BigDuckMassacer")
 
Der Speicher der Objekte wird dann freigegeben, wenn der Agent endet. Kurz bevor der Speicher freigegeben wird, ruft ein LotusScript automatisch den Destruktor delete() auf. Die delete-Methoden schreiben ins Log. z.B:
Code
Call myLogger.log("Info:MallardDuck::Delete starts")
Das Logger Objekt wird wie bei LotusScript defaultmässig üblich by-reference übergeben. Wir stellen das vor Ende des Agentenlaufs in der letzten Zeile um. Xtreme Geek fun und DAS IST ÜBERHAUTPT KEIN DESIGNPATTERN!
So landen aber alle LogNachrichten rund um das Thema Destruktor in einer eigenen Sektion „BigDuckMassacer“. Das ist der Effekt.
Ich bin mir nicht sicher, ob das hier jeder versteht, warum das so ist..
Warum ist das so?
Ich übergebe im initialize des Agenten EIN WIEDERVERWENDETES Objekt mit Namen theLogger an drei DuckKlassen, das heisst als Parameter im Konstruktor wird das Objekt erst mal aLogger und wird dann dem Member myLogger zugewiesen.
Code
AUFRUF: 
Set myMDuck = New MallardDuck(theLogger)

OBJEKT-KONSTRUKTOR:: 
Public Sub new(aLogger As Logger) 
		Set myLogger = aLogger
		myLogger.log("Info:MallardDuck.New called")
	End Sub

Das gleiche mache ich mit dem selben theLogger in Initialize mit allen 3 Enten-Objekten!

Dann verändere ich theLogger und das hat Auswirkungen auf gleich drei, in Zahlen: 3, Instanzvariablen, die völlig anders heissen?
Qué cosa más eficiente.
Aber eben auch unübersichtlich.
 Mit prozeduraler Programmierung geht das so nicht, weil ein Skript sequentiell abgearbeitet wird. Ein Objekt bleibt aber im Speicher, bis es zerstört wird (etwa am Ende des Agenten). Der Code im Initialize läuft weiter, aber das Objekt ist noch DA.

SELBSTVERSTÄNDLICH GEHT DAS NICHT. Solche Konstrukte sind Zeitbomben für zukünftig schwer zu findende bugs. Ich werde deshalb diesen Teil noch mal refaktorieren müssen. Jetzt soll den Enten eine eigene KOPIE des Logger Objekts übergeben werden. Am besten ginge das mit pass-by-value, wobei zu prüfen ist, ob das mit Klassen überhaupt geht. Aus Performance Gesichtspunkten sollte das auch ok sein, weil die Initialisierung des Logger-Objekts als die eigentlich kostpielige Operation erscheint (Zugriff auf config-Dokument). Ohne Profiling wissen wir das zwar nicht, ist aber sehr wahrscheinlich. Mit der oben skizzierten Lösung, das Enten Kopien des Logger-Objekts übergeben werden, wäre die Initialisierung des Loggers nach wie vor zentralisiert. D.h. es findet nur ein call gegen Logger.new statt.

NEUER GEDANKE: Objekte haben nicht nur Methoden und Eigenschaften. Nein. Sie haben auch einen Identifier, der auf sie verweist. theLogger ist so ein Identifier oder myMDuck.myLogger.
Die Objekte selbst sind ein Bereich im Adressraum des Speichers deines Rechners. Dort selbst sind eine Menge 1en und 0en. Wenn ich – wie in LotusScript defaultmässig üblich – by Reference übergebe, steht in dem Objekt also genauer:dem_Verweis_auf_die_Speicheradresse_mit_Bezeichner_theLogger_wo_die_ganzen_0en_und_1en_für_das_Logger_Objekt_stehen die, gut, Speicheradresse dieses Objekts.
Diese gleiche Speicheradresse_des_Objekts weise ich nun in den Parametern des Konstruktors der lokalen Variable aLogger zu. Im Konstruktor-Body weise ich dann der Instanzvariable myLogger die gleiche Speicheradresse im_Rechner zu. Eine Menge Variablen zeigen auf die gleiche Speicheradresse.
Wenn ich nun in der letzten Zeile von initialize sage:
Code
theLogger.setIdentifier("DecoyDucksDontFly_StartBetter::BigDuckMassacer") 
, dann verändert das die 0en und 1en des Adressbereichs auf den die ganzen Logger Identifier (myRHDuck.myLogger, myRHDuck.myLogger; myShouldNotBeInitialized.myLogger, theLogger) zeigen.
Wenn nun der Agent endet, werden die Objekte von Lotus Notes automatisch aus dem Speicher entfernt. Als Rückrufmethode vor dem entfernen wird bei jedem Objekt automatisch die public sub delete aufgerufen, wo Dinge drinstehen wie
Code
Call myLogger.log("Info:MallardDuck::Delete starts")
myLogger zeigt auf eine bestimmte Speicheradresse. Da sind 0en und 1en. Diese wurden in der letzten Zeile des initialize geändert. Und das hat Auswirkungen.

Das mag am Anfang verwirrend sein. Wer das nicht verstanden hat, bitte melden. Jens oder Bernhard erklären das sicher gerne 


Was haben wir getan?
Der Programmablauf macht eigentlich – mit ein paar Änderungen – nach wie vor dasselbe. Ohne die kleinen Änderungen in den sichtbaren Auswirkungen in der LogDB, hätten wir die Königsdisziplin der Javaprogrammierung durchgeführt: Refactoring.
Sichtbar ändert sich nichts, aber das Programm ist besser strukturiert.

Es ist wie gesagt nicht richtig Refactoring, aber ziemlich Refactoring-ähnlich. D.h. der Kern der Arbeit war Refactoring. Wir erzeugen die Instanzvariable myLogger nicht mehr im Konstruktor, sondern wir übergeben den Enten-Konstruktoren ein im initialize erzeugtes und dann von allen gemeinsam genutztes Logger-Objekt. Im Konstruktor wird der Instanzvariable der Enten myLogger nur dieses Logger Objekt zu gewiesen und nicht jedes Mal neu per new erzeugt.
Das ist eine Änderung der internen Struktur des Programms, die lediglich die vorher vorhandenen Nebenwirkungen bereinigt hat.

Refactoring hört sich vielleicht erst mal nicht besonders produktiv an, ist aber höchst produktiv. Wir verwenden glaub ich alle – ich auf jeden Fall – mehr Zeit damit, bestehenden Code zu verstehen als neuen Code hinzuzufügen. Wodurch werden debugging-sessions manchmal lang?
Durch das Ändern des codes oder durch das Auffinden des codes, der geändert werden muss?
Für uns ist das klar: Das Auffinden der Stelle, die den Fehler verursacht. Das Ändern ist meist kein Problem.
Für unsere Kunden ist das leider oft nicht klar.
Wieso ist das so?
Es gibt so was wie Software-Entrophie. Je mehr Funktion einem Programm hinzugefügt wird, desto unübersichtlicher wird es. Tendentiell und Reell. Kein Mensch kann wirklich perfekten Code schreiben. Deshalb ist es sinnvoll, zwischendurch die interne Struktur des Programms auf einen übersichtlichen Stand zu bringen. Das ist die Idee von Refactoring.
Zum Thema Refactoring in OO und v.a. Java hat Martin Fowler ein tolles Buch geschrieben, was irgendein Idiot auf amazon.de als OO-Anfänger-Buch bezeichnet hat. Das sind natürlich sehr kleine Schritte beschrieben und man weiss das eigentlich alles, aber der Typ hat irgendwie die Idee der Systematisierung nicht ganz begriffen. Systematisiertes Refactoring ist ein ziemlich monotoner low-level Prozess. Das Extrahieren eines Konstruktor-Aufrufs (myLogger = new Logger() aus einem anderen Konstruktor (Duck, MallardDuck, RedHeadDuck) nach aussen in den Client-Code und dann Übergabe dieses Objekts an die Konstruktoren der Ducks ist immer gleich und nicht besonders kompliziert. Wir haben das auch in prozeduralen Notesfunktionen 5 bis 80 mal gemacht.
Nein. Die Funktion benötigt einen weiteren Parameter und wir brauchen hier kein neues NotesDatabase-Objekt erzeugen, weil wir das im Initialize schon haben. Wir übergeben es mit dem Konstruktor.
Die Wiederholbarkeit des Prozesses macht Refactorings natürlich zu einem guten Thema für IDEs und tatsächlich gibt es in Eclipse 15 bis 20 per wizzard automatisierte Refactorings, die ich btw zum Teil echt nutze und die wirklich Sinn machen.
Erstaunlicherweise habe ich unter den ca. 50 Refactorings in Fowlers Buch KEIN EINZIGES GEFUNDEN, DAS AUF UNSEREN FALL PASST.
Die Erzeugung eines Objekts nach aussen zu verschieben, gibt es dort scheinbar nicht. Oder ich bin blind, weil ich eine ganze Weile nachgeschaut habe. Dann habe ich in in Kerievskys, Refactoring to Patterns etwas ähnliches gefunden. Sehr interessant. Es macht für Java aus verschiedenen Gründen nicht viel Sinn. Erstmal wäre Ducks in Java sowieso abstract. Zweitens könnte man das über Singletons lösen. Weil wir in Java static haben, können wir regeln, dass von 1 Klasse nur genau 1 Objekt existiert (später dazu mehr). Interessant ist, dass Kerievsky in Refactoring to Patterns ein „Inline Singleton“ hat. Ein Zeichen dafür, dass das Buch auch „Refactoring to and from Patterns“ heissen könnte. Manchmal sollte man Patterns auch vernichten, weil sie das Design komplizierter machen können. „Inline Singleton“ heisst: Wir machen den Singleton code aus der Singleton Klasse raus. Kerievsky konstatiert einen gewissen Hang zur „Singletonitis“ unter Java Programmierern. Er war ein bischen unsicher und hat das explizit mit anderen Experten besprochen und Ward Cunningham und Kent Beck finden das auch mit der Singletonitis. „Singleton pattern usage has grown out of propoertion“. „A singleton is unnecesary when its simpler to pass an object ressource as a reference to the object that needs it (S. 145f., Kerievski, Refactoring to Patterns)”. Unser Refactoring ist natürlich ein bischen anders. Es ist „Convert Creator To Global Object Receiver“ und das erste Marinero-Notes-OO-Refactoring und ein bischen problematisch..
Das Problem ist, dass das im Client erzeugte Objekt ein globales Objekt ist.
Dieser ganze Trick mit dem Ausnutzen von pass-by-reference zeigt, dass es eine gefährliche Geschichte ist, die zu schwer zu debuggenden Fehlern führen kann.
In Notes, wo wir eine sehr strikte Parameterübergabe in Konstruktoren, keine abstrakten Klassen und kein static haben, ist es vielleicht keine schlechte Idee.
Fowler nennt in einem anderen Buch (Patterns of Enterprise Architecture) ein sogenanntes Registry-Objekt als Singleton Ersatz. Darüber habe ich schon nachgedacht. Fowler meint aber zurecht, dass man mit solchen globalen Objekte, die man an andere Objekte ausgibt, sehr sparsam umgehen sollte und ich find er hat Recht, weil das wirklich unübersichtlich werden kann.