Autor Beitrag
HelgeLange
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: Sa 10.03.07 00:58 
UPDATE : Download link für die TechDemo am Ende des Beitrags hinzugefügt...
UPDATE 2 : Source der TechDemo hinzugefügt
UPDATE 3 : Title geändert

Wie es aussieht, bin ich wohl der erste, der sich hier mal etwas breit macht :) Ich werd mal versuchen, mich soweit an die Regeln zu halten, wie es im momentanen Stadium möglich ist. Ausserdem werde ich wohl das Ganze auf mehrere Beiträge verteilen müssen, da es doch recht unfangreich ist und es sich nicht in 3 Zeilen erklären lässt. Im Verlauf werden auch Screenshots und später ein Demo-Programm gepostet.

Hier erstmal der Link : www.maf-components.com

Die Website befindet sich noch im Design, deswegen hab ich erstmal im Blog angefangen, ein paar Artikel online zu stellen, die nächsten Tage folgen mehr davon, wo die Funktionsweisen soweit erklärt werden, dass die Vorzüge dieser Komponenten klar werden sollten. Ich werde versuchen, auf alle Fragen, die da kommen sollten, einzugehen, aber keine Anleitungen zum Selberbauen geben. :P

Für alle, die erstmal keine Lust haben, sich seitenlange Abhandlungen auf der Website durchzulesen hier mal eine mehr oder minder kurze Zusammenfassung. Es in 3 Sätzen zu beschreiben, wird natürlich nicht möglich sein, da es ein komplettes Komponenten-Pack ist und von daher einfach im Funktionsumfang zu gross.

1.) Wie kam ich eigentlich dazu, diese Komponenten zu schreiben und zu releasen ?

ERP (Enterprise Resource Planning, zu gut deutsch : Warenwirtschaft) - Systeme waren schon immer eine meiner Leidenschaften. Ich mag mit Datenbanken rumspielen und ich mag es logisch :) Irgendwann wollte ich mal neben dem Studium ein kleines ERP Programm basteln, welches allerdings so modular sein sollte, dass ich es jederzeit erweitern kann. Beim herkömmlichen Plugin-System kam ich recht schnell an die Grenzen, da Plugin starre interfaces haben und recht limitiert sind in deren Funktionen. Ein anderer Grund war natürlich die Austauschbarkeit von Funktionalität, denn durch Beruferfahrung wusste ich bereits, wie unterschiedlich Kundenwünsche sind. Auch das geht nicht mit einem herkömmlichen Plugin-System, ohne dass man neue Versionen der Plugins ausliefert und in denen auf Kundenwünsche eingeht. Besonders schlimm ist das natürlich, wenn es Wünsche sind, die nur auf einen Kunden zutreffen. Dann fängt man an, sich mit IFDEF oder If-Then-Else runzuschlagen.
Es war also aufgrund dieser Vorüberlegungen unumgänglich, ein System zu schreiben, in dem man nicht nur Module nachliefern/installieren kann, um neue Funktionalität ins Programm zu integrieren, sondern auch vorhandene Funktionalität zu verändern/auszutaschen. Und genau da setzt ein Teil der ERP Framework Components an.
Nun war die erste Komponente (THookClient) darauf ausgelegt, mir all das zur Verfügung zu stellen und es waren weder weitere Komponenten noch ein Release geplant. Aber im laufe der Jahre kamen immer mehr Komponenten dazu, die sich als sehr nützlich herausgestellt haben und ich fand es nachher doch recht schade, wenn sie bei mir auf der Festplatte verstauben.
Ein weiterer Punkt, der mich zum releasen veranlasst hat : Die Programme der anderen. Als Freelancer bekomme ich eine Menge Programme zu sehen und es tränt immer wieder in den Augen, wenn man 200 oder mehr Formulare in einer EXE sieht, dazu noch ne ganze Menge TTable und alles zum Programmstart erstellt. Jetzt kann ich natürlich meinen Clients in dem Stadium nicht meine Komponenten unterschwatzen, die wollen meist Probleme schnell gelöst bekommen, über alles andere später mal nachdenken. Zumindest mit einem Release könnte ich andere unterstützen, gute modulare Software zu schreiben.

2.) Was bietet ERP Framework Components meiner Software ?

wie unter Punkt 1.) schon erwähnt, ist der Ursprung eine Komponente für dynamische Funktionen, die es erlaubt, im Nachhinein neuen Code zu vorhandenem hinzuzufügen oder zu überschreiben bzw. zu löschen, ohne dass die vorhandenen Module neu übersetzt werden müssen. Beim Start des Programms wird vom HookManager (nicht zu verwechseln mit Windows-Hooks, hier wurde der Name gewählt, weil jeder Hook eigentlich ein Haken mit n-vielen Funktionen ist) eine DynamicFunctionTable erstellt, welche den Code so miteinander verknüpft, wie es sich der Programmier gewünscht hat. Dazu kommt ein Security-Layer, der bestimmte Funktionen (vom Programmierer festlegbar) vor unberechtigtem Zugriff schützt (zum Bsp. die Liste der Einkaufpreise eines Shops darf nicht jeder Mitarbeiter sehen). Das heisst, es wird für den Code, auf den der augenblicklich angemeldete Nutzer keinen Zugriff hat, gesperrt. bzw. erst garnicht geladen. Somit wird es schwerer, sich unberechtigt Zugang zu verschaffen.
Nur welchen Vorteil hat man von "dynamischen Funktionen" ? Ich will es mal am Beispiel eines Kunden erklären, weil der in fast jeder ERP Software gebraucht wird.
Nehmen wir an, hinter einem Button "Neuen Kunden erstellen" liegt folgende Procedure :
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
var CustomerID : Integer;
begin
  CustomerID := CreateCustomer;
  CreateCustomerAdressAndShipping(CustomerID);
  CreateCustomerAccount(CustomerID);
end;


Schreibt man auf Wunsch einer Kunden-Firma, die Ihre Software einsetzt, nun ein Modul, welches Einkaufsverhalten auswerten soll und entsprechend in Tabellen speichern etc., müsste der Code erweitert werden um eine Funktion, so dass Für neue Kunden die entsprechenden tabellen etc. auch angelegt werden.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
var CustomerID : Integer;
begin
  CustomerID := CreateCustomer;
  CreateCustomerAdressAndShipping(CustomerID);
  CreateCustomerAccount(CustomerID);
  CreateCustomerAnalyzeTables(CustomerID);
end;


Mit den ERP Framework Components ist das nicht nötig, die Procedure hinter dem Button würde in beiden Fällen ungefähr so aussehen :
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
begin
  // HM_CreateCustomer ist einfach eine ID, die vom Programmierer festgelegt wird
  // und unter welcher er die Funktionen dieses Hooks speichert
  HookClient1.ExecuteHook(HM_CreateCustomer, 0);
end;


Die CustomerID selbst wird in einem Event der Komponente THookClient geliefert und kann dort entnommen werden, ExecuteHook liefert einen FehlerCode bzw. dass kein Fehler aufgetreten ist. Dem HookManager (der die Anforderung vom HookClient bekommt, etwas ausführen), ist es dabei egal, wieviele Funktionen eigentlich da sind und, ungleich einem Script zum Beispiel, ist es auch egal, ob eine Funktion da ist. Man bekommt mitgeteilt, wenn eine Funktion nicht vorhanden ist, aber das stört den Programmablauf nicht, da es kein Script ist. Der Programmierer selbst kann über Massnahmen in solchen Fällen entscheiden, er kriegt für jede Funktion innerhalb eines Hooks einen Bericht und Zwischenergebnis über entsprechende Events. Dabei kann entschieden werden, ob die Ausführung gestoppt wird, die nächste Funktion übersprungen oder einfach weitergemacht werden soll.
Soll nun der neue Code an den Hook Angefügt werden, wird bei der Installation des Moduls mittels einer Register-Funktion einfach dem HookManager mitgeteilt, dass es für den Hook HM_CreateCustomer eine neue Funktion gibt. Dabei kann auch Position des Codes festgelegt werden oder vorhandener überschrieben.

Der HookManager selbst befindet sich in einer DLL, welche ausser den Hooks noch ein ganzes Set von Funktionen zur Verfügung stellt.
- Datenbank-Zugang
- Globale Variablen (auch speicherbare)
- Install-API für Module und deren Funktionen
- Rechte-Verwaltung für Hooks
- Templates

Rechte-Verwaltung hatte ich ja weiter oben schon kurz erklärt, ich glaube, da muss ich nichts weiter dazu sagen. Auch bei der Install-API sollte klar sein, was sie macht.
Globale Variablen können über den HookClient gelesen und geschrieben werden, sie stehen für alle Module in der Anwendung zur Verfügung und der Programmierer kann bestimmen, welche ihre Gültigkeit nur für die Session haben und dann automatisch gelöscht werden und welche gespeichert werden sollen.
Templates sind eigentlich Streams, die nach ID (primär) oder Name+Kategorie (sekundär) gespeichert werden und darüber auch angesprochen werden können. Was drin gespeichert wird, bleibt dem Programmierer überlassen.
Datenbank Zugang habe deswegen dort eingebaut, da jeder Aufruf einer Funktion sowieso durch diese DLL geht und somit Datenbank und Transaktion mitgegeben werden können um im Modul benutzt zu werden durch ein TQuery oder TTable oder was auch immer. Dabei gibt es ein Basis-Object, welches virtuelle und abstracte methoden zur Verfügung stellt, welche durch das finale Datenbank-Objekt überschrieben werden um die Funktionalität unter verschiedenen Datenbank-Systemen zur Verfügung zu stellen. Im jetzigen Stadium gibt es ein Modul für Firebird und für die Registry (ein Mini-Treiber, der für datenbanklose Systeme gedacht ist). Um für ein anderes DB-System zu programmieren muss man eigentlich nur vom Basis-Object ableiten und ein paar recht einfache Befehle umsetzen / anpassen, wobei man allerdings am Bsp. des Firebird-Treibers sieht, welche das sind und was gemacht wird. Die meisten kann man wahrscheinlich vom Firebird-Treiber selbst nehmen und nur die Zugriffs-Komponenten austauschen.

Weiter geht es in Part 2 später...

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw


Zuletzt bearbeitet von HelgeLange am Do 05.11.09 00:55, insgesamt 7-mal bearbeitet
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Sa 10.03.07 02:44 
Das klingt sehr interessant :-) Die mangelnde Flexibilität von Plugins via Interface hat mich auch schon gestört. Ich bin auf die weiteren Postings gespannt :zustimm:

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
HelgeLange Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: Sa 10.03.07 02:44 
Titel: Part 2
Die Benutzung der Komponenten selbst gestaltet sich relativ einfach, da sie nur einen Loader brauchen, der auf die MainForm gelegt wird. In dessen Properties kann man festlegen, woher die einzelnen Manager geladen werden sollen etc. Alle Client-Komponenten suchen sich diesen Loader und holen sich entsprechend die Schnittstelle für ihren entsprechenden Manager. Dadurch kommen die Komponenten nicht nur ohne Einstellungen aus, sondern sind dazu auch sehr klein im Speicherverbrauch.

3.) Was gibt es für Manager neben dem HookManager mit seinem HookClient ?

Da wären ResManager, LinkManager und WindowManager im Moment.
Der ResManager kümmert sich um das Laden von Resourcen, Strings für Milti-Language-Support on-the-fly ohne Programm-Neustart und Bilder für Listen, die auch noch geshared werden, so dass jedes Bild faktisch immer nur einmal im Speicher vorhanden ist, aber in allen Programmteilen genutzt werden kann über dessen Handle. Ausserdem lädt er SQL-Strings, da diese nicht im Programm selbst bei mir sind, sondern als Resource gespeichert werden. Warum ? Weil ich Datenbank-unabhängig programmieren will, und so kann ich für das Programm den DB-Treiber und die SQL-Resource gegen die eines anderen DB-Systems austauschen und meine Module kriegen das nichtmal mit. Damit kann ich besser auf Kundenwünsche eingehen.

Der LinkManager kümmert sich um das Real-Time-Verknüpfen von Modulen/Fenster, die sich nicht kennen. Da ich ja davon ausgehe, dass immer wieder neue Module hinzukommen können, die ich im Moment der Auslieferung nicht kenne, habe ich mich entschieden, das das ganze ERP-System auf der Annahme beruht, dass keiner jemanden anderes kennt, aber sie trotzdem kommunizieren müssen. Der Linkmanager ist eines der Ergebnisse davon. Mit ihm kann man in real-time Daten zu einer unbekannten Menge von Empfängern schicken, um diese auf dem laufenden zu halten, so dass diese nicht pollen müssen. Zum Bsp. wird ein Auto vermietet und über den LinkManager kann die Übersicht der verfügbaren Autos sofort geupdated werden. Dazu meldet sich der Empfänger für Events an und falls dieses eintritt, wird beim Empfänger ein Event gefeuert, welches neben der Event-Information auch entsprechend Informationen enthält, die für das update nötig sein könnten. Welche Informationen das sind, bestimmt der Programmierer natürlich, es ist ja sein ERP System :)

Ein WindowManager kümmert sich darum, eine Fensterliste bei Bedarf anzuzeigen, Fenster zu finden, die von anderen Teilen der Anwendung benötigt werden und in Zukunft auch, diese zu schliessen, wenn nötig. Eines der grossen Vorteile des Systems ist dabei, dass es nicht mehr darauf ankommt, ob ich als Programmteil ein Fenster kenne bzw. den Object-Typ. Es reicht aus zu sagen, ich hätte gern einen Suchdialog für Kunden und das war es. Dabei entscheidet der FormFinder selbst, ob ein vorhandenes offenes Fenster genommen wird oder ein neues erstellt werden muss. Das Verhalten kann natürlich konfiguriert werden vom Anwender. Zusätzlich nutze ich zum Bsp. den LinkManger dort, um Suchergebnisse im aufrufenden Fenster anzuzeigen, wenn sinnvoll. Bsp.: Ich habe einen Dialog zum Kunden bearbeiten, drücke F3 für die Kundensuche, der Formfinder bringt mir solch ein Formular an, ich suche einen Kunden, doppelklick ihn und im KundenEditor werden schon die Daten geladen. Das kann sogar soweit gehen, dass man mit einem einfachen Klick auf den Eintrag in der Suche die Daten im Editor lädt und anzeigt, ohne, dass sich die beiden Fenster kennen. Sie können in unterschiedlichen Modulen befinden, auch könnte der Kunden-Editor erst 1 Jahr später nachgeliefert worden sein, die Kundensuche könnte über den WindowManager trotzdem gefunden werden und beide können über den LinkManager kommunizieren.

4.) Was gibt es sonst noch im Package ?

Biher hatten wir folgende Komponenten :
- TManagerBaseContainer (er lädt und verwaltet alle Manager DLLs)
- THookClient + Manager-DLL
- TResClient + Manager-DLL
- TLinkClient/TLinkServer + Manager-DLL
- TWindowComm + WindowManager.dll

Desweiteren im BasePack (das sind alle nicht-visuellen Komponenten) sind enthalten im Moment :
- TFormAccessManager
- TInstallManager

Diese beiden benutzt man in den einzelnen Modulen, die InstallAPI habe ich ja schon erwähnt, sie kann über diese Komponente gesteuert werden oder direkt aufgerufen, was allerdings mit Komponente einfacher ist, da sie einen Property-Editor besitst, wo man alle Install-Einstellungen für das Modul visuell erledigen kann.
Der FormAccessManager verwaltet die Formulare eines Moduls und liefert an Enumeratoren und andere Funktionen alle Informationen, um das Formular zu präsentieren. Ausserdem erzeugt es die Formulare und gibt sie wieder frei, alles über eine einheitliche Schnittstelle.

Während man herkömmlich für jedes Form folgendes machen muss (es gibt mehrere Wege etc, das weiss ich, aber das sind die basics, auf die man es reduzieren kann) :
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
var Form1: TForm1;
begin
  Form1 := TForm1.Create(AOwner);
  Form1.Show;
  Form1.Free;
end;

Und dies muss eigentlich im Modul für jedes Form extra gemacht werden. Das erzeugt 'ne Menge Code und wird unübersichtlich. Der FormAccessManager reduziert das ganze auf eine Zeile im Programm und n-Zeilen (n=Anzahl Forms) im DLL-Init-Teil.

Zum Registrieren der Form braucht man pro Form 1 Zeile, damit wird der Code-Teil (der zu einem Hook gehört) mit der Form verknüpft. Das hört sich vielleicht kompliziert an, ist es aber nicht. Das ganze sieht so aus :

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
begin
  // HookSubID ist eine ID, welche die Unterfunktion eines Hooks identifiziert
  // sie muss eindeutig sein im Modul
  FormAccessManager1.RegisterFormClass(HookSubID, TForm1);
end;


und im Aufruf sieht das ganze dann so aus :
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
begin
  // Params sind ein record, welches zusätzliche Infos mitgeben an ein modul
  // auch enthalten ist die Info, ob man nur Informationen über die Form haben will,
  // sie erzeugen oder eben freigeben
  // dieser eine Aufruf reicht für ALLE Formulare im Modul, da das Formular
  // eindeutig über die SubHookID verknüpft ist und dadurch erkannt werden kann
  // man kann natürlich soviele Formulare registrieren, wie man will
  FormAccessManager1.RequestForm(HookSubID, Params);
end;

Der FormAccessManager kommt mit einem Property-Editor, über welchen man Informationen über ein Formular (Anzeige-Name, Icon etc), welche bei einem Aufrufer benötigt werden, mit der eindeutigen SubHookID verknüpft. Zur Laufzeit kommt dann ja noch die Verknüpfung der Form selbst hinzu. Normalerweise geht das auch zur Designzeit, aber ich habe dies extra so gemacht, weil damit sichergestellt wird, dass man kein Modul mit falschen Informationen übersetzen kann.
Da unterschiedliche Formular-Typen unterschiedliche Werte brauchen, um das Formular beim Aufrufer zu präsentieren, gibt es eine Basis-Klasse der Formular-Typen. Will man nun eigene definieren, kann man von der Basisklasse ableiten, sich eigene Typen definieren, registrieren und diese werden automatisch vom FormAccessManager gespeichert, da dieser eine Schnittstelle zu den Typen besitzt, der die Daten selbst egal sind, um sie zu speichern oder zu laden.


Mehr gibt es in einem 3. Teil über visuelle Komponenten...

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw


Zuletzt bearbeitet von HelgeLange am Sa 10.03.07 23:13, insgesamt 1-mal bearbeitet
HelgeLange Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: Sa 10.03.07 03:16 
Titel: Part 3 - Visuelle Komponenten
Es gibt 2 Arten von visuellen Komponenten. Zum einen sind vorgefertigte Basis-Formulare, die schon Basis-Schnittstellen besitzen um mit den non-visuellen Komponenten optimal zusammearbeiten zu können. Zum Bsp. werden Settings mittels der Delphi-Dispatch-Methode gleich nach dem Erstellen des Formulars gemacht. Allerdings muss auf eine solche Nachricht ja reagiert werden, wodurch ein normales TForm das ganze nicht interessiert, aber von den ERP-Base-Formlaren abgeleitete fangen daraufhin an, zu rotieren (für alle, die nun denken, das Formular würde sich drehen... vielleicht doch erstmal richtig die ersten beiden Parts lesen, es geht hier nämlich nicht um Grafik-Effekte ;)) :)

