Pull to refresh

Comments 49

коды GeoNames для городов и штатов

А почему именно GeoNames? Это, вроде, не стандарт. Для "штатов" (административного деления) есть тот же ISO 3166-2.

Потому что есть ещё города, а для них нет никаких стандартных кодов, насколько я знаю. Штатам, скорее всего, полезно будет всё, что имеется – GeoNames, ISO 3166-2, FIPS. Таким образом будет делом разработчика – к чему привязаться.

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

Так чем GeoNames лучше любой другой системы идентификации, хотя бы и собственной?

Модный на сегодня ответ – абстракцией. Уменьшением зависимостей, или то что в английском называется 'decoupling'.

Если у меня имеется 5 приложений и всем нужны географические данные, мне проще на всех 5 использовать идентификаторы GeoNames, чем 1) использовать 5 разных наборов 2) придумывать свою конвенцию.

А если выбирать не из своих систем – я не смог ничего глобального найти кроме GeoNames. Если есть что-то еще – то надо будет просто добавить эту систему в пакет, разработчик сможет выбрать, чему он больше доверяет в долгосрочной перспективе :)
Уменьшением зависимостей, или то что в английском называется 'decoupling'.

Ровно наоборот, вы не уменьшили зависимости, а добавили еще одну — от GeoNames.

Если приложений было 5 – вы заменили 5 зависимостей всего одной.

Если приложение было одно – вы заменили собственную кустарную (живущую в адресном пространстве конкретного приложения) зависимость – глобальной, стандартизированной, проверенной годами. Что не так уж и плохо само по себе! ;-)
Если приложений было 5 – вы заменили 5 зависимостей всего одной.

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


вы заменили собственную кустарную (живущую в адресном пространстве конкретного приложения) зависимость

Собственный классификатор не является зависимостью.


глобальной, стандартизированной, проверенной годами

GeoNames разве стандарт?

Хорошо, согласен про зависимости. Но все еще настаиваю на том, что работать в будущем (то, что называют термином 'maintainability') будет проще с приложением, использующим известные, документированные API и конвенции. В данном случае использовать GeoNames вместо специфичных для конкретного приложения идентификаторов – это как раз переход на API, на конвенцию, которую кто-то уже написал за нас.

Лично мне было бы удобно, что во всех моих приложениях код города 15 – это город X, и при этом мне не надо самому ничего документировать.

GeoNames – это, как говорится, не идеально, но лучшее, что у нас сегодня есть.
Но все еще настаиваю на том, что работать в будущем (то, что называют термином 'maintainability') будет проще с приложением, использующим известные, документированные API и конвенции.

Только в том случае, если эта конвенция (а) удобна для приложения (а не надо ее натягивать специально) и (б) известно, что она не изменится.


GeoNames – это, как говорится, не идеально, но лучшее, что у нас сегодня есть.

Кстати, что произойдет в GeoNames, если какой-то город переименуют? Или, что хуже, произойдет административная реорганизация?

У них есть поле – альтернативные названия города. Подозреваю, что старое название уйдет туда ;-) ID не сменится

… и что случится в этот момент в вашем интерфейсе в поле "пользователь родился в"?


И это только переименование. А представьте себе, что город удалили (или он разделился на две части). Или представьте себе, что пользователь хочет зачекиниться в городе, которого нет в GeoNames.

Вообще, все нормально будет — скажем, до 1991-ого года пользователь имел «родился в Ленинграде», после 91-ого «родился в Санкт-Петербурге» (что абсолютно верно). Ничего не меняя в базе или коде.

Пропадать города будут очень, очень редко. Не уверен, как GeoNames поступают в таких случаях. Если просто удаляют из базы навсегда — то да, надо думать как такие случаи обрабатывать.

В GeoNames есть все города с населением выше 1000 людей — этого достаточно должно быть большинству приложений.

Facebook, к примеру, имея миллиарды капитала, не может до сих пор многие ошибки в географии исправить. Подозреваю, что качество данных было бы выше, если бы любой пользователь мог исправлять ошибки (а в случае пакета на GitHub так и будет)
Вообще, все нормально будет — скажем, до 1991-ого года пользователь имел «родился в Ленинграде», после 91-ого «родился в Санкт-Петербурге» (что абсолютно верно)

Это с вашей точки зрения верно, а с его — не обязательно.


В GeoNames есть все города с населением выше 1000 людей — этого достаточно должно быть большинству приложений.

Что делать тем, которым недостаточно?


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

Вы совершенно зря так подозреваете. Даже GeoNames для предоставления более достоверных данных использует ручное курирование.


А главное, что делать, когда интересы пользователей конфликтуют? Например, для одного приложения нужно, чтобы Крым и Севастополь были частью Российской Федерации, для другого — чтобы нет. Как вы будете нормализовать иерархию в этом случае?

Ну, пограничные случаи всегда будут.

Если мой пакет будет полезен даже для 50% приложений – это уже будет прекрасный результат.

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

Про оспариваемые территории я пока еще думаю над решением :)

Речь не о пакете. Речь о предлагаемом подходе


Предвижу вопросы вроде «но как же тогда запоминать город пользователя?», и ответ тут достаточно прост – в своей БД (или куда вы там записываете данные) используйте стандартные идентификаторы, такие как коды ISO 3166-1 для стран, коды GeoNames для городов и штатов.

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

Переименован — выводим новое имя.
Расформирован в связи с реорганизацией (удален, разделен, присоединен) — флаг депрекейтед. В зависимости от задачи — или не давать новым указывать, но старых оставлять или давать, но рекомендовать не использовать и т.п.
Неизвестный город? Тут или ручной ввод разрешать или выбирать более общий вариант — область, район, штат, страна…
Переименован — выводим новое имя.

Это не всегда верно.


Неизвестный город? Тут или ручной ввод разрешать

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

GUID в рамках всей базы и галочка «не нормализован» для ручного ввода, с последующей заменой на нормализованное значение когда админ до этого доберется. Но именно поэтому я больше сторонник решения с деградацией до страны, чем ручным вводом.

А вообще у каждого своя задача, но некоторый меинстрим существует, и под некритичные задачи что-то универсальное сделать можно. А дальше форкать…
О том, что в магазине нужно давать человеку максимальную свободу я с Вами согласен полностью.
GUID в рамках всей базы и галочка «не нормализован» для ручного ввода, с последующей заменой на нормализованное значение когда админ до этого доберется.

Вот именно поэтому и не надо использовать значения из GeoNames в качестве внутренних идентификаторов.


Но именно поэтому я больше сторонник решения с деградацией до страны, чем ручным вводом.

А так вы теряете пользовательские данные.

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

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


но в качестве дефолтной фишки вполне себе хорошо было бы иметь.

Хорошо иметь сервис, который умеет отвечать на геозапросы (причем совершенно разных видов), но вот откуда для него брать данные — мне не очень понятно. Предложенная ниже идея аггрегации выглядит наиболее интересной, но это большая задача.

Даже самые простые сайты, как правило, имеют список стран или городов на какой-нибудь из своих страниц – магазины хотят знать, куда доставлять товары; социальные сети хотят знать, откуда пользователь; и так далее.

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

Ну, выбор страны как правило – все-таки выпадающий список, даже если все остальное в свободном формате вводится. Это по моему опыту онлайн-шоппинга :)

А тут в Австралии так вообще — любят принудительное распознавание адреса. Если сайт не смог распознать (интерпретировать) адрес — пользователь не может продолжить. Таким образом, можно использовать подобный пакет без проблем (точнее даже — он уменьшит количество проблем :)
Ну, выбор страны как правило

Выбор страны можно сделать и по ISO.


А тут в Австралии так вообще — любят принудительное распознавание адреса. Если сайт не смог распознать (интерпретировать) адрес — пользователь не может продолжить.

Сочувствую. Фишка, однако же, в том, что Австралией мир не ограничивается.

Выбор – можно по ISO, а как пользователю отображать? :) А если сайт на 15 языках?

Про Австралию согласен, это так – пример. Про адреса в свободной форме, мне кажется, было бы полезным какой-то умный парсер адресов сделать, который умеет приводить адреса вроде «УЛ НИКИТИНА МОСКВА» в «ул. Никитина, Москва, 125000 Россия». Точно знаю, что некоторым проектам это нужно
Выбор – можно по ISO, а как пользователю отображать?

Речь в этой ветке идет о формате хранения, а не отображения.


Про адреса в свободной форме, мне кажется, было бы полезным какой-то умный парсер адресов сделать, который умеет приводить адреса вроде «УЛ НИКИТИНА МОСКВА» в «ул. Никитина, Москва, 125000 Россия». Точно знаю, что некоторым проектам это нужно

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


А парсеры такие есть, и на хабре их уже неоднократно упоминали (по крайней мере, в части России), но они, очевидно, языкоспецифичны.

Речь в этой ветке идет о формате хранения, а не отображения.
Нормализация представления нужна.
В 1С есть такой парсер адресов, и работает примерно так:
* Нормализует введённую строку (по классификатору адресов),
* в базу записывает 3 значения: Код по классификатору, нормализованная строка, строка «как есть» от пользователя (кстати, данные в КЛАДР хранятся в очень понятном формате ключ-значение).
Я эту сохранялку адресов пару раз подгонял под новые стандарты компании, потому знаю, как оно внутри устроено.
Нормализация представления нужна.

Всем и всегда?

Мне, как программисту — нужна. Почте России тоже нужна, у них нормализованные адреса на конверте писать надо. Налоговой тоже нужен нормализованный адрес. Так что, нормализация нужна часто.
Мне, как программисту — нужна.

Ну, будем честными, пользователя это не очень волнует.


Почте России тоже нужна, у них нормализованные адреса на конверте писать надо.

Эээ, правда? Я несколько лет шлю по России открытки с адресами в формате "как сегодня проснулся", еще и латиницей часто — и ничего, доходит.

Перемудрили с API, на мой взгляд. И почему Planet а не Earth? Планет то много, а земля одна, родная.
Planet — это класс, а Earth — это конкретный объект, одна из планет :)

Старался сделать все максимально рационально.

Объект Planet всегда один и тот же, и это всегда Земля:

    /**
     * @return string
     */
    public function getShortName()
    {
        return 'Earth';
    }

    /**
     * @return string
     */
    public function getLongName()
    {
        return 'The Blue Marble';
    }
Тогда логичнее было бы делать интерфейс планеты, и класс Земли который его имплементирует. Потому что обращаясь к Planet мы не выбираем Землю как планету, то есть это даже не фабрика, а просто Земля, которая названа Planet.
Да, я уже понял ошибку — неудачно выбрано название.

Как минимум, в примере надо сделать имя переменной $earth, чтобы логика соблюдалась :) И объявить, что другие планеты создавать (как перевести instantiate?) пока нельзя

Насчет интерфейсов — я пока склоняюсь (на GitHub код уже видно) к абстрактному классу для всех видов делений вместо интерфейсов для разных уровней делений. Есть класс Divisible (делимый), и пока что логика планеты, стран и штатов почти полностью совпадает — это решение пока похоже на оптимальное.
Впадать в ООП безумие мне кажется не стоит. Убрать планету вообще, назвать только входной класс Землей, без стандартных методов, типа имени и расположения. Это конечно забавно, но практического смысла не имеет.

А вот что реально было бы хорошо иметь, это разные источники данных, база/файлы/пусть даже интернет. Плюс сделать возможность кеширования тех данных что ты вытаскиваешь.

Поиск по координатам, как я понял устроен топорно и просто сравнивает значения? Это плохо. В некоторых базах есть возможность искать координату приблизительно, да и алгоритмы для поиска есть. Это конечно в пределах пхп работать будет не очень быстро, но хотя бы честно.

Вещи типа useShortNames не совсем понимаю зачем? Если можно возвращать в том же массиве оба варианта. Метод inflict мне тоже не понятен, почему это должна делать библиотека, которая используется как база данных?

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


Про это я уже думаю :)

Поиск по координатам, как я понял устроен топорно и просто сравнивает значения? Это плохо. В некоторых базах есть возможность искать координату приблизительно, да и алгоритмы для поиска есть. Это конечно в пределах пхп работать будет не очень быстро, но хотя бы честно.


Поиска пока нет вообще – он просто показан в примере. В современных БД есть гео-индексы. Как поступить тут и сохранить при этом маленький размер – я ещё думаю.

Вещи типа useShortNames не совсем понимаю зачем? Если можно возвращать в том же массиве оба варианта. Метод inflict мне тоже не понятен, почему это должна делать библиотека, которая используется как база данных?


Сначала так и было – два варианта. Ход мыслей дальше был такой: длинный (полный) вариант есть всегда, короткий иногда. Если возвращать оба поля и одно из них может быть пустым – разработчику придется на своей стороне (приложения) делать условия, а условия уже давно никто не любит.

То есть, если я могу попросить useShortNames(), то после этого я могу просто отображать одно поле, а пакет его выбирает по принципу best effort (старались как могли).

Inflict() – потому что больше половины сайтов до сих пор не умеют правильно склонять слова русского языка. Скажем, у нас есть какая-то лента или стена, и там есть подписи вроде: «Написал Иван 5 минут назад из Владивостока». Где хранить правильную форму имени города?

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


Так все и делают, включая меня – и это занимает много времени, требует установки дополнительных сервисов и так далее. Было бы очень классно иметь легкую, независимую (от внешних демонов) библиотеку, которая покрывает хотя бы все базовые требования.
Страны на разных языках есть из коробки в php-intl, хоть и с мудреным апи.
А в Symfony Intl есть удобная абстракция над большинством справочных материалов intl, причем все с использованием iso, а не велосипедия.
Спасибо — посмотрел и то, и другое. Но, IMHO, не хватает падежей (хотя это, конечно, только для русского языка актуально) и возможности выбрать менее формальное название. Причем, они это никогда не добавят, потому что в рамках их библиотек это лишнее.

Если сайт на, скажем, английском, и нужен просто список стран — то можно intl использовать.
Идея геопакета хороша, но мне кажется основная проблема здесь не как назвать классы и методы, а как максимально автоматично заскриптовать сбор данных и обновления для обновления этого пактета. Понятно, что список стран и крупных городов будет относительно статичным, но все что ниже обновляется очень активно, тем более в масштабах планеты.
Есть много много разных БД, и для разных целей и разных местностей подходят разные базы. Например для России есть регулярно обновляемый КЛАДР, но в нем только адреса, нет геокоординат, нет возможности искать по запросам типа «Кафе у Ашота», и она не переведена на другие языки. У других стран есть свои подобные базы, есть базы OpenStreet, но у всех чего-то не хватает.
В общем, было бы хорошо иметь такую аггрегированную базу всего, и пакет, который бы к с ней работал, но подозреваю, что в итоге получится что-то типа геосервисов Гугла или Яндекса, который одному человеку не потянуть.
Ага. Шаг первый — стандарт базы.
Шаг второй — реализации (данные) поверх стандарта.
Шаг третий — библиотеки поверх данных (например, города России на русском, штаты на английском, города мира на русском, города мира на всех языках, все города на всех языках в конце концов).
пользовались ли бы вы таким пакетом в своих приложениях? Или предпочли бы и дальше сами хранить географические данные?

Однозначно, да!
Тривиальная задача, особенно актуальна для разработки сайтов (небольших проектов), т.к. надоедает просто копировать дамп базы из проекта в проект, при этом нужно поддерживать актуальность списка стран, регионов/штатов, городов.
Так же надо учитывать тот факт, что в бд может хранится ненужные геоданные, например, про Африку, что не совсем нужно, когда проект не ориентирован на ее жителей.
Не смотрели в сторону Geocoder? Мне думается, он мог бы помочь в реализации вашего пакета.
Посмотрел только что — мне кажется это больше в сторону трансляции координат в адрес и наоборот, не увидел ничего про локализацию там (а у меня это основная цель).
Не мешало бы сразу предусмотреть некое деление данных на части. Я о том, что если мой магазин работает только с могилевской областью Беларуси, то мне не хотелось бы в своей БД хранить данные об остальных областях, не говоря уже о всех населенных пунктах, областях, регионах, округах,… более чем двух сотен стран мира.

То же касается и языков. Далеко не каждому сайту нужно более 3-4 языков. Имхо.
Да — я сразу это во внимание беру

1) Сами данные будут подгружаться в режиме ленивой загрузи
2) Если базы станут большими, я думаю детализированные базы по странам можно будет выделить в отдельные репозитории. Тогда в начале разработчику просто 2+ пакета надо будет устанавливать — основной и необходимая база, набор языков
Очень интересная идея. Я сам на днях думал о чём-то похожем. Но думал больше с точки зрения того, где брать сами данные? Вот где взять в удобном формате список стран (ну это легко)? А может для какого-то проекта потребуется список всех фильмов, музыкальных исполнителей и т.п. Хотелось бы найти такой ресурс, где всё это доступно в открытом виде и машиночитаемом формате. Есть ли нечто подобное?
Sign up to leave a comment.

Articles