Обновить
8K+
53
Alex Gusev@flancer

Я кодирую, потому что я кодирую…

9,2
Рейтинг
99
Подписчики
Отправить сообщение

Вы по ходу дела плавно подменили первоначальную проблему "сложно уникально адресовать два класса с одинаковым названием, не привязываясь к файлам, в котором они определены" другой — "мне нужно импортировать два класса с одинаковым названием и это не решается алиасами" :)


Дело в том, что в PHP-проекте я могу написать:


$init = new \Doctrine\DBAL\Event\Listeners\MysqlSessionInit()

без того, чтобы использовать import или require. При этом я не должен знать о том, в каком каталоге находится файл, в котором находится исходный код. Именно потому, что в PHP/Java/TypeScript/… есть директива namespace. А в JS/Python этой директивы нет, вы её никогда не использовали и не понимаете для чего она вообще может быть нужна. Если вам она не нужна, то это говорит только о том, что вы ещё не достигли своего предела сложности в JS/Python.

Что такое doctrine/DBAL и doctrine/ORM? Каталог, файл или некоторая строковая метка для поиска пути к исходникам по некоторому алгоритму?

Я не программирую на TypeScript, а в JS нет namespace'ов (поэтому они не выручат). Что касается PHP, то вот два класса с одинаковым именем Configuration, конфликт которых "разводят" namespace'ы (оба класса, что характерно, находятся в файлах Configuration.php):



Для того, чтобы создать объекты этих классов в современном PHP-приложении мне достаточно знать их полные имена, все остальное делает менеджер зависимостей (autoloading).

Вы правильно сказали — "не попадают в глобальный скоуп". В JS вообще нет namespace'ов в смысле логической группировки элементов кода. Есть scope. Именно поэтому на JS'е сложно писать сложные проекты — сложно уникально адресовать два класса с одинаковым названием, не привязываясь к файлам, в котором они определены. А в PHP можно. И в Java можно. И в Typescript можно (если я правильно понял).

Сможет. Если прописать в ./vendor/composer/autoload_classmap.php


'Prophecy\\Call\\CallCenter' => $vendorDir . '/bla/bla/bla.php',

Пространства имён не привязаны к языку. В Java нет жестких требований по расположению файлов — вы указываете их местоположение в CLASSPATH при запуске приложения.


И пространства имён не являются обязательной фичей для достижения "максимальной сложности приложений". Я пытался донести мысль, что пространство имён при прочих равных условиях (например, язык и квалификация разработчика) позволяют создавать более сложные приложения, чем без них. Вы можете писать на PHP без использования namespace, некоторые до сих пор так и делают. Но в таких пакетах, как Zend2, Symfony, Laravel — используются namespaces.


Кстати, в Yii и CodeIgniter, к моему удивлению, не используют пространства имён. В результате в Yii имена файлов выглядят так:


image


А в CodeIgniter так:


image


Обратите внимание на префиксы в названиях файлов — разрабы вынуждены обеспечивать уникальность имени каждого файла в пределах проекта (по сути, вручную, не используя средств языка, вводят пространства CDb и DB_). Да, для 1000 файлов они выкрутятся (какой ценой?), а для 300 млн.?


Если вдруг решите попрограммировать на PHP, не начинайте с Yii и CodeIgniter ;)

В вашем проекте папки и файлы организованы так, в моём — по-другому, у кого-то — по третьему. Посмотрите содержимое файла autoload_namespaces.php, фрагмент которого я привёл в разделе "Автозагрузка кода". В нём видно, как файловая система каждого модуля (а сторонний модуль в вашем проекте с вашими правилами для кого-то является собственным проектом со своими правилами) монтируется в единую логическую структуру кода в вашем проекте. Вот, например, исходники модулей находятся в таких подкаталогах внутри каталога ./vendor вашего проекта:


  • ./magento/zendframework1/library
  • ./phpspec/prophecy/src
  • ./phpmd/phpmd/src/main/php

Но вы не заморачиваетесь путями к исходникам, а просто пишете в своём коде:


$center = new \Prophecy\Call\CallCenter();

Поиск файла с исходниками автозагрузчик autoload.php выполнит самостоятельно, на основании привязки пространства \Prophecy\* к каталогу ./vendor/phpspec/prophecy/src.


Если ваш проект собран при помощи PHP Composer, то ваш код не изменится, если Konstantin Kudryashov (автор модуля phpspec/prophecy) захочет изменить структуру своего модуля и перенести исходники в своём модуле в каталог, например, ./phpspec/prophecy/src/main/php. Он просто укажет в composer.json своего модуля:


    "autoload": {
        "psr-0": {
            "Prophecy\\": "src/main/php"
        }
    }

и при сборке или обновлении вашего проекта в следующий раз в карту пространства имен autoload_namespaces.php запишется так:


'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src/main/php'),

С появлением autoloader'a PHP-разработчики перестали держать в голове файловую структуру своего проекта (и файловую структуру сторонних модулей, используемых в своём проекте) и стали держать логическую структуру кода (которая гораздо проще).


Пространство имён не нужно, если на компьютере в проекте хранится участвует 5-10 файлов разработчиков со своими модулями. Но если на компьютере в проекте хранится участвует 1000 файлов разработчиков со своими модулями, то пространство имён становится более актуальным.

Похоже, я ввёл вас в заблуждение, пытаясь продемонстрировать работу "пространства имён" на примере библиотек.


namespace в PHP и package в Java относятся к исходному коду, а не к библиотекам.


Попробую запутать вас ещё больше. Всем известные интернетовские домены — это пример применения namespace'ов на практике. Две разные библиотеки два разных домена с именем mail одновременно существуют в одном проекте интернете именно потому, что они принадлежат двум разным пространствам имён:



Пространство имён — некоторое множество… созданное для логической группировки уникальных идентификаторов…


На самом деле можно в интернете проекте обойтись без доменов верхнего уровня и вообще без доменов namespace'ов и адресовать все хосты библиотеки "плоской" строкой. Это примерно то же самое, как хранить все файлы на компьютере в одном корневом каталоге. Да-да, файловая система — это тоже пример "логической группировки уникальных идентификаторов" (имён файлов) при помощи "некоторых множеств" (каталогов).


И если на компьютере хранить 5-10 файлов, то вполне резонно задаваться вопросом, а для чего мне вообще нужны каталоги? И получить вполне логичный ответ — для хранения 5-10 файлов каталоги не нужны.

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

Спасибо за развёрнутый коммент, коллега.


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

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


В java-мире, например, корпорация Oracle поглотила корпорацию Sun, а пакет com.oracle.json замечательно сосуществуют рядом с пакетом com.sun.net.httpserver.


А представьте, что вы бы захотели опубликовать свой приватный пакет debug для открытого использования?


Ничто не мешает генерировать ссылку типа такой: npm-module-name/path/to/file.js:123.

Это всё равно привязка к тексту в файле, а не к логической структуре кода (константа, метод, класс, ...). Адресация поплывет при изменении кол-ва строк в файле.


Имена классов в JS-модулях локальные, придумывать уникальные имена в рамках всего проекта не надо.

Вполне возможно, что мой прогноз — "пальцем в небо".

Файлы из своего проекта можно импортировать только через относительные пути.

Этот коммент замечательно иллюстрирует сказанное в пункте "Автозагрузка кода". Нам приходится отталкиваться от файловой структуры, если нам сложно отталкиваться от структуры кода.

Вы живёте в страшном мире, коллега. Вас окружают идиоты с торчащими из глаз карандашами и вокруг всё в крови. Сюрненько.

Согласен. Даже есть подозрение, что если бы человек слил уязвимость на сторону и ее начали бы эксплуатировать, то эту уязвимость законопатили бы значительно быстрее. Особенно, если тоннами начали сливаться деньги.

Ну чего вам стоило при наличии таких бюджетов обратиться в крупное или даже топовое агентство на Украине?

Может быть потому, что опытные рекламщики не смогли донести информацию о своей полезности до потенциального потребителя?

А универсального решения, устраивающего всех, нет. Если работаешь в разнородной среде то ради униформности чего только не приходится делать. Это вы ещё на фронт не залазили.

С точки зрения backend-разработчика человеческого пользователя нет всегда. Но это ограниченная точка зрения.


С точки зрения forntend-разработчика (в частности, разработчика SPA) человеческий пользователь есть слишком часто, чтобы его игнорировать. Разделение ошибок на 500-е (т.е., любые ошибки, не предусмотренные логикой операции, которые произошли в момент выполнения зпроса на сервере) и на ошибки бизнес-логики, зависящие от конкретной запрошенной операции (200-е с необходимостью анализа содержимого поля "ошибка") позволяют запускать на клиенте сценарии решения ошибочной с точки зрения бизнес-логики ситуации с использованием полученных с сервера данных.


Другими словами, 500-я ошибка — это всегда тупиковая ошибка. Ее обработка и на неинтерактивном клиенте и на интерактивном одинакова — логируем / показываем пользователю сообщение, что все плохо. Код ошибки в 200-м ответе сигнализирует, что выполнение запрошенной операции на сервере пошло по одному из предусмотренных разработчиками сценариев, не обеспечивающих успешного завершения в силу каких-то условий. В этом случае пользователь (интерактивный) или программа (неинтерактивный) может выполнить некоторые дополнительные действия, после чего повторить операцию.


То есть, если сценарий выполнения операции предусматривает возможность дублирования ИНН и имеются рекомендации для пользователя, что нужно сделать в данном случае — это ошибка бизнес-логики (код 200). Если на сервере при добавлении записи в БД произошла ошибка из-за того, что в таблице на поле ИНН повешен ключ уникальности, а записывались данные с повторяющимся значением ИНН, которая перехватилась и обернулась в типовое сообщение об ошибке на уровне REST framework'а, потому что разраб сервиса даже не предполагал такого варианта — это 500-я ошибка.


Почему не передавать все ошибки через 500-й код? Потому что в таком случае смешивают обычные ошибки (как правило выполнение операции невозможно по независящим от клиента обстоятельствам) и ошибки бизнес-логики (зачастую операция возможна при внесении некоторых изменений в данные или предварительном выполнении других операций), очень сильно привязанные к контексту текущих выполняемых действий (т.е. к тому же контексту, в котором на клиенте происходит дальнейшая обработка данных, полученных с сервера в результате успешного завершения операции с кодом 200).


Есть мнение, что ошибки валидации входных данных не являются ошибками, как таковыми — это предусмотренный сценарий взаимодействия. Эту точку зрения можно распростанить и на ошибки бизнес-логики, предусмотренные разработчиками сервисов. Все остальное — настоящие ошибки, 500-й код, окончательный тупик.

но оибку в бизнес логике, возврещается HTTP код 200 и документ с полем ошибка, описанием ошибки и кодом ошибки (код ошибки не HTTP, а самой системы).

Вот за то коллега evgenyk и говорил. Если ошибка бизнес-логики, значит пользователь что-то сделал не так, как предусматривалось разработчиками, и ему нужна дополнительная информация, чтобы он сам мог разрулить ситуацию (если она разруливаемая), которая через состояния HTTP-статуса не передается. Очень редко, когда пользователь остается доволен, видя на экране надпись "Ошибка 500. Обратитесь в службу поддержки".


Я понимаю, откуда ноги растут у вашего "и клиенту нужно каждый раз парсить содержимое поле "ошибка". Спасибо, нет." — вы серверный разработчик с соответствующим взглядом на разработку.

А тело ответа — оно зачем в таком случае? Либо его тоже нужно парсить, и тогда ваше "Спасибо, нет" неуместно, либо его парсить не нужно и тогда, согласно старику Оккаму, неуместно само тело. Вот это и улыбнуло.

и клиенту нужно каждый раз парсить содержимое поле "ошибка". Спасибо, нет.
© liar

а уже в теле будет написано "дублирующийся ИНН", или INN: "duplicate", или в меру нашего извращения.
© liar

улыбнуло.

Т.е., "код возврата" — это HTTP Status, в котором не предусмотрены ошибки бизнес-логики. Я правильно понимаю, что вы, как клиент, предпочитаете в случае ошибки на уровне бизнес-логики (например, "клиент с таким ИНН уже есть") получить ответ от сервера со статусом 200?

Информация

В рейтинге
843-й
Откуда
Рига, Латвия, Латвия
Дата рождения
Зарегистрирован
Активность

Специализация

Фулстек разработчик
Ведущий
От 3 000 €
JavaScript
HTML
CSS
Node.js
Vue.js
Веб-разработка
Progressive Web Apps
PostgreSQL
MySQL
GitHub