LINUX.ORG.RU

Java, PHP, Python. Что выбрать?


0

0

Ситуация такая. Я не профессиональный программист (я картограф). Несколько лет назад занялся программированием для картографических целей. Начал обучение с Fortran, затем перешел на C++. После окончания университета интернет и книжные магазины привели меня к «самому замечательному и современному решению» - C# и Ms Visual Studio (на освоение этого я потратил больше года). В то время я почти не догадывался, что в мире есть еще кто-то кроме Microsoft и ESRI (это крупнейший производитель картографичеких приложений). На C# мы реализовали крупный университетский проект для себя - настольное приложение WinForms, после чего на ASP.NET написали серверный вариант. У нас появилась возможность немного заработать на приложении. Т.к. все должно было передано официально, начали считать сколько стоит ПО, используемое нами - оказалось более 3 000 000 руб. Программа так и осталась для внутреннего пользования. Так я познакомился с GNU/Linux, Emacs, С, бесчисленными свободными ГИС библиотеками.

Мы решили портировать наше приложение на GNU/Linux, фактически переписать его с нуля. На сегодняшний день у нас готово ядро приложения (написано на C и shell), теперь приступаем к разработке сайта, позволяющего работать с ядром.

На этот раз решил более серьезно подойти к вопросу выбора технологии. Я ограничился на Java, PHP, Python, т.к. только для этих языков есть готовые решения для реализации WEB картографии (если говорить ОЧЕНЬ грубо, то что-то типа движка для Google Maps).

PHP синтаксис и идеология мне не близки, но в интернете есть решения для почти всех проблем, куча движков и т.п. Насколько я понимаю обслуживать код PHP довольно сложно. Java, насколько я понимаю, старший брат C#. Мне сложно сказать что-то о недостатках. В отличии от предыдущих, о Python я знаю только по статьям. Судя по отзывам, это, возможно, главный претендент. Код действительно выглядит симпатично, также радует, что на Python написано много в области Open Source GIS, что пригодится в последующем.

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

Ответ на: комментарий от SV0L0CH

> А мне вот интересно знать что отпугивает от JS

На вскидку. ЧТо сразу в голову пришло.

1. ООП подход в JS ужасен. Только не надо говорить, что ООП не нужен, у каждого свои потребности.

2. Эелементарно нельзя установить дефолтное значение переменной при объявление функции. Решаемо, но ведь неудобно.

3. Вся это модель прототайпов уныла и некрасива.

mobile
()
Ответ на: комментарий от mobile

Ну вот, теперь ясно что плюсы головного мозга. А ведь Smalltalk который считается классикой использует похожий подход. Аналогично Objective-C. А отождествлять плюсы и ООП довольно глупо. Тепрь код смотреть не интересно.

SV0L0CH
()
Ответ на: комментарий от SV0L0CH

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

mobile
()
Ответ на: комментарий от mobile

Ну я правильно понял что JS плох тем что не похож на C++?

то не нужно, се не нужно

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

SV0L0CH
()
Ответ на: комментарий от SV0L0CH

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

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

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

mobile
()
Ответ на: комментарий от mobile

>Он плох тем, что он неудобный, с плохочитаемым кодом язык, в котором многие вещи достигаются только хаками и не очевидны.

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

SV0L0CH
()
Ответ на: комментарий от SV0L0CH

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

mobile
()
Ответ на: комментарий от mobile

>Я настоятельно рекомендую попробовать что самому написать

Идеи есть? Хочу для http://fprog.ru/ статью про JS написать но не могу придумать тему.

SV0L0CH
()
Ответ на: комментарий от anonymous

>Когда понос в голове, это действительно не важно - главное просраться.
Интересная метафора. Я понимаю что ты пытался оскорбить меня глупышка :) Но в контексте оно звучит как руби - понос, а «просраться» - избавиться от руби. В принципе да, я согласен что его лучше даже не знать :)

которое я проводил

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

что python 3.1 все еще заметно медленнее 2.6 на 32бит и приближается к нему на 64бит

На x86 не знаю, ибо давно не юзал, а на x86_64 всё заметно быстрее чем в 2.6.

О «далеко впереди» речь даже и не идет

Идёт, и не только в ньюс-группе, малыш :)

давно бы трубили в трубы

Не руби слоу, а ты :)

Попросту, ты соврал

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

Зачем позориться

Да, ты выбрал верный путь - быть анонимусом чтобы не позориться. Правильно сделал :)

По традиции - пруф или не было

http://diveintopython3.org/
Вот тебе книжка, очень популярная, знаешь ли.
http://jessenoller.com/2010/01/06/unladen-swallow-python-3s-best-feature/
Вот кстати, ньюс о US и Py3k.
http://mail.python.org/pipermail/python-porting/
Вот ньюсгруппа о портинге.
http://regebro.wordpress.com/2009/10/10/time-for-python-3/
«Трубим».
http://www.linuxjournal.com/content/python-python-python-aka-python-3
Одна из тысяч wiki-значимых статей о портинге на Py3k. Что как-бы намекает.
В общем, думаю хватит. Анонимуса только бан подсети излечит, как говорится.

tia
()
Ответ на: комментарий от KRoN73

2.6 не быстрее, чем 2.5

А я раньше помнится чейнжлог смотрел и видел профиты. Точно помню что они ускорили циклы и работу со строчками.

У Питона с этим фигово достаточно.

Чито? python3 и python2. Здесь даже система слотов не так нужна. Если не ошибаюсь, у них нет конфликтных файлов.

Это даже не смешно. Надеюсь, это была неудчаная шутка?

Ты просто, видимо, не понял что я хочу сказать. Это один из примеров неоспоримой оптимизации. Не веришь мне или считаешь что шутка, то смотри:

iorlas@lastangel:~$ time python3 -c "for i in range(10000000): pass"
real   0m1.371s
user   0m1.340s
sys   0m0.030s
iorlas@lastangel:~$ time python2 -c "for i in range(10000000): pass"
real   0m2.632s
user   0m1.770s
sys   0m0.260s
iorlas@lastangel:~$ time python2 -c "for i in xrange(10000000): pass"
real   0m1.338s
user   0m1.170s
sys   0m0.000s
После 2х «прокруток» Py3k выдал 1.139, а python2 с xrange колеблился от 1.300 до 1.800.

tia
()
Ответ на: комментарий от tia

http://shootout.alioth.debian.org/u32q/benchmark.php?test=all&lang=python&lan...

В большинстве тестов Python3 успупает 2.6.4

После 2х «прокруток» Py3k выдал 1.139, а python2 с xrange колеблился от 1.300 до 1.800


Да, всё-таки, это грустно. (Не результат Питона, а то, о чём я говорил ранее)

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

В большинстве тестов Python3 успупает 2.6.4

Быстрейшие программы, которые были написаны с оптимизацией под конкретную платформу. Я хочу это подчеркнуть, ибо ты, видимо, думаешь что всё на 2.6 оптимизировано под 2.6, но оно не так. В больших и сложных модулях на пайтоне до сих пор используются медленные имплементации функций, таких как range.
В данном тесте были взяты(написаны) сферические куски кода в вакууме. При этом не в пользу Py3k, ибо были сконвертированы через утилиту 2to3, что говорит о том что тест не чист.
А так я проверил код binary-trees и... Оно работает быстрее чем у автора статей. Что Py2, что Py3k. При этом, Py3k обгоняет Py2:

iorlas@lastangel:~$ time python2 test.py 12
stretch tree of depth 13	 check: -1
8192	 trees of depth 4	 check: -8192
2048	 trees of depth 6	 check: -2048
512	 trees of depth 8	 check: -512
128	 trees of depth 10	 check: -128
32	 trees of depth 12	 check: -32
long lived tree of depth 12	 check: -1

real	0m1.374s
user	0m1.840s
sys	0m0.090s
iorlas@lastangel:~$ time python3 test.py 12
stretch tree of depth 13	 check: -1
8192	 trees of depth 4	 check: -8192
2048	 trees of depth 6	 check: -2048
512	 trees of depth 8	 check: -512
128	 trees of depth 10	 check: -128
32	 trees of depth 12	 check: -32
long lived tree of depth 12	 check: -1

real	0m1.266s
user	0m2.000s
sys	0m0.040s
Проверил раз 10. Да, иногда Py2 перегоняет, но то только случайная погрешность. В большинстве случаев Py3k выигрывает.
Что ещё может хочешь сказать? Или может я такой кривой и linux у меня кривой?

Да, всё-таки, это грустно

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

tia
()
Ответ на: комментарий от mobile

> JS ужасен

Язык хорош! Проблема же в том, что школота и студенты вроде тебя не удосуживаются ознакомиться с языком!

anonymous
()
Ответ на: комментарий от anonymous

> Если вам нравится забивать гвозди микроскопом, то и дескрипторы для разработки веб-сайтов вам, несомненно, понадобятся.

Сайты становятся всё сложнее и сложнее. Почему бы некоторые вещи не скрыть и упростить в использовании?

Какие свойства? Объектные? Что, в PHP нет ООП?

Свойства (декоратор property) - это синтаксический сахар, связанный с дескрипторами, но всё же. Писать на каждый чих заранее getter/setter тоже не хочется.

Это эфемерное понятие. Вот Python, он динамичный? А ассемблер? А что динамичнее, пайтон или ассемблер?

Не очень уж эфемерное. Не знаю как сейчас, но раньше в php рантайме добавить метод было сложно или даже невозможно.

PHP очень логичен.

var_dump(array('123' => 'Hello', 123 => 'World'));

Логично, но лично мне такая логика не нравится. Вообще это автоматическое преобразование типов - сплошная морока.

Пространства имён. Тут я уже «плаваю», но вроде добавили в 5.3. ЕМНИП разделителем является \. Это когда уже вся стандартная библиотека висит в одном огромном namespace. Ясное дело, эволюция, развитие языка и всё такое, но тут уже на любителя, каждый выбирает своё.

AlexKiriukha ★★★★
()
Ответ на: комментарий от AlexKiriukha

>Писать на каждый чих заранее getter/setter тоже не хочется.

Зачем? PHP же динамический язык. Там и __call есть, и __set/__get.

Вообще это автоматическое преобразование типов - сплошная морока.


Вот тут - согласен. В PHP это источник маскирования потенциальных ошибок.

Пространства имён. Тут я уже «плаваю», но вроде добавили в 5.3.


Полная попа. Лучше бы не добавляли :) Я пока так и остаюсь на своей эмуляции оной.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

>и ещё кто любит дескрипторы

Они появились в php?

свойства, динамичность

А что тут не так у PHP? :)

Как создать класс в рантайме? Функция - не first object class или как это правильно называется. Т.е. я не могу в переменной присвоить ту или иную функцию. Одним из следствий получается усложнённая реализация декораторов (честно говоря не пробовал их делать в php) и вообще понятия callable. Или, например, у меня в классе есть member-объект. Как его присвоить не в конструкторе, а описании класса? Есть ли генераторы?

Возможно в 5.3 это всё уже есть или не попросту не нужно. Но когда привыкаешь к такой простоте и логичности, то писать на php просто не хочется. Можно, но не хочется.

AlexKiriukha ★★★★
()
Ответ на: комментарий от AlexKiriukha

>Они появились в php?

Я не знаю, что скрывается под этим термином :) Знаю дескрипторы сегментов, файловые дескрипторы, html-дескрипторы. Но ты, полагаю, что-то другое имеешь в виду.

Как создать класс в рантайме?


eval. Я нередко генерирую их :)

Т.е. я не могу в переменной присвоить ту или иную функцию


$f = «my_cool_func»;

Одним из следствий получается усложнённая реализация декораторов


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

и вообще понятия callable


?

Или, например, у меня в классе есть member-объект. Как его присвоить не в конструкторе, а описании класса?


Давай лучше с практическими задачами, а не абстрактными :)

Но когда привыкаешь к такой простоте и логичности, то писать на php просто не хочется. Можно, но не хочется.


Мне кажется, что дело не в языке. А в привычке к инструменту. А язык и возможности тут не при чём. На Haskell или Erlang можно многое сделать приятно и красиво. Но мне просто не хочется это делать. Можно, но не хочется. Но я от этого не начинаю на форумах писать, что Haskell - недоязык :)

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> Зачем? PHP же динамический язык. Там и __call есть, и __set/__get.

Это немного не то. Точнее вообще не то. А как мне узнать есть ли метод, который будет отрабатываться через __call. К тому же если получу список методов объекта, то явно там таких не будет. И ещё из плохих вещей вспомнилось практически не использование исключений стандартной библиотекой. С ними как-то проще и логичнее. Естественно, что это обусловлено способом развития языка и никто не хочет сильно ломать обратную совместимость, но ведь хочется и вперёд идти. Поэтому часто получается, что используется сам язык и очень мало его библиотек, остальное переписывается под себя.

AlexKiriukha ★★★★
()
Ответ на: комментарий от AlexKiriukha

>А как мне узнать есть ли метод, который будет отрабатываться через __call

Написать соответствующий метод. Но, опять же, зачем?

И ещё из плохих вещей вспомнилось практически не использование исключений стандартной библиотекой.


Но перехватывается, ЕМНИП, почти всё при желании. Тут не могу сказать уверенно ни «за», ни «против», исключения не практикую, обрабатываю ошибки по коду возврата.

Поэтому часто получается, что используется сам язык и очень мало его библиотек


Ну, сложно сказать. Вот в моём фреймворке сторонних решений используется:
$ du -hs /var/www/bors/bors-third-party
106M   /var/www/bors/bors-third-party

$ find /var/www/bors/bors-third-party -name '*.php'|wc -l
1939

:)

В том же Gentoo-репозитории разных PHP-библиотек:
eix -cA dev-php
...
Found 334 matches


Конечно, это меньше, чем:
$ eix -cA dev-python
...
Found 659 matches.

но нельзя говорить, что библиотеками не пользуются :)

...

В общем, повторюсь, дело тут отнюдь не в PHP :)

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> Я не знаю, что скрывается под этим термином :) Знаю дескрипторы сегментов, файловые дескрипторы, html-дескрипторы. Но ты, полагаю, что-то другое имеешь в виду.

Да, другое. В общем смысле это класс, геттеры и сеттеры в котором переопределены. Но при этом с точки зрения кода, который использует дескрипторы, всё выглядит просто как присваивание, получение значения переменной или её удаление. Но при этом полностью контролируется программистом. В чём-то рядом с __get/__set, но просто значительно проще и логичнее. Фактически через __get и __set можно реализовать схожую функциональность, просто они могут быть большими.

eval. Я нередко генерирую их :)

Eval - это же немного не то. Фактически нужно генерировать код в строку, а потом её eval'ить. В пайтоне есть метаклассы. Я их полностью ещё не освоил, но это просто что-то. Даже сам класс - это объект со своими методами и свойствами. Динамический объект.

$f = «my_cool_func»;

Насколько я вижу тут присвоение строки переменной. В некоторых функциях эта строка может рассматриваться как имя функции, но фактически - это строка, а не callable. Для примера можно посмотреть как передаются функции в JS, там это вообще просто и естественно :-)

Давай лучше с практическими задачами, а не абстрактными :)

[code=php]

class SomeClass { function __construct() { print «SomeClass constructor\n»; } }

class Another { var $sc = new SomeClass(); function __construct() { print «Another constructor\n»; } }

$a = new Another();

[/code]

Мне кажется, что дело не в языке. А в привычке к инструменту. А язык и возможности тут не при чём.

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

AlexKiriukha ★★★★
()
Ответ на: комментарий от KRoN73

> Написать соответствующий метод. Но, опять же, зачем?

Удобно же. Сейчас попробую проверить как узнать как определить есть ли метод если он обрабатывается в __call. Боюсь это будет что-то типа «вызвать метод, если ошибка - значит его нету».

Но перехватывается, ЕМНИП, почти всё при желании. Тут не могу сказать уверенно ни «за», ни «против», исключения не практикую, обрабатываю ошибки по коду возврата.

Видимо тут уже разница в привычке и подходах. Мне кажется исключения во многих случаях удобнее.

AlexKiriukha ★★★★
()
Ответ на: комментарий от AlexKiriukha

В чём-то рядом с __get/__set, но просто значительно проще и логичнее.

Возможно. Но я предпочитаю напрямую свойства не дёргать ни в каком виде, а обращаться через функцию. А в динамичских языках (что PHP, что Python) чтобы не извращаться обвязками геттеров/сеттеров использую их фишки, типа PHP-шного __call().

Eval - это же немного не то. Фактически нужно генерировать код в строку, а потом её eval'ить.

Да. Но в нормальной системе вряд ли таким придётся заниматься часто :)

Насколько я вижу тут присвоение строки переменной. В некоторых функциях эта строка может рассматриваться как имя функции, но фактически - это строка, а не callable.

В PHP все строки - callable ;)

$f = «my_func»; $result = $f($args);

Для примера можно посмотреть как передаются функции в JS, там это вообще просто и естественно :-)

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

class Another { var $sc = new SomeClass(); function __construct() { print «Another constructor\n»; } }
$a = new Another();

Всё равно я не понимаю твоего вопроса.

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

class another_class
{
    // ...
    function auto_objects() { return array('some' => 'some_class(some_id)'); }
}

Ещё как причём. Язык - это же ещё и идиомы. А они часто и формируются языком.

Нет, дело в первую очередь в практике и навыках. PHP не настолько отличается от Python или Ruby, чтобы вопрос синтаксиса языка играл решающую роль. Да, в целом он, безусловно, уступает, но не до такой степени, чтобы считать работу на нём заведомо неэффективной :)

Мне кажется именно поэтому и нужно изучать разные по типу языки.

Безусловно. Правда, я бы отнёс все три перечисленных выше языка к одному типу. И к очень близким представителям :) Другие типы - это LISP, Forth, Haskell, Erlang, APL, Brainfuck :)

KRoN73 ★★★★★
()
Ответ на: комментарий от AlexKiriukha

>Удобно же. Сейчас попробую проверить как узнать как определить есть ли метод если он обрабатывается в __call. Боюсь это будет что-то типа «вызвать метод, если ошибка - значит его нету».

У меня во фреймворке так.

Есть обычные методы.

Есть функция __call(), которая в PHP вызывается при отсутствии метода, она проверяет ассоциативный массив свойств класса (раньше проверяла прямо свойства, но это оказалось немного медленнее и не работало в Quercus, да и с отдельным массивом это просто логичнее), если всё ок - возвращает или устанавливает значение. Если такого нет, делает ещё пару проверок на тему автоматических методов разной сложности (auto_objects в примере выше, например) и, в случае провала и там - выбрасывает ошибку «method not found».

Да, для написания такого метогда мне потребовалось задействовать десятка полтора-два строк. Пять лет назад :) С тех пор использую прозрачно, унифицированно и не задумываясь о внутреннем представлении. Когда, например, переписывал использование со штатных properties на массив, пришлось поменять лишь несколько строк в самом методе __call() и нигде ничего не пришлось менять в остальном коде.

Дополнительный бонус - если мне требуется поднять скорость в уже написанном и отлаженном классе, я просто прогоняю файл класса через препроцессор и он вставляет туда полный комплект уже жёстко прописанных геттеров/сеттеров. Понятно, что «снаружи» в использовании этого класса уже ничего не меняется.

Видимо тут уже разница в привычке и подходах. Мне кажется исключения во многих случаях удобнее.


Удобнее и правильнее. Но в моих проектах обработка исключений, как раз, смысла не имеет. Специфика Web-разработки :)

А вот в том же L2J, скажем, в сервере MMORPG на Java - там да, без исключений ни один чих не делался :) Опять же, иная специфика...

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

>Удобнее и правильнее. Но в моих проектах обработка исключений, как раз, смысла не имеет. Специфика Web-разработки :)

Ну не знаю как у вас в веб-разработке, а у нас без исключений никак. Они действительно удобны и полезны.

anonymous
()
Ответ на: комментарий от AndreyKl

>Удивил.

Ну так а где там может быть нужна обработка исключений? Всё равно, вся модификация данных - атомарная, в случае любой ошибки - пользователю выводим сообщение «извините» и логгируем проблему. Больше обычно ничего не предпринимается. Что я ещё упускаю? :)

KRoN73 ★★★★★
()
Ответ на: комментарий от mirocumo

Да, поэтому. Серьёзные php-разработчики уходят от php, и в индустрию вливаются студенты, которые на каждый чих гуглят и постят вопросы на форумах, тем и двигая php на третье место в рейтинге.

И так - из года в год, из года в год. Он видимо как русские в том анекдоте - долго прощаются но никак не уходят :)

bibi
()
Ответ на: комментарий от KRoN73

> В PHP все строки - callable ;)

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

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

PHP не настолько отличается от Python или Ruby, чтобы вопрос синтаксиса языка играл решающую роль. Да, в целом он, безусловно, уступает, но не до такой степени, чтобы считать работу на нём заведомо неэффективной

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

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

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

AlexKiriukha ★★★★
()
Ответ на: комментарий от AlexKiriukha

>> В PHP все строки - callable ;)

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

Когда уже випилят это наследие перла? :-/

Даже удивляюсь как «кодящие обезянки» умудряются на этом писать работающие приложения. Загадка природы, однако.

SV0L0CH
()
Ответ на: комментарий от SV0L0CH

> Когда уже випилят это наследие перла? :-/

Даже удивляюсь как «кодящие обезянки» умудряются на этом писать работающие приложения. Загадка природы, однако.

С пёрлом не знаком и похоже сейчас уже нет смысла его осваивать. Просто не могу сообразить как правильно донести понятие callable и передать ощущение, что простой очевидный код - это хорошо и у разных языков разная степень «очевидности» (или по крайней мере принято писать с этой степенью, правда это уже зависит от писателя кода).

AlexKiriukha ★★★★
()
Ответ на: комментарий от KRoN73

Так не удобно ж ни фига!? Или я чего-то недопонимаю?

вот мой обычный код:


try {
  switch($_REQUEST['action']) {
  case 'add_item_with_image':
    checkPermission($user, 'add_item_with_image'); //could throw exception
    checkFileSize($_FILES['myfile']['filesize']); //could throw exception
    checkFormat($_FILES['myfile']['tmpname']); //could throw exception
    $item = new Item();
    $item->setFile($_FILES['myfile']['tmpname']); //could trow exception
    $q = "INSERT INTO ...";
    $db->query($q); // could trhow exception
  break;
  default:
    throw new Exception("No such action");
  }

  echo json_encode(array('status' => 'ok', 'message' => 'all right, man! item just added!"));
} catch(Exception $e) {
  echo json_encode(array('status' => 'error', 'message' => "hello, man! Bad news - your operation was fail. Reason is: {$e->getMessage()}"));
  log->log("error: {$e->getMessage()}");
}

Итого 6 потенциальных исключительных ситуаций. Покажи, как ты обрабатываешь это без исключений?

AndreyKl ★★★★★
()
Ответ на: комментарий от boombick

> PHP 5.3 Я писал у себя про замыкания: http://boombick.org/blog/posts/87

Появилось, но нужно явно перечислять переменные из parent scope с помощью use (что, вобщем-то, может и хорошо для наглядности).

Возникли следующие вопросы:

[code]

$f = function() { print «Whoooaaa!\n»; }; print gettype($f);

object

print gettype(gettype($f));

string

print gettype(get_class($f));

string

[/code]

Выходит gettype возвращает не тип, а строковое название типа? get_class - тоже название класса? Или меня php окончательно запутал :-)

P.S. И ещё стиль схожих идентификаторов: get_class и gettype. Какой-то бардак.

AlexKiriukha ★★★★
()
Ответ на: комментарий от AndreyKl

>$item->setFile($_FILES['myfile']['tmpname']); //could trow exception

$q = «INSERT INTO ...»;


Извините, но это как раз те примеры, за которые не любят PHP и программистов на нём :D

...

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

KRoN73 ★★★★★
()
Ответ на: комментарий от AlexKiriukha

>И ещё стиль схожих идентификаторов: get_class и gettype. Какой-то бардак.

Выше это я отмечал как один из недостатков :) Смешение стилей, смешение подхода к порядку аргументов... Очень хорошо чувствуется, что язык прошёл огромный путь в своём развитии ;)

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

Это не реальный код, набросал на скорую руку, но всё же, исключительно чтобы побаловать твоё чувство прекрасного:

try { 
  switch($_REQUEST['action']) { 
  case 'add_item_with_image': 
    checkPermission($user, 'add_item_with_image'); //could throw exception 
    checkFileSize($_FILES['myfile']['filesize']); //could throw exception 
    checkFormat($_FILES['myfile']['tmpname']); //could throw exception 
    $item = new Item(); 
    $item->setFile($_FILES['myfile']['tmpname']); //could throw exception 
    $item->name = $_REQUEST['name']; // could throw exception
    $item->validate(); // could throw exception
    $itemDao->insert($item); // could throw exception
  break; 
  default: 
    throw new Exception("No such action"); 
  } 
 
  echo json_encode(array('status' => 'ok', 'message' => "all right, man! item just added!")); 
} catch(Exception $e) { 
  echo json_encode(array('status' => 'error', 'message' => "hello, man! Bad news - your operation was fail. Reason is: {$e->getMessage()}")); 
  log->log("error: {$e->getMessage()}"); 
} 

Итого 8 исключительных ситуаций, Покажи пожалуйста, как ты обрабатываешь это без исключений?

AndreyKl ★★★★★
()
Ответ на: комментарий от AndreyKl

Покажи пожалуйста, как ты обрабатываешь это без исключений?

switch($_REQUEST['action']) ... throw new Exception(«No such action»);

Зачем тут исключение? При корректном юзвере все action будут правильными по определению, а хакеру не жалко и 404-ю ошибку показать :)

Опять же, я в своём фреймворке не занимаюсь ручным switch-ированием action'ов. В шаблоне что-то типа:

{form act="add"}
...
{/form}

В классе-обработчике:


function on_action_add($data) { ... }

// Аплоад файла? Тоже автоматизирован:
function on_my_file_upload($path) { ... }

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

if(!file_exists($some))
    return bors_message(ec('Извините, ошибка загрузки файла'));

$new_file = my_file::register($some);
return go($new_file->url());

и т.д.

Получается намного менее громоздко, чем сочетания try/catch/$_FILES['myfile']['tmpname']/$_POST/$_REQUEST :)

Глобальные переменные, кстати, вообще - глобальное зло.

Остаётся только спорный момент:

    checkPermission($user, 'add_item_with_image'); //could throw exception  
    checkFileSize($_FILES['myfile']['filesize']); //could throw exception  
    checkFormat($_FILES['myfile']['tmpname']); //could throw exception  

Да, у меня тут будет три if'а. Хотя бы потому, что мне чаще всего нужно не тупо выбросить ошибку, а ещё достаточно детально обработать. И тут if() получается менее громоздким, чем try...catch на каждый чих.

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

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

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

switch($_REQUEST['action']) ... throw new Exception(«No such action»);

Зачем тут исключение? При корректном юзвере все action будут правильными по определению, а хакеру не жалко и 404-ю ошибку показать :)

Хм, затем что так проще в текущем контексте. При корректном пользователе все action будут правильными по определению, а хакеру не жалко и json выдать, чтобы лишний раз не заморачиваться.

В классе-обработчике: function on_action_add($data) { ... } function on_my_file_upload($path) { ... }

В принципе с этим ясно, но ты никуда не уходишь от if. Хотя если оно никогда не проверяется руками, то и фиг с ним, тут я согласен ежели так.

if(!file_exists($some)) return bors_message(ec('Извините, ошибка загрузки файла')); $new_file = my_file::register($some); return go($new_file->url());

Получается намного менее громоздко, чем сочетания try/catch/$_FILES['myfile']['tmpname']/$_POST/$_REQUEST :)

Как по мне, так в $some нужно сначала положить что-то, так что от $_FILES['myfile'] ты никуда не уйдёшь. Вопрос лишь в том, куда ты это спрячешь. Так что не аргумент. Как по мне, так у тебя получается более громоздко потому что сначала надо проверить if(!file_exists($some)), а потом ещё и там где ты проверяешь то, что вернула функция, и так для каждой функции. А у меня всё ловится в catch. У меня проще и лаконичней. Возникает проблема если ты хочешь на каждую ошибку хитрый ответ отдавать - но она и у тебя никуда не девается на самом деле. А в жизни 2(максимум 3) типа ошибок хватает с головой, что вполне великолепно обрабатывается через try/catch. Единственное, в кривобоком php finally нет (уж могли бы добавить..), ну да кому сейчас легко, как говорится се ля ви. Но и у тебя проблема с finally никуда не уходит, если надо освободить ресурс в случае неудачи (например, удалить копию файла), ты продублируешь код либо напишешь хитрый if. Что хуже - хитрый if или дублирование кода - не знаю, но вот finally меня бы выручил в этой ситуации.

Глобальные переменные, кстати, вообще - глобальное зло.

Кстати, да. Только к чему ты это?

Да, у меня тут будет три if'а. Хотя бы потому, что мне чаще всего нужно не тупо выбросить ошибку, а ещё достаточно детально обработать. И тут if() получается менее громоздким, чем try...catch на каждый чих.

try - один, а catch для каждого типа. Вполне себе экономия. Небольшая, конечно, но выглядит ясно и красиво, в отличие от ифов:


try {
  checkPermission($user, 'add_item_with_image');
  checkFileSize($_FILES['myfile']['filesize']);
  checkFormat($_FILES['myfile']['tmpname']);
} catch(PermissionException $e) {
  die("Ай-яй-яй, как нехорошо когда маленький мальчик пытатается сделать бяку! Всё расскажу администратору!");
} catch(Exception $e) {
  echo json_encode('status'=>'error', 'message'=>"Не судьба, братан, {$e->getMessage()}.");
  exit();
}

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

Комментарии были исключительно для того чтобы тебе было удобно читать. Это идиома - если checkPermission - то выбрасываем исключение, если hasPermission - то возвращаем true/false (так же с checkFormat и isValidFormat например и т.д.).

Но у меня под моими задачами с ними получается сложнее, непрозрачнее и неявнее.

С этим спорить не возьмусь, тебе конечно видно что там конкретно у тебя делается гораздо лучше чем мне. Это бесспорно в большинстве случаев я думаю.

AndreyKl ★★★★★
()
Ответ на: комментарий от KRoN73

Ну и ты не сказал, как ты обрабатываешь что-то вроде

try {
  $item->name = @$_REQUEST['name'];
  $item->lastname = @$_REQUEST['lastname'];
  $item->param1 = @$_REQUEST['param1'];
  $item->param2 = @$_REQUEST['param2'];
  $itemDao->insert($item);
} catch(Exception $e) {
  //...
}

?

У меня по задумке присваивание выполняется через __set в котором выполняется валидация посредством функций-валидаторов доступных по имени свойства в ассоциативном массиве. В случае недопустимого значения, выкидываем исключение.

AndreyKl ★★★★★
()
Ответ на: комментарий от AndreyKl

Как по мне, так в $some нужно сначала положить что-то, так что от $_FILES['myfile'] ты никуда не уйдёшь

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

Только к чему ты это?

К использованию $_FILES :)

...

По остальному спорить не буду, каждый делает так, как ему удобнее :)

KRoN73 ★★★★★
()
Ответ на: комментарий от AndreyKl

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

У меня этим тоже фреймворк занимается:

    function check_value_conditions()
    {
        return array(
            'title'         => ec("!=''|Название места не может быть пустым"),
            'city_id'       => ec("!=''|Вы не указали город"),
            'country_id'    => ec("!=0|Вы не указали страну"),
        );
    }

Механизм проверки и обработка ошибки сокрыты, так что, кстати, захоти я переписать систему на использование исключений - 3/4 всего кода этого изменения даже не заметит :)

$item->lastname = @$_REQUEST['lastname']; 

Ну и я писал ранее, что я не использую properties. Ибо механизм доступа к данным унифицирован, генерируемые данные встречаются не реже, чем статические, и обращаться к функциям через __set()/__get() дороже и менее прозоачно, чем к свойствам через функции и __call().

Т.е. у меня будет $item->set_last_name($data['last_name'], true);

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

Но такая форма записи (с передачей данных от юзера) - редкость. Я данные пишу обычно системные:

function views_inc()
{
    $this->set_counter($this->counter() + 1, true);
}

Если пользовательские, то почти всегда их записью занимается фреймворк:

my/class.php:

class my_class extends base_object_db
{
    function main_table() { return 'table_name'; }
    function main_table_fields() { return array('id', 'title', 'decription'; }
}

some/edit.php:

class some_edit extends my_admin_page
{
    // В принципе, всё это не обязательно. И, наоборот, бывают сложные расширения...
    function config_class() { return 'my_new_admin_config'; }
}

some/edit.html:

{form class="my_class" id=$this->id()}
Заголовок: {input name="title"}<br/>
Описание: {textarea name="description"}<br/>
{submit value="поехали!"}
{/form}

Ну и ещё привязка к URL. Или автопривязка прямо в классе, класс будет искаться в каталогах классов по пути относительно корня сайта, или прямая привязка regexp'а URL'а к имени класса в отдельном файле.

Генератор форм выдаст форму (для не существующих объектов - пустую, для имеющихся - загрузит значения), после сабмита процессом займётся обработчик POST'а, и или создаст новый объект, или сохранит изменения. Естественно, он проверит и наличие доступа, и валидность значений, вызовет все дополнительные методы, если обработка потребуется более расширенная, чем стандартная. Потом сохранит результат и перейдёт к администрированию сохранённого объекта (понятно, что и это тоже настраивается).

На практике обычно чуть сложнее. Скажем, вместо my_class я администрирую класс my_admin_class extends my_class, куда складываю все методы по администрированию, включая проверки на валидность и т.п. Т.е. к собственно классу объекта доступа нет ни у кого, кроме чисто системных вызовов. От этого и секьюрность лучше, и класс в основной работе не таскает с собой лишних потрохов, жрущих ресурсы.

...

Вся эта иерархия сейчас генерится кодогенератором. Т.е. я леплю, например, такое (формат самопальный) описание объекта (реальный пример):

class: aviaport_directory_publisher
title: Авиационное издание
titles: Авиационные издания
admin_class: aviaport_admin_directory_publisher
directory_publishers:
    int     id++!
    int     type_id!        //  Тип издание - выбор из перечня: Журнал, Газета, Бюллетень
    string  title           //  Название издания
    text    description     //  Аннотация:
    int     format_id       //  Формат: выбор из перечня: A4, A3
    int     copies          //  Тираж (экз.)
    int     size            //  Объем стр.
    string  www             //  WWW
    string  periodicity     //  Регулярность выхода
    string  distribution    //  Способ распространения
    string  geography       //  География распространения
    int     birthday_year   //  Год основания
    text    history         //  Краткая история создания
    text    rubrics         //  Рубрики
    text    chief           //  Главный редактор

    int     create_time!
    int     modify_time!
    int     owner_id
    int     last_editor_id

Натравливаю препроцессор и тот генерит кучку файлов-шаблонов: - SQL-код по генерации нужной таблицы (с комментариями полей) - Собственно основной файл класса - Файл админ-класса объекта - Файл класса редактора и HTML-шаблон к нему - Файл класса и HTML-шаблон админки для управления всеми объектами этого типа

Т.е. автономный отдельный раздел сайта по описанию полей нужных объектов организуется за считанные минуты :) Понятно, что потом приходит вопрос оформления, дизайна, объект этот часто связан с другими объектами, обладает особыми моментами в поведении и т.п... Вот на это и уходит 99% всего времени разработки...

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

реальный пример

Да, в работе оно уже лежит на страницах, типа http://www.aviaport.ru/directory/publishers/31/

Как раз на прошлой неделе закоммитил. Правда, в навигацию сайта ещё не включено, шеф тестирует и вносит пожелания :)

Плюс пришлось делать не новую БД, а организовывать привязку к уже имеющейся в таком духе:

   function main_table_fields()
    {
        return array(
            'id' => 'ID',
            'type_id' => 'category',
            'orientation_id' => 'orientation',
            'title' => 'name|aviaport_old_denormalize',
            'description',
            'about' => 'annotation|aviaport_old_denormalize',
//          'format_id' => 'format',
            'format',
            'copies' => 'circulation',
            'size' => 'num_of_columns',
            'periodicity' => 'period',
            'distribution',
//           => 'distrib_way',
//          'geography' => 'distrib_geography',
            'birthday_year' => 'since',
            'history' => 'history|aviaport_old_denormalize',
            'rubrics',
            'themes' => 'themes|aviaport_old_denormalize',
            'chief' => 'who_filled',
            'director',
            'editor',
            'is_contacts_shown',
            'address',
            'phone',
            'fax',
            'www',
            'email',
            'who_filled_position',
            'origin_id',
            'company_id',       // Компания-издатель из Справочника «Авиапредприятия»
            'agent_id',         // Компания-представитель в РФ из Справочника «Авиапредприятия»
            'create_time',
            'modify_time' => 'UNIX_TIMESTAMP(Modification)',
            'owner_id',
            'last_editor_id',
        );
    }

KRoN73 ★★★★★
()

>теперь приступаем к разработке сайта

PostgreSQL + PostGIS + Django + GeoDjango

Питон этоо кандидта номер один.

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

Ява вы просто не осилите и не найдете вменяемых прогеров для ней.

lorhellboy
()
Ответ на: комментарий от KRoN73

> К использованию $_FILES :)

ахх :), понял.

В своё оправдание - оно ж в контроллере :)

По остальному спорить не буду, каждый делает так, как ему удобнее :)

Ну это да.

AndreyKl ★★★★★
()
Ответ на: комментарий от KRoN73

> Механизм проверки и обработка ошибки сокрыты, так что, кстати, захоти я переписать систему на использование исключений - 3/4 всего кода этого изменения даже не заметит :)

Это, конечно, верный признак хорошего дизайна :)

Ну и я писал ранее, что я не использую properties. Ибо механизм доступа к данным унифицирован, генерируемые данные встречаются не реже, чем статические, и обращаться к функциям через __set()/__get() дороже и менее прозоачно, чем к свойствам через функции и __call().

Ну тут на вкус и цвет, как говорится. А идея с $item->set_last_name($data['last_name'], true); понравилась в принципе.

Натравливаю препроцессор и тот генерит кучку файлов-шаблонов: - SQL-код по генерации нужной таблицы (с комментариями полей) - Собственно основной файл класса - Файл админ-класса объекта - Файл класса редактора и HTML-шаблон к нему - Файл класса и HTML-шаблон админки для управления всеми объектами этого типа

Т.е. автономный отдельный раздел сайта по описанию полей нужных объектов организуется за считанные минуты :) Понятно, что потом приходит вопрос оформления, дизайна, объект этот часто связан с другими объектами, обладает особыми моментами в поведении и т.п... Вот на это и уходит 99% всего времени разработки...

В целом звучит очень интересно, особенно использование препроцессора для автоматической генерации кода. Мне аж захотелось попробовать твой фреймворк :), жаль со временем сейчас полный аут, боюсь руки всё-таки не дойдут.

AndreyKl ★★★★★
()
Ответ на: комментарий от AndreyKl

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

Пока это достаточно сырой концепт, фактически - примитивный PHP-скрипт. Но уже вполне работающий. По крайней мере пару-тройку разделов www.aviaport.ru с ним сделал. Но нужно будет сделать всё красиво, цивильно... :)

Мне аж захотелось попробовать твой фреймворк :)


Ну, будет время (и когда balancer.ru починю) - проект ещё явно на много лет вперёд.

...

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

KRoN73 ★★★★★
()

>На сегодняшний день у нас готово ядро приложения (написано на C и shell)

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


А почему бы Вам и веб-часть не написать на C?
Быстро и надежно :)

Harald ★★★★★
()

А почему бы не продолжать на си шарп? У корпорации зла есть какие-то программы. Тиа ВебСпарк Для небольших веб студий они бесплатно дают весь инструмент.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.