Действительно ли пространства имен полезны в рамках? - PullRequest
12 голосов
/ 01 июля 2010

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

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

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

new Zend_Db_Table_Rowset_Abstract;

или отключить его пространство имен

new Zend\Db\Table\Rowset\Abstract;

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

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

ОБНОВЛЕНИЕ Я не уверен, что понял суть.

Даже если бы я создал два файла с одинаковым 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".

Ответы [ 7 ]

13 голосов
/ 01 июля 2010

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

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

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

13 голосов
/ 01 июля 2010

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

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

\Application\Controller\User

и

\Application\Model\User

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

$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

7 голосов
/ 16 июля 2010

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

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 space, но никогда не приходилось ссылаться на них длинным именем. Конечно, в реальной жизни это, вероятно, не будет так просто :), но идея в том, что код, особенно библиотечный код, имеет тенденцию быть локализованным, т.е. если вы находитесь в Db-части библиотеки, скорее всего, вы используете DB связанные классы гораздо больше, чем классы LDAP или PDF. Пространство имен позволяет вам использовать эту местность, используя более короткие имена.

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

3 голосов
/ 01 июля 2010

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

2 голосов
/ 01 июля 2010

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

Например, в Java (поскольку мало кто использует пространства имен еще в PHP, я не смог найти подобных примеров).Вот варианты, которые подходят для List в моей 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, которое фактически описывает, что это такое, делает более очевидным, что это элемент графического интерфейса пользователя, и избегает столкновения.Я предпочел бы набрать более длинное и более описательное имя класса, чем иметь дело с этим.

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

1 голос
/ 01 июля 2010

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

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

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

следовать?

1 голос
/ 01 июля 2010

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...