Sollen Schnittstellen in einem separaten Paket platziert werden? [closed]

Lesezeit: 8 Minuten

Benutzer-Avatar
kctang

Ich bin neu in einem Team, das an einem ziemlich großen Projekt mit vielen Komponenten und Abhängigkeiten arbeitet. Für jede Komponente gibt es eine interfaces Paket, in dem die exponierten Schnittstellen für diese Komponente platziert sind. Ist das eine gute Praxis?

Meine übliche Praxis war immer, dass Schnittstellen und Implementierungen im selben Paket enthalten sind.

  • Warum ist das markiert [language-agnostic]?

    – finnw

    22. Mai 2011 um 9:45 Uhr

  • Eine andere Situation, in der dies bevorzugt werden könnte, wenn das Modul über einen RPC und nicht über einen direkten Aufruf kommuniziert werden soll – dann ist die Schnittstelle praktisch, um Proxys für den Client zu generieren.

    – redzedi

    13. Oktober 2020 um 5:28 Uhr

Benutzer-Avatar
coobird

Das Platzieren sowohl der Schnittstelle als auch der Implementierung ist üblich und scheint kein Problem zu sein.

Nehmen Sie zum Beispiel die Java-API – die meisten Klassen haben beide Schnittstellen und ihre Implementierungen im selben Paket enthalten.

Nehmen Sie zum Beispiel die java.util Paket:

Es enthält die Schnittstellen wie z Set, Map, Listwährend auch die Implementierungen wie z HashSet, HashMap und ArrayList.

Darüber hinaus sind die Javadocs so konzipiert, dass sie unter diesen Bedingungen gut funktionieren, da sie die Dokumentation in die Schnittstellen und Klassen Ansichten, wenn der Inhalt des Pakets angezeigt wird.

Pakete nur für Schnittstellen zu haben, kann tatsächlich etwas übertrieben sein, es sei denn, es gibt eine enorme Anzahl von Schnittstellen. Aber die Schnittstellen nur um des Zwecks willen in eigene Pakete aufzuteilen, klingt nach schlechter Praxis.

Wenn es notwendig ist, den Namen einer Schnittstelle von einer Implementierung zu unterscheiden, könnte man eine Namenskonvention haben, um die Identifizierung von Schnittstellen zu erleichtern:

  • Stellen Sie dem Schnittstellennamen ein voran I. Dieser Ansatz wird bei den Schnittstellen im .NET-Framework verfolgt. Es wäre ziemlich einfach, das zu sagen IList ist eine Schnittstelle für eine Liste.

  • Verwenden Sie die –able Suffix. Dieser Ansatz wird häufig in der Java-API verwendet, z Comparable, Iterableund Serializable um ein paar zu nennen.

  • +1, obwohl ich die I * -Namenskonvention nicht empfehlen würde, es sei denn, Sie befinden sich in .NETverse, und selbst dann nur aus Gründen der Konsistenz

    – VorhangHund

    17. Juni 2009 um 5:31 Uhr

  • Ich habe diese Konvention in Java-Code verwendet und fand sie nützlich …. YMMV

    – hhafez

    17. Juni 2009 um 6:14 Uhr

  • Ich weiß, dass dies etwas alt ist, aber was ich jetzt als Vorschlag gefunden habe, ist, die Schnittstelle klar zu benennen und die Implementierung etwas satter zu benennen. zB Interface = Store Implementation = StoreImpl Hauptsächlich, um hervorzuheben, dass die Schnittstelle über der Implementierung verwendet werden sollte.

    – frostigwunderbar

    6. Mai 2015 um 15:47 Uhr

  • Ich weiß, dass dieser Ansatz, auch wenn er richtig aussieht, zu architektonischen Problemen führt. Beispielsweise gibt es keine Möglichkeit, Bibliotheken zu definieren, die nur die Schnittstellen verwenden, und sie dann in einer gemeinsamen Bibliothek, dh der Infrastrukturschicht, zu implementieren.

    – Luca Masera

    18. Mai 2018 um 9:48 Uhr

  • Ich stimme dem Kommentar zu, das Präfix „I“ für Schnittstellen nicht auf die gleiche Weise zu verwenden, wie ich es nicht empfehlen würde, das Suffix „impl“ für Implementierungen zu verwenden. Dies ist ein netter Artikel, der sich mit diesen Fällen befasst: octoperf.com/blog/2016/10/27/impl-classes-are-evil

    – raspacorp

    16. April 2019 um 22:23 Uhr

Benutzer-Avatar
cjs

Für jede Sprache ist es in Ordnung, sie in demselben Paket zusammenzufassen. Wichtig ist, was der Außenwelt ausgesetzt ist und wie es von außen aussieht. Niemand wird wissen oder sich darum kümmern, ob die Implementierung in demselben Paket enthalten ist oder nicht.

Schauen wir uns diesen speziellen Fall an.

Wenn Sie alle öffentlichen Dinge in einem Paket und private Dinge in einem anderen Paket haben, das nicht öffentlich zugänglich ist, sieht der Client der Bibliothek ein Paket. Wenn Sie die privaten Dinge in das Paket mit den öffentlich zugänglichen Dingen verschieben, sie aber nicht innerhalb des Pakets verfügbar machen, sieht der Client genau dasselbe.

Das riecht also nach einer Regel ohne triftigen Grund: Es geht darum, eine Entscheidung zu treffen, die darauf basiert, dass etwas öffentlich sichtbar ist, ohne dass diese Entscheidung Auswirkungen auf das hat, was öffentlich sichtbar ist.

Wenn es jedoch in einem bestimmten Fall eine gute Idee zu sein scheint, die Schnittstelle und die Implementierung in separate Pakete aufzuteilen, tun Sie dies sofort. Gründe dafür, die mir in den Sinn kommen, sind, dass das Paket riesig ist oder Sie eine alternative Implementierung haben, die Sie anstelle der Standardimplementierung einbinden möchten.

  • Angesichts des ‘Java’-Tags auf der Frage – was bedeutet ein ‘öffentlich exponiertes Paket’ in Java? Oder ist Ihre Antwort nicht Java-spezifisch? Ich dachte, nur Paketmitglieder (wie Klassen, Schnittstellen und ihre Mitglieder), nicht die Pakete selbst, hätten Zugriffssteuerungsspezifizierer wie „öffentlich“, „privat“ usw. (Dies wird weiter diskutiert @ question stackoverflow.com/questions/4388715/… )

    – Bakar

    7. März 2012 um 22:12 Uhr


  • Ich habe nur den Wortlaut verdeutlicht; mit “öffentlich zugänglich gemachtem Paket” meinte ich eigentlich “das Paket mit den öffentlich zugänglichen Dingen”.

    – cjs

    6. Juli 2012 um 6:39 Uhr

  • Sicherlich sollten alle Pakete öffentliche Dinge haben; Wenn nicht, wie können Sie das Paket verwenden?

    – Bakar

    6. Juli 2012 um 7:59 Uhr

  • In diesem speziellen Fall gab es Pakete mit nichts Öffentlichem, die aber von Paketen verwendet wurden, die Dinge öffentlich machten. Ersteres kann also nicht direkt genutzt werden, sondern nur indirekt über letzteres.

    – cjs

    7. Dezember 2014 um 7:40 Uhr

  • Aber es gilt dieselbe Frage. Wie können die Pakete, die Dinge veröffentlicht haben, die Pakete verwenden, die nichts veröffentlicht haben? Ich kenne in Java keine Möglichkeit, zu erzwingen, dass “Ersteres nicht direkt, sondern nur indirekt über Letzteres verwendet werden kann”. Wenn Ihr Implementierungspaket nur private Mitglieder hat, ist es für Ihr Schnittstellenpaket ebenso unzugänglich wie für den Client. & ähnlich für andere Zugriffsbereiche. Es gibt kein Äquivalent zu friend (C++) bzw internal (C#) in Java.

    – Bakar

    9. Dezember 2014 um 9:25 Uhr

In vielen Frameworks wie OSGi muss man das fast. Ich denke, dies fördert eine lockerere Kopplung auf Paket- statt auf Glasebene.

Benutzer-Avatar
Kenci

Das Buch Praktisches Software-Engineering: Ein Fallstudienansatz befürwortet das Einfügen von Schnittstellen in separate Projekte/Pakete.

Die PCMEF+-Architektur, über die das Buch spricht, hat die folgenden Prinzipien:

  1. Abwärtsabhängigkeitsprinzip (DDP)
  2. Aufwärtsmeldeprinzip (UNP)
  3. Neighbour-Communication-Prinzip (NCP)
  4. Prinzip der expliziten Assoziation (EAP)
  5. Zykluseliminierungsprinzip (CEP)
  6. Prinzip der Klassenbenennung (CNP)
  7. Kennenlern-Paket-Prinzip (APP)

Die Beschreibung der Prinzipien Nr. 3 und Nr. 7 erklären, warum dies eine gute Idee ist:

Das Nachbarkommunikationsprinzip verlangt, dass ein Paket nur direkt mit seinem Nachbarpaket kommunizieren kann. Dieses Prinzip stellt sicher, dass das System nicht zu einem inkompressiblen Netzwerk miteinander kommunizierender Objekte zerfällt. Um dieses Prinzip durchzusetzen, verwendet die Nachrichtenübermittlung zwischen nicht benachbarten Objekten die Delegation (Abschnitt 9.1.5.1). In komplexeren Szenarien kann das Bekanntschaftspaket (Abschnitt 9.1.8.2) verwendet werden, um Schnittstellen zu gruppieren, um die Zusammenarbeit zu unterstützen, die entfernte Pakete einbezieht.

Das Bekanntschaftspaketprinzip ist die Konsequenz aus dem Nachbarschaftskommunikationsprinzip. Das Bekanntschaftspaket besteht aus Schnittstellen, die ein Objekt statt konkreter Objekte in Argumenten an Methodenaufrufe übergibt. Die Schnittstellen können in jedem PCMEF-Paket implementiert werden. Dies ermöglicht effektiv die Kommunikation zwischen nicht benachbarten Paketen, während die Abhängigkeitsverwaltung in einem einzigen bekannten Paket zentralisiert wird. Die Notwendigkeit eines Bekanntschaftspakets wurde in Abschnitt 9.1.8.2 erläutert und wird als nächstes erneut im PCMEF-Kontext erörtert.

Siehe diesen Link: http://comp.mq.edu.au/books/pse/about_book/Ch9.pdf

Ein Argument dafür, Schnittstellen in verschiedene Pakete zu packen, ist, dass es einfacher ist, „API“-Jars zu erstellen, die an die Verbraucher Ihres Produkts oder Ihrer Dienstleistung verteilt werden können. Es ist durchaus möglich, dies mit Schnittstellen und Implementierungen zusammen zu tun, aber einfacher zu skripten, wenn sie sich in verschiedenen Paketen befinden.

  • Sie können das API-Projekt separat haben (als separate verteilbare Datei), und das hindert Schnittstellen und Implementierung dennoch nicht daran, sich im selben Paket zu befinden. Ein bisschen so, als hätten Sie Komponententests im selben Paket wie getestete Klassen, aber immer noch in einem separaten Build-Artefakt. Jars und Pakete sind in Java ziemlich orthogonal.

    – George

    17. Juni 2009 um 9:49 Uhr

Benutzer-Avatar
Paul Sonier

Ja, es ist eine sehr gute Vorgehensweise, da Sie damit die Schnittstelle veröffentlichen können, ohne Ihre spezifische Implementierung zu veröffentlichen. Wenn Sie jedoch keine externen Schnittstellen veröffentlichen müssen, ist es kein Problem, die Schnittstellendefinitionen in dasselbe Paket wie die Implementierung zu stecken.

  • Sie können das API-Projekt separat haben (als separate verteilbare Datei), und das hindert Schnittstellen und Implementierung dennoch nicht daran, sich im selben Paket zu befinden. Ein bisschen so, als hätten Sie Komponententests im selben Paket wie getestete Klassen, aber immer noch in einem separaten Build-Artefakt. Jars und Pakete sind in Java ziemlich orthogonal.

    – George

    17. Juni 2009 um 9:49 Uhr

Benutzer-Avatar
hhafez

Wir machen das dort, wo ich arbeite (dh: Schnittstelle in ein Paket und Implementierung in ein anderes packen) und der Hauptvorteil, den wir daraus ziehen, ist, dass wir einfach zwischen Implementierungen wechseln können.

  • Wie hilft es Ihnen, die Implementierungen zu wechseln?

    – Janusz

    17. Juni 2009 um 3:57 Uhr

  • siehe die Antwort von Cameron Pope, das ist genau der Grund, warum wir es hier tun

    – hhafez

    17. Juni 2009 um 5:24 Uhr

1256360cookie-checkSollen Schnittstellen in einem separaten Paket platziert werden? [closed]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy