Ich habe mir gerade noch einmal das Namespace-Kapitel in der PHP-Doku zu
Gemᅵte gefᅵhrt, ohne allerdings verstanden zu haben, wie man das IMHO
entscheidende Problem, das Namespaces lᅵsen sollen, denn nun tatsᅵchlich
mit selbigen lᅵst.
Angenommen ich habe ein Script, das eine Klasse Foo definiert. Und ich
mᅵchte in meinem Script zwei verschiedene Bibliotheken von
Drittanbietern nutzen, die beide ebenfalls Foo-Klassen in ihrem Code
definieren. (Und diese Bibliotheken wurden lange vor PHP 5.3
geschrieben.) Ich hᅵtte also:
LibA.php:
class Foo { ... } // Bibliothek Nr. 1
LibB.php:
class Foo { ... } // Bibliothek Nr. 2
meins.php:
include 'LibA.php';
include 'LibB.php';
class Foo { ... }
So geht das natᅵrlich nicht. Ganz naiv wᅵrde ich jetzt erwarten, daᅵ mir
Namespaces folgendes ermᅵglichen (nicht unbedingt mit dieser Syntax):
meins.php:
include 'LibA.php' as A
include 'LibB.php' as B
class Foo { ... }
$a = new A\Foo(); // Foo aus LibA.php
$b = new B\Foo(); // Foo aus LibB.php
$c = new Foo(); // Foo aus meins.php
Hierbei sollte "include 'LibA.php' as A usw." bedeuten: "Inkludiere die
Datei. Innerhalb von LibA.php bezieht sich Foo auf die dort definierte
Klasse. Die in LibB.php und meins.php definierten Foo-Klassen sind fᅵr
LibA.php unsichtbar. In meins.php bezieht sich Foo auf die darin
definierte Klasse. Die gleichnamigen Klassen aus den Libs kᅵnnen ᅵber
die gewᅵhlten Prᅵfixe/Namespaces A\Foo bzw. B\Foo angesprochen werden."
Wenn ich die PHP-Doku nun richtig verstanden habe, ist dies aber
offenbar nicht mᅵglich. Ich mᅵᅵte vielmehr in LibA.php und LibB.php
jeweils eine Namespace-Deklaration hinzufᅵgen. Anderenfalls bliebe mir
nur die Mᅵglichkeit, in meins.php einen eigenen Namespace "aufzumachen"
und z.B. das Foo aus LibA.php als zum globalen Namespace gehᅵrig mit
\Foo anzusprechen. Allerdings kᅵnnte ich dann nicht gleichzeitig
LibA.php und LibB.php inkludieren.
Und wenn nun die Anbieter von LibA und LibB auf Namespaces "aufrᅵsten"
und sich (nehmen wir es jetzt einfach mal an, auch wenn es praktisch
unwahrscheinlich ist) zufᅵllig fᅵr den selben Namespace-Namen
entscheiden, den sie ihren Libs voranstellen, wie kann ich dann beide
Libs einbinden?
Gruᅵ,
Thomas
--
Ce n'est pas parce qu'ils sont nombreux ᅵ avoir tort qu'ils ont raison!
(Coluche)
> Angenommen ich habe ein Script, das eine Klasse Foo definiert. Und ich
> möchte in meinem Script zwei verschiedene Bibliotheken von
> Drittanbietern nutzen, die beide ebenfalls Foo-Klassen in ihrem Code
> definieren. (Und diese Bibliotheken wurden lange vor PHP 5.3
> geschrieben.) Ich hätte also:
>
> LibA.php:
> class Foo { ... } // Bibliothek Nr. 1
> LibB.php:
> class Foo { ... } // Bibliothek Nr. 2
Da scheinst Du aber was mißzuverstehen. Namenräume waren nie als Lösung
für alte Implementierungen gedacht sondern schlagen eine neues Kapitel
auf nach dem auch programmiert werden muß. Mal abgesehen davon halte ich
Libraries die Klassen unter dem Selben Namen definieren in 99,99% aller
Fälle für falsch designed was ein Grund wäre diese komplett zu
ignorieren. Die meisten Libs die bereits solche einfachste Fehler im
Design haben sind auch ansonsten schlecht durchdacht. Ordentliche
Libraries/Frameworks nutzen ausschließlich Klassen und Funktionen mit
Prefix. Das war nunmal früher (vor Namensräumen) die einzige Möglichkeit
um Verwechselungen auszuschließen.
Wenn Du die beiden Klassen trotzdem nutzen willst dan verpassen diesen
hat unterschiedliche Namensräume und schon Funktioniert auch schon alles
wie es soll.
MfG, Ulf
--
Wenn es nur eine Wahrheit gäbe, könnte man nicht hundert Bilder über
dasselbe Thema malen. [Pablo Picasso]
> Da scheinst Du aber was mißzuverstehen. Namenräume waren nie als Lösung
> für alte Implementierungen gedacht sondern schlagen eine neues Kapitel
> auf nach dem auch programmiert werden muß.
Die Libs müssen also in ihren Dateien jeweils namespace-Deklarationen
einbauen. Womit das Risiko besteht, daß zwei Libs, die nichts
voneinander wissen, sich zufällig für denselben Namespace entscheiden.
> Mal abgesehen davon halte ich
> Libraries die Klassen unter dem Selben Namen definieren in 99,99% aller
> Fälle für falsch designed was ein Grund wäre diese komplett zu
> ignorieren. Die meisten Libs die bereits solche einfachste Fehler im
> Design haben sind auch ansonsten schlecht durchdacht.
Äh - Moment. Wenn ich eine Library schreibe, dann kann es doch durchaus
sein, daß ich rein zufällig einen Klassennamen wähle, den eine mir
völlig unbekannte andere Lib bereits verwendet?
> Ordentliche
> Libraries/Frameworks nutzen ausschließlich Klassen und Funktionen mit
> Prefix. Das war nunmal früher (vor Namensräumen) die einzige Möglichkeit
> um Verwechselungen auszuschließen.
Und wenn nun zwei Libs zufällig dasselbe Präfix verwenden? Präfixe
sollten ja sinnvollerweise so kurz wie möglich sein, was die Gefahr von
Kollisionen aber gerade erhöht.
Was also können Namespaces eigentlich, was Präfixe nicht können? Außer
mir vielleicht etwas Tipparbeit zu ersparen?
> Wenn Du die beiden Klassen trotzdem nutzen willst dan verpassen diesen
> hat unterschiedliche Namensräume und schon Funktioniert auch schon alles
> wie es soll.
Meinst Du so?
namespace A { include 'LibA.php'; }
namespace B { include 'LibB.php'; }
namespace {
class Foo { ... }
$foo1 = new Foo();
$foo2 = new A\Foo();
$foo3 = new B\Foo();
}
Gruß,
Thomas
--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Ja kann passieren, sollte bei bekannten Libs aber kein Problem sein.
> Äh - Moment. Wenn ich eine Library schreibe, dann kann es doch durchaus
> sein, daß ich rein zufällig einen Klassennamen wähle, den eine mir
> völlig unbekannte andere Lib bereits verwendet?
> [...]
> Und wenn nun zwei Libs zufällig dasselbe Präfix verwenden? Präfixe
> sollten ja sinnvollerweise so kurz wie möglich sein, was die Gefahr von
> Kollisionen aber gerade erhöht.
Gleiches Problem wie bei Namespace, es kann passieren ja. Beim Zend
Framework fangen zum Beispiel alle Klassennamen mit Zend_ oder ZendX_
an. Niemand würde wohl auf die Idee kommen Zend als Präfix für die
eigenen Klassen zu verwenden.
> Was also können Namespaces eigentlich, was Präfixe nicht können? Außer
> mir vielleicht etwas Tipparbeit zu ersparen?
Nichts soweit ich weiß. Du erstparst dir vor allem auch innerhalb der
Klasse dann die Tipparbeit weil dich im Namespace der Klasse befindest
(wenn ich es mit den Namespaces in PHP richtig verstanden habe)
> Meinst Du so?
>
> namespace A { include 'LibA.php'; }
> namespace B { include 'LibB.php'; }
> namespace {
> class Foo { ... }
> $foo1 = new Foo();
> $foo2 = new A\Foo();
> $foo3 = new B\Foo();
> }
eher so:
LibA.php:
namespace A;
//Inhalt
LibB.php:
namespace B;
//Inhalt
Daher innerhalb der Dateien muss der Namespace gewählt werden. Elemente
werden nicht per geschweifte Klammern in den Namespace geschrieben
sondern die Namespaceangabe wird dem Quellcode der Datei vorangestellt.
--
Mit freundlichen Grüßen,
Christoph Herrmann
Nachtrag:
In Java finde ich dies übrigens gut gelöst durch Namenskonvention. Hier
wird einfach die Domain des Projekts umgedreht als Namespace verwendet.
Wird das Projekt zum Beispiel unter http://example.com bereit gestellt
landen alle Klassen des Projektes im Namespace com.example.
In PHP sind mir solche Konventionen nicht bekannt, daher kann es hier
durchaus vorkommen dass zwei Projekte sich den glechen Namespace aussuchen.
>> Äh - Moment. Wenn ich eine Library schreibe, dann kann es doch
>> durchaus sein, daß ich rein zufällig einen Klassennamen wähle, den
>> eine mir völlig unbekannte andere Lib bereits verwendet?
>> [...]
>> Und wenn nun zwei Libs zufällig dasselbe Präfix verwenden? Präfixe
>> sollten ja sinnvollerweise so kurz wie möglich sein, was die Gefahr
>> von Kollisionen aber gerade erhöht.
>
> Gleiches Problem wie bei Namespace, es kann passieren ja. Beim Zend
> Framework fangen zum Beispiel alle Klassennamen mit Zend_ oder ZendX_
> an. Niemand würde wohl auf die Idee kommen Zend als Präfix für die
> eigenen Klassen zu verwenden.
Solche Annahmen sind der Quell vieler Übel. Natürlich wird irgendjemand
auf diese Idee kommen. Selbst ich - als Meister der seltsamen
Projektbezeichnungen schon mehrfach betitelt - hatte vor etlichen Jahren
ein Projekt mit dem Präfix Zend. Da war mir Zend noch völlig unbekannt. ;)
Gruß,
Torsten
--
http://www.dddbl.de - ein Datenbank-Layer, der die Arbeit mit 8
verschiedenen Datenbanksystemen abstrahiert,
Queries von Applikationen trennt und automatisch die Query-Ergebnisse
auswerten kann.
Also ich hab mir ein Präfix überlegt, in Google eingegeben und erstmal
geschaut ob a) die Domain frei ist und b) kein Projekt im Bereich
Entwicklung existiert bezüglich Verwechslungen zu vermeiden.
Aber klar, Ausnahmen gibts immer. ;)
Murphys Gesetz halt, die Wahrscheinlichkeit selbst bei 3 oder 4
Buchstaben zu kollidieren ist so klein, aber man wird davon verfolgt
wenn man es nicht erwartet. :)
Zu a) mache ich mir selten Gedanken - schließlich gibt es genügend TLDs ;)
Und wenn ich ein neues Projekt starte, suche ich einen Namen der zum
Projekt paßt. Anderes ist mir egal. Man kann sich nicht immer an Anderen
orientieren.
> Aber klar, Ausnahmen gibts immer. ;)
;)
> Murphys Gesetz halt, die Wahrscheinlichkeit selbst bei 3 oder 4
> Buchstaben zu kollidieren ist so klein, aber man wird davon verfolgt
> wenn man es nicht erwartet. :)
Bei 4 Buchstaben gibt es lediglich 456.976 Möglichkeiten der
Kombination. Beim heutigen Softwarespektrum etwas, dass vermutlich schon
längst überschritten wurde.
Erschwerend kommt hinzu, dass Präfixe in der Regel auch nach
phonetischen (Wohl)Klang gewählt werden, was die Auswahl deutlich
einschränkt.
> an. Niemand würde wohl auf die Idee kommen Zend als Präfix für die
> eigenen Klassen zu verwenden.
Aber hundertprozentig auszuschließen ist es nicht.
>> Was also können Namespaces eigentlich, was Präfixe nicht können?
> Nichts soweit ich weiß.
Dann kann ich dieses Feature also vergessen und bei Präfixen bleiben?
>> namespace A { include 'LibA.php'; }
> eher so:
>
> LibA.php:
> namespace A;
> //Inhalt
> Daher innerhalb der Dateien muss der Namespace gewählt werden. Elemente
> werden nicht per geschweifte Klammern in den Namespace geschrieben
Ich meinte aber, die Doku hätte die geschweiften Klammern als
alternative Syntax erlaubt. Was mir ermöglichen würde, mein
Ausgangsproblem zu lösen, ohne in fremden Libs herumpfuschen zu müssen.
> Nachtrag:
> In Java finde ich dies übrigens gut gelöst durch Namenskonvention. Hier
> wird einfach die Domain des Projekts umgedreht als Namespace verwendet.
> Wird das Projekt zum Beispiel unter http://example.com bereit gestellt
> landen alle Klassen des Projektes im Namespace com.example.
Interessant. Setzt allerdings voraus, daß jedes Projekt tatsächlich eine
eigene Domain hat.
> In PHP sind mir solche Konventionen nicht bekannt, daher kann es hier
> durchaus vorkommen dass zwei Projekte sich den glechen Namespace aussuchen.
Wobei natürlich niemand daran gehindert ist, seinerseits eine solche
Konvention anzuwenden.
> Erschwerend kommt hinzu, dass Präfixe in der Regel auch nach
> phonetischen (Wohl)Klang gewählt werden, was die Auswahl deutlich
> einschränkt.
Das kann man mit Phantasie mehr als ausgleichen: Qt = "cute". Auf diese
Weise läßt sich wohl zu jeder Buchstabenkombination eine nette
Aussprachevariante finden.
>> Erschwerend kommt hinzu, dass Präfixe in der Regel auch nach
>> phonetischen (Wohl)Klang gewählt werden, was die Auswahl deutlich
>> einschränkt.
>
> Das kann man mit Phantasie mehr als ausgleichen: Qt = "cute". Auf diese
> Weise läßt sich wohl zu jeder Buchstabenkombination eine nette
> Aussprachevariante finden.
XY? Solche phonetischen Ähnlichkeiten sind ebenso beschränkt. Im Bereich
der Musik gibt es zum Teil sehr umfangreiche Abhandlungen, was dieses
Thema angeht.
Abgesehen davon müßtest du bei Aussprachebedingter Unterscheidung immer
hoffen, dass jeder die Aussprache so herleiten kann. Das ist aber selten
der Fall.
Gruß,
Torsten
> XY?
"Crossy" (Was auch immer das jetzt heißen mag. Google liefert jedenfalls
eine ganze Menge Treffer.)
> Abgesehen davon müßtest du bei Aussprachebedingter Unterscheidung immer
> hoffen, dass jeder die Aussprache so herleiten kann. Das ist aber selten
> der Fall.
In der Tat. Andererseits - wir reden hier von Präfixen bei Klassennamen.
Die muß eigentlich niemand aussprechen. Man kann das Projekt ja
"Crossy" nennen (um mal bei obigem Beispiel zu bleiben) und als Präfix
"Xy" nehmen. Dann möge jeder selbst entscheiden, wie er das
auszusprechen gedenkt. Ich würde vermutlich spontan auf "Ksi" verfallen,
was sich wohl mit der Zeit zu "Si" oder "Chi" verschleifen würde. Immer
vorausgesetzt, daß ich tatsächlich oft genug gezwungen bin, das
auszusprechen. Aber in diesem Fall müßte ich mich sowieso gründlicher
mit dieser fiktiven Library befassen und da sollte mir ein hinreichend
deutlich platzierter Aussprachehinweis in der Doku nicht entgehen.
Das ist nicht nötig. Es reicht, wenn der Entwickler besitzer einer Domain
ist (hier example.com):
com\example\projectA\class
com\example\projectB\class
Sollte später noch ein Entwicklerteam (example.net) hinzustoßen könnten
dieses unter seinem eigenen Namespace arbeiten:
net\example\projectA\class
net\example\projectB\class
So wissen alle wer welchen Code geschrieben hat, keiner kommt sich ins
Gehege nur untereinander sollten dann die Schnittstellen klar definiert
werden.
Grüße
Johannes
--
Emails ohne "[nospam]" im Betreff werden kommentarlos gelöscht.
> com\example\projectA\class
> com\example\projectB\class
de\mlynarczyk-webdesign\project\class
Autsch. Bindestrich geht ja nicht bei Namespaces. Ich sollte mir wohl
doch noch mal eine kürzere Domain zulegen. Okay, ich kann den
Bindestrich durch _ ersetzen, aber zu lang ist es trotzdem noch.
Aber Du hast natürlich recht: mit dieser Konvention werden Kollisionen
zuverlässig vermieden.
Dennoch wäre es schön, wenn man als Anwender einer fremden Library
selbiger ein eigenes Präfix verpassen könnte, ohne in dero Code
herumpfuschen zu müssen.