Как стать автором
Обновить

Комментарии 111

ЗакрепленныеЗакреплённые комментарии

Думаю у меня получилось! Попробуйте код и посмотрите стек вызова:

<?php

function fibGenerator($n) {

    if ($n === 0) {

        yield $n;

        return;

    } else {

        yield $n + ($n - 1);

    }

    yield from fibGenerator($n - 1);

}

foreach (fibGenerator(7) as $x) {

    var_dump($x);

}

Да, считает он не то что нужно, правильной вариант я доработаю и допишу в статью.

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

Рекурсии у вас просто принимает номер числа и считает, а генератор лениво последовательно ищет бесконечность чисел.

Аналогом генератору должна быть функция, возвращающая массив чисел Фибоначчи до n. Ее алгоритм будет такой же, да и стэктрэйс примерно тоже

Поменяйте пожалуйста название. Не соответствует статье

debug_print_backtrace(); заменить на echo $k . PHP_EOL;

нет, вы все ещё будете считать рекурсивно и у вас выведется дерево кажется, а не последовательность.

Алгоритм такой же как в генераторе. Только вместо yield какой-нибудь пушбэк в выходной массив

Я сначала тоже хотел порекомендовать убрать всё словоблудие про джуниоров и оставить только код. Но потом присмотрелся уже к коду ?...

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

  • то ли невнятное словоблудие про мемы и джуниоров

  • то ли пример кода, представляющий собой традиционное шулерство: берем цикл while который и делает всю работу, зачем-то оборачиваем его в генератор, и все лавры отдаём последнему

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

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

Пришлось запускать 2 раз, был неправ. Но присмотритесь к моему коду, в цикле while есть ключевое слово yield.

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

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

Но проблема шизофазии, увы, все равно остаётся. Так что лучше уж оставить статью как есть. Сама она служит наглядным примером мышления зумера, воспитанного тиктоком, а текущий пример - иллюстрацией поговорки "смотрит в книгу - видит фигу" :)

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

И ещё, в меня закрадывается подозрение, что вы так и не поняли свою ошибку. И тут я с вами полностью согласен:

Думаю что не каждый тимлид ответит вам на вопросы про генераторы.

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

Поэтому очень важно рассказывать тимлидам про генераторы 
@AlexUnderCover не забудьте рассказать еще про существование кешей и hashMap

Вы в цикле while вызываете debug_print_backtrace(); 7 раз. Мой код обращается 7 раз к функции-генератора которая включает в себя цикл while. Это ведь разные вещи.

Ну где они разные-то? :)
В обоих случаях один и тот же цикл while выполняет одну и ту же работу, отработав 6 итераций.

 Мой код обращается 7 раз к функции которая включает в себя цикл while. 

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

Посмотрите какая функция выводится в трейс с вашим примером и сравните с примером из статьи. У вас не вызывается никакая. И вы мне говорите что это тоже самое?

Я скоро устану. То, что вы даже близко не поняли, как работает генератор - это не беда. Как вы сами заметили, это в принципе мало кто понимает. И я готов объяснять. Но ваши реплики выглядят так, как будто вы хотите поспорить, а не разобраться. И с этим я уже ничего не могу поделать.

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

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

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

Я заостряю внимание в статье на стек не просто так, и ваше тоже. Из-за своей токсичности вы просто этого не замечаете.

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

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

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

В статье я прошу читателя запустить генератор на 100 чисел из последовательности и запустить рекурсивно на те-же 100 чисел. Понимаю что просьбу вы мою проигнорировали, ведь там же и кроется главный вывод по коду (но не статьи): Генератор помогает нам выигрывать за счет работы с функцией. А стек, как часть работы с функцией это наглядный пример.

Думаю наоборот что минусы это хороший показатель того что я хочу сказать

О, господи.

Не генератор вам помогает, а цикл. А генератор здесь нужен, как корове седло.

Я вам говорю про стек вызова, вы мне про результат функции. Зачем?

Смотрите, я попробую в последний раз.

  1. Вы изобрели вычисление чисел Фибоначчи с помощью цикла. Ускоряет вычисление сотого числа цикл. Короткий стек вызовов получается благодаря циклу. Ваш пример на самом деле про банальнейший вопрос, цикл vs. рекурсия при вычислении чисел Фибоначчи, который разбирался миллион раз. Это просто два разных подхода к решению задачи.

  2. К этому циклу вы присобачили совершенно ненужный здесь генератор.

  3. И дальше вы вообразили, будто подход остался тот же (рекурсия), а проблему со стеком решил генератор. Ну так вот, говоря без обиняков - это бред. Вы использовали другой метод вычисления. Цикл вместо рекурсии. Который решил проблему со стеком. А генератор здесь никакой пользы не приносит, и в принципе не нужен.

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

Мне кажется вы не до конца выделили главную мысль 2 пункта вашего комментария. "Совершенно ненужный здесь генератор.". Здесь это где? В комментариях где я не могу вам объяснить что не важен получаемый результат. В пример я не привожу результат функции, я привожу стек вызова функции! Напишите функцию которая за 7 вызов подряд самой себя, прошу заметить без входных параметров, даст вам число из последовательности Фибоначчи. - это будет примером а не цикл while, он тут вообще роли не играет, как и результат, скажу еще раз, на всякий случай. Вот вам будет задачка на вечер.
Но опять же эта функция последовательности Фибоначчи может получится у вас и без генератора, например через анонимную функцию и замыкание, да хоть на листке с бумажкой посчитайте, результат тут не важен. А в статье генератор нужен по конкретно описанной мной причине.

Напишите функцию которая за 7 вызов подряд самой себя

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

Но это, разумеется, не так. Добавив генератор, вы не "переписали рекурсию". Вы отказались от неё. Вы взяли цикл, и посчитали число фибоначии не рекурсией, а циклом. А потом навесили на этот цикл ненужный генератор, только для того, чтобы увидеть в стеке вызовов вожделенное имя функции! Как по мне - это на редкость дурацкая самоцель, но не будем на этом останавливаться. Куда важнее то, что ваше утверждение, процитированное выше, не имеет ничего общего с реальностью. Генератор не вызывает сам себя. Обращения к генератору не увеличивают глубину стека вызовов. Вы можете перебрать с помощью генератора хоть миллиард значений - и ваш стек будет оставаться мягким и шелковистым. В отличие от рекурсии.

Это моя оговорка, конечно генератор не вызывает сам себя. Что такое генератор я привожу в статье как цитаты из документации.
Думаю что-бы понять о чем я говорю вам нужно чтобы вы написали такую функцию которая после 7 вызовов, вот так:
<?php

fib()
fib()
fib()
fib()
fib()
fib()
$fib_result = fib()

Вернет вам правильное значение из ряда чисел в переменной $fib_result. Цикл while в примере это всего лишь обертка этого вызова.

Написал. Дальше что?

Теперь попробуйте что-бы на последний вызов (любой, не только седьмой) функции она вызывала себя (к слову о рекурсии), но результат ее был "Ответ выведен"

зачем?

Спасибо что помогли мне придумать хороший пример к статье.

Чтобы попробовать, что такое генераторы в РНР, мне не нужен идиотский код, который решает несуществующую проблему.

Поэтому потрудитесь объяснить, что вы имеете в виду под "чтобы на последний вызов функции она вызывала себя". Как вы себе представляете этот код.

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

Код в статье не решает проблем

6 часов назад вы так не думали. А раздувались от гордости за свое гениальное решение проблемы нахождения сотого числа Фибоначчи

вы сможете написать эту функцию.

Хорошо. Я напишу. Но потрудитесь объяснить, что она должна делать. Что конкретно вы себе воображаете под "при последнем вызове должна вызвать сама себя." Потрудитесь объяснить свои хотелки нормальным русским языком, а не этим вашим неграмотным бормотанием себе под нос.

Я вам и пишу - попробуйте на последний вызов функции после подсчета чисел Фибоначчи из этой-же функции вызвать себя и получить строку "Ответ выведен".

Проше говоря рекурсия, про что я сразу и упомянул.

Давайте вернемся к примеру из комментариев выше и дополним его что-бы было понятно что я хочу показать. Смотрите:

<?php

fib()
fib()
fib()
fib()
fib()
fib()
$fib_result = fib()
$string_result = fib()

Немного упростим задачу. Попробуйте что-бы на 8 вызов функции, она "вызывала" себя же и вы получили в переменную $string_result строку 'Ответ выведен'.
P.S. Сравнивать функции и генераторы не совсем корректно. Они взаимосвязаны, но функция описывающая генератор это его часть, что очень важно понимать. Попробуйте добиться этого поведения через генератор.

Я не понимаю, что значит "вызвала" себя же. Почему в кавычках? Так вызвала или нет? Словами у вас не получается изъясняться, русский язык вам дается с большим трудом. Мы это уже поняли. Попробуйте написать кодом. Покажите код, который делает то, что вы хотите. Тогда я пойму, что вы с таким трудом силитесь сказать.

Когда вы вызовите функцию в 8 раз. Функция в своем теле еще раз "вызывает" себя. После выполнения вызова она вернет вам строку. В кавычки я беру слово "вызвал" потому-что используя обычные функции вы этого поведения не добьетесь. Но вот функция-генератор так может. Более правильно будет сказать так - генератор обратился к своей функции (вызвал)

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

Наконец-то я понял о чем вы говорите. И вы абсолютно правы, в статье я выигрываю в производительности и стеке за счет цикла while, а не из-за использования генератора. Завтра отредактирую публикацию и приведу нормальный пример.

Думаю у меня получилось! Попробуйте код и посмотрите стек вызова:

<?php

function fibGenerator($n) {

    if ($n === 0) {

        yield $n;

        return;

    } else {

        yield $n + ($n - 1);

    }

    yield from fibGenerator($n - 1);

}

foreach (fibGenerator(7) as $x) {

    var_dump($x);

}

Да, считает он не то что нужно, правильной вариант я доработаю и допишу в статью.

Я долго втыкал в этот код, и кажется понял, как он работает. Вы переписали цикл на рекурсию, в которую потом впилили свой любимый генератор :)

Но это не та рекурсия, которая у вас в первом варианте. Это просто второй вариант, с циклом, реализованным через хвостовую рекурсию. А не оптимизированный с помощью генератора первый вариант - что, как я понимаю, являлось вашей целью.

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

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

:))))

Ваша упёртость могла бы найти гораздо лучшее применение.

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

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

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

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

И это не говоря уже о том, что у цикла, переписанного на рекурсию, стек будет короче, чем у вашего "дегенератора".

Мне к сожалению запретили писать чаще чем раз в час.

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

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

Но давайте отвлечемся от генераторов и взглянем еще раз на название статьи.

Как будто бы мы в комментариях как в рекурсии.

Честно, не понимаю откуда столько минусов. Я не утверждал что нашел что-то новое, хотел сказать что новое, как бы это очевидно не звучало, надо искать.

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

К слову статья не называется "я нашел новый алгоритм". Статья про то как я использовал язык по другому. Что я в ней и подчеркиваю.

Я писал выше, но мельком. Напишу подробно. Минусы идут по трем основным направлениям:

Во-первых, чудовищная сумбурность статьи. Совершенно непонятно, о чем она, и что вы вообще хотели сказать. Минусы показывают, что вам еще учиться и учиться писать статьи. И в первую очередь - структурировать свои мысли. Я предполагаю, что вы не злоупотребляете чтением книг и выше тройки за сочинения в школе не получали? Умение писать тексты, увы, не появляется из ниоткуда.

Во-вторых, очень много людей обратили внимание на то, что от джуна как раз НЕ требуется "использовать язык по-другому", да еще и на пустом месте. От него требуется писать максимально стандартный код. А вот эти выкрутасы чаще всего приводят к проблемам, от которых потом сеньоры за голову хватаются. Что мы и видим в данном случае - вы написали код, непонятно зачем, который непонятно как работает, и непонятно какую задачу решает. Минусы говорят о том, что вам ещё рановато давать советы другим джунам.

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

"Вы можете переписать её на обычную функцию без всяких генераторов."

Напишите что-бы при последнем вызове она возвращала строку 'Отсчет закончен'. Дежавю.

Вывод фразы "расчет окончен"не имеет ничего общего с решаемой задачей. Да, в генератор можно добавить лишний yield. И ЧТО?

Какое это имеет отношение к расчету числа Фибоначчи? К самому алгоритму? Никакого. Я могу посчитать циклом, и вывести эту фразу, за которую вы так цепляетесь, по его завершении.

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

И запомните уже наконец, "чтобы" пишется вместе.

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

Кстати да. Еще одна причина минусов - это ваша упёртость, и нежелание слышать собеседника. после полусотни коментариев вы все-таки признаёте, что были неправы, и тут же начинаете упираться в чем-то другом :)

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

Что-бы попробовать что такое генераторы в PHP. И причем здесь рекурсия.

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

А не то что вы там приводили в примере. Благо, как вам уже раза 3-4 (если не больше) написали - код ещё больше можно оптимизировать и ускорить просто избавившись от этих самых генераторов. К слову, рекурсия, подозреваю, тоже будет быстрее (но не в вашем коде, кажется) за счёт хвостовой оптимизации (а я даже и не помню, есть ли она в пыхе?).

Ответ в закрепленном комментарии

Кто дочитал ветку досюда, пририсуй вагончик...

   o O___ _________
 _][__|o| |O O O O|
<_______|-|_______|
 /O-O-O     o   o

Генератор помогает нам выигрывать за счет работы с функцией.

Я не пхпшник, но уже понял, что за генератор. Не генератор помогает. Вот вам для сравнения код на другом языке без генераторов, без рекурсии и даже без while. "Стек вызовов" "плоский".

static void Main(string[] args)
{
    Console.Write("Введите конец диапазона от 1 до ");

    if (int.TryParse(Console.ReadLine(), out int end))
    {
        // бизнес-код начало
        int j = 1;

        for (int i = 0; i <= end; i += j)
        {
            Console.Write("{0} ", i);

            if (i > 0)
            {
                j = i - j;
            }
        }
        // бизнес-код конец
    }

    Console.ReadKey();
}

Не могу прокомментировать ваш код по причине того что не знаю как генератор выглядит под капотом языка который будет компилировать пример.
Перед написанием статьи я обращался в git-репозиторий движка Zend и посмотрел как выглядят генераторы там. Что собственно и толкнуло меня на написание статьи. И опять же, дело не в результате, дело в том каким способом мы используем PHP что-бы получить этот результат.

А какая была реальная задача, где вы применили генератор и он вам помог?

Постараюсь рассказать в следующей статье.

даже без while

Ну, вообще говоря, for - это синтаксический сахар для while :)

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

А while -- это синтаксический сахар для goto. Шах и мат, шахматисты! =)

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

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

А вот внутренняя кухня компании-разработчика - это процессы разработки. И да, об этом надо спрашивать у коллег.

Проблема очень многих джунов в том, что вместо того, чтобы вникать в суть бизнес-процесса, они начинают рассуждать о числах Фибоначчи и генераторах.

Алгоритм переписали с рекурсии на генераторы, чтобы что? Чтобы на код ревью блеснуть тем, что знаешь какую-то редко используемую фичу языка? Код получился длиннее и непонятнее, значит потенцально будет дороже в сопровождении. А какова выгода? Насколько быстрее стал проходить рассчёт? Насколько изменилось потребление ресурсов? Ну и два главных вопроса: на сколько миллисекунд сократилось время загрузки страницы, и сколько денег сэкономит клиент за счёт снижения нагрузки на сервер. Полагаю, в обоих случаях ответ будет ноль.

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

НЛО прилетело и опубликовало эту надпись здесь

Если честно, всё это литкодопоклонничество мне абсолютно не понятно. Я не вижу никакого практического смысла спрашивать это на собеседованиях. Более того, за свою 10-летнюю карьеру разработчика я не видел ни разу, чтобы это где-то действительно спрашивали. И не знаю лично ни одного человека, у которого это спрашивали на собесах. Иногда даже кажется, что это какая-то выдумка, потому что не может быть так, что все вокруг говорят о чем-то, но никто не сталкивался с этим.

НЛО прилетело и опубликовало эту надпись здесь

Собеседовался обычно в небольшие аутсорсинговые компании численностью 15-100 человек. Тестовое задание видел в последний раз в 2016 году.

обычно спрашивают что-то о чем знают сами в силу опыта или о чем читали недавно

Это вообще какой-то странный кейс из разряда, что джуна попросили провести собес. У опытного разработчика обычно есть в арсенале пару вопросов, по которым полностью понятно, что из себя представляет человек. Например "расскажи про контейнер зависимостей в Symfony" - и тут сразу понятно будет с чем человек работал, какой у него уровень, насколько хорошо он понимает ООП, паттерны и всё остальное

А чем DI контейнер в Symfony отличается от других реализаций DI контейнера?

Принципиально ничем, но это вовсе не теоретический вопрос, т.к. постановка вопроса не "что такое DI контейнер?", а "расскажи о DI-контейнере в Symfony". Если человек собирается тянуть в проект на Symfony какую-то свою реализацию контейнера, то такому лучше с ходу отказать. Ну и в процессе рассказа будет понятно, насколько большой или небольшой у человека опыт. И ответ на такой вопрос невозможно заучить. Более того сам вопрос не подразумевает наличие единственно правильного ответа.

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

Вот по вашему ответу я уже склоняюсь к тому, чтобы сказать вам "Спасибо, вы нам не подходите". Задавая такой вопрос, я ожидаю услышать о том, как объявить сервис, как его использовать, как передать в него аргументы, что такое автовайринг, какие опции можно задать в yaml-файле конфигурации, как декорировать сервисы, что такое ленивые сервисы, зачем сервисам теги. И если человек может по каким-то пунктам привести примеры из своего опыта, где он это использовал или хотя бы где он видел, как это используется, то это выйдет рассказ минут на 40. И сразу будет понятно, какой у человека опыт, с какими проектами он работал, и какова была лично его роль в реализации этих проектов.

Хм, ну ок, значит мы бы с вами точно не сработались. Объявлять сервисы и их аргументы можно в любой из известных мне реализаций контейнеров, декорирование - почти в любой. Тегирование есть в контейнере Ларавеля, например, а автовайринг - в Spring. Поэтому непонятно, что именно из перечисленного вами является особенностями именно контейнера в Symfony и мне как кандидату вообще неочевидно, что вы ожидаете услышать...

Вы упорно не понимаете вопрос. Вы почему-то считаете, что вас сапрашивают про "именно особенности контейнера в Symfony".

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

 про невозможность обращаться к контейнеру в контроллерах

В каком смысле невозможность? Кто вам запретит?

Симфони :)

Симфони мешает реализовать свой контроллер?

Согласен, "невозможность" не очень удачный термин. Для документации. Для описания своего опыта - вполне подойдёт.

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

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

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

Вопрос был "расскажи о DI-контейнере в Symfony". Где вы в этом вопросе увидели что-то об отличиях контейнера Symfony от других реализаций?

Тегирование есть в контейнере Ларавеля

И что с того? Значит ли это что тэгирования нет в Symfony. Представьте, дали вам на работе что-то сделать в проекте на Symfony. И надо там объявить сервис с тегом. И что вы будете делать, ведь тэгирование есть в Laravel, а у вас проект на Symfony? Станете из-за этого решать задачу обходным путём? Звучит глупо? Но ведь вы сами дали такой ответ на уточняющий вопрос.

Если в рассказе о DI-контейнере Symfony человек не упоминает тэги, то тут два варианта, либо он просто забыл о них сказать, (что в принципе нормально, потому что рассказать можно ещё много чего другого), либо он просто не знает что это.

мне как кандидату вообще неочевидно, что вы ожидаете услышать

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

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

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

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

Попросить запроектировать что-то - это тоже вполне универсальный способ оценки знаний. Если конечно речь идёт именно о рассказе в стиле "как бы я проектировал вот это", а не о том, что нужно выдать готовый и работоспособный код проекта))) Если бы я собеседовал кого-то, скажем, по реакту, я бы тоже попросил что-то спроектировать, потому что я пока ещё не придумал такой вопрос по реакту, чтобы по ответу на него был виден столь объёмный срез, как по вопросу о контейнере зависимостей.

НЛО прилетело и опубликовало эту надпись здесь

Если вы по такому вопросу можете только пересказать документацию, то я бы мог вам смело предложить позицию джуна. Кандидат на более высокие позиции сможет дополнить свой рассказ пояснениями, зачем это всё вообще нужно и где это используется.

В точности аналогичная ситуация произошла и с автором статьи - он прочитал и выучил документацию по yield, но пока ещё не понял, зачем.

НЛО прилетело и опубликовало эту надпись здесь

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

В подавляющем большинстве случаев от работника требуется умение опытного ремесленника. Когда последний раз от вас (от нас) на работе требовалось применить нестандартный или хитроумный алгоритм с пользой для дела?

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

Насколько я понимаю -- сама статья и подобная подводка появилась просто потому, что человек впервые увидел конструкцию, которая не похожа на типичные while/if/for/do/etc. Это вполне типично и нормально для любого джуниора, ничего страшного в этом нет.

Однако, хочу заметить почему такая реакция сообщества:

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

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

  • В-третьих, есть delcare ticks, которые позволят творить ещё большую магию. Удивления тут будет ещё больше.

  • Если нужно ещё больше наркомании, то можно ознакомиться с FFI и делать паузы в выполнении функции напрямую отправляя команды в VM. Тут глаза у вчерашнего джуниора вообще могут на лоб вылезти.

  • О, а ещё можно это сделать через создание нового потока или подпроцесса, и работу через SysV очереди или сигналы. Тут ещё больше наркоты всякой можно запилить.

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

  • P.P.S. Реально получилась бы прикольная статья про инлайнинг подобного вычисления. А уж особенно, если это как-то решалось бы через VM, как это сейчас делается для strlen, is_null и других функций.

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

P.S. Ну и тимлид -- это всё же больше полу-менеджерская полу-разработческая позиция и на такой позиции не обязательно знать всё подряд, задача -- принимать решения что делать и кому делать исходя из вводных данных. Любая позиция сеньора требует на порядки больше технических знаний и умений. Так что тимлидам можно даже код не знать как писать... в теории, конечно)

НЛО прилетело и опубликовало эту надпись здесь

ну да. если вы не знали, у каждого языка программирования есть свой кармический уровень, у java и с# он настолько чистый, что все чакры открываются автоматически, где-то посередине программисты на go проводят часы за медитацией, в самом низу, на восьмом кругу ада, программисты на php и javascript обречены на бесконечные страдания. /s

НЛО прилетело и опубликовало эту надпись здесь

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

НЛО прилетело и опубликовало эту надпись здесь

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

Я пишу, собственно, на основе собственного опыта как со стороны заказчика (складские приложения, WMS), так и со стороны человека, немного разрабатывавшего кое-что и лично.

В идеале - оно, как вы сказали, и ДОЛЖНО работать. Но между ДОЛЖНО и ПРАКТИКОЙ - огромное расстояние.
Начинается с того, что люди, которые работают с клиентом, очень смутно представляют процессы клиента, и клиент закономерно может не суметь эти процессы объяснить (потому что заказывают разработку не каждый день). Кроме того, сам клиент может собственные процессы представлять не полностью (нельзя объять необъятное), и зачастую, людей, непосредственно в процессы вовлеченных, никто даже и не спрашивает на этапе составления ТЗ. Документ, который исходит от клиента после согласования ЗАВЕДОМО искаженно отражает реальные процессы клиента. Например, многие вещи выясняются только когда начинают масштабировать на проде с кучей пользователей. Но все идет далее. Не понявший до конца процессы архитектор с техлидом закладывают решение, которое мешает в будущем дорабатывать систему под РЕАЛЬНЫЕ нужды клиента, а не те, которые удалось собрать и прописать в ТЗ. Свои методы, точно так же вслепую, имея перед собой неверную картину прописывают и разработчики свой код. В результате все сделано, как сказано, деньги получили, а клиент продуктом пользоваться не может. Ладно, предположим, клиент не порвал все договоренности и не убежал к конкурентам, начали исправлять. И выясняется, что эту фичу мы не сможем сделать, так как она противоречит архитектуре, эта будет стоить как чугунный мост, потому что надо переписывать всю структуру объектов, тут нам надо протаскивать один признак через море регистров и так далее.

Ваша аналогия с домом некорректна. Потому что промышленные/бизнес процессы живые и меняются, и имеют массу нюансов. Программный продукт - это практически всегда конструктор, содержащий в себе инвариантность. Потому исключить уточнения и доработки вообще невозможно. И тут выясняется, что чем лучше работники понимают ОБЩУЮ КАРТИНУ, чем больше они осведомлены о процессах заказчика, тем меньше вероятности, что придется что-то очень сильно менять.

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

НЛО прилетело и опубликовало эту надпись здесь

Рекурсии у вас просто принимает номер числа и считает, а генератор лениво последовательно ищет бесконечность чисел.

Аналогом генератору должна быть функция, возвращающая массив чисел Фибоначчи до n. Ее алгоритм будет такой же, да и стэктрэйс примерно тоже

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

https://web.archive.org/web/20130203112951/http://www.vr-online.ru/old/review.html@id=130.html

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

Лол, не пофиг ли) Многие компиляторы на сколько знаю сами умеют разворачивать рекурсии в for/each/while чтобы уйти от проблемы глубины стека (агрессивная оптимизация в компиляторе флаги).

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

Статья называется "Когда в первый рабочий день джуном смотришь на свои задач", то есть подразумевается, что всё непонятно, не можешь понять, что там написано и для чего.
Прочитав статью, я тоже сначала не понял, что в ней вообще написано и для чего.
А теперь понимаю - это просто пример, чтобы человек вспомнил свой первый рабочий день.

Джуны на 'бизнес' задачах сталкиваются наоборот с тем, что не нужно доводить решения до идеала, а реальность работы - ХХ и в прод, чтобы показать результат заказчику. Что код, который они красиво оптимизировали, никто не посмотрит, а компании дешевле докупить мощностей, чем оплачивать время на перфекционизм. А в статье нечто обратное, тиктокерское.

А теперь сравним со стеком вызовов с вычислением чисел Фибоначчи через формулу Бине:

function fib($n) {

$phi = (1 + sqrt(5)) / 2;

return (pow($phi, $n) - pow(-$phi, -$n)) / (2 * $phi - 1);

}

#0 C:\xampp\htdocs\fib.php(40): fib(7)

Конец стека вызовов.

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

В реальной практике (если вдруг действительно нужны Фибоначчи), к этому способу в нагрузку понадобится длинная вещественная арифметика, помимо длинной целочисленной. Так что, имхо, проще взять "fast doubling" и не морочить себе голову.

Как же сложно всё. В C# тема yield return/break как-то вообще легко воспринимается, и о таком суръезном слове, как "генератор", я и помыслить не мог. На IEnumerable строится весь Linq, который является, наверное, одной из базовых фишек .net, который уж тимлид ну ни как не может знать (если только он C# ни когда в глаза не видел).

Ну вот видите, какая плезная статья для вас оказалась. Когда дорастете до тимлида, то будете называть генераторы правильно, а не "тема yield" :)

Мне больше интересно все эти вопросы с собеседований, вроде такого, как минимальным числом заездов из 25 лошадей по 5 в каждой группе найти самых быстрых, как узнать с какого этажа стеклянный шарик разобьётся, все эти числа Фибоначчи в реальной работе как-то используются?

НЛО прилетело и опубликовало эту надпись здесь

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории