| Autor |
Nachricht |
theo
      
Beiträge: 62
Win 2000, XP, Vista; Win 7
Delphi 6, 7, 2010, MSSQL, Firebird, DevExpress
|
Verfasst: Mo 07.11.11 22:27
Hallo,
ich möchte die Meinungen von anderen Programmiern zu folgenden Thema hören:
Was spricht für oder gegen den Ansatz:
- ALLE! Objekte über ein interface abzubilden und den Zugriff nur über interface zuerstellen -
|
| |
|
|
Werbung ausblenden? Dann registriere Dich kostenlos.
Weitere Gründe für eine Registrierung.
Werbung ausblenden? Dann registriere Dich kostenlos.
Weitere Gründe für eine Registrierung.
|
|
jaenicke
      
Beiträge: 15840
Erhaltene Danke: 741
XP, W7 x64 (Chrome, IE9, FF), Debian, (OSX 10.7)
RAD XE 2, Java (NB), C++, C# (VS 2010), JS/HTML, PHP, Lazarus
|
Verfasst: Mo 07.11.11 22:57
Wenn die Performance keine Rolle spielt, mag man daran denken. Aber eine der Vorteile von Delphi ist gerade, dass es keinen integrierten Garbage Collector hat. Wenn man alle Objekte über Interfaces ansprechen würde, würde man sich die entsprechenden Nachteile mit aufhalsen.
Ich sehe aber weder einen Sinn, noch echte Vorteile darin, also warum sollte man das wollen?
Mit Interfaces kann man die rein baumartige Vererbung in Delphi erweitern. Und dafür sind Interfaces auch gut. Auch für einige andere Zwecke sind sie sinnvoll. Aber für alle Objekte?
|
| |
|
|
Lemmy
       
Beiträge: 617
Erhaltene Danke: 9
Windows XP/7 Kubuntu
RAD XE2
|
Verfasst: Mo 07.11.11 23:19
also ALLE Objekte über EIN interface?
Der Vorteil von Interfaces liegt klar im Design der Anwendung. Wenn man das Fachmodell über Interfaces aufbaut kann man dieses sehr einfach über Unit-Tests überprüfen (Stichwort MOCK), ein ggf. tief geschachteltes Vererbungsmonster kann abgeflacht werden und Abhängigkeiten zwischen Klassen werden aufgebrochen (Stichwort programmieren gegen Schnittstellen und nicht gegen eine Implementierung).
Aber klar bringt das auch Nachteile mit sich. In der letzten Ekon (vor 2 Wochen) gab es dazu einen KLasse Workshop von Bern Ua und Daniel Wischnewski. Da meinte Bernd Ua sinngemäß: eine gut zu testende Anwendung hat ne schlechte Performance.
|
| |
|
|
theo 
      
Beiträge: 62
Win 2000, XP, Vista; Win 7
Delphi 6, 7, 2010, MSSQL, Firebird, DevExpress
|
Verfasst: Di 08.11.11 00:46
|
| |
|
|
baka0815
      
Beiträge: 452
Erhaltene Danke: 10
Win XP, Debian GNU/Linux
Delphi 2007 Enterprise, Java, C#
|
Verfasst: Di 08.11.11 12:12
|
| |
|
|
theo 
      
Beiträge: 62
Win 2000, XP, Vista; Win 7
Delphi 6, 7, 2010, MSSQL, Firebird, DevExpress
|
Verfasst: Di 08.11.11 20:04
|
| |
|
|
jaenicke
      
Beiträge: 15840
Erhaltene Danke: 741
XP, W7 x64 (Chrome, IE9, FF), Debian, (OSX 10.7)
RAD XE 2, Java (NB), C++, C# (VS 2010), JS/HTML, PHP, Lazarus
|
Verfasst: Di 08.11.11 20:56
theo hat folgendes geschrieben : | | Dieses "Warum" ist genau meine Frage, weil wir im Team einen Kollegen haben, der fast Alles über INTERFACES macht. |
Wie es in dem Fall ist, kann man von außen natürlich schlecht sagen, aber positive Gründe fallen mir beim besten Willen nicht ein.
Jetzt mal abgesehen von COM oder ähnlichem, wo man nicht um Interfaces herumkommt, können Interfaces rein in Delphicode helfen, wenn man es nicht hinbekommt eine saubere Klassenkapselung zu erstellen, bei denen die Beziehungen zwischen den Klassen nur in eine Richtung gehen. Ohne Interfaces ließe sich so etwas nur durch Kreuzbezüge lösen, was aber nicht immer hinzubekommen ist, wenn man sich da zu sehr festgefahren hat. In manchen Fällen machen Interfaces dann aber durchaus Sinn.
Zudem hilft es, wenn man keine saubere Struktur hinbekommt, bei der man an definierten Stellen die Objekte auch wieder freigibt. Denn durch die Interfaces erledigt das der automatisch generierte Code des Compilers automatisch.
Aber hast du denn nicht mal gefragt was der Hintergrund ist? Ich meine er muss es doch (hoffentlich) am besten wissen warum er das so macht.
|
| |
|
|
baka0815
      
Beiträge: 452
Erhaltene Danke: 10
Win XP, Debian GNU/Linux
Delphi 2007 Enterprise, Java, C#
|
Verfasst: Mi 09.11.11 10:02
Interfaces machen nur dann Sinn, wenn man mehrere Objekte hat, die dasselbe Ziel verfolgen.
Wenn man z.B. das Laden einer Datei generalisieren möchte:
Man bekommt z.B. ein Objekt vom Typ IFile von der FileLoadFactory zurück, welches dann ein TWord, TExcel, TText, TWhatever ist.
Wenn man ein Listener-Konzept (siehe Java) umsetzen möchte:
Das Listener-Interface liefert nur die aufzurufende Methode, die Implementierung bleibt dann wem anders überlassen.
Warum man jedoch für JEDES Objekt auch ein Interface haben möchte, ist für mich so nicht ersichtlich.
|
| |
|
|
delfiphan
       
Beiträge: 2682
Erhaltene Danke: 26
|
Verfasst: Sa 12.11.11 01:55
In .NET/Java macht man das manchmal, um die Klassen isoliert voneinander testen zu können. Allerdings setzt das einen DI-Mechanismus voraus. DI ohne GC ist schwer zu realisieren und verkompliziert das ganze wahrscheinlich nur.
Interfaces sind in Delphi schlecht umgesetzt. Das ganze ist zu stark an COM angelehnt. Ich denke mal dafür wurde es ursprünglich entwickelt. Das ganze hat einfach noch viele Kanten und Ecken. Es gibt keine volle Unterstützung von Properties; kein voller Language-Support mit "is" und "as" sondern über "Supports"; man muss für gewisse Features Guids angeben; man muss einen anderen Programmierstil verwenden wegen der Referenzzählung; man kann trotz Referenzzählung Memory-Leaks erzeugen (Interface-Instanz weist sich einem Childobjekt zu oder zirkuläre Abhängigkeit) dagegen gibt es kein Gegenmittel wie Weak References ausser man manipuliert die Referenzzählung; früher konnte man Interfaces nicht mehr zu Objekte casten.
Für viele dieser Dinge gibt es technische Erklärungen, aber .NET hat all diese Problemchen und Einschränkungen einfach nicht...
Fazit: In Delphi ist es unüblich und ich würde davon abraten.
|
| |
|
|
jaenicke
      
Beiträge: 15840
Erhaltene Danke: 741
XP, W7 x64 (Chrome, IE9, FF), Debian, (OSX 10.7)
RAD XE 2, Java (NB), C++, C# (VS 2010), JS/HTML, PHP, Lazarus
|
Verfasst: Di 29.11.11 20:30
Mittlerweile habe ich auch herausgefunden, dass z.B. Nick Hodges ein Anhänger dieser Verfahrensweise ist. Hauptzweck: Die einzelnen Codeteile voneinander entkoppeln. Mehr dazu hier im Video:
www.embarcadero.com/coderage/sessions
(Mittwoch: Delphi, Dependency Injection, and the Delphi Spring Framework)
Kurzfassung meiner Meinung dazu:
Die Idee dahinter ist durchaus nachvollziehbar und an sich nicht schlecht, aber ich halte das so nicht für sauberen Code. Mit irgendwelchen Generatorklassen herumwerfen, die Klassen erzeugen ohne dass man direkt sieht wo die Implementierung herkommt? Aus Versehen die falsche Unit entfernt oder hinzugefügt und plötzlich geht etwas nicht mehr, weil es keine Fehlermeldung gibt? (Weil der Compiler das nicht prüfen kann.)
Sorry, aber das ist meiner Meinung nach einfach nicht richtig durchdacht, birgt Gefahren insbesondere bei der Arbeit im Team und ist daher keine saubere Softwarearchitektur.
Die Verwendung von Interfaces um gezielt Codeteile zu entkoppeln macht an den richtigen Stellen durchaus Sinn, aber in der Form nicht. So überwiegen die Nachteile und es besteht die Gefahr, dass jemand durch Änderungen Probleme an ganz anderer Stelle verursacht und es durch das Konzept gar nicht mitbekommen kann. Eben weil man die Compilerunterstützung gezielt abkoppelt.
Wobei, um das noch einmal deutlich zu schreiben, meine Kritik jetzt speziell für den Weg gilt, der in dem Video vorgestellt wird, nicht für die Verwendung von Interfaces für den Zweck der Entkoppelung an sich.
|
| |
|
|
delfiphan
       
Beiträge: 2682
Erhaltene Danke: 26
|
Verfasst: Di 29.11.11 23:42
Der Code ist vermutlich nicht einfacher zu lesen, da die Abhängigkeiten praktisch nur in der Konfiguration (in einer Form oder anderen) definiert sind.
Ich würde jedoch behaupten, dass man bei gutem Languagesupport von Interfaces besseren Code schreibt. Mit besser mein ich mehr Separation of Concern, mehr Single Responsibility Principle und bessere Testability.
In Delphi habe ich die Erfahrung gemacht, dass man im Vergleich zu .NET einfach um eine Grössenordnung oder zwei weniger unit- und integrationstestet. Ich kann mir das nur mit der Umgebung, der Sprache und dem Framework erklären.
Von "Gefahren" wie "aus Versehen was gelöscht ohne zu merken" kann man nur sprechen, wenn man die Richtigkeit des Codes vor allem dadurch erkennt, dass der Code kompiliert... Das kann's ja nicht sein. Hätte man jetzt gute Tests (die man eben in einer guten Umgebung und Architektur eben relativ leicht schreibt), könnte sowas gar nicht passieren: In .NET Häusern wird häufig ein Gated-Check-In konfiguriert, sodass man nichts einchecken kann, das entweder nicht kompiliert oder irgend einen Test bricht.
Die Angst, an einer Stelle was zu ändern und an einer ganz anderen Stelle ein Problem zu kriegen, hat man vor allem dann, wenn man kein gutes Separation of Concern hat. Ohne Abstraktion z.B. über Interfaces ist die Versuchung eben viel grösser, harte Annahmen über eine abhängige Komponente zu machen.
|
| |
|
|
jaenicke
      
Beiträge: 15840
Erhaltene Danke: 741
XP, W7 x64 (Chrome, IE9, FF), Debian, (OSX 10.7)
RAD XE 2, Java (NB), C++, C# (VS 2010), JS/HTML, PHP, Lazarus
|
Verfasst: Mi 30.11.11 11:59
delfiphan hat folgendes geschrieben : | | Von "Gefahren" wie "aus Versehen was gelöscht ohne zu merken" kann man nur sprechen, wenn man die Richtigkeit des Codes vor allem dadurch erkennt, dass der Code kompiliert... Das kann's ja nicht sein. |
Schon, aber man kann nicht alles testen. Beispielsweise Hardware-, Netzwerk- oder öffentliche Internetschnittstellen wirst du nicht immer per Unittest erschlagen können. Und dann merkt man einen Fehler eben erst, wenn man bei einem Kunden ein Update macht, der dieses Feature auch benutzt.
|
| |
|
|
delfiphan
       
Beiträge: 2682
Erhaltene Danke: 26
|
Verfasst: Mi 30.11.11 19:00
Sowas kannst du überhaupt nicht unittesten. Das kannst du nur integrationstesten. Das ist zugegebenermassen etwas komplexer und aufwändiger.
Aber normalerweise sind die Libraries mit den Abhängigkeiten mit der Aussenwelt Off-the-Shelf-Software. Sowas musst du ja nicht nochmals selber testen. Der Punkt ist eben, dass dein Code nicht direkt auf die Implementation eines Netzwerkzugriffs geht sondern auf ein Interface. Dieses Interface ist im Testfall gemockt. Somit kannst du deinen gesamten Code sauber unittesten, ohne, dass jemals ein echter Netzwerkzugriff stattgefunden hat.
In einer regulierten Umgebung (z.B. medizinische Anwendung) kann und darf man eigentlich nichts dem Zufall überlassen. Da musst du jedes Requirement an Unittests, Unit-Integrationstests und Integrationstests tracen und beweisen, dass das Ding richtig tut, und dass das Ding das Richtige tut. Das ganze hat im Ernstfall auch juristische Relevanz. "Das kann ich nicht testen" gibt es da nicht, sonst kommt das ganze nicht auf den Markt 
|
| |
|
|
baka0815
      
Beiträge: 452
Erhaltene Danke: 10
Win XP, Debian GNU/Linux
Delphi 2007 Enterprise, Java, C#
|
Verfasst: Mo 23.01.12 12:30
Zum Thema ein Artikel von Nick Hodges, den ich hier einmal unkommentiert verlinken möchte.
|
| |
|
|
jaenicke
      
Beiträge: 15840
Erhaltene Danke: 741
XP, W7 x64 (Chrome, IE9, FF), Debian, (OSX 10.7)
RAD XE 2, Java (NB), C++, C# (VS 2010), JS/HTML, PHP, Lazarus
|
Verfasst: Mo 23.01.12 13:12
Ja, den hatte ich auch heute Morgen schon gelesen. Im Grunde ist das das gleiche wie im Video, nur in Schriftform.
Ich hatte mittlerweile auch ein wenig mit dem Konzept herumgespielt. Bisher hatte ich wenige positive Erlebnisse. Einerseits macht es das ganze ziemlich aufwendig. Andererseits fallen mir für bisher leicht machbare Zuordnungen von Strukturen keine adäquaten Möglichkeiten ein das nur mit Interfaces so einfach umzusetzen. Es geht zwar, aber es sieht nicht schön aus.
Im Moment hat sich nur der Codeumfang ca. verdoppelt und das Programm ist spürbar langsamer ohne dass ich bisher einen besonderen Mehrwert sehe.
Naja, wenn ich mal Zeit habe, schreibe ich das ganze einfach mal auf. Vielleicht hat ja dann jemand ein paar schlaue Ideen wie man es besser machen kann...
|
| |
|
|
delfiphan
       
Beiträge: 2682
Erhaltene Danke: 26
|
Verfasst: Mo 23.01.12 23:02
Naja, ich kann mich nur wiederholen: In Delphi würde ich würde davon abraten. In Delphi mach ich das nie. In .NET mach ich das fast immer. Der Unterschied ist der schlechte Language und IDE Support für Interfaces in Delphi und Libraries für Dependency Injection.
Der Blogeintrag ist mässig gut und leider relativ einseitig. Als ob Interfaces die Welt retten könnten und in Delphi keine Probleme mit sich brächten. Ich habe das Gefühl, er hat grad die Interfaces entdeckt und ist noch ganz ausser sich. Nach dem vierten Satz in folgendem Stil musste ich schon etwas schmunzeln...
| Zitat: | | there is one bottom line reason why you should use interfaces in Delphi: They They provide a very thin – but very powerful -- abstraction to your code. That’s why. |
| Zitat: | | A good developer codes against abstractions, and not implementations. |
| Zitat: | | all the cool kids are doing interfaces, and you want to be part of the cool kid group, right? |
| Zitat: | | And we all know that loosely coupled code is good. So interfaces help produce good code. |
Eigentlich sollte man richtige und gute Gründe für etwas haben. Einfach so ein Prinzip anwenden, weil es "cool" ist, ist schlecht. Sonst passiert genau das, was jaenicke erzählt: Man hat etwas übertrieben gesprochen am Schluss doppelt so viel Code, der halb so schnell läuft und schwieriger zu verstehen ist -- und weiss nicht einmal, wofür.
In .NET ist für mich der Hauptgrund für die generelle Verwendung von Interfaces das Testen, zusammen mit einem guten Mock Framework ist das super. Was für mich Loosely Couple Code bringt ist aber vor allem Inversion of Contorl in Form von Dependency Injection. Ohne Garbage Collection ist Depdenency Injection mühsam, genauso die langsame Referenzzählung, und das ohne Support von Weak References und Events. Ausserdem gibt's keine guten und verbreiteten Mock oder DI Frameworks. In Delphi muss ich zu viele Kompromisse eingehen. Naja. Das gilt für mich mittlerweile eigentlich für die ganze Sprache 
|
| |
|
|
jaenicke
      
Beiträge: 15840
Erhaltene Danke: 741
XP, W7 x64 (Chrome, IE9, FF), Debian, (OSX 10.7)
RAD XE 2, Java (NB), C++, C# (VS 2010), JS/HTML, PHP, Lazarus
|
Verfasst: Di 24.01.12 07:02
delfiphan hat folgendes geschrieben : | | Ausserdem gibt's keine guten und verbreiteten Mock oder DI Frameworks. |
Nick Hodges macht ja für dieses Werbung, worum es auch in dem Video ging:
code.google.com/p/delphi-spring-framework/
Für diesen Beitrag haben gedankt: baka0815
|
| |
|
|
baka0815
      
Beiträge: 452
Erhaltene Danke: 10
Win XP, Debian GNU/Linux
Delphi 2007 Enterprise, Java, C#
|
Verfasst: Di 24.01.12 14:02
@Jaenicke: Danke für den Link zum Spring4Delphi!
Ich würde gern mehr zur Referenzzählung von Interfaces wissen.
Was Nick Hodges da schreibt klingt nach: Nutze Interfaces und du brauchst dich nie wieder um die Laufzeit von Objekten kümmern.
Wenn man damit also wirklich (zuverlässig) auf try..finally verzichten könnte, wäre das doch eine feine Sache, oder?
|
| |
|
|
jaenicke
      
Beiträge: 15840
Erhaltene Danke: 741
XP, W7 x64 (Chrome, IE9, FF), Debian, (OSX 10.7)
RAD XE 2, Java (NB), C++, C# (VS 2010), JS/HTML, PHP, Lazarus
|
Verfasst: Di 24.01.12 14:12
Theoretisch ja, aber praktisch möchte ich das gar nicht immer. In C# ärgere ich mich auch bisweilen über den Garbage Collector und in Java noch öfter. Bei relativ überschaubaren Tools ist das in der Tat sehr praktisch, aber wenn dann größere Speichermengen aufgrund des Scopes der Variable erst viel später freigegeben werden, ist das nicht so toll. Das ist vor allem bei Delphi ein Problem, da eben ein echter Garbage Collector fehlt.
Ich muss aber sagen, dass Interfaces in den aktuellen Delphiversionen sehr gut funktionieren. Das heißt man kann durchaus gut so arbeiten. Wenn man denn einen Vorteil daraus ziehen kann...
|
| |
|
|
Martok
      

Beiträge: 2837
Erhaltene Danke: 182
Win 2000, Win XP
Delphi 7, Turbo Delphi Exp.
|
Verfasst: Di 24.01.12 17:38
Wer mal sehen möchte, wie schön Code mit Interfaces selbst in Delphi werden kann, darf sich gerne mal die Standard Interface Library angucken. Man merkt sehr, dass die Entwickler die positiven Neuerungen aus C# bzw. der CLR zurückklauen wollten.
Damit gearbeitet hab ich noch nicht, aber die Samples sehen sehr elegant aus - anders als man das von Delphi sonst kennt.
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Ich code EdgeMonkey -~==~- #ee-lounge in Freenode
|
| |
|
|
|