AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Schon wieder: Warum Interfaces

Ein Thema von exilant · begonnen am 19. Okt 2016 · letzter Beitrag vom 21. Okt 2016
Antwort Antwort
Seite 2 von 8     12 34     Letzte » 
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.364 Beiträge
 
Delphi 10.3 Rio
 
#11

AW: Schon wieder: Warum Interfaces

  Alt 20. Okt 2016, 10:03
Ich finde, Interface-Programmierung verhält sich zu OOP wie die OOP zur prozeduralen Programmierung.

Grundsätzlich kannst Du jedes Problem auch ohne Interfaces und ohne OOP lösen. Und keinen interessiert es. Allerdings handelst Du dir immer irgend welche Probleme ein, in der Fachwelt wird dafür der Begriff der technischen Schulden verwendet. Keiner sieht sie, man riecht sie nicht und eines Tages schwappen sie über dich

Genauso wenig wie

Delphi-Quellcode:
type
  TFoo = class(TObject)
  public
    procedure DoFoo; //mit 1.000 Zeile Code
  end;
objektorientierte Programmierung ist, ist die Definition eines Interfaces, die Implementierung und Verwendung davon automatisch auch eine sinnvolle Verwendung eines Interfaces, weil es oft schlicht und ergreifend nur mehr Arbeit ist aber keinen Vorteil bietet, weil man die Technik falsch anwendet bzw. im falschen Kontext.

Interfaces sind eine logische Weiterführung der OOP, vielleicht müsste man auch sagen, eine zwingende Weiterführung. Aber es ist wie gesagt nicht damit getan ein

Delphi-Quellcode:
type
  IFoo = Interface
    procedure DoFoo;
  end;
zu schreiben und zu Jubeln "Ich kann Interfaces", sondern dann folgen automatisch auch weiter Punkte die dann wichtig werden, denn Interfaces werfen wie vieles andere auch, mehr Fragen auf, als sie beantworten Als ein Stichpunkt werfe ich hier nur mal Dependency Injection ein.


Der große Vorteil von Interfaces eröffnet sich erst in etwas komplexeren Systemen, in denen div. Klassen miteinander kommunizieren müssen. Hier hast Du die Möglichkeit, dass diese Klassen weiterhin miteinander arbeiten könne, sich aber gegenseitig nicht mehr persönlich kennen müssen:

Delphi-Quellcode:
TAdresse = class()
...
public
  function GetAnrede: String;
  function GetName1: String;
  function GetName2: String;
  function GetStrasse: String;
....
end;

TPerson = class()
private
  FName, FVOrname: String;
  FStrasse: String;
....
public
  property Adresse: TAdresse read FAdresse;
Und damit wir einen Konsumenten haben:

Delphi-Quellcode:
TBrief = class()
public
  procedure ErstelleBrief(Empfaenger: TAdresse);
end;
hier hast Du einen harte Kopplung wie sie in div. Projekten vorkommt und alles ist OK.
Willst Du jetzt aber TBrief durch einen Unittest jagen hast Du das Problem, dass Du zwingend auch eine Instanz von TAdresse erzeugen und übergeben musst. Kein Problem, solange TAdresse keine weiteren Abhängigkeiten hat. Sobald das System und das BOM komplexer werden, wirst Du hier immer mehr abhängige Klassen vorbereiten müssen, instanziieren müssen bis du zu dem Punkt kommst: Unittests sind scheiße, weil Du für eine Zeile Testcode, 10, 20 Zeilen Code für die Instanziierung und für die Aufräumaktionen brauchst. Und du merkst nicht, dass eigentlich dein Modell ein Problem hat.

Mit Interfaces sieht das ganze so aus:

Delphi-Quellcode:
IAdresse = Interface
  function GetAnrede: String;
  function GetName1: String;
  function GetName2: String;
  function GetStrasse: String;
end;

TPerson = class()
private
  FName, FVOrname: String;
  FStrasse: String;
....
public
  property Adresse: IAdresse read FAdresse;
Und damit wir einen Konsumenten haben:

Delphi-Quellcode:
TBrief = class()
public
  procedure ErstelleBrief(Empfaenger: IAdresse);
end;
Nun kann TPerson selbst entscheiden, welche Implementierung von IAdresse (es kann mehrere geben) für seinen Zwecke am besten ist. TBrief ist das aber völlig egal, durch das Interface weiß die Klasse, dass die vertraglich vereinbarten Methoden vorhanden sind und funktionieren, d.h. Du kannst TBrief dann auch damit verwenden:

Delphi-Quellcode:
type
  TStudent = class(X,IAdresse)
  ...
  public
    function GetAnrede: String;
    function GetName1: String;
    function GetName2: String;
    function GetStrasse: String;
und TStudent muss kein weiteres Element deines TPerson-Frameworks kennen, muss nicht von einer gemeinsamen Basisklasse abgeleitet werden,....


Kommen wir aber nochmal zurück zur TPerson: ich habe oben geschrieben, dass TPerson entscheidet welche Implementierung von IAdresse es verwendet. Das ist aber schon wieder ein Fehler! Weil du baust dir hier wieder über die Hintertür eine harte Kopplung von 2 Klassen ein. Und genau das kann später wieder zu einem Problem werden, weil du dann an dem Punkt bis: Verflixt, jetzt wollte ich harte Kopplung vermeinden, muss aber halt irgend wo implementieren:

Delphi-Quellcode:
TPerson = class()
private
  FName, FVOrname: String;
  FStrasse: String;
....
public
  property Adresse: IAdresse read FAdresse;

...

TPerson.Create()
begin
  FAdresse := TFooAdresse.Create();
end;
Lösung für dieses Problem bietet die Dependency Injection: Ich kopple das Interface nicht an einer bestimmten Stelle mit einer konkreten Implementierung sondern biete über eine Liste (sog. Container) verschiedene Möglichkeiten an (oder vielleicht auch nur eine) wie IAdresse implementiert sein soll. TPerson instanziiert dann die IAdresse nicht selbst, sondern fragt bei der Liste an: Gib mir eine Instanz von IAdresse. Aber den Part könnte Stefan G. nun wirklich besser erklären

wie auch bei der OOP ist auch bei Interfaces das Problem: Mit 2 Sätzen und einem einfachen Beispiel ist das nicht erklärt....

Geändert von Lemmy (20. Okt 2016 um 10:52 Uhr)
  Mit Zitat antworten Zitat
OlafSt

Registriert seit: 2. Mär 2007
Ort: Hamburg
284 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#12

AW: Schon wieder: Warum Interfaces

  Alt 20. Okt 2016, 10:54
All das ist ja alles sehr interessant und auch absolut sinnvoll. Nebenbei, ich gehöre auch zu denen, die gern was mit Interfaces machen würden (und auch schon mögliche Projekte in der Pipeline haben), aber irgendwie über eine Brücke nicht rüberkommen.

Meine Blockade ist die vielbeschworene Sprachenunabhängigkeit. Man schreibt eine DLL in Delphi, schraubt ein paar Interfaces um die Klassen herum und kann das dann in C# verwenden. Wie soll das aussehen, kann da jemand einen 30-Zeiler (okay, weils 2 Sprachen sind, 60-Zeiler) zusammenschustern, wo man das mal sehen kann ?
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.336 Beiträge
 
Delphi 11 Alexandria
 
#13

AW: Schon wieder: Warum Interfaces

  Alt 20. Okt 2016, 11:03
@DeddyH + vor allem Lemmy


So etwa hätte ich das auch sagen wollen...


@OlafSt

Dazu hat Mavarik ja etwas angekündigt. Ich selbst habe diesbezüglich keine Erfahrungen.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.123 Beiträge
 
Delphi 10.3 Rio
 
#14

AW: Schon wieder: Warum Interfaces

  Alt 20. Okt 2016, 11:33
Das „reference counting“ finde ich z. B. nach meinem derzeitigen Verständnis von interfaces gelinde gesagt sche.. ääh nicht gut.
Genau das war mein Grund sich näher mit Interfaces zu beschäftigen... Thema Arc unter Windows... Um eine FMX App gleicht unter Mobil und Windows zu programmieren, nimmt man keine Objecte, sondern Interfaces, so mit gibt es keinen Plattformunterschied.


Und das hat genau was mit Interfaces zu tun?
Frage an mich? Hast nix gequotete... Nur so kann ich etwas verwenden ohne einen Link zu Klasse...



Referenzzählung:
...

Eigentlich ist das eine ganz nette Sache, aber es hat zwei Haken:
Wen ich in aMotor ein Motor-Interface habe und ich Nil zuweise (aMotor := Nil) kann es sein, dass das Objekt noch nicht freigegeben wird, weil irgendwo im Speicher möglicherweise noch ein Zugriff auf dieses Interface existiert (z.B. in einer Liste oder so).
Durch meine Nil-Zuweisung wird der RefCounter verringert (z.B. von 2 auf 1) und das Objekt aber erst bei 0 freigegeben.

Für die Liste existiert der Motor noch.
Wenn man mit Objekten arbeitet und hier aMotor.Free angegeben hätte, könnte es später bei Zugriff auf die Motoren-Objekte in der Liste knallen.

Bei Motoren-Interfaces in der Liste knallt nix, da das Objekt noch nicht freigegeben wurde.

Wenn ich aber vorhin das Objekt wirklich FREIGEBEN wollte, dann kann das Projekt den Motor noch verwenden, der eigentlich aber nicht mehr existieren sollte.

Ok, welche fehlerhafte Arbeit des Projektes ist die schlechtere? Das kann man so nicht entscheiden. Wichtig ist, dass man bei Vewrwendung von Interfaces mit Referenzzählung beachten muss, dass man nicht ohne weiteres in der Hand hat, wann das Objekt tatsächlich freigegeben wird.
Na zum Glück gibt es für Interfaces "jetzt" das Attribut [WEAK] somit bewirkt Dein Whatever := NIL, wenn Du alle anderen Referenzen mit [WEAK] geflaged hast wirklich ein Free...

Wenn ich etwas in einer Liste speichere, und das "Ding" an andererstelle Frei geben, dann wollte ich es - wenn es in der Liste ist - sicherlich noch verwenden, oder?

Ich brauche einfach nicht die Try Finally ketten...

Delphi-Quellcode:
begin
  AFoo := TFoo.Create;
  try
    ABar := TBar.Create;
    try
      AFile := TFilestream.Create(..)
      try
        ABar.LoadFormStream(AFile);
        AFoo.Add(ABar);
        AFoo.Machwas;
      finally
        AFile.Free;
      end;
    finally
      ABar.free; // ggf. könnte ich das AFoo überlassen, aber dann würde ich im Source immer darüber stolpern.
    end;
  finally
   AFoo.Free;
  end;
end;
oder

Delphi-Quellcode:
begin
  IFoo := TFoo.Construct(TBar.Construct(TiFile.Construct(..)));
  IFoo.Machwas;
end;
Mavarik
  Mit Zitat antworten Zitat
Jim Carrey
(Gast)

n/a Beiträge
 
#15

AW: Schon wieder: Warum Interfaces

  Alt 20. Okt 2016, 11:35
All das ist ja alles sehr interessant und auch absolut sinnvoll. Nebenbei, ich gehöre auch zu denen, die gern was mit Interfaces machen würden (und auch schon mögliche Projekte in der Pipeline haben), aber irgendwie über eine Brücke nicht rüberkommen.

Meine Blockade ist die vielbeschworene Sprachenunabhängigkeit. Man schreibt eine DLL in Delphi, schraubt ein paar Interfaces um die Klassen herum und kann das dann in C# verwenden. Wie soll das aussehen, kann da jemand einen 30-Zeiler (okay, weils 2 Sprachen sind, 60-Zeiler) zusammenschustern, wo man das mal sehen kann ?
Ich verstehe Interfaces auch in keinster Art und Weise.
Ich bin der Meinung... solange man der alleinige Entwickler an einem Projekt ist, ist es vollkommen egal was man verwendet.
Hauptsache man versteht seinen eigenen Code, er funktioniert und lässt sich gut ändern.

Gegenfrage: haben Interfaces irgendeinen Vorteil in der erzeugten Programmdatei?
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.123 Beiträge
 
Delphi 10.3 Rio
 
#16

AW: Schon wieder: Warum Interfaces

  Alt 20. Okt 2016, 11:39
Gegenfrage: haben Interfaces irgendeinen Vorteil in der erzeugten Programmdatei?
Klar...

Aber 90% der Vorteile sind für Dich als Entwickler...

Ein Beispiel:

Code:
SchreibeDatenWeg.exe /SQLite
SchreibeDatenWeg.exe /REST:https://www.meinserver.de
SchreibeDatenWeg.exe /MySQL
ist in der exe 1. Zeile

IDatenZiel := TDatenWriter.CreateFromParamOrDefault(Params);
  Mit Zitat antworten Zitat
Jim Carrey
(Gast)

n/a Beiträge
 
#17

AW: Schon wieder: Warum Interfaces

  Alt 20. Okt 2016, 11:41
Also kann man grundlegend festhalten, dass Interfaces immens zur Code-Minimierung beitragen wenn nicht sogar dafür vorgesehen sind?
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.123 Beiträge
 
Delphi 10.3 Rio
 
#18

AW: Schon wieder: Warum Interfaces

  Alt 20. Okt 2016, 11:46

@OlafSt

Dazu hat Mavarik ja etwas angekündigt. Ich selbst habe diesbezüglich keine Erfahrungen.

Höchstwahrscheinlich - ab Januar, wenn ich meine Youtube-Tutorial Reihe zu meinem FDK beginne.

Das FDK arbeiten hauptsächlich - aus den genannten Gründen (Windows & ARC) - mit Interfaces.

Geändert von Mavarik (20. Okt 2016 um 13:57 Uhr)
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.610 Beiträge
 
Delphi 10.3 Rio
 
#19

AW: Schon wieder: Warum Interfaces

  Alt 20. Okt 2016, 11:50
Ich sehe aktuell wie bereits geschrieben den Vorteil in Interfaces, wenn man DLLs programmieren will um seinen Code irgendwie auszulagern. Dann haben die Dinger extreme Vorteile.

Ein anderer Punkt an dem man Interfaces verwenden kann ist eben dann, wenn man 2 unterschiedliche Klassen hat, die aber die gleichen Informationen zur Anzeige auf der GUI zur Verfügung stellen sollen. Jede Klasse verarbeitet die Informationen allerdings anders und daher ist auch das angezeigte Ergebnis ein anderes. Die Abfrage im Programm bleibt aber immer gleich.

Delphi-Quellcode:
ITest = interface
  function GetValue: string;
end;

Delphi-Quellcode:
TMyClass1 = class(TInterfacedObject, ITest)
  function GetValue: string;
end;

implementation

function TMyClass1.GetValue: string;
begin
  Result := 'Das ist der Wert aus MyClass1';
end;
Delphi-Quellcode:
TMyClass2 = class(TInterfacedObject, ITest)
  function GetValue: string;
end;

implementation

function TMyClass2.GetValue: string;
begin
  Result := 'Das ist der Wert aus MyClass2';
end;
Delphi-Quellcode:
TForm1 = class(TForm)
  procedure ShowValue(FromInterface: ITest);
end;

implementation

function TForm1.ShowValue(FromInterface: ITest);
begin
  Label1.Caption := FromInterface.GetValue;
end;
Hier habe ich jetzt den Vorteil, dass ich einfach eine beliebige Interface Instanz übergeben bekomme aus der ich mir dann mit dem gleichen Aufruf die benötigten Informationen ziehen kann. Das würde bei Klassen zwar auch gehen, aber dafür müssten alle übergebenen Klassen von der gleichen Basisklasse abgeleitet werden. Diese müsste wiederum eine abstrakte Methode GetValue zur Verfügung stellen, welche von jeder Ableitung implementiert werden muss. In diesem Fall sind Interfaces deutlich leichter zu handlen.

Wenn man allerdings nur eine Klasse hat welche Informationen zur Verfügung stellen soll, dann lohnt sich ein Interface meines Erachtens nicht wirklich. Man hat nur den Vorteil den Mavarik angesprochen hat. Diese try..finally Blöcke und das Object.Free fallen weg. Wenn man die Interface Instanzen dann korrekt verwendet, dann sollte man auch kein Problem mit der Referenzzählung haben.
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.123 Beiträge
 
Delphi 10.3 Rio
 
#20

AW: Schon wieder: Warum Interfaces

  Alt 20. Okt 2016, 12:07
Was mir noch einfällt.

Beispiel mit : IStreamPersist

Delphi-Quellcode:
TFoo = Class(TInterfacedObject,ICanCompress);
...
TBar = Class(TInterfacedObject,ICanCompress,IStreamPersist)
Jetzt kann ich abfragen, ob ein Object, dass Interface unterstützt. Und dann in einen Stream schreiben oder vom Stream lesen...
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:55 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