Подтвердить что ты не робот

Являются ли пространства имен действительно полезными в рамках?

Насколько я могу судить, единственная причина, по которой мы имеем пространство имен в PHP, заключается в том, чтобы исправить проблему классов (+ функций и констант), столкнувшихся с другими классами с одним и тем же именем.

Проблема в том, что большинство фреймворков настраивают свои иерархии autoload и файловой системы, чтобы отразить имена классов. И никто не требует больше() s или include() s файлов.

Итак, как это упрощает namespacing? Либо класс загружается на основе его имени:

new Zend_Db_Table_Rowset_Abstract;

или покинуть это пространство имен

new Zend\Db\Table\Rowset\Abstract;

В любом случае я застрял, имея возможность создать только один класс с этим именем.

/var/www/public/Zend/Db/Table/Rowset/Abstract.php

UPDATE Я не уверен, что у меня есть точка.

Даже если я создал два файла с тем же class Zend\Db\Table\Rowset\Abstract в них, я все равно не мог использовать их вместе, так как они оба претендуют на одно и то же пространство имен. Мне нужно было бы изменить имена имен имен, которые мы уже делаем!

Это оставляет мне поверить, что единственное использование для пространств имен - это имена функций. Теперь мы можем, наконец, иметь три функции, которые все называются одинаковыми!

Или подождите, я забыл, что вы не можете этого сделать, поскольку каждый из них требует префикс пространства имен!

a\myfunction();
b\myfunction();
c\myfunction();

Взяв пример ircmaxell:

$model = new \Application\Model\User;
$controller = new \Application\Controller\User;

Как это иначе, чем без?

$model = new Application_Model_User;
$controller = new Application_Controller_User;

Это также аккуратная функция звучания - но что это действительно делает для нас?

use \Application\Model\User as UserModel;
use \Application\Controller\User as UserController;

$foo = new UserModel;
$bar = new UserController;

Теперь у вас не может быть класса с именем "UserModel", так как у вас есть параметр пространства имен для этого термина. У вас также не может быть двух классов, названных под одним и тем же псевдонимом.

Я думаю, хорошо, что вы можете переименовать длинный Zend_Db_Table_Rowset_Abstract

use Zend_Db_Table_Rowset_Abstract as RowAbstract;

что приводит к путанице разработчиков в отношении того, где неопределенный класс "RowAbstract" определен и поступает из системы.

4b9b3361

Ответ 1

У меня сложилось впечатление, что пространства имен используются в культах культуры. Потому что он новый, он используется как сумасшедший. Глубоко вложенные пространства имен, например, в Doctrine2, не добавляют дополнительной защиты от конфликтов имен. И очень очевидно, что \inested\name\spaces используются для достижения сопоставления 1:1 в именах каталогов/файлов. Очевидно, что запах кода.

Но я полагаю, что это явление также вызвано попыткой сопоставить имена модулей Java в PHP. И более того синтаксис обратной косой черты не передает разумную семантику, как на других языках.

В любом случае, возможность переименовывать классы при импорте пространств имен - это большой бон. Это полезно, когда на самом деле происходит смешивание противоречивых определений. И синтаксис пространства имен можно просто добавить, как только возникнет конфликт имен. (Я не вижу необходимости сразу создавать пространства имен, когда конфликты имен редко встречаются, а для большинства проектов - чисто фиктивная проблема.)
Если вы это сделаете только тогда, когда требуется, неудобный синтаксис пространства имен даже не должен заводить свою уродливую голову. Если для импорта требуется только один уровень пространства имен, вы можете просто use namespace1\Class as LocalName и не сверять приложение с помощью любого синтаксиса namespace1\Class. (Тем не менее, лучше не использовать чрезмерно общие имена классов в пространствах имен.)

Ответ 2

На самом деле вы можете создать более одного класса с тем же именем

Предположим, что у вас есть 2 класса:

\Application\Controller\User

и

\Application\Model\User

Вы не могли импортировать оба файла в один и тот же файл без наложения псевдонимов, но вы все равно можете определить оба способа:

$model = new \Application\Model\User;
$controller = new \Application\Controller\User;

Плюс вы можете импортировать и псевдоним:

use \Application\Model\User as UserModel;
use \Application\Controller\User as UserController;

$foo = new UserModel;
$bar = new UserController;

Таким образом, он действительно достаточно мощный, так как позволяет вам называть ваши классы, как вы хотите (и ссылаться на них произвольными именами внутри вашего кода). Единственными правилами являются зарезервированные ключевые слова... См.: http://www.php.net/manual/en/language.namespaces.importing.php

Ответ 3

Точка, в которой вы, кажется, отсутствуете, - это то, что имена пространства имен являются составными. То есть вы можете сделать:

use Zend\Db\Table as Table;
$a = new Table\Rowset();
$b = new Table\Fields();

и т.д.. То есть он позволяет определить ваш контекст (или набор контекстов), а затем обратиться к нему. Конечно, вы можете сократить его до одного имени, но вам не обязательно. Это также помогает с именами общих классов. Поля могут быть слишком общими, но Table\Fields меньше.

Другое дело, если вы устали от таблиц Zend и хотите написать свои собственные классы таблицы Db, вы измените приведенное выше на:

use My\Own\Table as Table;

и весь код теперь использует ваш набор классов. Кроме того, вы фактически не определяете класс по длинному имени. Что вы делаете:

namespace Zend\Db\Table;
class Rowset exteds AbstractRowset {
    function doStuff() {
       $this->fields = new Fields();
       if($this->fields->areBroken()) {
          throw Exception("Alas, fields are broken!");
       }
    }
 }

Обратите внимание, что здесь мы использовали 4 класса из Zend\Db\Table, но ни разу не приходилось ссылаться на них по длинному имени. Конечно, в реальной жизни это, вероятно, будет не так просто:), но идея состоит в том, что код, особенно код библиотеки, имеет тенденцию быть локализованным - то есть, если вы находитесь в части Db библиотеки, скорее всего, вы используете DB связанных классов гораздо больше, чем классы LDAP или PDF. Namespacing позволяет использовать эту локальность, используя более короткие имена.

Вы правы, что пространство имен не помогает при загрузке - поскольку класс должен быть все еще загружен с использованием полного имени. Но как только вы заработаете ваш загрузчик, вы можете использовать приятные псевдонимы вместо уродливых полных имен - так же, как в файловой системе вы можете использовать красивые относительные пути и символические ссылки вместо уродливого полного пути.

Ответ 4

В вашем примере Zend, вы можете бросить namespace Zend; вверху каждого файла класса, удалить префикс Zend_ из всех ваших классов и функций, а вы (в основном) на Не нужно больше беспокоиться о столкновениях с именами. Ваш класс Zend_Date можно переименовать как просто Date, не вмешиваясь в встроенные классы даты. Между тем, пользователи вашей структуры могут писать Zend\Date вместо Zend_Date, который больше не нужно вводить, но теперь у них есть несколько других вариантов доступа к классу.

Ответ 5

Вероятно, не стоит использовать пространства имен, если у вас нет большого проекта с несколькими разработчиками. Я бы даже утверждал, что пространства имен переоценены.

Например, в Java (поскольку несколько человек используют пространства имен еще в PHP, я не мог найти подобных примеров). Вот список, который появляется в списке в моей среде IDE (Eclipse):

java.util.List
com.ibm.toad.utils.Strings.List
com.ibm.ws.objectManager.List
com.ibm.ws.webcontainer.util.List
java.awt.List

В этом случае я действительно не понимаю, почему они не могли просто сохранить java.util.List только как List и, например, переименовали java.awt.List в ScrollingList, что фактически описывает, что это такое, делает его более очевидным, что он является элементом GUI и позволяет избежать столкновения. Я бы предпочел набрать более длинное и более описательное имя класса, чем иметь дело с этим.

Как и в случае с одним из вышеприведенных плакатов, если каждый из членов вашей команды делает класс под названием Database, возможно, вам нужно провести некоторое обсуждение дизайна и использовать только один класс Database вместо того, чтобы перетаскивать личный дубликат каждого человека в пространство имен.

Ответ 6

Вы действительно пытаетесь создать новый класс с именем Zend_Db_Table_Rowset_Abstract?

Более вероятным сценарием является то, что у вас есть локальный класс, называемый чем-то общим, например Date, Project, User или что-то подобное, или у вас есть структура, которая уже имеет эти классы. Имея пространства имен, не должно быть никаких столкновений.

В web2project мы просто добавили поддержку пространства имен в версии 2.0 (но нам не нужен PHP 5.3), потому что наши классы, такие как Date, DBQuery, Mail и некоторые другие, столкнулись с вещами довольно легко. Хотя у нас нет намерения добавить внешнюю инфраструктуру в систему, кто-то может довольно легко, если захочет.

Существуют ли менее исчерпывающие способы решения проблемы? Потенциально.. но это сработало в мире Java со своими кучами библиотек, так что это не все новое пространство.

Ответ 7

Возможно, если вы немного расширите свой взгляд:)

"Насколько я могу судить, единственная причина, по которой мы имеем пространство имен в PHP, - это исправить проблему классов (+ функций и констант), столкнувшихся с другими классами с одним и тем же именем". - да, это огромная проблема, которая на протяжении многих лет вызывала проблемы на всех языках, на которых нет пространств имен: каждый создает базу данных классов, дату, URL и т.д., и это исправляет:)

"Проблема в том, что большинство фреймворков настраивают свою иерархию автозагрузки и файловой системы, чтобы отражать имена классов. И никто не требует больше() s или include() s файлов". - ну, на самом деле, они часто, просто потому, что некоторые общие рамки должны были придумать методы для работы вокруг нехватки пространств имен, не означает, что эти работы или хаки должны привести к аннулированию "реального" исправления проблемы все:)

следовать?