Ausserdem haben die Fenster schon alle Einstellungen, um mit anderen visuellen ERP-Komponenten zusammenzuarbeiten. Zum Bsp. dem TabSheetServer oder der Wizard-Komponente. Diese beiden haben eine Property HookID, in welcher man den Hook angibt, an welchem sie ihre Formulare zusammensammeln. Da ja ein Hook aus n-vielen Funktionen besteht, die auch einfach Formulare sein können, kann zum Bsp. ein TabSheetServer (ist ein erweitertes TPageControl) sich über einen Hook seine Formulare zusammensammeln und diese auf den einzelnen TabSheets des PageControl darstellen. Dadurch ergibt sich natürlich die Möglichkeit, auch im Nachhinein neue TabSheets mit neuen Modulen anzufügen, ohne den Code des Formulars mit dem PageControl nochmal anfassen zu müssen. Neue Module bringen ja neue Informationen und Dialoge, die ins System eingefügt werden müssen, was somit natürlich zum Kinderspiel wird. Deswegen sage ich ja auch auf der WebSite, dass nun endlich ERP Programme leichter als ein Hello-World-Programm zu schreiben sind ;)
Oh.. und die Wizard-Komponente sammelt sich natürlich die einzelnen Steps aus den Modulen über einen Hook zusammen und zeigt sie in der Reihenfolge an, wie sie der Programmierer im Hook selbst vorgesehen hat. Methoden wie Next, Previous, First, Last und entsprechnde Events sind eine Selbstverständlichkeit und sollten der Erwähnung nicht benötigen. :)

Ausserdem mit hinzugelegt habe ich einige Komponenten als Beispiele, wie etwas in eigenen Controls bennutzt werden kann. Da gibt es zum Bsp. eine LinkedComboBox, LinkedListBox und LinkedCheckListBox, welche sich über einen Hook die darzustellenden Daten holen können und über den LinkManager mit einem Editor verbunden sind, um ihren Inhalt zu refreshen. Bsp.: In einer ListBox sind alle Genres für Filme dargestellt, der User muss diese nur entsprechend an/abwählen. Im Editor für die Genres wird ein neues Genre eingegeben, weil der User festegestellt hat, dass es dieses noch nicht gibt und normalerweise müsste er in herkömmlichen Systemen entweder das Fenster schliessen und neu öffnen, damit das neue Genre angezeigt wird.. oder aber eben drauf hoffen, dass der Programmierer clever genug war, dies vorauszusehen und über F5 zum Beispiel die Box refreshen kann. Oder es liegen die ERP Componenten dahinter und linken sich und können die Daten austauschen ohne User-Interaktion :P

Ausserdem dabei ist ein TResBitmap, welches an einer einfachen TPaintBox
zeigt, wie man eine Bitmap-resource lädt und mit Handle zeichnet. Denn ein gutes ERP System ist meiner Meinung nach unbedingt ein MDI-System und es kann von jedem Fenster n-viele Kopien offen geben. Dadurch werden aber TImage zum Bsp. n-mal geladen und Resourcen für das Bild verbraucht. Der ResManager lädt auf Anfrage Bilder, bei erneuter Anfrage wird nur ein ReferenzCounter erhöht bzw. gesenkt, wenn das Bild freigegeben wird und schlussendlich entladen, sowie der ReferenzCounter bei 0 ist. Dadurch wird nicht nur Resourcen-sparend gearbeitet sondern auch der Speicherverbrauch niedrig gehalten. In meiner ERP-Testanwendung daheim kam ich noch nie über 20 MB speicherverbrauch im TaskManager !


Ok, das erstmal zum Produkt selbst, im nächsten Part werde ich versuchen, auf Probleme der Programmierung, Marketing etc. einzugehen...

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
HelgeLange Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: Sa 10.03.07 04:39 
Titel: Part 4
Als Entwicklungsumgebung wurde ja offensichtlich Delphi genommen, C++-Versionen sind im Moment nicht geplant, da ich a) erstmal genug mit dem Release zu tun habe und b) mit BDS das wohl kaum noch nötig sein wird.

Erstellt wurden die Komponenten selbst mit Delphi 7 und BDS2006. Sie sollten ohne Probleme ab Delphi6 lauffähig sein, die Property-Editoren müssten eventuell angepasst werden mit ihrer uses-Liste, da Borland ja die Units nach Delphi 5 umbenannt hat.

Fertiggestellt wurden/werden sie mit BDS2006, aber es werden Projektdateien für Delphi 6 und 7 beigelegt und die Komponenten auch nochmal unter diesen Versionen getestet. BDS2005 kann ich leider nicht anbieten, da mir dazu im moment die Entwicklungsumgebung selbst fehlt, aber ich denke, dass sie dort ohne Probleme einzusetzen sind, wenn sie unter Delphi 6/7 und BDS2006 laufen.
Zum Bugtracking wird zur Zeit ein Mantis-Server eingesetzt und zur Versionskontrolle ein SVN mit einem TortoiseSVN-Client unter Windows. Mit beiden habe ich sehr gute Erfahrungen gemacht und die Kostenlosigkeit beider Produkte machen sie nur umso attraktiver für den Anfang. Zusätzlich wurde MemProof unter Delphi 7 und AQtime unter BDS benutzt, um Memory-Leaks zu suchen.

Die Entwicklung selbst ging über einige Jahre, wobei zwischendurch Pausen waren, wo ich manchmal für 1 Jahr oder mehr nichts dran gemacht habe. Denn urspünglich waren sie nur für mein System gedacht und dadurch auch relativ eng mit ihm verbunden.
Mit der Überlegung, die Komponenten entsprechend zu vermarkten (da ja offensichtlich Interesse und Bedarf besteht), stellte sich natürlich auch die Frage nach der Offenheit für andere Programmierer. So entschied ich mich zum Bsp. den TManagerBaseContainer zu schreiben und auch die Basis-Komponente TERPComponent komplett neu zu designen. Das war nötig, da ich bisher einfach in den Client-Komponenten eine Property HandleShared hatte, welche darüber entschieden hat, ob die Komponente den Manager lädt oder nicht. Solche Daten kann man sich natürlich sparen, gerade weil THookClient von mir auf 90% aller Formulare benötigt wird. TResClient sogar auf 100%, da diese sich auch um Sprachumschaltung kümmert und wenn in der Konfiguration die Sprache umgeschaltet wird, feuert die Client-Komponente ein entsprechendes Event, um auf Eigenheiten des Komponenten eingehen zu lassen und ändert die Sprache bei den Standard-Komponenten von Delphi selbst. Die Container-Komponente kommt mit ca. 650 Zeilen Code daher, kann mit allen meinen Managern klarkommen, benötigt 0 Zeilen Code auf dem Hauptformular, wenn man will und hat mich ca. 1 Tag Arbeit gekostet. Und obwohl das garnichtmal so wenig ist, lohnte sich das trotzdem, da die Benutzbarkeit des Komponenten-Paketes ingesamt stark gestiegen ist. Und für den Anwender später ist der Aufwand extrem stark gesunken, meine Komponenten in ein vorhandenes System zu integrieren.
Insgesamt muss man sowieso immer mal wieder drüber nachdenken, wie es wäre, wenn man NICHTS über die eigenen Komponenten weiss und sie einsetzen muss. Am besten einfach mal ein leeres Projekt machen und versuchen, sie su implementieren. Dann fallen einem sehr schnell Schwachstellen auf.

Das gleiche gilt für den FormAccessManager. Diesen habe ich erst nach der Entscheidung zum Publish gebaut, um es für den Anwender einfacher zu machen, Formulare an Hooks anzubinden und diese anzuzeigen. In einem Modul mit 5 Formularen ist der Aufwand, diese anzubinden, von ca. 20 Zeilen pro Formular (also ca. 100 Zeilen insgesamt) auf 6 Zeilen geschrumpft, 5 davon im init-teil um die Formulare zu registrieren, 1 Zeile um auf sie zuzugreifen. Weiterhin stellte sich dabei das Problem der Daten für ein Formular, hier mal ein Screenshot als visuelles Beispiel :
user defined image

Um den Tree auf der linken Seite aufzubauen benötigt man folgende Daten :
- Name des Nodes
- Image des Nodes
- Parent name
- Parent Image

Letzeres eigentlich deswegen, da Parent-nodes kein Formular besizten und deswegen die Daten nicht über den Hook selbst kommen. Jedes Formular meldet sich dabei mit seinem Parent-Node an, welches erstellt wird, falls nicht vorhanden. Und zum Erstellen wird natürlich die entsprechende Information benötigt. Und da ich ja eher für generelle Sachen bin, lass ich die Formulare eben entscheiden, unter welchem Eintrag sie angemeldet sein wollen. Natürlich kommen Name und Image aus dem ResourceManager und werden bei Sprachumschaltung übersetzt. Auch die Bilder kann man in Update-Modulen ändern, ohne das ursprüngliche Modul zur Anzeige des Dialogs nochmal anzufassen.

Und gerade weil Daten auf die entsprechende Darstellung im System zugeschnitten sind oder sein sollten, musste ich mir zusätzlich einen Weg überlegen, wie ich das alles in einer Komponente unterbekomme, so dass sie später von Programmierern nicht nur benutzt, sondern auchg erweitert werden kann mit neuen Datentypen etc, ohne, dass diese sich fregen müssen, wie sie das ganze im DFM speichern. Ich selbst baue mir einen binären Stream für das DFM und mir ist es dabei egal, welche Daten das sind, die Daten-Typen so so geschrieben, dass ich sie wegschreiben und lesen kann, wenn sie bei mir registriert sind, was rein technisch auch zur Laufzeit geschehen kann. Das einzigste, was geändert werden muss für neue Typen : der Property-Editor. Aber jeder Datentyp hat eine Editor-Funktion, so dass auch das kein Problem ist.

Auch extra angefertigt wurde ein Registry-Mini-Treiber für die Hooks. Ursprünglich basierend auf einem Datenbank-System war natürlich die Benutzung auf Datenbank-Systeme beschränkt. Mit dem Registry-Treiber hat sich das geändert und nun ist es nun auch möglich, den Funktionsumfang in Projekten zu nutzen, die nichts mit Datenbanken zu haben (wollen). Es ist also rein technisch auch als ganz normales Plugin-System zu benutzen, mit dem Vorteil der dynamischen Funktionen etc. Dabei muss natürlich bedacht werden, dass manche Funktionen, die im DBTreiber drin waren, hier sinnlos geworden sind und deswegen nicht unterstützt werden. Zu nennen wären da Templates, die recht gross werden können und nichts in der registry zu suchen haben. Aber wenn doch benötigt, kann der Benutzer sich ja die Schnittstelle implementieren, den im Moment liest er ja nur keine Templates und schreibt sich nicht im Registry-Modul, aber die interfaces sind da.

Zum Marketing kann ich leider noch nicht soviel sagen, da ich gerade damit anfange. Zum einen ist es das Vorstellen in Foren wie hier, dann ein DevBlog (link oben im 1. Post) und dass man halt den Link zum DevBlob in seine Signatur der Foren, wo dies möglich ist, packt. Regelmässiges Posten in Foren zu Problemen hilft a) zu zeigen, dass man eine Ahnung von dem hat, was man tut und b) werden unterschiedliche Posts von unterschiedlichen Leuten gelesen. Das erhöht die Zahl derjenigen, die eventuell die eigene Seite besuchen und sich für das eigene Produkt entscheiden. Natürlich darf das nicht in Spam-Posts ausarten, das macht nicht nur einen schlechten Eindruck bei potentiellen Kunden, sondern man kann sicher auch schnell Ärger mit dem Admin bekommen :P
Weiterhin werde ich nächste Woche versuchen, mein DevBlog in Delphi-RSS-Feeds zu bekommen, so dass der Bekanntheitsgrad der Komponenten jetzt schon gesteigert werden kann, bevor sie überhaupt auf dem Markt sind. Damit weckt man das Interesse und kann sich Sorgen/Meinungen potentieller Kunden schon vorher anhören und evntuell drauf reagieren :)
Auch das Erstellen eines Demo-Programms und das zur Verfügung stellen einer Shareware-Version bei verschiedenen Komponenten-Seiten im Netz (Torry etc) hilft, die eigenen Komponenten zu vermarkten. Nichts desto trotz soll man so zeitig wie möglich damit anfangen, seine Komponenten im Netz bekannt zu machen, am besten schon mit der 1. Zeile Code, die man dazu schreibt.

Was allerdings recht schwer gerade bei nicht-visuellen Komponenten ist : Screenshots. Auch kann der User sich nicht viel unter einer ListBox vorstellen, wenn da 3 Einträge drin sind. Er weiss ja erstmal nicht, welche Technik dahinter steckt, diese Einträge zusammenzustellen.

Ich habe mich daher entschieden, dieser Tage eine Demo zu basteln, wo im oberen Teil der Anwendung die demo selbst auf TabSheets dargestellt wird und im unteren Teil in einem Memo der Code-Aufwand, um dies zu realisieren. Denn im Endeffekt geht es ja darum, dem potentiellem Kunden zu zeigen, wie einfach es ist, etwas mit diesem System zu tun :)

Ok, das war es erstmal für heute an Geschreibsel, dieser Tage folgt mehr mit Demo und vielleicht ein paar Schreenshots aus meiner ERP-Anwendung.
Hoffe natürlich, mit dieser ewig langen Vorstellung nicht zusehr gelangweilt zu haben, aber die erste Reaktion von Christian S. hat gezeigt, dass Interesse vom technisch versierten Programierern doch so gross sein könnte, wie ich es hoffe...

Und immer schön an einen meiner Leitsätze in der Programierung erinnern, das hilft bei der Entschedung, etwas zu machen : Andere Programmierer kochen auch nur mit Wasser !

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
matze
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 4613
Erhaltene Danke: 24

XP home, prof
Delphi 2009 Prof,
BeitragVerfasst: Sa 10.03.07 11:57 
Hallo Helge.

Also ich möchte dir hier jetzt einfach mal ein großes Lob aussprechen. Dein Beitrag ist wirklich ein würdiger erster Beitrag für diese junge Sparte. :zustimm:
Alles gut, sauber und interessant beschrieben, sodass man sich was darunter vorstellen kann.

Ich bin schon auf die Demo-Programme und die Shareware Versionen der Komponenten gespannt :wink:

_________________
In the beginning was the word.
And the word was content-type: text/plain.
HelgeLange Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: Sa 10.03.07 15:02 
Danke matze.. nach den Stunden an Arbeit, die man investiert hat, um den Beitrag zu schreiben, hört man das natürlich das natürlich doppelt gern.

Das Thema selbst ist für mich selbst schon immer interessant gewesen, weswegen ich wahrscheinlich auch die Energie reingesteckt habe, es zu programmieren. Nut fürchte ich auch ein wenig, dass der Text, der ja unbestritten über 3 Zeilen hinausgeht, vielleicht doch etwas zu lang geraten ist, damit er auch wirklich gelesen wird.

Was ich ausserdem total gern sehen würde hier, wären ein paar Tipps zu Marketing etc, da ich da etwas unbewandert bin, bin halt eigentlich nur ein Programmierschwein.
In einer Sache hatte ich Glück, zumindest für mein Land im Moment : Meine Freundin ist Journalistin hier für ein Business-Magazin, dadurch kennt sie natürlich alle möglichen Leute, auch in anderen Zeitungen/Magazinen und wird zum Release selbst eine Pressemitteilung machen und auch ein grossen beitrag für das grösste Technology-Magazin hier schreiben. Allerdings sind weder Venezuela noch Kolumbien (wo das Magazin erscheint) für ihre Software in der Welt bekannt ;) Aber ist besser als nichts.

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
JDKDelphi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 115
Erhaltene Danke: 22

WIN2000, XP, WIN 7 , UNIX, LINUX
Assembler für (Z8x, 68xxx,R6000,Intel), DELPHI 6 Enterprise, MAGIC eDeveloper V9+V10, C++, C#,VB, .NET, zertifizierter iBOLT-Programmierer
BeitragVerfasst: Sa 10.03.07 15:49 
Hallo Helge,

ich habe diesen Artikel mit äusserstem Interesse gelesen!

Such' schon lange nach einer ERP/CRM-Lösung, die ggf. in der Industrie eingesetzt werden kann. Ich programmiere so etwas in MAGIG oder IBOLT (Fa.(c)Magic)..

Sehr guter Artikel !!!


Gruss
Blawen
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 616
Erhaltene Danke: 33

Win XP, Vista, 7
Delphi 5 Prof., BDS 2006 Prof. RAD Studio XE
BeitragVerfasst: Sa 10.03.07 22:50 
user profile iconHelgeLange hat folgendes geschrieben:
Danke matze.. nach den Stunden an Arbeit, die man investiert hat, um den Beitrag zu schreiben, hört man das natürlich das natürlich doppelt gern.

Das Thema selbst ist für mich selbst schon immer interessant gewesen, weswegen ich wahrscheinlich auch die Energie reingesteckt habe, es zu programmieren. Nut fürchte ich auch ein wenig, dass der Text, der ja unbestritten über 3 Zeilen hinausgeht, vielleicht doch etwas zu lang geraten ist, damit er auch wirklich gelesen wird.
Wenn Du den Text mit ein paar Bildern garnierst, lässt sich der Aufmerksamkeitseffekt problemlos steigern.
Du hast bisher ein Bild veröffentlicht und dies hat bei mir zumindest die Aufmerksamkeit geweckt! Gratulation auch von meiner Seite!

_________________
Es kompilert, wir können ausliefern.
Und es kompiliert wieder - das Update ist fertig - bitte 100 Euro ;-)


Zuletzt bearbeitet von Blawen am Sa 10.03.07 23:05, insgesamt 1-mal bearbeitet
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Sa 10.03.07 23:02 
Hallo!

Auch von mir erst einmal großes Lob und Danke! Das ist genau so, wie wir uns Programmvorstellungen hier gedacht haben :-)

Ich finde den Text nicht zu lang, aber es würde vielleicht helfen, wenn Du ein paar Zwischenüberschriften in fett reinmachst, damit man eher den roten Faden erkennt.

Planst Du eigentlich auch etwas in Richtung .NET-Umsetzung?

Grüße
Christian

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
HelgeLange Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: Sa 10.03.07 23:10 
Hi,

wie ich schon im Text oben erwähnt habe, ist es natürlich schwer, Screenshots für nicht-visuelle Komponenten zu machen, da ja die Komponenten nicht zu sehen sind. Bei denen kommt es drauf an, was sie unter der Haube haben. Der eine Screenshot war ein Beispiel aus meiner ERP Test Anwendung, bei welcher ich die Komponenten intensiv nutze.

Gerade in diesem Moment bin ich an der Umsetzung des Demos, natürlich modular, so dass ich immer mal neue Module nachschieben kann und der User sich nur diese laden muss und dazu installieren :)

Über die Möglichkeit der .NET Umseztung habe ich nachgedacht, muss aber erstmal evaluieren, ob das so überhaupt geht, den .NET hat viele Restriktionen. Ich arbeite zum Bsp. viel mit Pointern etc., Ich habe mehr "New"s und "GetMem"s im Code als alles andere.. (stimmt natürlich nicht, aber ich nutze das schon sehr häufig). Also muss ich erstmal rausfinden, wie ich das überhaupt in .NET ohne dies machen kann. Sowie das Release fertig ist, werd ich mir das mal anschauen, versprochen :)

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: So 11.03.07 13:02 
Hallo Helge,

ich hab mal eine kleine Frage bezüglich deines ersten Posts. Und zwar hast du ja geschrieben, dass man Methoden über deine Hook-Kapselung erweitern kann. Wie Variabel ist da deine Hookklasse? Also kann man da auf Parameter reagieren (also auf temporäre Variablen) und kann man seine Methode aufrufen lassen, bevor die "gehookte" an der Reihe ist?
MrSaint
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1033
Erhaltene Danke: 1

WinXP Pro SP2
Delphi 6 Prof.
BeitragVerfasst: So 11.03.07 13:43 
user profile iconHeiko hat folgendes geschrieben:
und kann man seine Methode aufrufen lassen, bevor die "gehookte" an der Reihe ist?


Das würde mich auch interessieren ;) Wenn ich mir jetzt vorstell, dass ich so ein Programm mit deinen Kompos schreib und dann später dazu auch noch PlugIns. Angenommen, ich hab ein Plugin, dass bei irgendeiner Aktion, die das Programm macht, einen Dialog anzeigt und da dann irgendwas machen läßt. Und jetzt das zweite PlugIn, das das gleiche macht (man kann da halt irgendwas anderes mit einstellen), dessen Dialog muss aber zwingend vor dem Dialog des ersten PlugIns kommen (aus irgendwelchen Abhängigkeitsgründen). Geht sowas? Ich denke nämlich, dass das ein komplexeres Problem ist, da man ja nicht einfach jedem PlugIn einen Integer mit eineer Priorität mitgeben kann...

Allgemein find ich aber auch: Gute Arbeit! Sind hübsche Ideen mit dabei :)


MrSaint

_________________
"people knew how to write small, efficient programs [...], a skill that has subsequently been lost"
Andrew S. Tanenbaum - Modern Operating Systems
HelgeLange Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: So 11.03.07 16:06 
Wenn man in Hooks neuen Code einfügt, hat man eine Option :
ausblenden Delphi-Quelltext
1:
     THookInsertDirection = (hidWhoCares, hidBefore, hidAfter, hidFirst, hidLast);					


wobei hidWhoCares bedeuted, es wird eingefügt, wo Platz ist, hidBefore und hidAfter brauchen einen Bezugs-Punkt, also man sagt, dass man diesen Code vor oder nach einem bestimmten vorhandene Code-Teil haben will. Also ist es kein Problem, vor einem Code später noch einen Config-Dialog einzubauen etc.

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
HelgeLange Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: So 11.03.07 16:48 
oh, glatt die Frage von Heiko vergessen. Ja, man kann Variablen, Objekte, was auch immer mitgeben und in den HookFunktionen manipulieren lassen. Das sah zwar erstmal nicht so aus, aber es gibt da 4 Events bei der Ausführung eines Hooks. Der 1. tritt auf, wenn der HookClient zum HookManager geht. In der Zwischenzeit wurde nämlich ein QueryInfoBlock erstellt und gefüllt und Speicher für eine var-Variable erzeugt. Im Event selbst kann man dann Felder des QueryInfoBlock nutzen oder auch einfach die var-Variable (ist vom Typ Pointer) und irgendwas dran hängen, was man halt so brauch.
Das nächste Event wird gefeuert, wenn der HookManager eine angemeldete Funktion ausführen will. Man erhält die gleichen Möglichkeiten wie vorher auch, allerdings ist dabei zu bedenken, dass sie vor jeder einzelnen Funktion innerhalb eines Hooks gefeuert wird, während die erste genannte nur einmal aufgerufen wird.
Nachdem eine Funktion innerhalb eines Hooks ausgeführt wurde, wird wieder ein Event gefeuert und der Aufrufer kann nun die ersten Ergebnisse lesen, die Daten für die nächste HookFunktion manipulieren oder zurücksetzen und auch FehlerCode auswerten und entscheiden, wie bei der Ausführung des Hooks weiterverfahren soll, kann die nächste Funktion überspringen, wenn er will oder den Hook gänzlich stoppen.
Sind alle Funktionen des Hooks ausgeführt, wird wieder ein einmaliges Event gefeuert, so dass man die Ergebnisse des Hooks auswerten kann, speicher freigeben, den man für die Funktionen des Hooks eventuell angefordert hatte etc.
Danach gibt der HookClient seinen angeforderten Speicher frei und landet wieder bei der Aufrufer-Funktion.

Um das ganze Variablen-Zeug etwas zu erleichtern, da es ja über Events geregelt wird (das muss so sein, da der HookClient sich um seinen Speicher kümmert, nicht der Anwender!), habe ich einen Stack dazu gebastelt. Da kann man Variablen drauflegen (String/Integer/Objekte/Pointer) und im Event wieder runternehmen und in den vom HookClient zur Verfügung gestellten Speicher legen. Dadurch hat man den grossen Vorteil, dass man Daten, die einem nicht selbst gehören, aber die an die Funktion, welche den dann Hook aufrufen, übergeben wurden, nicht zwischenspeichern muss in Variablen, die man extra dafür anlegt, sondern man pusht sie auf den Stack, ruft den Hook auf, der trottelt im 1. Event an (BeforeCallRouter) und dort poppt man sie vom Stack und arbeitet mit ihnen.

So, hoffe, die Frage nach Variablen ist ausreichend erklärt worden :)

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
MrSaint
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1033
Erhaltene Danke: 1

WinXP Pro SP2
Delphi 6 Prof.
BeitragVerfasst: So 11.03.07 16:58 
user profile iconHelgeLange hat folgendes geschrieben:
Wenn man in Hooks neuen Code einfügt, hat man eine Option :
ausblenden Delphi-Quelltext
1:
     THookInsertDirection = (hidWhoCares, hidBefore, hidAfter, hidFirst, hidLast);					


wobei hidWhoCares bedeuted, es wird eingefügt, wo Platz ist, hidBefore und hidAfter brauchen einen Bezugs-Punkt, also man sagt, dass man diesen Code vor oder nach einem bestimmten vorhandene Code-Teil haben will. Also ist es kein Problem, vor einem Code später noch einen Config-Dialog einzubauen etc.



Hmm... das würde doch aber vorraussetzen, dass jedes PlugIn jedes andere kennt, oder? Weil sonst machen einfach beide PlugIns ein hidAfter (in Bezug auf den Original-Code im Programm) und dann ist wieder ein Konflikt da. Und da muss man dann ja auch Glück haben, dass die beiden dann gerade richtig rum angeordnet werden.
Ich mein, das ist schonmal ein guter Ansatz mit den HookInsertionDirections, aber es reicht wohl leider noch nicht aus. Eine Idee wie man das besser machen könnte, hab ich aber leider momentan auch net...
Ich stell mir das halt so vor, wenn ich mal 100 PlugIns oder so für ein Programm hab, dann weiß ein Programmierer, der jetz noch eins dazu programmiert nicht unbedingt die genauen Einstellungen von allen anderen und vergißt dann eben solche Seiteneffekte. Ganz zu schweigen, wenn man PlugIns für sein Programm von anderen Firmen oder sogar öffentlich (also dass jeder Mensch einfach ein Plugin schreiben kann, wies ihm so passt) programmieren läßt. Und durchtesten mit allen vorhandenen PlugIns kann ja auch net die Lösung sein...


MrSaint


EDIT: vllt wäre es eine Möglichkeit die Sortierung solcher PlugIns zentral auf einem Server zu managen und das Programm lädt sich diese Reihenfolge bei einer PlugIn-Installation einmal runter und passt das dann richtig an... Das würd mir jetzt dazu einfallen...

_________________
"people knew how to write small, efficient programs [...], a skill that has subsequently been lost"
Andrew S. Tanenbaum - Modern Operating Systems
HelgeLange Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: So 11.03.07 17:28 
Naja, diese Komponenten sind ja keine FreeWare/OpenSource-Komponenten, von daher, wird es nicht passieren, dass man etwas schreibt wie Miranda und die Welt schreibt Plugins.
Von daher reicht mein Ansatz, nämlich dem, der eine Software schreibt und später erweitern will, die Möglichkeit zu geben, die Position des neuen Codes innerhalb eines Hooks zu bestimmen. Und der sollte schon wissen, was bei ihm im System passiert, gerade wenn es um sensitive Stllen des Programms geht, bei denen die richtige Reihenfolge des Codes eine Rolle spielt.

Ich selbst benutzte das bisher 2 mal in meinem Programm, für alle anderen Hooks ist mir die Reihenfolge egal. Oft hat ein Hooks auch nur eine Funktion bei mir. Warum ? Weil ich den Code austauschbar machen wollte. Ich weiss oftmals schon im voraus, dass man da vllt mal was anderes dahinter stellen könnte.

Nehmen wir mal das Beispiel eines ERP-Systems. Was sind die Mängel aktueller Lösungen auf dem Markt ? Sie sind Monolith-Anwendungen, die alles schon können und daher im Preis extrem hoch. Das schreckt viele Anfänger mit einem Geschäft ab, weil die Software a) zu teuer ist und b) zu kompliziert, da man von Funktionen, die man erstmal nicht braucht, erschlagen wird.

Die Lösung dafür liegt auf der Hand : Man baut eine modulare ERP-Lösung, die wie ein Baukasten funktioniert. Das gibt dem Einsteiger die Möglichkeit, eine "kleine"Version für den Anfang zu kaufen, die genau das macht, was er erstmal braucht und nur einen Bruchteil kostet. Und wenn er später mehr braucht, kauft er sich die Module dazu, die ihm die Funktionen liefern, die im jeweiligen Moment benötigt werden.
Ok, das hört sich vllt. kompliziert an, aber es bringt Vorteile, denn für den Kunden fällt es am Anfang natürlich leichter, sich für eine 100-200 Euro Lösung zu entscheiden und die dann langsam zu erweitern, wie halt Geld reinfliesst (gerade am Anfang will man sein Geld so optimal wie möglich anlegen), zum anderen sieht der Kunde schon im Vorfeld, dass er sich "sein" Programm modellieren kann wie eine Statuette und kriegt nicht einen Klotz vors Gesicht gestellt. Das gibt ihm das Gefühl von Freiheit zu entscheiden, wieviel er bezahlt und ob er für etwas bezahlt, was er nicht braucht.

Die Lizenz für mein eigenes ERP-Programm wird zum Bsp. beinhalten, dass es frei kopiert und unbeschränkt evaluiert werden kann, aber wenn es komerziell eingesetzt wird (also in einem Shop etc.), muss es lizensiert werden. Das mache ich deswegen so, weil ich ja möchte, dass die Leute mein Programm weitergeben. Und heutzutage kann man es sich nicht wirklich erlauben, Raubkopien/unlizensierte Software in seinem Laden zu haben, wenn es nur um 200 euro geht. Plugins werden bei mir für 50 Euro wahrscheinlich angeboten, Festpreis. Das macht es dem Kunden einfach, zu kalkulieren.

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
Bex
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 47

Win XP, Linux
C# (VS 2008), Java (Eclipse)
BeitragVerfasst: Mo 12.03.07 10:45 
Titel: Re: ERP Framework Components + Developers Blog
user profile iconHelgeLange hat folgendes geschrieben:
ERP (Enterprise Resource Planning, zu gut deutsch : Warenwirtschaft) - Systeme waren schon immer eine meiner Leidenschaften.


Sorry, wenn ich die allgemeine Begeisterung hier mal unterbrechen muss, aber: ERP mit WaWi zu übersetzen - darauf muss man auch erst einmal kommen (etwa so wie "Truck, zu deutsch Fahrrad").
Bei ERP geht es um weit mehr als bloß die Waren, beispielsweise Personal- und Finanzplanung, Material, Arbeitspläne, Kapazitäten, Produktionsprozesse etc.
Robert.Wachtel
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 895
Erhaltene Danke: 7

Windows 7 Ultimate x64
D5 Ent, D7 Arch, RAD Studio 2010 Pro, VS 2008
BeitragVerfasst: Mo 12.03.07 11:02 
Titel: Re: ERP Framework Components + Developers Blog
user profile iconBex hat folgendes geschrieben:
Sorry, wenn ich die allgemeine Begeisterung hier mal unterbrechen muss, aber: ERP mit WaWi zu übersetzen - darauf muss man auch erst einmal kommen (etwa so wie "Truck, zu deutsch Fahrrad").

Danke, dass es mal jemand erwähnt hat...
HelgeLange Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: Mo 12.03.07 13:51 
doh.. und warum schreib ich dann extra hin "zu gut deutsch" ? Ich habe versucht, alles so einfach wie möglich zu halten, damit einfach jeder weiss, worum es geht. Leider ist es so, dass in Deutschland ERP für WaWi benutzt wird. Wie man "Enterprise Resource Planning" Wort für Wort übersetzt, weiss ich selbst. Und ich habe gerade nachgeschaut, auch Leo übersetzt Warenwirtschaft mit ERP :P
Also komm mal wieder runter.

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw