Niedoróbki przestrzeni nazw, a może jednak nie?
O co tu właściwie chodzi
Jest to odniesienie do tegoż wpisu Niedoróbki przestrzeni nazw PHP.
Nie da się importować całych przestrzeni
Importowanie jest, koślawe i brzydkie - ale jest. Nie da się niestety przejść do unqualified names. Tak na prawdę, to jest to coś w rodzaju "automatycznego aliasu": use \yada\foo; == use \yada\foo as foo;
namespace yada\foo;
class FooA { }
class FooB { }
namespace yada\bar;
class BarA { }
class BarB { }
namespace yada\buzz;
class BuzzA { }
class BuzzB { }
namespace flop;
use \yada\foo;
use \yada\bar;
use \yada\buzz as bz;
$obj = new \ArrayObject(array , 2);
$obj[] = new foo\FooA ;
$obj[] = new foo\FooB ;
$obj[] = new \yada\bar\BarA ;
$obj[] = new \yada\bar\BarB ;
$obj[] = new bz\BuzzA ;
$obj[] = new bz\BuzzB ;
Trzeba w kółko powtarzać instrukcje use, zapomniane importy/aliasy
I dobrze, dzięki temu każdy plik ma wpisane zależności. Jeszcze tylko tego było trzeba, by jakieś patałachy include'owały definicje "juzów" i potem gubiły pliki. Ctrl+C Ctrl+V jest tego warte.
Kolejnym "za" jest fakt, że wszystkie zależności są wypisane na początku. Jeśli dało by się zrobić import wszystkiego z danej przestrzeni - trzeba by zgadywać, co gdzie było. Przykładowo
Przykład:
namespace flop;
use foo/*;
use bar/*;
class Yada extends Hop { }
Pytanie brzmi: czy Hop jest w foo czy w bar?
Aliasy nie działają z funkcjami operującymi na klasach
Przykro mi, ale problem nie tkwi w przestrzeniach nazw, ale w błędnym wywołaniu Either a string containing the name of the class to reflect, or an object. Tak samo jest z innymi funkcjami/obiektami (przyznaję, że nie sprawdzałem wszystkich), a z tego co wiem, to string ma się nijak do przestrzeni nazw. Za to obiekt - ma pełną świadomość jakiej klasy jest instancją.
$Ref = new \ReflectionClass(stdClass);
To też się rypnie - wywali warrning, działanie jest tylko efektem "ratowania sytuacji" przez PHP.
Przestrzenie nazw mogą powodować kolizje nazw
Mogą i powinny! Powód to wyżej wymieniony "automatycznego aliasu"
Zagnieżdżanie przestrzeni nazw jest niedorobione
Jak na mój łeb, przyniosło by to więcej strat niż pożytku.
Przykład:
namespace foo;
class Foo { }
namespace foo/bar;
class Bar extends Foo { }
W efekcie, PHP musiałby sprawdzić czy istnieje definicja Foo w foo/bar, potem w foo/ a potem w / - a żeby tego dokonać, musiał by mieć świadomość definicji klas w tychże przestrzeniach. Po cholerę includować pliki, z których się nie korzysta? Bo przecież zdefiniowanie przestrzeni foo/bar, oznaczałoby, że istnieje foo/ i trzeba sprawdzić co tam jest.
Pomijam tutaj problem z konfliktami - Foo może być implementacją w foo/ ale też może być abstrakcją w / i zgaduj co się wgra.
Jeżeli z nich korzystamy, to przecież trzeba mieć je w jakiś sposób zaincludowane.
Więc może traktujmy wszystkie "use" jako deklaracje "to będzie tutaj używane", samo wczytanie definicji klasy i tak odbywa się dopiero przy pierwszym tworzeniu instancji. Dzięki temu, na początku pliku mam pięknie napisane w jakiej przestrzeni działamy i jakie są zależności z zewnętrznymi elementami.
Wyszukiwanie nazw jest dziwaczne i niespójne
Tu się w pełni zgadzam z Pornelem.
Nazwy z przedrostkiem nie działają w deklaracjach klas
Ok, tu się zgodzę - nie działają. Może to i dobrze, bo brzydkie są.
Popularne projekty w PHP nadużywają podprzestrzeni nazw
Frameworki nadużywają wielu rzeczy. Ale ok, trzeba przyznać rację - tworzenie przestrzeni nazw dla jednego, jedynego wyjątku. Cóż tak to jest jak się przekłada teorię na rzeczywistość.
Przestrzenie nie mogą być ładowane automatycznie
Ano nie są bo i jak? Problem wg mnie tkwi w określaniu gdzie stała jest definiowana - jak określić miejsce jej definiowania?
To się nazywa kontynuacja dyskusji - oby więcej takich odpowiedzi! :)
OdpowiedzPS. Proszę, zwiększ trochę czcionkę w tym formularzu - ledwo widzę, co piszę. :)
Była 11px, za małe - jest 12. Większych nie dam (przynajmniej do momentu aż nie zmienię silnika...)
Odpowiedz1. To, że use jest aliasem to wiem, ale nie zmienia to faktu, że trzeba use klepać w każdym pliku.
Odpowiedz2. Prawdziwe zależności klas robi się przez Dependency Injection.
Ręczne deklaracje mogą kłamać - np. usuniesz zależność z kodu, ale zapomnisz usunąć use. W drugą stronę też może kłamać jak użyjesz fully-qualified name.
Jak na listę zależności to takie bylejakie przybliżenie, które musisz utrzymywać, czy potrzebujesz, czy nie.
A skąd bierze się klasa Hop to język D ma odpowiedź - jak jest kolizja, to wymaga aliasu, żeby nie było wątpliwości.
Wiem, że import * z dowolnej cudzej przestrzeni jest ryzykowny, ale import * z mojego projektu nie ma ryzyka - ja wiem, co definiuję.
3. object działa tylko z instancjami. Jak nie masz instancji, to nie ma wyboru - tylko string. W doccomment (adnotacje phpunit) - też tylko string.
4. chyba nie zrozumiałeś. Tu chodzi o skopany tokenizer/gramatykę. W normalnej implementacji nie powinno być takiej sytuacji.
5 & ostatnie — to, że nie ma łatwego oczywist
ad. 2. Wg mnie, use'y można traktować jako listę. Przybliżoną? Zależy od tego jak piszesz. Piszesz źle to i dependency injection nie uratuje sytuacji.
OdpowiedzImport "z gwiazdką" był by fajny - nie przeczę. Jednak będzie to furtka dla bałaganu - ty importujesz, ja importuję, on importuje - wszyscy będą tak importować.
ad 3. To czemu wpisujesz tam namespace i piszesz, że to "niedoróbka" ?
ad 4. Zrozumiałem, po prostu chcesz by implementacja była jak najbardziej podobna do innych.
ad 5. Sam stosuję mapy klas w swoim frameworku i wątpię by rozwiązało to problem. Moim zdaniem będzie to zbędnym narzutem.