Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Zirkuläre Unit Referenz auflösen (https://www.delphipraxis.net/194644-zirkulaere-unit-referenz-aufloesen.html)

Aviator 15. Dez 2017 15:48

Zirkuläre Unit Referenz auflösen
 
Hallo zusammen,

ich stehe gerade vor einem etwas blöden Problem wo ich gerne mal eure Hilfe hätte. :-D


Ich habe folgendes Konstrukt:


Unit A (verkürzt):
Delphi-Quellcode:
unit Common.Interfaces;

interface

uses
  UnitB;

type
  IMyInterface = interface
    procedure SomeMethod;
  end;

  IMyOtherInterface = interface
    function SomeOtherFunction: TSomeRecord;
  end;

Unit B:
Delphi-Quellcode:
unit Common.Types;

interface

uses
  UnitA; //  <--- Ist ja nicht möglich, da UnitA schon UnitB referenziert

type
  TSomeRecord = record
    SomeInteger: Integer;
    InterfaceReference: IMyInterface;
  end;
Wie kann ich elegant diese zirkuläre Referenz auflösen? Es gäbe meiner Meinung nach zwei Möglichkeiten. Entweder den Record in die Unit
Delphi-Quellcode:
Common.Interfaces
reinschubsen oder für
Delphi-Quellcode:
IMyInterface
eine eigene Unit zu machen.

Bei der ersten Lösung habe ich keine saubere Trennung mehr zwischen Interfaces und anderen Datentypen. Das gefällt mir irgendwie nicht.

Bei der zweiten Lösung gefällt mir nicht, dass ich dann prinzipiell für jedes Interface eine einzelne Unit machen müsste wenn denn da noch mehr Referenzierungen auftreten würden.



Wie löst ihr ein solches Problem? Gibt es eventuell noch irgendwelche Möglichkeiten das besser zu machen?

stahli 15. Dez 2017 16:01

AW: Zirkuläre Unit Referenz auflösen
 
Ich sehe kein Problem, den Record in Common.Interfaces zu definieren.
Er ist ja dann auch "Teil der Interfaces".

Er sollte dann natürlich keine Geschäftslogik implementieren (das ginge ja wohl inzwischen mit Records) sondern als reiner Datentyp genutzt werden.

Stevie 15. Dez 2017 16:45

AW: Zirkuläre Unit Referenz auflösen
 
Record in die Interface Unit. Sobald du IMyOtherInterface irgendwo implementierst wirst sonst eh die 2. Unit brauchen.

Zitat:

Zitat von Aviator (Beitrag 1388966)
Bei der ersten Lösung habe ich keine saubere Trennung mehr zwischen Interfaces und anderen Datentypen.

Wenn ein Typ Teil einer Interface Deklaration ist, dann ist dieser Typ Teil des Interfaces/deiner API und gehört dementsprechend dort hinzu.

Ansonsten darfst du keinen Record zurück geben, sondern ein Interface.

Aviator 15. Dez 2017 16:55

AW: Zirkuläre Unit Referenz auflösen
 
Alles klar. Danke für die Antworten. Dann werde ich mir mal überlegen ob ich aus dem Record eine Klasse mit einem passenden Interface mache oder ob ich es bei einem Record belasse.


Ein schönes Wochenende wünsche ich. :thumb:

jaenicke 16. Dez 2017 06:51

AW: Zirkuläre Unit Referenz auflösen
 
Wir benutzen für jedes Interface eine eigene Unit. Dann hast du das Problem nur bei echten Kreuzreferenzen.

Unsere Units heißen genauso wie das Interface. Zum Beispiel könnte es ein Interface ICustomPrinter in Common.Interfaces.Hardware.CustomPrinter.pas geben. Analog landet TCustomPrinter in Common.Hardware.CustomPrinter.pas. Auf die Weise findet man auch sehr schnell die Units für die Einbindung eines Typs.

Ich würde hier unabhängig davon ebenfalls ein Interface zurückgeben. Interfacereferenzen in Records finde ich nicht schön.

Aviator 16. Dez 2017 11:13

AW: Zirkuläre Unit Referenz auflösen
 
Zitat:

Zitat von jaenicke (Beitrag 1388991)
Wir benutzen für jedes Interface eine eigene Unit. Dann hast du das Problem nur bei echten Kreuzreferenzen.

Unsere Units heißen genauso wie das Interface. Zum Beispiel könnte es ein Interface ICustomPrinter in Common.Interfaces.Hardware.CustomPrinter.pas geben. Analog landet TCustomPrinter in Common.Hardware.CustomPrinter.pas. Auf die Weise findet man auch sehr schnell die Units für die Einbindung eines Typs.

Ich würde hier unabhängig davon ebenfalls ein Interface zurückgeben. Interfacereferenzen in Records finde ich nicht schön.

Ja ich werde es wohl per Interface machen.

Aber für jedes Interface eine einzelne Klasse machen. :shock:
Das ist sportlich und resultiert bestimmt ist sehr vielen Dateien. Klar, dass hat eben genau den Vorteil, dass das Problem das ich beschreibe nicht auftritt. Das werde ich mir mal überlegen. Danke für die Info.

stahli 16. Dez 2017 12:13

AW: Zirkuläre Unit Referenz auflösen
 
Für jedes Interface eine eigene Unit? Das kann ich auch nicht nachvollziehen.
Dann braucht man ja ggf. extrem umfangreiche uses-Anweisungen.

Also ich würde das jedenfalls nicht als Zielstellung setzen.

Ich habe inzwischen für jedes Projekt bzw. Package i.d.R. eine Interface-Unit, in der alle Interfaces deklariert sind, ggf. auch mit foreward-Deklarationen.

Die Klassen sind dann hinter einer Factory verborgen und Objekte werden nur über die Factory instanziiert.

Normalerweise braucht nur die Factory-Unit und die Interface-Unit in anderen Units bekannt zu sein.

jaenicke 16. Dez 2017 14:00

AW: Zirkuläre Unit Referenz auflösen
 
Zitat:

Zitat von stahli (Beitrag 1389018)
Dann braucht man ja ggf. extrem umfangreiche uses-Anweisungen.

Unsere Units sind in aller Regel alle relativ klein. Seitdem haben wir mit Error Insight oder der Performance der Syntaxergänzung usw. auch kaum noch Probleme. Auch interne Fehler beim Kompilieren sind seitdem sehr viel weniger geworden.

Aber natürlich kommen da schon mal einige Units zusammen, aber es ist eben auch direkt klar was da eigentlich eingebunden ist (uses aufräumen...) und man findet auch schnell die Unit zu einem Typ. Vor allem ist es aber extrem viel einfacher verschiedene Branches zu mergen usw., wenn nicht in einer Datei viele Änderungen für viele verschiedene Zwecke drin drin.

Und nebenbei kommt auch der Skriptcompiler besser klar, wenn die Units kleiner sind und weniger interne Beziehungen enthalten. Manchmal gab es beim Linken sonst Probleme, wenn viele Typen im gleichen Kontext lagen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:51 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