Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Funktionsbibliotheken, Code-Organisation - Wie macht Ihr das? (https://www.delphipraxis.net/191338-funktionsbibliotheken-code-organisation-wie-macht-ihr-das.html)

hschmid67 4. Jan 2017 07:51

Funktionsbibliotheken, Code-Organisation - Wie macht Ihr das?
 
Liebe Delphi-Gemeinde,

seit Jahren habe ich in einer Unit Funktionen gesammelt, die ich immer mal wieder brauche; selbstgeschriebene und irgendwo als Snippet kopierte. Das geht von einfachen Stringmanipulationen über RegEx bis hin zu DB-Funktionen und einfachen Netz- und Betriebssystemfunktionen. Also alles bunt durcheinander. Der große Vorteil: ein einfaches Einbinden der "mytools.pas" in die uses-Klausel genügte, um immer alles parat zu haben.

Doch die Nachteile werden immer größer: Die Unit wird immer größer und unübersichtlicher, die Exe-Dateien werde sehr groß (spielt zwar heute selten wirklich eine Rolle) und man braucht, wenn man mit Packages arbeitet, immer viele andere Packages, die eingebunden werden müssen. Das sind keine großen Probleme, aber "schön" ist das auch nicht :wink:

Also überlege ich, wie ich meine Funktionen besser organisieren kann, ohne mir zu viele Nachteile aufzuladen. Wie habt Ihr das bei Euch gelöst? Was sind Eure Überlegungen? Welche "best practices" habt Ihr gefunden? Ich würde bei einer Neuorganisation gerne das "fluent interface" an manchen Stellen nutzen (das gefällt mir z.B. in jQuery ganz gut).

1. Man könnte also die bisherigen Funktionen (meist wirklich einfache procedure/function-Aufrufe) in verschiedene Units aufteilen, nach Themengebieten geordnet: String, Convert, DB, Net... - fluent ist dann zwar nicht, aber es wird übersichtlicher.

2. Packe ich alle einzelnen Funktionen in Klassen und rufe sie dann als class procedures auf? Für ein fluent interface bräuchte ich dann wohl class var...

3. Oder sind - einen Schritt weiter - Interfaces zu solchen Klassen die bessere Wahl, da ich mich nicht um die Freigabe kümmern müsste?

4. Hier würden auch Records in Frage kommen. Was wäre der Vor- und Nachteil? Lässt sich hier ein fluent interface ohne Probleme verwirklichen?

Tja, manche Idee schwirrt in meinem Kopf herum. Und ich weiß nicht so recht, was weshalb besser ist. So würden mich also Eure Erfahrungen interessieren. Wie organisiert Ihr eure Funktionsbibliotheken? Alles in einer unit? Viele units mit vielen Klassen/Interfaces/Records? In welchem Fall ggf. welches Pattern/Modell? Und wie behaltet Ihr den Überblick?

Herzliche Grüße mit den besten Wünschen noch zum Neuen Jahr
Harald

DeddyH 4. Jan 2017 08:04

AW: Funktionsbibliotheken, Code-Organisation - Wie macht Ihr das?
 
Erst gestern wurde ein ähnlicher Thread gestartet: http://www.delphipraxis.net/191329-u...rzugt-ihr.html

jaenicke 4. Jan 2017 08:28

AW: Funktionsbibliotheken, Code-Organisation - Wie macht Ihr das?
 
Das ist im Grunde noch ein Schritt weiter als der andere Thread.

Wir machen das so, dass wir für diverse Funktionalitäten Interfaces bereitstellen indem wir diese an einer zentralen Stelle registrieren. Wollen wir das Interface nutzen, binden wir die Verwaltungsstelle und die Unit mit dem Interface ein.

Es spricht aber auch nicht viel dagegen (außer der Übersicht und nicht ganz so einfaches Mergen usw.) auch alle Interfaces in eine Unit zu packen. Da das nur die Interfaces und nicht die Implementierungen sind, sollten sich die Abhängigkeiten in engen Grenzen halten. Dann hättest du es quasi ähnlich wie bisher, nur besser strukturiert.

Die Implementierungen kannst du dann auch auf viele Units verteilen und in mehreren Units alle registrieren. Dann bindest du im Projekt die Registrierungs-Units ein, die du brauchst und fertig. Du musst das aber nicht überall bei der Verwendung machen.

Rollo62 4. Jan 2017 13:36

AW: Funktionsbibliotheken, Code-Organisation - Wie macht Ihr das?
 
Hallo Jaenicke,

hältst Du die Interfaces dann global vor, oder erzeugst/zerstörst du die jedesmal OnDemand ?

Die Fmx.Platform Interfaces scheinen so ausgelegt zu sein das man immer kurz für eine Aufgabe (z.B. ScreenOrientation) das Erzeugt/Abfragt/Freigibt.

Oder sollte man solche globalen Interfaces benutzen
Z.B.
Initialization: Erzeugen
Globales Interface merhfach benutzen
Finalization: Freigabe

Bei Desktop wäre beides wohl OK, aber vielleicht auch 1. die bevorzugte Variante,
aber bei Mobile sollte man wohl auf jeden Fall auf globale Interfaces verzichten
(wg. Memory footprint, Speichergrenzen, etc. ... ).

Wie haltet ihr das mit solchen zentralen Interfaces, wie
ScreenOrientation, Screen Abmessungen, Portrait/Landscape, etc. ?

Rollo

jaenicke 4. Jan 2017 13:55

AW: Funktionsbibliotheken, Code-Organisation - Wie macht Ihr das?
 
Wir haben die Möglichkeit eine Getter-Methode oder ein konkretes Interface zu hinterlegen. Manche werden so direkt beim Start erzeugt, manche erst durch Aufruf des Getters bei Verwendung.
Der Getter kann auch Parameter bekommen.

Mavarik 4. Jan 2017 14:28

AW: Funktionsbibliotheken, Code-Organisation - Wie macht Ihr das?
 
Ich mache das ganz einfach...

Erstmal die die Voraussetzung eine entsprechende Factory, die die Klassen zu den Interfaces erzeugen kann.
Die Interfaces sind themenbezogen in Definitions-Units. Die Implementation ist NIE im Interface teil der Unit, somit linkt auch keiner "dagegen".

Ggf. gibt es noch einen IFDEF für die Unittests, damit man doch an die Klasse "ran kommt".

Ich brauche dann überall nur die Factory und die Interface Unit an zu geben.

ggf. nutze ich auch das Singelton Pattern - wie es Delphi auch macht mit.

Delphi-Quellcode:
Services.Default.Whatever.


Es gibt in meinem FDK auch noch die Möglichkeit, nur für einen Moment ein Interface zu erzeugen.

Beispiel:

Delphi-Quellcode:
begin
  TAnyFactory.Default.CallIfExists<IFOO>(Procedure (AFoo : IFoo)
    begin
      AFoo.Whatever;
    end,'special'); // Optionaler Selector
end;
Wenn die Unit, die IFoo Implementiert im Projekt enthalten ist wird die Funktionalität aufgerufen, sonst nicht.
Und die Instance existiert nur für die Dauer der anonymen procedure.
(Bei Klassen mit autofree)

Somit kann ich durch hinzufügen, z.B. eines Plugin,s Funktionalitäten an und abschalten.

Mavarik

hschmid67 4. Jan 2017 15:18

AW: Funktionsbibliotheken, Code-Organisation - Wie macht Ihr das?
 
Vielen Dank zusammen!
Diese Hinweise und Erfahrungen helfen mir schon viel weiter. - Und so werde ich mal folgendes versuchen:
  1. Unit mit einer Factory-Klasse
  2. Verschiedene Units mit den Interfaces, diese in Factory-Klassen-Unit einbinden (wie benennt Ihr solche Units?)
  3. Verschiedene Units mit den Klassen, hier die jeweilige Interface-Unit einbinden

Zuletzt müsste ich dann nur die Unit mit der(den) Factory-Klasse(n) einbinden, und hätte alle Funktionalität verfügbar. Genau so hatte ich es gehofft, auch wenn es erstmal eine Menge Arbeit ist, die alten Funktionen entsprechend umzuverteilen... :wink:

Zwei Fragen bleiben für mich:

Dieses Vorgehen müsste doch trotzdem den Code von allen Units (auch den Klassen-Units und den darin verlinkten Units) ins Programm compilieren/linken, oder? Auch wenn ich ein Interface / eine Klasse im Projekt gar nicht brauche? Also brauche ich bei Verwendung von Packages auch alle verknüpften Packages aus allen Units?

Das mit dem "Default" hab ich noch nicht verstanden - bisher nie verwendet. Aber ich suche mal in der Doku und den anderen Posts im Forum.

Herzlichen Dank an alle!

Rollo62 4. Jan 2017 16:16

AW: Funktionsbibliotheken, Code-Organisation - Wie macht Ihr das?
 
Ob Getter oder Factory, das Erzeugen ist klar.

Mir ist nicht klar ob man z.B. für Screen-Abmessungen ein Singleton (das meinte ich ja mit globales Interface) bereithalten sollte.

Also den Lebenszyklus: vom Programmstart bis -Ende

Ich gehe z.B. wenn möglich so vor:

- fasst man das selten an
(z.B. IFMXDeviceMetricsService, IFMXDialogService, IMXSaveState)
--> dann erzeuge ich das lokal OnDemand

- fasst man das möglicherweise andauernd an
(z.B. IFMXLoggingService, IFMXLocaleService, IFMXScreenService)
--> dann lasse ich manchmal globale Singletons zu

Die große Frage:
Ab wann sollte man von lokal auf global Umschwenken, wenn überhaupt ?
Gibt es da eine gute Daumenregel ?

Und ist die Regel gleich bei Desktop und Mobile, wohl eher nicht ...

Rollo

Rollo62 4. Jan 2017 19:56

AW: Funktionsbibliotheken, Code-Organisation - Wie macht Ihr das?
 
Zitat:

Das mit dem "Default" hab ich noch nicht verstanden - bisher nie verwendet
Hinter Default ist z. b. eine Class Function welche eine Class Variable beim ersten Aufruf erzeugt.
Jeder weitere Aufruf nimmt dann diese Class Variable und es ist nur ein Singleton Objekt für die ganze Programmlaufzeit angelegt.

Das ist dann im Prinzip die globale Varable\Klasse mit der man jederzeit arbeiten kann.

Sorry für meine Tippfehler - sitze nur vorm Tablet :stupid:


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:59 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz