Вступление
Для начала расскажу одну историю, которая будет знакома, возможно, большинству из тусовки хаба «PHP».
Будучи школьником, ты играл в GTA Vice City и CS 1.6 в компьютерных клубах в начале за 8, потом за 10 рублей в час (60 ночь). Деньги раздобыть было не проблемой, можно всегда навешать лапши на уши родителям, что завтра нужно срочно сдать на ремонт школьного крыльца. Потом родители купили тебе собственный компьютер (для учебы, конечно же). Буквально за пару лет компьютеры появились в каждой семье и компьютерные залы закрылись. Кто-то продолжает и сейчас только играть за компьютером, но не ты. Ты пассионарен и сразу захотел написать свою игру, либо гайд на героя из Доты в формате HTML и JS, либо создать свой форум по играм и разместить там в футере рекламу.
В школе ты учился на «4», редко скатывался в тройки. Среди парней ты был вторым по успеваемости. Ты мог учиться и на 5ки, как те два парня на параллели, но сидеть 2 часа и зубрить отличия митоза от мейоза — задача непосильная, когда дома есть компьютер, а в нем — какой-то сериальчик или возможность попробовать разместить счетчик на своем сайте. Какое тебе дело до этого митоза? И вообще, ты не понимаешь, зачем начинать делать курсовую работу сейчас, когда можно за день до сдачи погуглить, скачать, ознакомиться и своими словами навешать лапши на уши учителю.
Прошел год, ты все еще молод и дерзок. Именно ты пишешь говнокод на фрилансе и можешь продать его за большие деньги. Ведь ты продаешь не код и не час своей работы, как прилежные мальчики в костюмах. Ты продаешь решение проблемы заказчика и умеешь навешать лапши на уши кому угодно, даже самому себе, чтобы не терять драгоценное времени на объяснения непонятных вещей.
Вскоре ты уже являешься типичным представителем среднего класса. А те парни-отличники с твоей параллели получили два высших образования и теперь либо работают консультантом в разделе утюгов Эльдорадо, либо стали Java программистом и давно уехали в США, оставив Россию наедине с PHP.
Минусы PHP
Статья с содержанием «минусы PHP» выходит стабильно раз в год. Здесь не хочу снова мусолить темы, о которых все и так знают: нейминг SPL функций, нейминг операторов, неожиданное поведение функций, скорость выполнения сценариев. Все это мелочи, либо попытка вывести PHP вне своей весовой категории. Здесь я перечислю пару архитектурных минусов, чего не видел в других статьях, но это очень важно.
1. Отсутствие стандартизации на низком уровне. PHP — язык с нестрогой, динамической типизацией. Типизация PHP настолько нестрога, что я бы лучше поискал другое слово, в котором нет подстроки «строго» вообще. Например, пусть это будет добрая типизация, или типизация — бревно, тряпка и ***. Нельзя назвать это минусом, язык программирования не виноват, что его используют не по назначению, в высоконагруженных сложных системах, где типизация крайне важна. Но вот есть еще такой интересный момент, как стандартизация работы с типами:
<?php
//Эталонный набор данных типа "массив" из главной палаты мер и весов
$array = [
'foo' => 1,
];
//Эталонный набор данных типа "объект" из главной палаты мер и весов
$object = new stdClass;
$object->foo = 1;
//Теперь создаем копию:
$arrayCopy = $array;
$objectCopy = $object;
//Подменяем данные:
$arrayCopy['foo'] = 2;
$objectCopy->foo = 2;
//Выведет 12
echo $array['foo'];
echo $object->foo;
Если вы попробуете изменить $objectCopy->foo, вы измените и $object->foo. А в случае с массивом, меняя foo в $arrayCopy, вы измените данные только в $arrayCopy, не касаясь $array.
Да-да, в PHP оператор присваивания "=" либо клонирует данные, либо передает их по ссылке в зависимости от того, данные какого типа следуют за оператором. Однажды пришлось тушить сидушку моего кресла, когда в сложной системе, где на ходу меняются типы, причиной бага оказалось именно эта «особенность» и я потратил полдня на дебаг.
2. Нестабильность архитектуры. В настоящий момент PHP разных версий похож на Perl, C++, Java. В каждом из перечисленных языков есть что-то свое, хорошее. Наверно, к этому хорошему стремились разработчики PHP, каждый раз поворачивая на 180 грудусов со своего пути. Наиболее эпичным стало добавление ООП в PHP, когда вода с низов давно утекла и утверждение «ООП — это когда все является объектом» к PHP применено быть уже не может, ведь в этом ЯП всё может является всем.
Если мы хотим хотябы на 99% объектно-ориентированный PHP проект, где мы будем «жестить» и наследовать низкоуровневые объекты типа «строка», нам придется делать некоторые страшные и глупые вещи, например:
<?php
class String {
private $string;
function __construct($string) {
$this->string = $string;
}
function char($num) {
$num = $num-1;
//да-да, не удивляйтесь, мы используем метод объекта для возвращения символа строки как массива
return $this->string[$num];
}
}
//Выведем второй символ строки Hello World
echo (new String('Hello World'))->char(2);
Интересно, что мы не можем проверить тип $num в char ООП'шным способом: «function char(integer $num)», хотя этот integer в системе есть. Нам придется проверять тип функцией SPL, либо писать свой собственный class Integer, такой же как String.
Как итог, сейчас на ООП в PHP можно делать лишь самую высокоуровневую архитектуру, что без нижней выглядит не очень приятно. но толи еще будет.
3. Излишняя свобода. В PHP нестрогой является не только типизация. Тут вообще мир добра и единорогов. Можно взять и прямо в футере шаблона, посреди HTML кода, сделать подключение к базе и записать туда какие-то входящие от пользователя данные из глобальной переменной без экранирования. В других языках программирования за это светит синтаксическая ошибка. Но PHP создавался, как шаблонизатор и тянет за собой эту тяжелую ношу всю жизнь. Это является еще и плюсом.
Плюсы PHP
А теперь самое интересное. Перечислю конкретные плюсы PHP.
1. Мужественность. Я разрабатываю на PHP уже 10 лет. За это время мимо меня прошло куча модных альтернатив, типа Ruby (on rails) или NodeJS. У всех этих решений не было лишних конечностей или ампутированной головы, как у PHP. Но все они быстро приходили и куда-то уходили, оставив после себя кучу полуживых разрозненных островков готового кода. А PHP оставался и развивался, хоть и не в сторону усовершенствования языка. В итоге, мир получил мощную инфраструктуру веб-разработчика: любой маленький людишка может сесть за консоль и через Composer установить себе терабайт разных мелких и больших штучек под каждый чих.
2. Стабильность. PHP развивается, не отказываясь от прошлого. Это по-прежнему шаблонизатор, но в 2016 — еще и с надстроенными сверху этажами абстракции, которые по высоте обогнали все другие ЯП. Теперь на шаблонизаторе PHP может быть написан другой шаблонизатор, типа Smarty.
Недавно я встретил человека, который ушел из Java в PHP. Человек был вполне психически здоров, умен и востребован в мире Java. Тогда-то я и осознал, что архитектура в PHP на верхах уже очень хороша. И, что самое важное, в PHP уже можно писать все на верхах — о трудном детстве и деревянных игрушках PHP напоминают только разные странные операторы, ну и огромный костыль (или фишка) «магия» с этими нижними подчеркиваниями.
У меня вызывает уважение тот факт, что ребята все еще не плюнули и не переписали все с нуля, забыв о всех работающих проектах и людях, которые не хотят переучиваться.
3. Сообщество хороших парней. Нам, высокопассионарным парням, которые в учебе не дотягивали до отличников, но умели быстро мобилизироваться и самообучаться, PHP очень помог стать человеком. Тогда, будучи школьником, я бы не смог преодолеть порог языка со строгой типизацией, даже с хорошим учителем (это скучно и сложно). Как итог — я бы не стал программистом, не писал бы сейчас эту статью. Возможно, пил бы водку с наркоманами и проститутками, грабил прохожих. Благодаря PHP, я смог сам себе навешать лапши на уши, убедить себя, что программирование — это просто и интересно, сделать первый шаг, простой шаг, без типизации и ООП. Деньги пришли сразу, а все остальное приходит позже, на практике.
Cпасибо, PHP!
Комментарии (196)
lukdiman
02.04.2016 13:49+50Почему PHP программисты всегда пишут всякие исповеди? Ни разу не видел статей про производительность, про какие-то низкоуровневые вещи. Только исповеди и фреймворки. А как все там внутри устроено знают похоже единицы.
alexkunin
02.04.2016 15:24+2Исповеди исповедями, а вот гугл на запрос «php производительность site:habrahabr.ru» (а также «site:geektimes.ru») выдет десятки релевантных ссылок. Некоторые в контексте фреймворков, да. По «zend engine site:habrahabr.ru» тоже немало (в основном про написание расширений, но есть и просто про внутренности движка).
unStaiL
03.04.2016 13:25Мне как то сказали, не важно какую технологию вы используете на своем проекте. Если вы можете быстро стартовать с RoR или Django то стартуйте с нее, если проект себя оправдает, вы всегда сможете переписать на более надежную и проверенную технологию, где как вы думаете, ваш проект будет проще масштабировать, поддерживать и т.д.
heathen
04.04.2016 19:10-1А вот это такой вопрос… неоднозначный. С одной стороны, согласен целиком и полностью. С другой — будет ли у вас время на переписывание, миграцию данных? Особенно при взрывном росте и появлении ста пятисот тысяч клонов? Вам нужно будет пилить новые штучки, а не переписывать движок. Конечно, если подобрать правильную архитектуру на старте, можно избежать многих косяков, но это уже отход от "быстро стартовать".
Fesor
04.04.2016 19:15+1вы всегда сможете переписать на более надежную и проверенную технологию
Как круто живется в вашем розовом мире. В реальности никто в здравом уме не будет принимать решение "переписывать". Если это монолитное приложение — постепенно критические места будут выпилены как отдельные микросервисы и тогда уже можно их реализовать на чем-то другом. Либо проект просто будет постепенно перепиливаться целиком на микросервисы. Но переписывать именно никто не даст. Практика показывает что на крупных проектах монолитным остается где-то половина приложения, просто потому что там не важно.
oxidmod
02.04.2016 13:50+8>> Да-да, в PHP оператор присваивания "=" либо клонирует данные, либо передает их по ссылке в зависимости от того, данные какого типа следуют за оператором
Это описано в документации. Объекты передаются по ссылке. Если хотите, то можно и массив и строку и число передать по ссылке. А можно объект скопировать, точней склонировать.
>> Нам придется проверять тип функцией SPL
а можно использовать php.net/manual/en/book.spl-types.php, если вам действительно нужно завернуть примитивы в объекты
>> Излишняя свобода
как и в реальном мире свобода сама по себе не является проблемой. Другое дело как Вы ею распорядитесь, но PHP тут ни при чем.
gro
02.04.2016 21:40-8Объекты не передаются по ссылке. Во всяком случае не так, как «по ссылке» подразумевается в мане.
SerafimArts
02.04.2016 23:09+1А как в мане подразумевается? Не, ну может я чего не знаю, но мой узколобый мирок ограничивается "передачей по ссылке" и "передачей по значению", никаких иных "передач", в том числе каких-то "тюниногванных" — не бывает.
gro
03.04.2016 00:04+3Мне не совсем понятны ваши пассажи про «узколобый мирок», но не будем.
Термин «по ссылке» в PHP используется вместе с операцией "&" и как не спорить о терминах, за ним стоят совершенно другие механизмы, чем за передачем объектов.
В первом случае ссылка между именами переменных, во втором между значениями. Ещё любят говорить «объекты передаются по значению, коим для них является ссылка на собственно объект».
Если опять таки не холиварить о терминах, различия явно видны на примерах:
$a = &$b;
$b = 5; // $a тоже присваивается 5
$a = $object;
$object = 5; // $a не затрагивается. Оператор = рвёт связь между переменной obj и значением объектаoxidmod
03.04.2016 00:23я почему-то думаю, что & указывает что примитив нужно присвоить как объект, тобишь по ссылке.
объекты по умолчанию присваиваются таким образом, без необходимости указания &.
вот и вся разница. в пхп4 объекты присваивались как и примитивы, по значению, что приводило к ряду не совсем очевидных на тот момент проблем. тогда же появился &, который позволял передать любую переменную по ссылке. в пхп5 такая передача стала основной для объектов.
SerafimArts
03.04.2016 00:33+3Да, вы совершенно правы, есть такое. Прошу прощения за "пассаж". Это действительно может быть не очевидным для тех, кто перешёл с других языкв, слишком уж "замылилось" подобное поведение гуру-php, чтобы воспринимать его как нечто необычное.
Fesor
03.04.2016 01:00Так, давайте упростим. Представим себе что переменные всегда хранят ТОЛЬКО значения. И есть такой вариант значения как ссылка. Ссылку можно получить явно:
$foo = &$bar; // тут явно мы берем ссылку на $bar и присваиваем ее $foo
Или неявно, если у нас нет доступа к конкретному значению, что и происходит за кадром в PHP и других языках в случае объектов.
А теперь задумаемся почему объекты всегда передаются по ссылке (во всяком случае со времен php 5.0, в php4 объекты передавались по значению, потому что по сути это были тупые структуры данных). У объектов внутри могут быть зависимости, какое-то состояние, циклические ссылки на другие объекты. И на любой чих копировать все это несколько сложно. В итоге во всех языках программирования это решили отдать на откуп разработчикам, мол "вот тебе чувак clone и делай как хочешь".MacIn
03.04.2016 01:02Необязательно; есть же С++ со своим "конструктором копирования". Который реализован по умолчанию как бинарная копия 1 в 1.
MacIn
03.04.2016 00:39В ряде сообществ некоторых языков сложилась своя терминология.
В частности, в том же С++ "передача по ссылке" — это, внезапно, не то же самое, что и "передача через указатель". Отсюда иногда происходят тонны батхерта и непонимания, когда общаются люди из разных "миров".Fesor
03.04.2016 01:01Потому что ссылка это не указатель.
MacIn
03.04.2016 01:04facepalm. Вы приводите статью "Ссылка (C++)", при том что я ровно о том и сказал — что в С++ ссылка — это не указатель:
в том же С++ «передача по ссылке» — это, внезапно, не то же самое, что и «передача через указатель».
Как?Fesor
03.04.2016 13:20Нет, вы сказали что они должны быть "то же самое", а они не то же самое и потому мне совершенно не понятно ваше удивление.
MacIn
05.04.2016 02:36Нет, вы сказали что они должны быть «то же самое»
Это ложь.
Я сказал, что у разных языков разная терминология. И в ряде языков ссылка и указатель — это разные понятия. В частности, в С++.
Вот точная цитата, еще раз:
В ряде сообществ некоторых языков сложилась своя терминология.
В частности, в том же С++ «передача по ссылке» — это, внезапно, не то же самое, что и «передача через указатель»
Вы в качестве опровержения моего утверждения (о том, что в С++ уазатель и ссылка — разное) про ряд языков приводите ссылку на тот самый язык (С++).Fesor
05.04.2016 09:18-1Я возможно не так вас понял.
В частности, в том же С++ «передача по ссылке» — это, внезапно, не то же самое, что и «передача через указатель».
Меня смутило слово "внезапно". В PHP нет указателей, есть только ссылки. В C++ же есть ссылки и указатели, так что слово внезапно тут не подходит. Да и указатель это такое же значение как и ссылка.MacIn
05.04.2016 21:04«Внезапно» — это просто саркастический элемент, призванный отметить то, что некоторые люди не понимают того, что в некоторых языках (и в некоторый период времени) ссылка и указатель — синонимы, а в других — нет. «внезапно» для них.
Пассажи вида «передать по значению / ссылке» появились задолго до и PHP и C++.
Flex25
05.04.2016 20:26+1>> Да-да, в PHP оператор присваивания "=" либо клонирует данные, либо передает их по ссылке в зависимости от того, данные какого типа следуют за оператором
По поводу этого лишь добавлю, что в Java ситуация аналогична: примитивные типы присваиваются по значению, объекты — по ссылке. Так что не вижу повода для паники.pistol
06.04.2016 05:31Речь шла про хранилища данных, типа массив и объект. Я не точно выразился в том абзаце.
Fesor
06.04.2016 10:37Массивы в php это такие же скалярные значения, как и строки. Объекты же не тупо хранилища даных, они должны предоставлять нам поведение, а внутреннее состояние — это детали реализации и мы не должны об этом думать.
Для случаев с value object-тами, где копирование объектов по значению оправдано, была дискуссия на php-internals отностельно недавно, но я не смог ее быстро найти. Предлагалось либо ввести отдельный модификатор для класса либо вовсе ввести структуры данных по аналогии с C#.pistol
06.04.2016 12:28Заменил в статье обычный объект на stdClass, чтобы было понятнее, о чем я говорю. Уже в нескольких проектах, где была конвертация массива в объект и обратно, начиналась наркомания на определенной фазе жизни проекта. Программисту (особенно такому, кто работает не только с PHP) такое поведение неочевидно, сколько бы документации не держал он в голове.
Буду очень благодарен, если найдете ту дискуссию, интересно :)Fesor
06.04.2016 15:10вы можете заменить объект вашего типа на объект типа stdClass, разница не существенна. На данный момент все объекты передаются по ссылке. А массивы — не объекты.
Ссылку поищу.
RussianSpy
02.04.2016 13:57+21Я бы не сказал, что Ruby и тем более node.js «куда-то уходили». Та же нода последние два года развивается очень активно. Безусловно, не без проблем. Ну, а у кого их нет?
А вообще такое ощущение, что вы испытываете комплекс вины за то, что используете PHP.
NekitoSP
02.04.2016 14:12+20Ностальгическая история про (до)школьное время и GTA:VC была, пожалуй, самой интересной частью статьи.
Skull
02.04.2016 14:47+4А дальше лучше и не читать. Что минусы высосаны из пальца, что плюсы с намеком что PHP язык для хорошистов, не то что Java!
hmntnl
03.04.2016 09:44с намеком что PHP язык для хорошистов
Ага, а еще для «пассионариев». Хотя стремление к тому, чтобы было без всякой зауми, попроще-побыстрее- это все что угодно, но только не пассионарность. Для этого есть другое слово ;).
schroeder
02.04.2016 14:16+11Погуглил по "исповедь java программиста". Ничего не нагуглил. Господа пхпэшники, что с вами? Мыши плакали, кололись, но продолжали есть кактус?
sayber
02.04.2016 15:36+2Все просто.
Многие разработчики упираются в определенный уровень знаний PHP и дальше не понимают как развиваться.
Что то свое придумать не могут а изучить и использовать проф. инструменты не могут.
Вот и начинают писать всякую ересь.atc
03.04.2016 09:44+1А что вы подразумеваете под «проф. инструментами»?
sayber
03.04.2016 19:43Из банального — профессиональная готовка проектов на Symfony (не давний опрос показал, что более 70% разработчиков не осилили его)
Столько же или больше разработчиков при работе с БД используют свои велосипеды и/или AR а когда смотрят в сторону data mapper, то хватаются за волосы и проходят мимо (doctrina, spot ...).
Как выяснилось, с composer тоже мало кто дружит. Знают как добавить сторонний код и все.
Я уже не говорю про сторонние разработки которые облегчают жизнь PHP программисту.
Вообще тут можно писать очень долго и начать долгий спор.
P.S.
Еще есть такой слой ПхПешников, которые слыша вокруг — PHP плохой, это вообще не язык и т.д. — начинают ныть в унисон и стараться на что то пересесть.
Сам работаю с PHP (15 лет), JS (серверный уровень), Go, Javaatc
03.04.2016 20:01Не со всем согласен, composer сейчас используется во всех современных фреймворках, а добавление кода из своих репозиториев\использование скриптов — совсем не редкость. По поводу сложности Data Mapper, кажется вы её слегка преувеличиваете, чаще всего достаточно внимательно прочитать документацию и написать несколько конфигов, в остальном оно не сложнее типичного AR из Laravel\Yii2.
Еще есть такой слой ПхПешников, которые слыша вокруг — PHP плохой, это вообще не язык и т.д. — начинают ныть в унисон и стараться на что то пересесть.
Не встречал таких, чаще всего стеб по поводу php слышу от людей, которые пробовали его либо слишком давно, либо на простых и примитивных задачах.
PS: Вопрос по поводу Symfony, чем он примечателен на фоне zend\laravel\yii, раз вы его специально выделили в своем ответе?Fesor
03.04.2016 22:37-2По поводу сложности Data Mapper, кажется вы её слегка преувеличиваете
Если мы про доктрину, то data mapper это гдето 10% того что такое доктрина.
в остальном оно не сложнее типичного AR из Laravel\Yii2.
От часть да, но возможностей намного больше. Как и ограничений.
Вопрос по поводу Symfony, чем он примечателен на фоне zend\laravel\yii,
Ну вот Zend еще может потягаться с Symfony, а Laravel — это хороший фреймворк, но он хорош только для простых проектов. Хотя опять же, если для апишек, и заменить элоквент доктриной — все очень даже неплохо.
Yii — это подборка велосипедов, за комьюнити которого не стоит серьезных людей. А стало быть его использование в серьезных проектах я нахожу несколько неоправданным, хотя с другой стороны можно за день проглядеть все его исходники. Но я не вижу в нем смысла. Ровным счетом никакого.
webmoder
04.04.2016 13:14Вообще тут можно писать очень долго и начать долгий спор.
Не спора ради, но хотелось бы чтобы вы написали по больше.
в частности в какую сторону двигаться разработчикам которые входят в те самые 70%(в плане повышения профессионализма и выхода в золотую тридцатку).VolCh
04.04.2016 13:16Освоить, для начала, Symfony :)
Diden05
06.04.2016 05:38Зачем? Почему именно Symfony, а не ZendFramework etc?
То что знание Symphony для вас является признаком хорошего php программиста, ну это слабо мотивирует :)
Коммент выше про тесты, мне кажется даже более актуальным. Код должен быть тестируемым.oxidmod
06.04.2016 09:16+1потому что симфони это баланс между качеством, расширяемостью и простотой использования. в то время как зенд — академическое ООП в вакууме
shoomyst
02.04.2016 14:21+2Куда Node уходит? В том же 2015 была такая движуха, что крышу сносило. Каждый день новый фремворк, как в PHP в лучшие времена :)
Ruby действительно как-то потерялся, возможно просто страсти поутихли, и он занял свою нишу. В том же tiobe index у него неплохие позиции.
Python как-то постабильнееFedcomp
02.04.2016 15:23+2не знаю куда ruby уходит, скоро rails 5 выходит, используемые лично мной гемы периодически обновляются. Это скорее стабильность.
MartinX
03.04.2016 09:44Ruby тихо сидит себе на рельсах, в других областях мало используется, в отличии от того же Java, Python, C++ (хоть его в статье упомянули, но целиком использовать для веб разработки ИМХО слишком, имеет смысл лишь какие-то алгоритмы выносить).
googol
03.04.2016 19:33Python сливается потихоньку, многие питонисты которых я знаю перешли на Go как основной язык для новых проектов.
MartinX
03.04.2016 19:37Да я бы так не сказал. Как бы не говорили, что Python/C/PHP/ect отмирают, но они живут (сужу по проектам и упоминанию).
SowingSadness
05.04.2016 12:43-1github.com/search?utf8=?&q=created%3A>%3D2014-01-01+created%3Ahttps://github.com/search?utf8=?&q=created%3A>%3D2015-01-01+created%3A
sl_bug
05.04.2016 09:01Sinatra, hanami — не только рельсами живет руби. Да и не только веб фреймворками (тот же менеджер пакетов для osx — homebrew).
eoffsock
03.04.2016 09:44Ruby и Rails просто перешли из разряда «хипста-игрушек» в разряд рабочих инструментов. Ну, тут конечно у всех свое мнение, но для меня это так.
То есть тут нет необходимости уже как-то разжигать интерес: кому нужно, тот работает.
akubintsev
02.04.2016 14:45+13Вступление как-то мимо меня. Я школу покинул на рубеже нового тысячелетия, то есть вырос в «тяжелые 90-е», а компьютер был с 11 лет. Восторгов вокруг CS и GTA никогда не понимал. Деньги обманом не клянчил у родителей. Но что характерно, никогда в отличники не стремился. Так что да, 4-3 — характерно :)
В компьютерные клубы ходил только потому что это было единственной доступной возможностью поиграть с кем-то по сетке в StarCraft или Quake.
Теперь по поводу PHP. Пора избавиться от навязанного комплекса неполноценности этого ЯП. Достаточно вспомнить мысль, что каждый ЯП выполняет свой спектр задач. Если ты пытаешься делать с его помощью то, для чего он не предназначен, то пенять надо не на язык, а на свою «кривую рожу».
Комментарии про «минусы»:
> 1. Отсутствие стандартизации на низком уровне.
Просто надо почитывать changelog-и версий php. А то, что в js объекты тоже передаются по ссылке вы тоже не знали, js плохой?
> 2. Нестабильность архитектуры
Если приведенный пример иллюстрирует реальную проблему в решении поставленной перед программистом задачи, то наверное стоит использовать другой ЯП. Но назвать нестабильностью динамическую типизацию минусом — это странно как-то.
А на счёт плюсов всё так. Я бы еще добавил то, что специалисты этого ЯП хорошо востребованы практически везде и оплачиваются достойно.MacIn
03.04.2016 00:45А то, что в js объекты тоже передаются по ссылке вы тоже не знали, js плохой?
И в С#, и в Delphi.
Source
03.04.2016 00:48Вы всерьёз приводите js в качестве примера языка, хорошо продуманного на низком уровне? JavaScript?
Посмотрите хотя бы https://www.destroyallsoftware.com/talks/watFesor
03.04.2016 01:04Это историческое наследие. посмотрите последние стандарты — они прекрасны. Хотя если так на PHP смотреть там тоже не так плохо. Я же все надеюсь на то что проект yay взлетит и это сильно ускорит развитие PHP.
Source
04.04.2016 01:49Да я ещё стандарт Javascript 2.0 помню, он тоже был неплох )
Только от обратной совместимости они вряд ли откажутся, поэтому так и останется WAT на низком уровне.Fesor
04.04.2016 10:10Вот честно, за 4 года работы с JS я ни разу не испытывал проблем с WAT. Это просто странности, в реальной жизни таких ситуаций практически не возникает. А потому можно.
SerafimArts
04.04.2016 10:48+2Ну раз пасуешь и не было проблем за 4 года с WAT — повбрасываю, с вашего позволения:
['1','2','3','4','5'].map(parseInt);
Если знать что происходит — никакого WAT нет, но для неискушённой детской психики результат вывода может её травмировать.Fesor
04.04.2016 12:56тут даже не WAT, тут банально здравый смысл. у praseInt как бы два аргумента, в чем тут WAT?
['1','2','3','4','5'].map(str => Number(str));
Source
04.04.2016 16:29WAT хотя бы в том, что функцию с одним или с двумя аргументами можно вызывать в качестве коллбека с 3-мя аргументами.
Если абстрагироваться от опыта работы с JS, то понятно, что это совсем неочевидное и даже нелогичное поведение.
Вы пишете "это просто странности", но когда осваиваешь несколько языков, понимаешь, что именно JS просто таки пропитан этими странностями.Fesor
04.04.2016 16:40функцию с одним или с двумя аргументами можно вызывать в качестве коллбека с 3-мя аргументами.
вообще-то так можно сделать в любом динамическом языке программирования, доступ то к аргументам всеравно есть (arguments в js, func_get_args в php и т.д.), variadic arguments и все такое. Скажем вот такой код:
function foo(a, ...b) { // ... } fo(1, 2, 3, 4, 5);
Это более чем нормально.Source
05.04.2016 15:17variadic arguments есть много где — это правда, но где это есть по умолчанию для всех функций, без возможности отключить данную фичу и строго указать необходимые аргументы в сигнатуре функции? В случае с функциями высшего порядка variadic arguments, имхо, вообще не к месту.
herr_kaizer
03.04.2016 15:21+1Скажите честно: какой из приведенных примеров может стать проблемой в реальной разработке?
Source
04.04.2016 01:54Любой. Или Вы считаете, что это всё выдуманные кейсы? Тогда ведь нет никакой проблемы в следующей версии стандарта кидать TypeError?
Так нет же, эти извраты используются в куче уже написанного кода.herr_kaizer
04.04.2016 08:51Да, считаю. Потому что никакому здравомыслящему человеку не придёт в голову складывать массив с объектом ради получения пустой строки, например.
Source
04.04.2016 10:551) В крупных проектах существуют разные edge-кейсы, и там где по коду предполагалось сложить 2 массива, по факту может получиться, что оба массива оказались пустыми или вместо массива пришёл объект, и всё — получайте либо пустую строку, либо Object, либо 0. Т.е. даже если Вы явно не полагаетесь на WAT, то вполне можете получить трудные в отладке ошибки, связанные с таким поведением. А чтобы исправить подобные ошибки придётся в явном виде учитывать это неадекватное поведение.
2) JavaScript — вообще источник несчётного количества WAT, вот для примера ещё несколько, как минимум 2 из которых часто используются и всё так же вызывают недоумение у людей, которые не съели собаку на странностях JS
-new Date() 0-new Date() +new Date() 0+new Date() 15/7|1 15/7|0
Можете, не выполняя код, сказать какой будет результат каждой строки?Fesor
04.04.2016 13:01предполагалось сложить 2 массива
arr = a.contact(b);
и какие тут могут быть сюрпризы?
Можете, не выполняя код, сказать какой будет результат каждой строки?
Я знаю что такой код не пройдет код ревью. Достаточно знать что возвращаетvalueOf
у даты и в каких случаях происходит каст к строке. А с побитовыми операциями надо просто знать приоритеты операторов. Я просто не позволяю двусмысленные операции в коде, все должно быть явно с одного прочтения.Source
04.04.2016 16:08arr = a.contact(b);
т.е. продолжая мысль herr_kaizer: «никакому здравомыслящему человеку не придёт в голову складывать массивы с помощью оператора сложения, ведь это же JS»
Я знаю что такой код не пройдет код ревью.
Вы так это сказали, как-будто на code review есть стандарт и он гораздо лучше, чем стандарт на JavaScript :-)
А вообще изначальный тезис был в том, что не стоит упоминать JS в качестве языка, хорошо продуманного на низком уровне.
И то, что на нём можно писать понятный код, не отменяет тот факт, что можно писать и непонятный.
А продуманность языка как раз заключается в том, чтобы непонятный код не работал (не компилировался, сразу валился с TypeError и прочее).
Source
04.04.2016 16:21ну и, кстати, concat не особо уменьшает кол-во сюрпризов
// V8 version 4.9.385.28 [sample shell] > [].concat([]) > [].concat([]) == [] false > a = [].concat({}) [object Object] > a.concat([]) [object Object]
Fesor
04.04.2016 16:43И все сюрпризы из-за того что люди не читают документацию?
valueN
Arrays and/or values to concatenate into a new array. See the description below for details.
так что приведенный вами код вполне себе валидный и логичный.
[].concat([], [1], 1, 'foo', {bar: 'bar'}); //[1 , 1, foo, object Object]
Source
05.04.2016 14:54+1Понимаете в чём дело, от того, что что-то описано в документации, это не становится логичным автоматически.
Добавление элемента в массив и конкатенация массивов — это 2 разных операции. И то, что concat делает и то и то, это нифига нелогично.
[1].concat([2, 3]) // => [1, 2, 3] //ok [1].concat(2) // => [1, 2] // WAT?
Хоть жирным капсом на главной странице документации об этом напиши, всё равно это останется WAT.
Попробуйте найти хотя бы 2-3 других ЯП, в которых добавление в массив и объединение массивов делается одинаково в рамках стандартной библиотеки.
RomanPyr
03.04.2016 19:27Достаточно вспомнить мысль, что каждый ЯП выполняет свой спектр задач.
Писать шаблоны HTML-страниц?
michael_vostrikov
02.04.2016 15:00+3Если вы попробуете изменить $objectCopy->foo, вы измените и $object->foo
Как вы лихо записали документированное поведение в архитектурные минусы и отсутствие стандартизации) Не говоря уже о том, что такое поведение есть и в других языках.
Если мы хотим хотя бы на 99% объектно-ориентированный PHP проект, где мы будем «жестить» и наследовать низкоуровневые объекты типа «строка», нам придется делать некоторые страшные и глупые вещи
В C++, представьте себе, вообще нет встроенного типа для строк, и там точно также надо писать свой класс (либо использовать готовый). C++ из-за этого не объектно-ориентированный?
Интересно, что мы не можем проверить тип $num в char ООП'шным способом
Каким образом проверка типов связана с ООП?
В других языках программирования за это светит синтаксическая ошибка
В других языках программирования нужно сильно больше действий, чтобы хотя бы что-то вывести. Особенно во времена появления PHP. Именно поэтому он и создавался.grossws
02.04.2016 15:57В C++, представьте себе, вообще нет встроенного типа для строк, и там точно также надо писать свой класс (либо использовать готовый). C++ из-за этого не объектно-ориентированный?
А чем вам std::string в качестве стандартного типа строк не угодил?michael_vostrikov
02.04.2016 17:37Я имел в виду, что он не поддерживается на уровне языка, как например char и int. Это отдельно написанный класс с исходным кодом на этом языке, аналогично примеру из статьи.
pistol
03.04.2016 10:10"Не говоря уже о том, что такое поведение есть и в других языках." в каких, например? Обычно везде массив тоже является объектом.
michael_vostrikov
03.04.2016 11:21+1Эм, то есть вы ожидали не что объект скопируется, а что исходный массив будет присвоен по ссылке и изменится? Ну извините, из вашей заключительной фразы "Да-да, в PHP оператор присваивания "=" либо клонирует данные, либо передает их по ссылке в зависимости от того, данные какого типа следуют за оператором" это не очень непонятно. Потому что например скалярные типы и константы по ссылке не передаются, и складывается впечатление (и судя по комментам, не у меня одного), что у вас вызывает удивление поведение объектов при присваивании. В любом случае, присваивание массивов по значению это тоже документированное поведение.
pistol
03.04.2016 13:18-1Я ожидал, что массив и объект ведут себя одинаково (не важно, клонируются или по по ссылке передаются). Так это работает во всех других языках, которые я ковырял.
Согласен, не совсем ясно и четко выразил мысль в статье.
alex1covo
02.04.2016 15:26-1Весь цимес написан в конце статьи в самом последнем абзаце. Согласен на 100% Добавлю, что ко всему прочему пхп является языком для веб разработки, что на мой скромный взгляд является мейнстримом. 10 лет назад это не было так очевидно и можно было запросто свернуть в сторону скажем делфи и стать не веб, а прикладным программистом. Поэтому спасибо пхп!
Naymen
02.04.2016 15:26-11Я всегда вспоминаю доклад Сергея Рыжикова, который создал компанию 1С-Битрикс и активно внедряет PHP в государственные структуры.
И вот он как раз и говорит, почему многие перестали писать на Java и других языках программирования.
Все потому-что, PHP проще всех развернуть на любом компьютере или сервере. Вам все лишь останется открыть браузер и заходить в свое приложение из любой точки мира и с любого устройства.
Люди давно стремятся придумать универсальный язык, который подходил бы всем и на нем можно было легко написать.
Я считаю PHP идеальный вариант. Он прост в изучении и написать простой сайт нам нем не проблема.
Если бы PHP изучали со школы, то у нас была бы армия программистов с кучей сайтов и веб-приложений :)
Ссылка на его доклад: www.youtube.com/watch?v=x7HWRTbHgAUNaymen
02.04.2016 22:12-1Почему минусы, что я не так написал?
SerafimArts
02.04.2016 23:13+13Потому что битрикс — худшее что произошло с миром PHP и учиться у таких людей я бы стал только маркетингу. Ну и плюс отличий между Java и PHP невероятно мало, нежели между PHP и, допустим, Python.
P.S. я не минусовал, просто это мои предположения.Naymen
02.04.2016 23:30+1Да я согласен с вами, что Битрикс давно уже не идеальный. Но я писал именно пересказ человека, который говорил, что будущее за веб приложениями, а точнее то что открывается прямо в браузере.
boodda
04.04.2016 10:52+1Давно уже не идеальный ?
Это вы сейчас про "Битрикс"?
К этому УГ продукту, можно разные эпитеты придумать, но "не идельный". Это…
Laravel 5 не идеальный, Symfony 2/3 не идельный, а Битрикс — это ад для программиста и рай для маркетолога.
roswell
03.04.2016 09:44В фидах с Upwork-а ежедневно встречается как минимум пара-тройка десятков (ежедневно, десятков, Карл!) задач на тему «My Wordpress (Joomla, etc) is hacked, need this fixed ASAP». Так что всё это было бы забавно и даже интересно, если не было настолько печально.
Blumfontein
02.04.2016 15:39-5Для языка, ориентированного на веб, нестрогая динамическая типизация — очень удобно. Попробуйте распарсить json на PHP и на java.
lukdiman
02.04.2016 20:56+1А в чем проблема распарсить на java?
Fesor
03.04.2016 01:05Ну скажем так, не так удобно с этим работать. В Java намного удобнее мэпить json на объекты определенного типа а не генерить все рефлексией.
Blumfontein
03.04.2016 08:07Проблемы-то нет, но покажите, как это сделать в одну строчку, как в PHP
lukdiman
03.04.2016 10:34+3Добавляете в classpath любую библиотеку, которая работает с json и будет вам в одну строчку и парсинг и мапинг на объект. Может в php это встроено в язык, но по сути это одно и тоже. Я могу даже сделать, чтобы эта библиотека всегда была доступна. Только зачем. Не всегда нужен парсинг json в java. А самое главное я могу не видеть json, а просто посмотреть в существующем коде на что мапится этот json и понять какие данные содержатся в нем. Это очень упрощает понимание людям, которые этот код не писали.
Blumfontein
03.04.2016 12:40>> Добавляете в classpath любую библиотеку, которая работает с json и будет вам в одну строчку и парсинг и мапинг на объект
Ну тут вы слукавили. В одну строчку не получится, потому что объект, на который вы маппите, писать тоже надо как бы. Ну и от библиотеки зависит: а вдруг у вас в json придет невалидный тип данных в какое-то поле, скажем «1234» вместо 1234, вот уже и exception хандлеры пишем.lukdiman
03.04.2016 13:46+1Уж лучше exception, чем невалидные данные. Я узнаю об этом сразу и если это json из внешней системы, то я просто говорю им, что они сами дураки, что присылают мне невалидные данные. Можно вообще заюзать json schema или xsd написать для xml. И будет вполне себе понятный exception о том, что данные не по схеме. Или вы предпочитаете распарсить кое как, а потом где-то в коде будут валится странные ошибки из-за того что json или xml у вас не той структуры или невалидные данные. А хуже если и вообще валиться ничего не будет, а будет передаваться null куда-то, потому что php позволил хранить любую структуру, даже если она вообще не соответствует вашим нуждам.
Blumfontein
03.04.2016 16:28>> Уж лучше exception, чем невалидные данные.
Стоп, стоп, валидацию никто не отменял. Валидировать данные мы и на PHP будем. Но и на джаве, написать объект для маппинга — это еще не валидация. В итоге полноценная валидация будет что там, что там. Но при этом в PHP строку json преобразовать в структуру, с которой можно работать можно за 11 символов независимо от размера json-a (json_decode), тогда как в языках со статической типизацией символов потребуется гораздо больше в силу этой самой статической типизации.solver
03.04.2016 19:08-1Сразу видно PHP-шников, никогда в глаза не видевших нормальных языков)
И о статической типизации имеющих весьма посредственное представление.
>Но при этом в PHP строку json преобразовать в структуру, с которой можно работать
Вот пример из мира статической Java. Дает структуру с которой можно работать, в одну строку.
Map map = mapper.readValue(json, new TypeReference<Map<String, Object>>());
Даст хешмапу с данными. Работай сколько влезет.atc
03.04.2016 20:06Только не забудьте упомянуть, что за этим стоит либо отдельный пакет для работы с json, либо свой самописный адок с шаблонами и генериками.
На php это действительно в разы проще, как на уровне интерфейса, так и на уровне реализации.solver
04.04.2016 00:25+1Т.е. в PHP за этой одной строчкой ничего не стоит? Серьезно?
P.S. Уже даже не смешно такую чушь читать. А потом еще удивляются, чего это о ПХП-шниках многие так плохо отзываются…atc
04.04.2016 00:42Вероятно вы недостаточно внимательно читали ответ выше, там было что-то о простоте реализации данной функциональности в условиях динамической типизации.
Попробуйте поискать что-то вроде https://github.com/FasterXML/jackson-databind для php, все найденные пакеты будут на порядок проще, а чаще всего — совсем не нужны, в силу элементарности реализации.
PS: сколько у вас java опыта и когда вы в последний раз серьезно использовали php?
Fesor
04.04.2016 00:47Т.е. в PHP за этой одной строчкой ничего не стоит? Серьезно?
В целом для разработчика — ничего, все из коробки. Если же нам нужен честный мэппинг json на объекты то уже ставим пакет и тогда процесс с java не особо различается.
Основной холивар тут — статические структуры vs динамические. По моим наблюдениям джависты не особо любят возиться с последними, ибо возможность представить все в виде кэшмэп не очень то устраивает людей. Взять хотя бы такой простенький json:
{ "foo": "string", "bar: false, "date": "2016-01-01T23:28:56.782Z" }
Я не хочу для него заводить объект, но и хэшмэпа мне уже неудобно. Как быть?
Blumfontein
04.04.2016 08:12>> Map map = mapper.readValue(json, new TypeReference<Map<String, Object>>());
А что если у вас в Object будет еще один json?
Fesor
03.04.2016 14:48и будет вам в одну строчку и парсинг и мапинг на объект.
Если мы говорим о сериалайзерах/мэпперах, в PHP тоже все это есть на уровне сторонних библиотек (symfony/serializer как пример).
Но суть то в том что бы сделать так:
$data = json_encode($request->getContent()); // динамическая структурка $errors = $this->validator->validate($data, [ 'name' => new Assert\NotBlank(), 'email' => new Assert\Email(), 'date' => new Assert\Date('iso8601'), ]); if (empty($errors)) { throw InvalidRequest::fromValidationErrors($errors); }
Ну то есть исключение это хорошо, но я хотел бы еще на клиенте получить список того что пошло не так. Скажем я не очень уверен можно ли красиво и понятно в jsonschema описать что даты надо присылать исключительно в iso8601 и т.д.
А если именно мэппинг интересует...
$data = $this->serializer->deserialize($request->getContent(), Person::class, $request->getFormat());
lukdiman
03.04.2016 15:01Я не спорю что в php такое есть. Речь шла о том что в java так нельзя. Я написал что можно.
Fesor
03.04.2016 16:10Я написал что можно.
Да мне вообще сложно придумать чего нельзя сделать в принципе, но вопрос то в удобстве. PHP для динамических структур — хорошо, а вот в java обычно при отладке случаются веселые приключения. Хотя опять же не думаю что это хоть сколько нибудь проблема.
impwx
04.04.2016 11:36В C# есть ключевое слово
dynamic
, которое позволяет работать с объектами "вслепую", как в PHP или JS. Распарсить Json можно в одну строчку:
dynamic value = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}");
Опытного программиста такая строчка настораживает. Она говорит в первую очередь о том, что писавший ее программист поленился сделать нормальный DTO-класс и наплевал на обработку ошибок. Такое допустимо в одноразовом скрипте, но в серьезном проекте это потенциальный рассадник багов.Blumfontein
04.04.2016 17:26https://habrahabr.ru/post/280730/#comment_8837332
impwx
04.04.2016 17:51Я читал ваш комментарий, но речь не про валидацию. На выходе из
json_decode
получаем ассоциативный массив, либо объект (что в php практически одно и то же), и с ключами этого массива придется работать, как со строками. Из этого — сразу целый ворох неприятных моментов:
- Можно банально опечататься в одном из мест и заметить не сразу
- IDE будет очень сложно/невозможно вывести адекватные подсказки
- Рефакторинг также невозможен
В особых случаях может потребоваться также "простукивать" структуру перед обращением к конкретным вложенным ключам.VolCh
05.04.2016 09:40+1По хорошему, стремясь к сильной типизации (хотя бы только для IDE), результат json_decode в большинстве случаев нужно использовать только для одного — для заполнения обычных объектов (конструктор, сеттер, фабрика и т. п.). И, желательно, не использовать тупые циклы без захардкоженного маппинга.
Fesor
04.04.2016 18:30Валидация происходит после сериализации и выглядит это примерно одинаково как в случае java так и php так и вообще любого языка. Нам же надо всеравно правила валидации задать, и это не всегда только обязательные/опциональные поля, это еще и формат данных, другие ограничения, все что высказано в требованиях к входящим данным.
molchanoviv
04.04.2016 13:14Я ниразу не джавист, но даже я знаю как сделать это в одну строчку.
gson.fromJson(jsonString, JsonObject.class)Blumfontein
04.04.2016 17:19Так нет же. JsonObject.class Пушкин писать будет? Или сам собой волшебным образом появится?
molchanoviv
04.04.2016 17:28он уже есть. его не надо писать
Blumfontein
04.04.2016 17:41Можно ссылочку на описание этого класса? Или вы про org.json.JSONObject? Его нельзя использовать в таком контексте, насколько я знаю.
zim32
02.04.2016 16:09+1Не люблю когда навешивают ярлыки. В мире пхп уже давно не все так прямолинейно и уже достаточно инструментов чтобы писать расширяемый, понятный и качетсвенный код. Ну а те кто застрял в своем развитии в пхп и не знает что дальше делать… так их везде достаточно.
yvm
02.04.2016 16:37+8Я сама пэхапэшница. Дочь сисопа. Просто поверьте, — у нас не все так однозначно… Никто не хочет писать чистый код!
zim32
02.04.2016 16:47+5Думаете если у вас заменили бы пхп на к примеру питон, все стало бы по-другому?
slonopotamus
02.04.2016 19:43Конечно, нет. Потому что эти языки ничем существенным друг от друга не отличаются.
Fesor
04.04.2016 10:13Может быть вы просто плохо знаете питон? Ибо если так то можно все приравнять и сказать что джава ну это как хаскель
slonopotamus
04.04.2016 16:14Я не приравнивал джаву к хаскелю. Я приравнивал php к питону (и ruby с perl'ом в ту же кучу). Между ними есть небольшие различия, но они ничтожны между пропастью, которая лежит между любым из этих языков и каким-нибудь C или Prolog.
Fesor
04.04.2016 17:47+1небольшие различия
То есть полностю различающиеся объектная модель, система типов и т.д. это "небольшие различия"? Ну ладно тогда.
SuperKozel
02.04.2016 16:20+2а вот и нет! У меня был свой проводной интернет с локалкой и я рубал в CS 1.3-1.6 сидя дома с фпс 1-5 кадров в секунду
Fesor
02.04.2016 17:40+6Отсутствие стандартизации на низком уровне.
PHP — язык со слабой динамической типизацией. Важный момент, существует слабая и сильная система типов. Например в python и ruby — сильная динамическая. А строгий/не строший — это уже вольности перевода.
Станадртизация на низком уровне есть, просто появилась она всего-то лет так 7 назад, и искоренить просчеты при проектировании языка, накопленные за десятилетие существоания, при наличии миллиарддов и миллиардов строк легаси кода написанного на PHP — задача не из простых.
Скажем слабой динамической типизации мы обязаны Си, у которого слабая статическая типизация. В свое время это казалось удобным и логичным, правда с тех пор требования бизнеса значительно усложнились.
в высоконагруженных сложных системах, где типизация крайне важна
С каких это пор в высоконагруженных системах важна типизация? Да и для сложных систем есть более важные момменты, предсказуемая система типов просто позволяет отлавливать глупые ошибки в рантайме во время разработки а не в продакшене.
В любом случае, есть php7, там тайпхинтинг покрывает значительную долю этих ошибок. В php 7.1 появятся (надеюсь) typed properties, и возможно к версии 7.2 подвезут дженерики, и тогда тайпхинтинг будет полностью обеспечит предсказуемость системы типов PHP. В целом же PHP в этом плане постепенно растет, просто слишком много кода на эти фичи завязаны, потому переход будет очень долгим. Скорее всего мы придем к тому, как строгая динамическая типизация реализована в hack.
Если вы попробуете изменить $objectCopy->foo, вы измените и $object->foo. А в случае с массивом, меняя foo в $arrayCopy, вы измените данные только в $arrayCopy, не касаясь $array.
Ну то есть тот факт что массивы всегда передаются по значению а объекты — по ссылке вас не смущает? То есть массив — это просто значение. Когда мы просто сделали переменную$arrayCopy
мы сделали переменную со ссылкой на массив, а при записи срабатывает copy-on-wirte и массив явно копируется перед изменением. Объекты передаются по ссылке не только в PHP, но и в Python, Ruby и практически во всех языках. Что бы передать объект по значению нужно явно произвести копирование. Есть правда исключения вроде data-only классов в kotlin и т.д. Что-то подобное недавно обсуждалось в php-internals.
Так что сидушку стоит тушить от того что к работе в сложной системе допускают людей, которые не разобрались с основными концепциями языка программирования, который они используют каждый день.
Наиболее эпичным стало добавление ООП в PHP, когда вода с низов давно утекла и утверждение «ООП — это когда все является объектом»
Нет, ООП это когда мы изолируем побочные эффекты внутрь объектов. Использование скажем функций, скаляров и т.д. не противоречит идее ООП.
Как итог, сейчас на ООП в PHP можно делать лишь самую высокоуровневую архитектуру, что без нижней выглядит не очень приятно. но толи еще будет.
Я подозреваю что вы просто не знаете зачем нужно ООП на самом деле. То что внутри объектов — не столь важно сколько взаимодействие оных.
Я разрабатываю на PHP уже 10 лет.
Чисто для статистики… Вы пишите тесты? Как часто? Сколько у вас было максимум тест кейсов на одном проекте?
Сообщество хороших парней.
Отсутствие культуры разработки. Собственно ваши минусы — это следствие культуры разработки. Типизация — решается тестами + тайп хинтингом. Архитектура — решается банально архитектурой, то есть от PHP тут ничего не зависит, объектную модель слизанную у java/c# оно вам предоставляет и ок. А плюсы… ну они из пальца высосаты. Единственный плюс PHP — это то что можно не замарачиваться в большинстве случаев по поводу побочных эффектов. PHP отработал, почистил за нас все, и это позволяет писать страшнейший но работающий говнокод. Это его плюс и одновременно минус, поскольку первые два-три года похапэшники просто говнокодят, пока что-нибудь не случается в их головах.
Old_Chroft
02.04.2016 17:48+6нам придется делать некоторые страшные и глупые вещи
//Выведем второй символ строки Hello World echo (new String('Hello World'))->char(2);
На самом деле — страшно и глупо.
Не надо ругать молоток за то, что он попал не по гвоздю, а по пальцу.// возьмем набор данных типа "строка" из главной палаты мер и весов $str = 'Hello World'; // воспользуемся ЗАДОКУМЕНТИРОВАННЫМИ возможностями языка "типизация" echo $str[1]; // Да, строка в PHP - это еще и массив символов
Akhristenko
03.04.2016 09:42+1К сожалению это работает только для однобайтных кодировок, так как строка в php это массив байтов, а не символов.
Old_Chroft
03.04.2016 15:57Пример из статьи, который я вынес в цитату — делает ровно тоже самое:
Своим комментарием я хотел выказать удивление: зачем автор нагородил целый класс для того, чтобы обращаться к символу "по номеру", а не "по индексу"? Какие-то трудности со счетом от нуля?function char($num) { $num = $num-1; //да-да, не удивляйтесь, мы используем метод объекта для возвращения символа строки как массива return $this->string[$num]; }
А вот кодировки — другой разговор, и это на самом деле не выдуманная проблема. Насколько я помню, PHP-6 как раз из за трудностей с кодировками и бросили.shoomyst
03.04.2016 17:13Только автор может легко добавить поддержку юникода, а вам придется бегать по всему проекту и городить костыли.
PS. Я не очень вникал в предмет спора, просто 5 копеек почему в этом случае ооп-обертка может быть полезна
pistol
03.04.2016 18:29+1Я нагородил целый класс, чтобы в будущем его можно было унаследовать, взаимодействовать с другими классами. Чтобы у нас был объект, а не "не пойми что".
boodda
04.04.2016 10:57но зачем ?
pistol
04.04.2016 13:16Чтобы можно было подменить этот самый ->char в каких-то ситуациях. Редко, но это бывает нужно и на низком уровне. Это я назвал "жестить" в статье.
boodda
04.04.2016 21:05+1чем вас функция не устроила, зачем на все лепить объекты ?
pistol
05.04.2016 07:57Либо вопрос глупый, либо я его не понимаю :) Потому что хочу ООП и на верхнем и на нижнем уровне.
zhigalin
05.04.2016 13:07А ЗАЧЕМ это вам?
pistol
05.04.2016 13:12Для красоты, расширяемости, удобства, безопасности.
Fesor
05.04.2016 14:24+1ООП нужно не для красоты, а для управления сайд эффектами. Если можно для хэндлинга сайд эффектов обойтись функцией — лучше обходиться функциями. А ООП ради того что бы все просто так было объектами — вы таким образом только в болото влезите.
dim_s
02.04.2016 21:19+1Все перечисленные минусы в PHP есть в других языках. Слабая типизация? Она достаточно комфортная и предсказуемая, но не строгая, слабая типизация не должна быть строгой, она должна быть предсказуемой, а в php она более предсказуемая чем например в JS.
Другой минус, который описан в статье, это ООП. Да ладно, далеко не во всех языках все является объектом! В той же Java и C#.
Излишняя свобода? Тоже сомнительный минус, во многих шаблонизаторах на других языках есть возможность исполнять любой код, можно и базу дергать из шаблона если передать нужный объект.
P.S. Не нужно перед кем-то оправдываться, что вы пишите на PHP, все эти холивары языковые бессмысленная трата времени и сил.Veikedo
03.04.2016 09:42-2В c# (да, наверное, и в java) всё является объектом.
А вот копируется ли объект или только ссылка на него (при передаче/присвоении) это другое дело.grossws
04.04.2016 00:52+1Расскажите это примитивам. И там, и там они есть.
Veikedo
04.04.2016 07:29-2То, что тип "примитивный" не делает его не объектом.
Можете объяснить, как отличить примитивный тип от непримитивного?
В C# "примитивный" int (Int32) является экземпляром System.Int32.
Никто не мешает мне написать:
Int32 i = new Int32();
или
Console.Write(457.ToString())grossws
04.04.2016 13:08+1С шарпом и CLR не знаком, поэтому скажу за JVM. Примитив хранится как примитивное значение на стеке jvm (byte, char, short, int, float — 4 байта, long и double — 8), не имеет методов и внутренней структуры.
А объект располагается в куче (на стеке или в полях других объектов хранится указатель размером 4 байта на 32bit/64bit+CompressedOOPS, 8 байт на 64bit без компрессии указателей). По указателю на объект лежит сложная структура, состоящая из заголовка объекта и его содержимого.
Соответственно, объекты при создании всегда размещаются в куче (насколько знаю, в CLR возможно размещение структур на стеке) и имеют сложную структуру, а примитивы всегда располагаются на стеке или в полях объекта и не имеют внутренней структуры, зато более компактны и операции над ними дают существенно меньший оверхед.
В частности, примитивы не имеют методов (т. к. не имеют vtable), но может выполняться прозрачный боксинг в объекты-обёртки, который дают примитивам набор методов (например, в scala это так). В java автоматический боксинг происходит при работе с коллекциями из java.util.collection и подобными, т. к. эти коллекции хранят только объекты.
В scala пошли другим путём и коллекции примитивов могут существовать (если на классе коллекции есть аннотация@specialized
, которая указывает компилятору на необходимость генерации набора реализаций под примитивы).
gro
02.04.2016 21:46+4в функциональных языках не все сущности являются функциями.
в процедурных не все процедурами.
почему в ООП обязательно сто процентов должно быть объектами?MacIn
03.04.2016 00:58почему в ООП обязательно сто процентов должно быть объектами?
Как с этим в Java?grossws
03.04.2016 02:44+1Кроме объектов есть примитивы (char, byte, short, int, long, float, double).
MacIn
03.04.2016 03:35Нет, это само собой, я о методах/процедурах.
grossws
03.04.2016 08:34+1Это приводит к активному использованию static-методов и static initializer'ов, да.
Если же говорить за примитивы, то в том же ruby или smalltalk'е они просто отсутствуют. Ещё более чистые ОО-языки, нежели java.
В scala эти же примитивы не выглядят таковыми за счёт наличия implicit class'ов в predef, которые добавляют большое количество методов к этим "объектам". Плюс они могут использоваться в качестве generic-параметров. Для тех же коллекций крайне удобно (плюс, в отличии от явы, легко сгенерировать специализированные под примитивы коллекции с помощью стандартной аннотации@specialized
)MacIn
05.04.2016 02:40Ещё более чистые ОО-языки, нежели java.
Да, я согласен. Просто Java используется для обучения программированию, например, в ВУЗах, и у подхода "только хардкор, только ООП" ноги растут, втч и отсюда.grossws
05.04.2016 09:59Это где как. У нас Си был, но вполне допустимо было использовать плюсы.
MacIn
05.04.2016 17:49Разумеется. В моем ВУЗе у нас был Паскаль в первом семестре, потом объектный Паскаль во втором семестре и С++ в третьем. Но ты было давно, уж почти 10 лет как, а сейчас с первого на Java сажают.
Fesor
05.04.2016 10:07У нас был C# и javascript, как попытка ознакомить студентов с разными объектными моделями. Но сути это не меняет, из 100-ни студентов что такое инкапсуляция знали все, а вот понимание оной — ну хорошо если 10 человек додумались. Это как бы и не требовалось. И различные принципы вроде SOLID давали мельком сильно позже, и то типа в порядке факультатива. А про GRASP вообще никогда никто не говорит.
А без понимание что такое инкапсуляция, полиморфизм, из которых все эти принципы вылазят, какой толк от такого ООП? А ведь могло бы быть все чуть подругому.MacIn
05.04.2016 17:51А без понимание что такое инкапсуляция, полиморфизм, из которых все эти принципы вылазят, какой толк от такого ООП?
Нам давали понятие ООП во втором семестре, с контрольными и прочими прелестями. Вроде все усваивали. Ну, из тех, кто программировать вообще мог — как и в других местах, были люди, которые пошли на эту специальность из-за «моды».
Но поскольку мы проходили втч и через чисто процедурную методологию, нет стремления использовать ООП ради ООП. А вот у тех, кого учат сегодня, начиная с Java, с этим иначе.
Prapor
02.04.2016 22:09+2Пока все остальные решали как лучше делать, PHP решал проблемы.
ЗЫ.
Всё остальное, попытка оправдать почему PHP смог, а они нет.
KpuTuK
03.04.2016 09:43+1Имя класса/интерфейса PHP 5.0.0
array PHP 5.1.0
callable PHP 5.4.0
bool, float, int, string PHP 7.0.0
wiki.php.net/rfc/typed-properties
Типизация семимильными шагами входит в php
LexaZ
03.04.2016 09:43+2Отсутствие стандартизации на низком уровне
дочитал до этой фразы. дальше читать уже не надо. все ясно-понятно. пишите сайты на с++ и другим советуйте.
andrievski88
03.04.2016 09:43Вопрос, скорее к автору:
– Сейчас реально пройти путь, который вы начали 10 лет назад начиная с все того же PHP?
vasac
03.04.2016 09:43каждый раз поворачивая на 180 грудусов со своего пути.
какие 180? как раз относительная стабильность и плавность одно из немногих его преимуществ.
по сравнению с JS, где как только ты наконец смог осилить какую-нибудь самую супер-пупер мейнстримовую штучку, как оказывается она уже давно устарела и теперь в тренде другая супер-пупер-мега-штучка-пердучка. Правда на гитхабе уже и для неё есть пятьдесят конкурентов непонятно от кого, которые обязательно сделают её устаревшей уже завтра.
или с питоном, где уже скоро десятый год, как на 3-ю версию перейти не могут.
Misanthropist
03.04.2016 09:43В целом, кроме пункта о присваивании и передаче по ссылке, согласен; но(!) документацию никто не отменял. Периодически нахожу там (в документации) очень интересные вещи. Поэтому, обычно, мне трудно ответить на вопрос: чтобы вы хотели добавить в PHP: думаю — скажу, а это там уже есть.
Несомненный плюс PHP — низкий порог вхождения. В универе я начинал с C, а уже в 27 — начать разработку на Python было сложновато. И это ЯП с достаточно высоким порогом входа. А вот PHP пришелся как раз кстати.
andrievski88
03.04.2016 09:55Ответьте человеку, который только начал изучать PHP, что менее печально из двух зол:
- Игнорировать все холивары на тему это лучше, а это хуже, постигая все сугубо на практике и набивая 100500 шишек.
- Читать 100500 тем с холиварами в надежде найти истину и понять, что лучше, а что хуже.
P.S. Вариант три, забить на 1 и 2 и просто учить язык с практикой и нужной литературой.
???
pistol
03.04.2016 10:21Учи PHP и все, он сейчас очень хорош с хорошим фреймворком. Раньше, выучив PHP, было нефиг делать на других языках, сейчас ситуация выровнялась.
andrievski88
03.04.2016 10:45-1Я уже года два клепаю разные "говно сайтики" на free cms и понимаю, чтобы с него (говна) соскочить, надо знать PHP и JS. Начал с PHP. И мне реально это нравится. Я даже забил на все игрухи, которые пожирали невероятно много времени.
coh
03.04.2016 10:25Не читайте холивары, читайте исходники современных гигантов типа Zend, YII, Doctrine, итп. Изучайте архитектуру, приемы программирования.
Fesor
03.04.2016 13:28читать холивары полезно что бы знать на что обращать внимание в процессе обучения, но не увлекайтесь этим делом.
В любом случае я рекомендую вам, если вы хотите развиваться, выучить еще один два языка, желательно не java/c#, то есть использующие совершенно другую объектую модель или фундаментально отличные от пыха идеи (python, ruby, javascript, rust, Clojure). Просто что бы знать что можно делать дела подругому. При этом не нужно бросать PHP.
MartinX
03.04.2016 14:42+1Я не могу сказать, что PHP дико плохой язык, но костыльность и сохранение старья в нем есть. По факту начинал свой путь в программировании с Delphi, но очень быстро перебросился на PHP (веб все же нужен был мне). По началу это удобно, типизация не парит, можно в процедурном стиле писать.
Но со временем понимаешь, что не все в нем удобно для больших проектов. Да и вообще функции стандартной библиотеки (те же строковые) не имеют общего стиля именования, что неудобно (хотя IDE все решает, но без нее приходится подглядывать в документацию). Нестрогая типизация начинает тоже мешать, как и стиль работы PHP: "отработать любой ценой скрипт и умереть".
ООП в нем есть, но язык не является полностью ООПшным. Это просто придаток, которым можно не пользоваться. В отличии от того же C#, Ruby, которые являются полностью ООП языками. Что бесит — это исключения есть, но стандартные функции почти ими не пользуются. Надо городить свои костыли над error_handler.
Что язык являлся шаблонизатором — это да. Но по факту решается тем, что в начале файла просто стоит <?php. Хотелось бы в будущих версиях иметь опцию отключения такой вот возможности смешивания HTML с кодом. Хотя это имеет плюсы, что шаблонизатор не нужен или довольно удобно транслировать шаблоны в PHP-мешанину.
Хоть мне и нравится тот же Python и большие проекты на нем удобнее писать. Как и библиотеки намного понятнее (смотрел Symfony2, но это какой-то академический монстр. та же Django более лаконичная. как и многие другие библиотеки в Python — есть она одна и хорошо выполняет свои функции). Однако же для каких-то простых целей (вроде накидать форму обратной связи) не будешь тащить весь стек другого языка. PHP есть везде и пишется это за пару минут.
То же самое с популярными CMS. PHP есть везде, разработчиков много, порог вхождения низкий, все прекрасно создается. Однако CMS — это тоже отдельная тема. Большинство тоже застряли во временах PHP4, написаны по большей части в процедурном стиле (к ООП лишь при необходимости прибегают), порой опять же та же мешанина из кода и разметки. Хоть они и работают на последних версиях PHP (но это чисто фиксы, тот же WordPress и php-fusion довольно жестоко написаны).
Однако радует, что в последних версиях язык карабкается и улучшается, избавляется от всяких magic_quotes и safe_mode. Я бы не назвал NodeJS приходящей и уходящей платформой, она успешно используется. Среди таких языков я бы скорее выделил всякие Rust, Go, D и прочие, которые молодые, хотят потеснить C/C++, к которым относятся к опаской в серьезных проектах.
И, кстати, JS тоже веселая штука. Возраст с PHP примерно одинаков. Однако имеется прототипная модель ООП, мешанина с object и array (с этой точки зрения в PHP рай), множество реализаций (разные JS движки у разных браузерах, разные версии используемых браузеров у пользователей. но это уже особенность среды исполнения так сказать, ибо серверная часть более контролируемая).
xmeoff
03.04.2016 19:07+2Впервые встречаю исповедь, написанную не от первого лица. Весьма оригинально, ничего не скажешь.
Начинается вроде привычно (для исповеди): "Для начала расскажу одну историю...". А дальше идет что-то непонятное, то ли обвинение, то ли агитация. Но больше всего это напоминает вступление к рекламе ("Ты все еще молод и дерзок? Приходи к нам!"). Только вместо рекламы идет какое-то невнятное и скомканное описание минусов и плюсов PHP. Заголовки пунктов, не имеющие почти ничего общего с их содержанием. Как связаны динамическая типизация и стандартизация? (чего, кстати?) В минусах — нестабильность, в плюсах — (внезапно!) стабильность. Но что особенно доставило, так это мужественность:). Чего, кого? — языка, его создателей, разработчиков пишущих на нем, или, может, лично автора?
onqu
04.04.2016 04:48+3Сложилось впечатление, что человек 10 лет, будучи прикованным к батарее, писал на битрикс. Мои соболезнования.
sl_bug
05.04.2016 09:09На счет плохого ООП — https://www.youtube.com/watch?v=QM1iUe6IofM и https://www.youtube.com/watch?v=IRTfhkiAqPw
Fesor
06.04.2016 00:22Занятные видяшки. Спасибо.
из них я могу сделать вывод что чувака смущает тот факт, что могут быть stateless-объекты, содержащие только поведение без состояния. Вот только он не учитывает в своих примерах зависимости и параметры. Допустим для Net::FTP нам нужны параметры подключения, которые по хорошему должны пробрасываться в конструктор объекта. Путь к файлу — по хорошему тоже (а еще лучше разделить эти методы на отдельные маленькие объекты-сервисы). У нас есть зависимость от FasterCSV. Ну и конечно же работа с транзакциями и т.д.
Вывод — чувак умело скрывает тот факт, что помимо изоляции сайд эффектов ООП позволяет управлять зависимостями.
По сути все его примеры основаны на «я не понимаю ООП и пишу как придется». Если рассуждать так — то да, все плохо. Но это проблема не с подходом а с тем как им пользуются люди. Дайте этим же людям процедурщину и вы погрязните в сайд эффектах.MacIn
06.04.2016 21:47Что вы подразумеваете под stateless объектом? Если мы создали объект, скажем, «connection» и инициализировали через конструктор его параметрами соединения — это stateless или нет?
Fesor
06.04.2016 22:11+1Для начала давайте условимся что понастоящему stateless вещей не бывает. Даже если мы возьмем любую чистую функцию — на каком-то уровне всегда будет состояние.
Что до вашего примера, соединение с базой данных — это состояние. Так что объект вроде-бы stateful. Однако:
function foo(Connection $connection) { // ... }
тут мы понятия не имеем имеет ли объект типа `Connection` какое-либо состояние. Точнее даже, мы знаем что какое-то состояние у него есть, но какое — это детали реализации этого объекта. Скорее всего `Connection` это не конкретная реализация а лишь интерфейс. Соединение с базой? А друг там ленивая инициализация, и пока мы не дернем метод соединения не будет? А возможно это вообще фэйковая реализация, и она просто будет отдавать одинаковый результат на все вызовы.
И в этом собственно весь смысл. Мы как пользователи этого объекта не должны париться о тех побочных эффектах, которые возникают внутри этого объекта. Этот объект должен хэндлить их за нас.
А если же взять какой-нибудь сервисный объект, например, хэшер паролей, у какой-то из реализаций оного может попросту отсутствовать внутреннее состояние. Скажем внутри используетя старый добрый `password_hash` которому кроме аргумента метода больше ничего и не нужно. Никаких зависимости и никаких параметров. Но с точки зрения кода, который будет использовать этот объект, мы не будем об этом знать.VolCh
08.04.2016 11:45Точнее даже, мы знаем что какое-то состояние у него есть, но какое — это детали реализации этого объекта.… Мы как пользователи этого объекта не должны париться о тех побочных эффектах, которые возникают внутри этого объекта. Этот объект должен хэндлить их за нас.
Не совсем так. Контрактом объекта могут быть предусмотрены вполне конкретные состояния, доступные пользователю объекта, как для чтения (через какие-то срезы), так и для модификации (через какие-то команды), которые мы можем, а то и должны учитывать, и по другому некоторые вещи реализовать если и не невозможно, то весьма проблематично. Но хороший контракт объекта (включая, но не ограничиваясь чисто синтаксическими интерфейсами) максимально абстрагирует нас от того, как и где это состояние хранится в самом объекте, как обрабатывается, мы не имеем никакого доступу к самому состоянию, можем лишь получать какие-то его характеристики, и влиять на него, вызывая какие-то команды. Скажем, для объекта соединения с СУБД, мы можем указать кодировку символов наших последующих запросов и его ответов, мы знаем о таком состоянии объекта как «текущая кодировка», знаем как его узнать, знаем, что без нашего вмешательства она измениться не может, но понятия не имеем отдаёт ли объект команду СУБД по переводу кодировки один раз и запрашивает её когда нам нужна текущая, не храня её сам, или хранит и применяет при каждом вызове, а может хранит, но лишь в целях кэширования, чтобы не грузить СУБД запросами если нас заинтересует какая сейчас. Состояние объекта нам известно, мы можем его попытаться изменить, но не должны знать как оно реализовано. По крайней мере пока не столкнёмся с непредсказуемыми изменениями состояния (или отсутствия предсказуемых), нарушающими публичный контракт и не решим дебажить и патчить код объекта сами. А до тех пор у нас лишь абстракция реального состояния, реальной кодировки реального состояния реального соединения (как правило, какой-то переменной в процессе/потоке СУБД, может быть на другом конце мира) «все наши запросы интерпретируются в указанной нами ранее кодировки», кто, где и когда учитывает наше указание, нас не волнует, пока нет признаков, что не учитывает. Побочный эффект от указания кодировки не просто налицо, а он нам требуется, но мы не знаем и не должны знать при обычном использовании как именно этот эффект реализован.
Собственно, можно сказать, что у хорошо инкапсулированного объекта мы, как правило, можем спокойно узнать некоторые аспекты его состояния, а некоторые даже пытаться менять, но не имеем доступа к полному состоянию напрямую и даже не должны знать не то, что как оно реализовано, а каково оно вообще, полное. Разработчик объекта дал нам публичные свойства и методы (или какую-нибудь их магическую имитацию) для получения и изменения тех аспектов реального состояния, которые нас должны интересовать, но это лишь абстрактная модель реального состояния для пользователей, то есть нас. Скажем, простая (вроде бы) коллекция, реализующая ArrayAccess, для нас выступает почти как обычный массив, но реально может хранить данные на другом конце света, причём без нашего ведома на сервере разработчика :)
eee
В PHP 7 можно включить строгую проверку типов:
<?php declare(strict_types = 1);
По мне так надуманная проблема. ООП ради ООП?
Можно взять и прямо в футере шаблона, посреди HTML кода, сделать подключение к базе и записать туда какие-то входящие от пользователя данные из глобальной переменной без экранирования.
Плата за низкий порог вхождения. Да и другие языки позволяют такое делать. На PHP можно писать качественный код.
В целом язык развивается. PHP 7 тому подтверждение.
DrPass
> Плата за низкий порог вхождения.
Я никогда не понимал, почему отсутствие строгой типизации называют «платой за низкий порог вхождения». В первом случае надо всего лишь объяснить, что такое тип переменной. Во втором случае надо объяснять на пальцах, чем 2 отличается от «2», и потом мучительно долго вылавливать мелкие гадостные ошибки, где вместо 4 получается 22 (ладно, в случае PHP спасибо хоть на том, что конкатенация строк и сложение чисел обозначаются разными операторами). По-моему, нетипизированные языки придумали как раз ленивые матёрые программисты, чтобы им было меньше писать кода, а новички больше страдали :)
eee
Новичок будет страдать везде: и в строго-типизированных, и в не типизированных языках. Другое дело, когда новичок так и остается быдлокодить не понимая архитектуры языка.
wordwild
Но ведь работает же!!!
Fesor
тут не в архитектуре дело (любитя это слово красивое завернуть в неверном контексте), а просто люди не понимают что такое сайд эффекты. Ну мол кодит себе допустим php разработчик, и первое время может вообще не париться о сайд эффектах. Локи, работа с файловой системой и т.д. — тут проблемы только при нагрузках могут всплыть. Обработка каждого запроса у нас в отдельном процессе и мы тоже не можем ничего сломать.
Но достаточно просто подключить постоянное соединение с базой данных (что бы ускорить систему) и уже лезут наружу проблемы. Или демон написать. Или еще чего. Допустим у node.js ребят осознание что сайд эффектов надо боятьсяи прятать их вылазит намного раньше просто потому что у них могут обрабатываться сотни и тысячи запросов в одном процессе, а стало быть код может случайно влиять на то кому что достается.
bapewka
declare(strict_types = 1);
Работает только на тайп-хинтинг, то есть отключает приведение типов в аргументах функций.
Такая каша всё равно допустима:
print 1+1; // 2
print 1+'1'; // 2