Комментарии 1153
Разработчик изучает только то, что ему нужно по текущей задаче: ничего, кроме этого, и ограничивается минимально возможным набором знаний.
Делает по решениям, подставляя код, а не разбираясь в принципах. Вот в памяти
и не остается.
28 вопросов на самом деле очень легких. Широта знаний и практический опыт.
Большего от кандидатов не требуется, но они и этого не предоставляют.
Зачем тогда идут? Неужели не стыдно отвечать «не знаю» на собеседовании
себя, как специалиста
А как узнать знаю или не знаю, пока не видел вопроса?
Я вот с более чем 10 летним опытом, но на собесах иногда на очень простые вещи могу не ответить. А где-то прохожу собес в легкую и потом никого не разочаровываю (вроде). В примерно одинаковых по запросам вакансиях
А как узнать знаю или не знаю, пока не видел вопроса?
Я вот с более чем 10 летним опытом, но на собесах иногда на очень простые вещи могу не ответить.
Учить, повторять, использовать знания на практике. 10-летний опыт при белых пятнах,
видимо, в теории? Меня бы не впечатлило
2. Теоретические знания помогут на практике только чтобы осадить ретивых коллег в комментах к пулл-реквесту или надуть щёки на собеседовании, чтобы лягушка показалась больше, опаснее и увесистее. Ну, наверное эти слои брони хороши для кандидата, раз он их на себя навешивает. Только вы нанимаете писателя кода руками или говорителя ртом университетских лекций?
Знания per se, на мой взгляд, в решениях проблем имеют более низкий приоритет перед умением своевременно их отыскивать и применять.
Не снимаю вину с интервьюера и вопросов по конкретным
методикам — логичнее выглядит поставка формальной задачи для
оценки хода рассуждений кандидата.
Но при собеседовании сеньора ни один работодатель не будет
готов услышать «не знаю». Понятно, что узнает, разок прочитав.
Но реноме по первому впечатлению в глазах руководства
будет не очень
Но при собеседовании сеньора ни один работодатель не будет
готов услышать «не знаю»
вы переоцениваете и работодателей и соискателей и ситуацию на рынке, чтобы так считать
при собеседовании сеньора ни один работодатель не будет
готов услышать «не знаю»
а что, сеньор обязан в голове держать весь scope сабжевого стека, которым он пользуется?
я вот, например, пересеньор Java, но нюансы Core Java — такие как JMM, ассортимент GC, и подход к реализации compare-and-set навскидку не помню, потому что давно не сталкивался с performance issues. И я спокойно отвечаю на подобные вопросы — «не помню». Но столкнувшись с проблемой и легонько погуглив — вспомню. В том числе, и что я делал, и как решал. Просто некоторый опыт лежит в cold storage и без нужного количества ассоциаций из глубин памяти не поднимается.
А если зарплатодатель хочет пафосного решения задачек на вайтборде/листочке — это без меня, пожалуйста. Я пришел участвовать в решении реальных проблем, а не академических коней в вакууме.
Вы в вакансии видите список скиллов требуемых для работы. Видите в вакансии описание обязанностей. Ну сложите паззл в голове перед собеседованием. Подумайте что вам понадобится знать. Освежите память. Че вы прям на собеседование без подготовки идете даже описаниемвакансии не прочитав?
Че вы прям на собеседование без подготовки идете
Да. Знаете почему? Чтобы на испытательном не выглядеть бледно. Можно пройти любой собес задрочив теорию. А испытательный слить, столкнувшись с задачами, которые превышают ваши скиллы.
даже описаниемвакансии не прочитав?
Ну, почему же. Прочитав. И даже часто погуглив отзывы кандидатов. Но когда речь заходит «давайте нарисуйте на листочке» — говорю, что мне это неинтересно. Дальше — по обстоятельствам.
Обычно крупноблочного разбора близких к бизнесовым кейсов на уровне сеньора/лида/архитекта хватает.
Че вы прям на собеседование без подготовки идете
Это не школа и не ВУЗ. Где можно выучить перед экзаменом за день-два, а потом благополучно забыть навечно.
Вас нанимают как профессионала в какой-то сфере.
Стать профессионалом, прочитав за день перед этим «билеты по экзамену» невозможно.
Что-то можно освежить в голове. Но не более.
А львиная часть профессиональных познаний и навыков при вас всегда, пока вы работаете в этой сфере.
Стать профессионалом, прочитав за день перед этим «билеты по экзамену» невозможно.
Простите но вы ерунду какуюто говорите я не о том чтобы выучить а о том чтобы осведить в памяти. Идя на турник вы же мышцы разминаете как оо связки готовите к нагрузке? Или рвете 20 раз без разминки и подготовки?
Простите но вы ерунду какуюто говорите я не о том чтобы выучить а о том чтобы осведить в памяти. Идя на турник вы же мышцы разминаете как оо связки готовите к нагрузке? Или рвете 20 раз без разминки и подготовки?
Сравнивать умственную деятельность, которой вы занимаетесь как профессионал ежедневно полный день?
С физической деятельностью, которой вы занимаетесь через день в течение пары часов?
И после этого ерунду говорю я?
простите, но даже как профессионал занимаясь этми каждый день мне нужн овремя на раскачку подготовку концентрацию и освежить в памяти что вчера было. так что вы тут зря пытаетесь натянуть сову на глобус
простите, но даже как профессионал занимаясь этми каждый день мне нужн овремя на раскачку подготовку концентрацию и освежить в памяти что вчера было. так что вы тут зря пытаетесь натянуть сову на глобус
Не прощаю.
Разве речь шла о том, что с вами будут проводить 5-ти минутое блиц-интервью, где вам нужно показать всё, что вы умеете?
Напротив, если вы читали статью — речь о довольно обстоятельной неспешной беседе.
Рвете 20 раз без разминки и подготовки?
Да, 20 раз без разминки сделаю и не замечу. А вот условно уже 40 вряд-ли, но подготовив мыщцы(около недели-двух) смогу сделать без проблем. Именно подготовив конкретные мыщцы(ака конкретный навык). Для этого необходим бэкграунд.
травма вам обеспечена. я вас честно говорю. как потерпевший
Пысы я это писал к тому, что если ты привык к определенной комфортной нагрузке, то и готовится нет смысла. А то дальше нужно будет постоянно рекорды ставить, можешь ты это или нет. Лучше расширять границы рутины, чем делать до предела. И это не важно, спорт или работа.
Пысы 2. пересмотрел профиль, за время вашего опыта у вас наверняка были какие-то личные нюансы, которые повлияли на получение травмы.
А че так со штпнгой? Подошел и 100 раз раанул. Без разминки и подготовки. Ну как на собеседовании.
Простите, но когда я мог подтянуться 100 раз "силой" (в юности пытался заниматься спортом, в итоге из-за травмы завязал), 20 раз без разминки-подготовки для меня было абсолютно безопасным... Сильно от бэкграунда зависит...
Не поверите, но когда перестал готовиться к собеседованиям лет 10-15 назад, то их качество резко возросло.
И я спокойно отвечаю на подобные вопросы — «не помню»
Не знаю, не помню, не пробовал — три огромные разницы. :)
Качественные
Но при собеседовании сеньора ни один работодатель не будет
готов услышать «не знаю».
Вот как раз от сеньора вполне ожидаемо получить ответ "не знаю" на сугубо теоретические вопросы, которые джуны заучивали огромными списками перед собеседованиями.
Не готовый услышать «не знаю» работодатель в интервью
спрашивает про задачи, которые решал соискатель, а не
углублялся в детали определенных методов, которыми мог быть
не ограничен соискатель.
Подобная ограниченность вопросов на собеседованиях высокого
уровня снимает абсолютно все претензии.
Еще раз извините, не посмотрел на себя со стороны
1.
шанс знания любого из них составляет 95%, то шанс безошибочного ответа по всему чек-листу составляет 23%
во-первых, нет такой величины как "шанс знания", если ты работаешь с этим инструментом, то объём знаний зависит не от шанса, а от опыта работы. Да, ты можешь не использовать какую-то часть языка, но как раз именно объём (и глубина) знаний и отличает например сеньора от джуна. Если бы у сеньора был такой же "шанс знаний", как и у джуна, наверно, никому не требовались бы сеньоры.
Во-вторых, знать — это не обязательно в 100%-ном объёме помнить все детали. Знать — значит понимать и быть способным аргументировать (подразумевается, верно). Если человек может и не "знать", почему (к примеру) поиск в линейном массиве менее эффективен, чем в хэшированном дереве, то один может это вывести на ходу, а для другого разницы никакой нет — и это тоже один из факторов, которые проверяются на собеседовании.
Не нужно знать ответы на 100% вопросов, но уровень знания и понимания технологии коррелирует с уровнем ответов. Поэтому и спрашивают.
2.
Теоретические знания помогут на практике только чтобы осадить ретивых коллег
Это либо наивность, либо провокация. Если бы было так, наверно сеньорам платили бы 23% от джунов (типа сеньор больше знает и поэтому будет злоупотреблять знаниями?)
Знания, конечно, можно и найти. Но представьте себе, если ваш сотрудник вместо "писания кода руками" только и делает что ищет эти "знания" в интернете? Знание, в том числе теоретическое, абсолютно необходимо для писания кода руками. Потому что каждый раз, при написании кода, вы принимаете решение. Если у вас нет знания за этим, то ваше решение — буллшит. И совершенно оправдано будет "осадить ретивого коллегу в комментах", если он не понимает, что — и почему — он наваял.
А умение отыскивать и применять, если за этим не стоит фундаментального знания и понимания технологии, приводит к такому:
https://habr.com/ru/post/521104/
Если у вас нет знания за этим, то ваше решение — буллшит.
А если эти решения принимаются уже над подсознательном уровне? Например, много лет назад были все эти знания, перед принятием решения анализировались все варианты, но постепенно это стало потерей времени с одной стороны, первое пришедшее в голову решение в итоге оказалось тем же, что и выбранное по результатам анализа. Ну и анализ с использованием знаний проводился всё реже в виду бессмысленной потери времени и неиспользуемые знания утратились.
А если эти решения принимаются уже над подсознательном уровне? Например, много лет назад были все эти знания, ...
Я не очень понял предпосылку. Таки знания были? Таки можно аргументировать или нет?
Скажем, из последних примеров, пришёл программист на РНР в питон и пишет:
if "x" in the_dict.keys(): ...
Да, он пишет на подсознательном уровне потому, что isset()
в питоне нет. Если я ему в ревью напишу, что в питоне есть оператор "x" in the_dict
, это кому-то повредит? Ущемит эго похаписта? Может он как-то аргументировать в свою пользу или нет?
Или вариант 2: в Python 3.7 добавили функцию datetime.fromisoformat()
. Да, раньше приходилось либо писать в каждом проекте это заново, т.е. просто копипастить ("на подсознательном уровне"), либо использовать какую-то библиотеку. Если я в ревью напишу автору кода, что "в 3.7 это уже встроено", это кому-то как-то повредит? Ущемит эго?
Я же не буду, в обоих случаях, орать и материться "вы тупые свиньи, тупой похапист и идиот, который за 3 года не удосужился в релиз ноты глянуть". Больше того, то, что я могу дать им новые знания, мне гораздо важнее того, что код в данном конкретном месте будет лучше (мне было бы быстрее и проще самому взять и поправить). Это как дать рыбу чтобы утолить голод, или научить рыбачить.
Но знания устаревают, и если ты считаешь себя пригодным для работы в современных условиях, твои знания должны быть современны. А если ты считаешь обновления знаний "бессмысленной потерей времени", ну будешь через 10 лет как те, кто сейчас на дельфи ваяют монохромные ГУИ под виндовс 98 для кассовых компов в Нигерии. Хотя возможно, это и было нормой 20 лет назад.
Поэтому да, если вы не можете аргументировать ваши решения, которые вы принимаете здесь и сейчас, то это буллшит.
Знания были и я не про миграцию с языка на язык или даже с версии на версию. Сходу аргументировать не получится, время на повторный рисерч нужно будет. Результаты которого, да, могут быть сюрпризом, если версия сменилась. Вот, например, для многих пэхепэшников сюрприз, что true и false с некоторых пор занимают столько же места как null. По факту нисколько, типы с одним значение и значение не хранит, а bool = true|false под капотом, и теперь чаще всего лучше писать ['val1' => true, 'val2' => true]
вместо ['val1' => null, 'val2' => null]
: затраты памяти те же, а работать удобнее чаще всего.
datetime.fromisoformat()
Пишу на питоне раз в 100 лет, обрадовался как-то что наконец затащаили в стд работу с датами… А потом оказалось, что нет, не затащили
from datetime import datetime
print(datetime.fromisoformat("2020-10-03T11:39:26.084730Z"))
# ValueError: Invalid isoformat string: '2020-10-03T11:39:26.084730Z'
Все правильно, таймзон. Мне и нужно таймзон. Например так работает:
from datetime import datetime
print(datetime.fromisoformat("2020-10-03T11:39:26.084730+00:00"))
А если заменить +00:00 на эквивлентный Z то уже нет.
Учитывая, что все смещения отсчитываются от зоны Z, то 00:00 ему эквивалентно.
Никакая из однобуквенных таймзон не подвержена политике или летнему времени.
вместо Z — +00:00
хотя согласен, Z это практически стандарт. Сам немного напрягался по этому поводу.
Да не "практически", а стандарт и есть.
Спасибо :) как раз к вопросу о пользе знаний.
У питона правда несколько другой подход к реализации данной функции:
Caution This does not support parsing arbitrary ISO 8601 strings — it is only intended as the inverse operation of datetime.isoformat(). A more full-featured ISO 8601 parser, dateutil.parser.isoparse is available in the third-party package dateutil.
https://docs.python.org/3/library/datetime.html#datetime.datetime.fromisoformat
что, конечно, немного удивительно.
Больше того, то, что я могу дать им новые знания, мне гораздо важнее того, что код в данном конкретном месте будет лучше
Это мода.
Мода диктуется в первую очередь не удобством или прагматичностью, а укоренённостью среди активных приверженцев, которые распространяют её с помощью широкого спектра механик отторжения (включая насмешки, отказ в приёме на работу, обширные атаки репутации других стэков etc).
Совсем нежизнеспособная мода в высококонкурентных областях может вымереть (потому что бизнес иногда подсчитывает деньги и увольняет / не нанимает модников, следующих стэкам, которые не обладают достаточно весомой репутацией в требуемой области). Из-за этого отсева модные стэки как-то решают свои задачи помимо обычной для себя генерации сопутствующего инфомусора, который станет бессмысленным через несколько лет.
Мода оперирует абстрактными параметрами привлекательности («лучший», «современный», «престижный»), которые лишены другого внутреннего содержания, кроме маркировки апологетов моды и тех, кто не успел или не захотел перейти на сторону этого агрессивного меньшинства.
Мода, безусловно, является подмножеством знания, однако её конечной целью не является решение задачи бизнеса, а извлечение для своей ядерной группы некоторого количества престижа, способного удовлетворить их человеческие потребности.
Согласно этой трактовке, «сеньорность» как признак сводится к совпадению модных фетишей у двух охотников из техно-варварских племён, один из которых оценивает, а другой — оценивается; при этом набор паролей и ответов постоянно меняется. Что ж… Раз это даёт какие-то результаты, которые можно зримо оценить, это иногда работает. Но меня смущает в этом механизме то, что если сотрудник умеет очень хорошо проходить собеседования (то есть обладает большим количеством паролей от них), значит он часто по ним ходит, а следовательно не занят производительной деятельностью и/или может обладать другими качественными недостатками, которые не может вскрыть система чеклистов.
Поэтому да, если вы не можете аргументировать ваши решения, которые вы принимаете здесь и сейчас, то это буллшит.
Среди всех возражений, которые я получал когда-либо на код-ревью, я встречал следующие виды:
1. Структурно значимые (решение задачи является неверным во всех случаях, в некоторых случаях или выполнено неоптимально по некоторым метрикам, например время выполнения или потребляемая память в высоконагруженном участке кода).
2. Сепульки (задача формально решена, но ход её решения оскорбляет глаза ревьюера, который придерживается определённых взглядов — или наоборот игнорирует — цикломатическую сложность, среднюю длину метода, нейминг переменных, включает в себя изменение написанных лично ревьюером методов etc). Заметная часть сепулек можно автоматизировать однажды настроенным линтером, остальные запоминаются как больные мозоли ревьюера, на которые лишний раз наступать нежелательно.
3. Неверные (предлагаемое и подразумеваемое ревьюером решение в принципе не будет работать в силу специфики кодовой базы, при этом ревьюер может ухитриться проигнорировать даже поясняющий комментарий в коде, в котором прямо упоминается об этом нюансе).
Поэтому любое собеседование в сущности сводится к двум вещам:
1. к тестированию, насколько велик запас терпения
2. и насколько хорошо тимлид умеет обучать новоприобретённого серва прыгать на минах своего собственного ОКР (потому что вполне возможно, что нанимаемый гребец может не подавать сигналы желания пройти очередной этап дрессуры, а следовательно бесполезен для дрессировщика).
А умение отыскивать и применять, если за этим не стоит фундаментального знания и понимания технологии, приводит к такому:
Если проблемы проекта обычно невозможно решить пятью минутами гуглежа, значит у него есть проблемы (для разработчика или для бизнеса). Например, отсутствие архитектора. Или бас-фактор, стремящийся к единице. Или есть велосипеды. Или высокая сложность, которая приводит к отваливанию кусков при попытке добавить к этому дирижаблю новую фабрику бассейнов.
Я однажды участвовал в проекте, который включал в себя редкоиспользуемый диалект скриптового языка, который почти нигде не используется (и следовательно, невозможно нагуглить решение типовых задач, посмотреть лучшие практики организации кода и т. п. — по сути, были доступны только кодовая база, доставшаяся от предыдущего поколения разработчиков, и исходники компилятора вместо документации). Для доступа к статистике использовалась самописная база данных, которая не справлялась с выросшим за годы объёмом данных. Что ж… После этого проекта мне пришлось заливать в себя уйму инфотрэша перед тем, как я снова смог ходить по собеседованиям и не просыпаться после них утром с ощущением, что мои глаза сейчас взорвутся.
Я согласен, что слепая вставка нагугленного кода без подгонки к реалиям проекта (хотя бы обычного форматирования под его стандарты или проверки, что эта штука решает задачу слишком избыточно и неоптимально) — порочная практика, которая ведёт к усложнению чтения проекта (а следовательно, и удлиннения времени выполнения задач, поскольку большую часть жизни программист проводит за чтением, немного времени пишет код, а остаток времени кричит). Тем не менее, где ещё программист наберётся модных техник, как не изучая то, что используют другие модники?
Вроде верно говорите, но мне кажется что «знания» это не список, это граф. И некоторый вершины имеют резко более высокую центральность. Отсюда вероятность совпадения возрастает многократно если взять вопросы по самым центральным «знаниям».
Иначе — потому, что я уверен, что хорошему разработчику нужно уделять время не только обучению, но и, в идеале, преподаванию. Немного, но надо.
осадить ретивых коллег в комментах к пулл-реквесту
О, классная формулировка - утащу, с вашего позволения)
Вчера проходил собеседование на другую должность в своей же фирме.
Поплыл на двух простейших вопросах:
1. Поплыл на порядке вызовов виртуальных деструкторов в С++. Как работают конструкторы и деструкторы в нормальной ситуации я прекрасно помню. Как ведет себя всё это если делать не правильно — я с трудом осознавал в процессе собеса. Потому что в жизни я когда-то прочитал про то, как работают виртуальные деструкторы, какие могут быть проблемы. И просто пишу правильно всегда. Вспомнить порядок вызовов(вернее даже не вспомнить, а попытаться воспроизвести на основе знаний о внутренностях С++, вот что я пытался сделать). Хотя вопрос просто стыдный, даже для моей текущей должности.
2. Поплыл на левосторонних и правосторонних системах координат. Хотя казалось бы, куда проще вопрос то для программиста графики?
3. Не смог сформулировать факт, что в матрице трансофрмации подматрица 3х3 это просто три вектора базиса. Вместо этого пытался рассказать что там углы наклона векторов.
Это я всё к чему: ответы на вопросы не обязательно напрямую показываются уровень. На собесе достаточно часто поплыть в вопросах которые ты знаешь очень даже неплохо. Это же не расслабленный разговор с другом за компотом.
Потому что в жизни я когда-то прочитал про то, как работают виртуальные деструкторы, какие могут быть проблемы. И просто пишу правильно всегда.
Нет, это интервьюер поплыл. Если сам составлял анкету — слишком
болезненный удар по самолюбию.
Поплыл на левосторонних и правосторонних системах координат. Хотя казалось бы, куда проще вопрос то для программиста графики?
Слишком простой, из подкорки долго доставать. :D
Это я всё к чему: ответы на вопросы не обязательно напрямую показываются уровень.
Это вопросы его показывают, верно. Которые помогают кандидату
почувствовать себя уверенно, а не интервьюеру тешить свои знания
в узких областях до запятой
Поплыл на порядке вызовов виртуальных деструкторов в С++Заинтриговали. И что же хотел услышать интервьюер?
Неужели не стыдно отвечать «не знаю» на собеседовании
У меня друг, который решил уйти в программирование, сидит дома второй год. Он не ходит на собеседования, не ищет себе ментора, не сидит на смежных форумах.
Почему? Ему стыдно.
И на мой взгляд это неправильно — нет ничего постыдного, если ты чего-то не знаешь. Стыдно, если не хочешь узнать.
Неужели не стыдно отвечать «не знаю» на собеседованиисебя, как специалиста
А как тогда искать работу? Собеседования для этого и существуют чтобы оценить уровень знаний. Кандидат уходит с офером или набором вопросов к себе.
6. Как устроен тип map?
Самый популярный неправильный ответ: «то хеш-таблица». Да, это хеш-таблица. Как устроена хеш-таблица?
Наводящие вопросы: какая hash-функция используется в map в Go? Что такое bucket?
-_\ это вы серьезно сейчас? Ну т.е. какая *реальная* польза от того, что чел будет знать, какая там хэш-функция используется? Если хотите спросить про хэш-таблицы — ну так и спросите без применения к языку «Какие хэш-таблицы вы знаете?». А считать первый ответ «хэш-таблица» неправильным на вопрос «Как устроен тип map» — ну, такое.
12. Сколько времени в минутах займет у вас написание процедуры обращения односвязного списка?
Самый популярный неправильный ответ: «А что такое односвязанный список?». Это такая структура данных...
Благодаря усилиям хэдхантеров Evrone Екатерины Тхоржевской и Анны Кудряшовой — спасибо им! — до меня добираются только резюме интересных кандидатов
А на этом моменте закралось подозрение, что ваш «базовый фильтр» кандидатов вообще работает. И, наверное, стоит или посмотреть повнимательнее на ваших «хэдхантеров» или, по крайней мере, этот вопрос делегировать им — во время первого телефонного созвона должно быть достаточно просто и понятно.
Подобная задача это же абсолютно типичная задачка на кодинг почти в любом языке и любой человек, оценивающий это больше чем в 5 минут должен вызывать подозрения (ну или по крайней мере уточнить, вдруг вы спрашиваете про «тупокод», а кандидат ответил «час», имея в виду полный процесс от кода, до тестов, документации, упаковки в реюзабельный пакет и всего прочего)
P.S. Ну и да, кажется подозрительным, что у вас большинство кандидатов знает слово «хэш-таблица», но не знает слова «односвязный список».
про хеш-таблицу — люди знают словосочетание, но не знают, что за ним скрывается.
про список — я сам сначала не поверил, стал на собесах задавать вопрос на собесах.
это плохой вопрос и вот почему: 1) без спецификации там может быть что-угодно, да ещё и зависящее от платформы, runtime окружения, «времени суток и уровня воды на берегу» 2) код подобных типов склонен меняться и, зачастую, в более сложный мутировать, так что сегодняшнее представление о map может быть совсем неверным завтра (например — обрастать условиями на количество элементов в map-е или runtime эвристиками).
Вот вы сами рассуждаете о императивности и декларативности — и тут же просите от кандиата того, что в общем-то не декларируется нигде и никем (ну, исключая исходники, конечно). Реальность же такова, что ответ «там бакеты» вполне годный — это как минимум говорит о том, что человек где-то что-то слышал или имеет базовые (академические) представления о реализации подобных структур. А вот момент когда ему действительно понадобится лазить «в кишки» может и не настать вовсе, а когда настанет — добро пожаловать в мир профилирования…
или, возможно, про их устройство не надо спрашивать вообще. я, конечно, думаю, что надо.
если у вас есть идеи, что спрашивать на этом месте — предлагайте!
Я не написал ни строки но Go, но я сильно сомневаюсь, что используемая хеш-функция в стандартной библиотеке специфицирована и ее неизменность гарантируется от версии к версии. Как и внутренние детали реализации.
Гораздо важнее, чтобы разработчик понимал свойства и гарантии используемых инструментов, а не внутренюю реализацию. Я вот знаю как устроен HashMap в Rust, но лучше бы не знал – там столько SIMD и черной магии, что можно засмущать любого интервьювера на собеседовании.
Аналогичный вопрос: как работет динамический массив? Вы вот точно знаете все ньюнсы его реализации? Сколько будет по факту выделено памяти в каждом случае инициализации и релокации?
Причем ладно бы это имело какой смысл и было бы что предложить кандидату, но 95% российских компаний ничего не могут предложить разработчику, кроме ежедневной рутины за копейки. Но собеседования с таким выпендрёжем смеху подобно. Вместо того, чтобы брать с запада зарплаты и условия труда, берут подобные фильтры отсева. Но раз это хавают, то что поделаешь.
технические характеристики цемента, виды кирпичей, диаметры патрубков
а вот это прораб должен знать, хотя бы в общих чертах
У меня все-таки вопрос — зачем вам нужен прораб? И как вы жили без него до сего момента? Смайлик.
У меня все-таки вопрос — зачем вам нужен прораб? И как вы жили без него до сего момента? Смайлик.
У меня всё таки вопрос:
Зачем вы инженерную специальность (software engeneer) сравниваете с рабочим?
Но отказываетесь принять тот факт, что она по уровню, всё же, ближе к должности прораба.
Тот факт, что в ИТ нет такого количества простых рабочих, а все разработчики, по сути, инженеры — ну вот так это в ИТ. Полной аналогии со строительством нет.
P.S.:
Когда я получал разряд простого слесаря в прошлом веке — на экзамене меня гоняли по видам резьб и особенностям обработки металла. И это нормально.
P.S.:
Когда я получал разряд простого слесаря в прошлом веке — на экзамене меня гоняли по видам резьб и особенностям обработки металла. И это нормально.
а вас не гоняли по особенностям устройства токарного станка? насколько микрон отклонение у него при определенных оборотах? а какая зависимость от того 220 или 380 у него напряжение питания? а как масса шпинделя влияет на качество обработки? обоснуйте, и в микронах.
а теперь тоже самое но со сверлильным станком
а вас не гоняли по особенностям устройства токарного станка?
Да, были несколько вопросов по форме резцов токарного станка.
а какая зависимость от того 220 или 380 у него напряжение питания
В приведенном в статье выше никаких настолько абсурдных вопросов, как вы приводите в пример нет.
потому что есть влияние от напряжения питания как минимум на мощность станка и на особенности его работы.
И вы, если хотите считать себя сеньором-токарем, должны хотябы образно знать его устройство, принципы работы привода (асинхронный, обычный_, люфты в КПП их влияние на качество обработки.
(сарказм конечно, но в теме статьи и вполне может быть правдой если совсем упарыватся теорией)
И вы, если хотите считать себя сеньором-токарем, должны хотябы образно знать его устройство, принципы работы привода (асинхронный, обычный_, люфты в КПП их влияние на качество обработки.
1) Я писал о слесаре. Не токаре.
2) Про высокий разряд ни словом ни обмолвился. Там ни о каком сеньоре-слесаре и речи ни шло.
3) Вы серьезно считает что опросник из статьи предназначен для тестирования сеньоров?
1) Я писал о слесаре. Не токаре.
Пфф… я вам могу придумать кучу вопросов по кувалде (состав стали? влияние веса и состава на максимальную температуру детали по которой вы бъете, ухудшаются и насколько характеристики металла при ударе и почему)
3) Вы серьезно считает что опросник из статьи предназначен для тестирования сеньоров?
Я серьезно? так там в статье написано что автор считает что по данному опроснику сеньор должен набирать +8 баллов, а джун 3+
и мой опыт собеседований на сеньора (не golang) подсказывает что такие опросники действительно поляризуются популярностью
Интервьюер: Итак, вы считаете себя плотником?
Плотник: Всё верно. Это именно то, чем я занимаюсь.
Интервьюер: Как долго вы занимаетесь этим?
Плотник: Десять лет.
Интервьюер: Очень хорошо. А теперь я бы хотел задать вам несколько технических вопросов, чтобы оценить, насколько вы впишетесь в нашу команду. Договорились?
Плотник: Конечно, было бы неплохо.
Интервьюер: Должен вам сказать, что мы работаем в подразделении, занимающимся постройкой большого количества коричневых домов. Доводилось ли вам строить множество коричневых домов?
Плотник: Ну, я же плотник — я строю дома, а люди уже красят их так, как пожелают.
Интервьюер: Да, я понимаю, но не могли бы вы подсказать мне, сколько у вас опыта именно с коричневыми? Ну, плюс-минус.
Плотник: Я действительно понятия не имею. С того момента, как дом построен, меня не волнует, в какой цвет его покрасят. Может, шесть месяцев?
Интервьюер: Шесть месяцев? Вообще-то мы ищем кого-нибудь с гораздо большим опытом коричневого, но позвольте мне задать вам ещё несколько вопросов.
Плотник: Ладно. Но, знаете, покраска — это покраска.
Интервьюер: Да-да, хорошо. Что насчёт Ореха?
Плотник: А что с ним?
Интервьюер: Много ли вы работали с ореховым деревом?
Плотник: Конечно. Ореховое дерево, сосна, дуб, красное дерево — всё, что угодно.
Интервьюер: Но сколько лет вы работали с Орехом?
Плотник: Да не знаю я, чёрт возьми. Я что, должен считать каждую доску?
Интервьюер: Ну хотя бы примерно?
Плотник: Хорошо, тогда я бы сказал, что у меня есть полтора года опыта работы с ореховым деревом.
Интервьюер: Но вы не ореховый гуру?
Плотник: Ну, я же плотник — я работаю с любыми типами дерева, которые, конечно, имеют некоторые отличия, но я считаю, что если ты хороший плотник…
Интервьюер: Да, да, но мы используем ореховое дерево. Это нормально?
Плотник: Ореховое дерево — это прекрасно! Всё, чего пожелаете — я же плотник.
Интервьюер: Что насчёт чёрного Ореха?
Плотник: А с ним что?
Интервьюер: У нас было несколько ореховых плотников, но потом случайно выяснилось, что они не были плотниками по чёрному Ореху. Имеется ли у вас опыт с ним?
Плотник: Конечно, немного. Полагаю, было бы хорошо иметь больше опыта для моего резюме.
Интервьюер: Ладно. Позвольте мне свериться со списком вопросов.
Плотник: Да пожалуйста.
Интервьюер: Итак, последний вопрос на сегодня. Мы используем Камень 5.1 для забивания гвоздей. Использовали ли вы Камень 5.1?
Плотник: [становясь белым...] Ну, я знаю, что множество плотников начали использовать камни, чтобы забивать гвозди, когда Craftsman купил каменоломню, но, вы знаете, честно говоря, у меня это получается гораздо лучше с моим гвоздомётом. Или молотком, если хотите. Мне кажется, что, когда я использую камень, то слишком часто ударяю себя по пальцам, и моя рука сильно болит, потому что камень очень большой.
Интервьюер: Но другие компании используют камни. Вы хотите сказать, что камни не работают?
Плотник: Нет, я вообще-то не говорю, что камни не работают. Я лишь считаю, что гвоздомёты работают лучше.
Интервьюер: Все наши архитекторы начинали использовать камни и им понравилось.
Плотник: Конечно они это делали, но я забиваю гвозди целый день и — ладно, слушайте, мне нужна работа, так что я определённо готов к использованию камней, если вы захотите. Я стараюсь сохранить объективность.
Интервьюер: Ок. У нас есть ещё несколько кандидатов; мы свяжемся с вами, когда примем решение.
Плотник: Что ж, спасибо за ваше время. Было приятно поговорить.
СЛЕДУЮЩИЙ ДЕНЬ
Звонок…
Интервьюер: Алло?
Плотник: Здравствуйте! Помните меня? Я тот плотник, которого вы собеседовали для работы с чёрным ореховым деревом. Хотел лишь узнать, приняли ли вы решение.
Интервьюер: Вообще-то приняли. В целом, нам нравится ваш опыт, но мы решили взять кого-то, кто больше работал с коричневыми.
Плотник: Правда? И это всё? Меня не взяли на работу, потому что у меня недостаточно коричневых?
Интервьюер: Ну, это только частично правда, но частично, мы взяли другого парня, потому что он намного дешевле.
Плотник: Серьёзно? И сколько же у него опыта?
Интервьюер: Ладно, он не совсем плотник, он продавец машин. Однако он продал много коричневых машин и работал с отделкой из орехового дерева.
Плотник: [короткие гудки]
А потом ещё эти компании пишут статьи какие они умные, и как они в шоке.
Там не просто разные функции, там разные реализации(map_fast32.go, map_fast64.go, map_faststr)?
про хеш-таблицу — люди знают словосочетание, но не знают, что за ним скрывается.
Ну так повторюсь — спрашивайте тогда без контекста в виде языка. Потому что надо быть достаточно упоротым, чтобы навскидку знать, какая хэш-функция используется в конкретном языке для конкретного типа данных, но при этом слова «метод цепочек» и «открытая адресация» (а в упоротых случаях еще и какой-нибудь «Cuckoo hashing» можно вспомнить) вполне можно знать, особенно если недавно открывал Кормена (что, конечно, в реальной работе особо не поможет, да и «вы не гугл» (с))
И да, забыл еще это упомнянуть:
10. Как вы отсортируете массив структур по алфавиту по полю Name?
Самый популярный неправильный ответ: «Методом пузырька». Пузырек — прекрасный алгоритм, но есть сегодня и поэффективнее. Например — quicksort. Не можете с ходу имплементировать quicksort? Так ведь и не надо!
Я допускаю этот ответ в контексте «пошутить». Т.е. это просто самое первое, что ты говоришь с улыбкой, но через две секунды следует уточнение «но, конечно, так в жизни делать не надо, в реальности я бы сделал так и так». Если же вам кандидат в синьоры (да что там, даже кандидат в джуны такую ересь не должен пороть) прямо всерьез без шуток говорит и предлагает «пузырьком» — я бы сразу пожал руки и пожелал удачного дня, сохранив и ваше время, и время кандидата.
Собственно, поставьте этот и вопрос про список двумя первыми и сэкономьте свое время.
Я вот не могу сходу правильно реализовать quicksort, потому что не помню как эфективно выбирать медиану, чтобы побороть деградацию производительности к O(n^2). Я плохой разработчик? А вы помните?
Если вам правда нужно реализовать свою сортировку – использование quicksort скорее всего плохая идея. Большинство стандартных библиотек полагаются на mergesort, как основной алгоритм, реализуя поверх него гибридные схемы (timsort и другие). Гораздо важнее знать эту информацию, чем помнить наизусть школьный алгоритм.
Или вопросы ставить нормально. Вы же не даёте синьорам-помидорам задачи не на сортировку массивов.
Если это список пользователей, почему, к примеру, order by
в SQL запрос не добавить?
Можно не использовать sort
в течение длительного времени (да и любой другой частный пакет) и просто забыть о его существовании, и нормально использовать когда появляется кейс. Нормальный рабочий кейс, я имею в виду, а не дядек, которые умные вопросы задают.
Потому что надо быть достаточно упоротым
Это Go, детка :) Прошу прощения за фамильярность, но это передаёт суть
А потом на практике окажется что метод пузырьком будет быстрее на малом объеме данных, потому-что кеш.
А потом окажется, что время, бездарно потраченное потраченное на множество оптимизаций до таких незначительных мелочей, превращает изначально коммерчески перспективный проект в убыточный.
Вы уверены, что на нынешнем железе стоит тратить на это время?
При том, что львиная затрата времени вашей программы идет вовсе не на сортировку в кэше или не в кэше, а на совсем иные вещи:
Задержки по сети, задержки на диске, ожидание ввода пользователя.
Метод пузырьком нахрен не нужен, потому что Шелл лучше всегда
… а потом окажется, что 99% времени приложение проводит в IO, на ожидании сетевых/дисковых ресурсов. и эти микрооптимизации никому не впились, потому что один умник решил в цикле запрашивать базу/rest-сервис на каждый элемент.
зато про сортировку знал!
"Разрабатывать БД" обычно входит в "писать круды", редко бывает выделеный DBA или типа того.
Я согласен, поэтому и считаю, что если берешь на работу человека, где в основном нужно писать круды, то нужно и на собеседованиях спрашивать про работу сети, бд, инедексацию итд. Если же человек идет разрабатывать бд, то знать про сортировку полезно.
В наше время работа с СУБД встречается на каждом шагу.
Не нужно быть выделенным DBA чтобы тебя это коснулось.
Да фиг с ним с самим списком. Что такое его обращение? Что такое его разворачивание или развёртывание? Операция обратная свёртке? Как это будет по-английски?
I see what you did here! :)
А какие тут могут быть разные формулировки?
Ну вот я много лет был уверен, что разворот списка это что-то из функционального анализа, операция в чём-то обратная свёртке, например.
Даже если высасывать из пальца, то это была бы "развёртка в список", а не "разворачивание списка".
Вопрос все равно не праздный. Люди которые проверяют разворот чуть надежнее чем тестом rev [1,2,3] == [3,2,1]
требуют понимания, когда мы считаем что разворот успешно завершен. Формальный критерий.
Формальные критерии — это точно не про мейнстримные языки. Тут максимум — тесты. Впрочем, их писать тоже мало кто умеет. Вон, автор статьи даже не задаёт вопросов на эту тему.
но тестовые задания батхертят аудиторию еще сильнее, чем мой опросник :)
После Питона и Джавы возможности Go в этой области меня очень расстроили.
Я про свои ассоциации при чтении холиваров о "правильных" собесах и тестовых, где задача "развернуть/обратить/… список" регулярно упоминается. Звучит как задача из предметной области высшей математики, на уровне "эффективно отсортировать массив"
Интервьюерам выгодно придумывать чеклисты, нанимать по гороскопу и строить как можно более высокий барьер при собеседовании. Это экономит ресурсы компании и позволяет нанять каких-то кандидатов (не совсем обязательно лучших, но достаточно сервильных, чтобы впитать весь не имеющий отношения к самому труду инфомусор, который от них требуется усвоить). Опять же, можно прогнуть по зарплате, пользуясь тем что кандидат что-то не знает (а он гарантированно чего-то не знает).
Работникам выгодно минимизировать затраты на собеседование и не хранить в голове знания, которые они не используют каждый день. Благодаря чрезвычайно мощным средствам поиска информации такое в наше время уже возможно: умение искать и адаптировать информацию может быть ценнее, чем хранение информации у себя в кэше.
> Ну т.е. какая *реальная* польза от того, что чел будет знать, какая там хэш-функция используется?
Я однажды заморочился и откопал типовой комплект ответов на вопросы по Java, залил себе в мозг эту мусорную инфу по хэш-таблицам и потом пугал ею интервьюеров на собеседованиях, которые спрашивали что такое hash index в MySQL. Думаю, они ожидали менее развёрнутый ответ, который и приличествовал программисту LAMP-стэка. Такие знания — это сила. Это мощь паровоза, который несётся по болотам, распугивая квакающих лягушек. Это булава интеллектуальной битвы, это боевой клич берсерка из драккара компьютерных наук, обожравшегося пшеницы со спорыньей и прочих некачественных продуктов.
Практически неприменимо в быту, но вы же не станете требовать, чтобы руны образовывали вокруг голого торса огненный щит? Один покарает вас за такое желание облегчить свою участь инфоберсерка.
Интервьюверы часто просто не знают, что спрашивать. Вот и составляют "чеклисты", а потом делают оффер, тому кто, больше всех ответил, например 15 из 100, когда остальные 6-12
На самом деле нет. Тут нельзя посчитать сколько ответил из скольки. Это чеклист для спрашивающего, чтобы не забыть спросить эти темы. Это не вопросы — это темы. На собеседовании ты прощупываешь насколько хорошо человек знает рабочий инструмент.
Если видишь, что он ответил, но сказал неуместное слово, то уточняешь, чтобы проверить что он оговорился, а не зазубрил и на самом деле не понимает. И т.д.
Хоть и согласен с комментарием, всё равно поспорю с аргументом про необходимость знать функцию хэширования по умолчанию конкретно в Java (в java.lang.Object) Это нужно знать, иначе рискуешь встретить коллегу, который вставит ключ в HashMap или элемент в HashSet, не переопределив hashCode(), и потом не может найти его снова. У меня такие коллеги были, как и те, кто пытался массив сделать ключом в HashMap.
Подобная задача это же абсолютно типичная задачка на кодинг почти в любом языке и любой человек, оценивающий это больше чем в 5 минут должен вызывать подозренияНу не знаю. Например я односвязные списки в последний раз писал лет 10 назад, на Си. Разворот списка не писал ни разу в жизни, о такой задаче читал только в статьях о собеседованиях.
Ну то есть у меня нет никаких сомнений, что я этот разворот напишу (когда мне расскажут что это именно значит). Но так сходу сказать, что напишу за 5 мин… За 5 мин. пишутся только вещи, которые «на кончике пера», которые используются постоянно. А на кой черт мне, простите, разворот односвязного списка? Ощущение, что эта задача показывает только то, что ты в клубе. Клубе любителей ходить по собеседованиям.
upd. Проясню. Против самой задачи я ничего против не имею. В целом такие простые задачи неплохой способ отсеять совсем слабых программистов. Но требовать, чтобы их знали, держали в пальцах, да ещё допытывать время выполнения. Возможно я в чем-то не прав (я все-таки не лид и сам собеседования не проводил ещё), но мне это кажется сильно странным.
И, в отличие от возможных способов построения хэш-таблиц, само знание о том, что есть такая структура — список и чем она отличается от массива и хэш-таблицы — это, на мой взгляд, обязательно знать каждому девелоперу. Не обязательно знать детали, можно загуглить. Но банальный факт, что операция «remove» в массиве будет занимать дольше, чем в хэш-таблице или что поиск элемента в списке будет долгим — это же из разряда знаний на подкорке, как можно писать что угодно сложнее хелловорлда без этого знания? Я так в коде нашего сеньора как-то увидел очевидно квадратичную конструкцию, где на каждой итерации довольно длинного цикла вызывался поиск по списку вместо того, чтобы сделать некий препроцессинг в хэш-таблицу сначала. Так и тут — если человек не понимает, какие вообще основные структуры есть (для реальной жизни достаточно знать три: массив, список, хэш-таблица) — к такому чуваку могут быть вопросы. У Гугла будут вопросы, если чувак не может хотя бы три вида самобалансирующихся деревьев назвать, но вы не гугл, достаточно базы. А базу стыдно не знать имхо.
Это не задача на графы, не задача на хитрые алгоритмы, не задача на что-то, что нельзя сообразить на пальцах. Это как fizzbuzz, я не знаю. Вы же не будете говорить, что на физзбазз вам нужно больше 5 минут?
Нужно ещё знать, что такое "развернуть", "обратить" и прочее что в голове у постановщика. Вот из всех этих собеседеных холиварах я вынес просписки, что есть набор каких-то "магических" операций над списками типа функции свёртки, но более сложное. И при просьбе оценит время написания функции разворачивания списка я б сказал что-то вроде "минимум час на гугление рисёч и минимум час на реализацию — очень оптимистичная оценка, я матан совсем не помню"
банальный факт, что операция «remove» в массиве будет занимать дольше, чем в хэш-таблице или что поиск элемента в списке будет долгим
Не факт, всё это зависит от реализации и контекста использования.
Но банальный факт, что операция «remove» в массиве будет занимать дольше, чем в хэш-таблице или что поиск элемента в списке будет долгим
Но ведь если брать в общем, то это не так. Удаление последнего элемента
в массиве точно быстрее удаления в сложной структуре, нужно же всего лишь размер на единицу уменьшить. И скорее всего удаление нескольких последних элементов тоже может быть быстрее чем удаление в хэш таблице, хотя за счет кэшей процессора.
Ну и например если массив небольшой, то поиск в нем вполне может быть быстрее,
конечно все зависит еще от типов данных в массиве и хэш-таблице.
зависит от языка же. Например я не писал разваороты на хаскелле, но могу написать его думаю секунд за 30
rev :: [a] -> [a]
rev [] = []
rev (x : xs) = rev xs ++ [x]
затем можно заметить что он неоптимален (аллоцирует много) и заменить на аккумулятор который работает по принципу стека, на которорый уже пара минут нужна (проверить правильность рекурсии):
rev :: [a] -> [a]
rev = revInner [] where
revInner acc [] = acc
revInner acc (x : xs) = revInner (x : acc) xs
Как мне кажется, достсаточно простой вопрос, чуть сложнее fizzbuzz. С другой стороны, ни разу не писал функции разворота списка на практике. Самое близкое — stateful fmap.
С чего бы это? Вот определение списка:
data List a = [] | (a :: List a)
Это не очень похоже на массив, зато очень похоже на список. Чем и является. Не дайте себя запутать тем, что для списков в хаскелле используются квадратные скобочки.
Ну а персистентные структуры возможны везде, в том же компиляторе сишарпа везде используются исключительно персистентные массивы/списки/..., никаких изменяемых. Потому что перфоманс нужен.
Ну, тут всё просто. data
обозначает АДТ, то есть тип-сумму, то есть энум на который можно дополнительные данные прицепить. Соответственно список либо является []
(он же Nil, он же пустой список), либо (::)
(он же Cons) состоящий из элемента типа a
и хвоста. Варианты удобно перечисляются через |
.
Сначала немного непривычно, что конструктор это не слово а какой-нибудь оператор (например :: вместо Cons), но потом начинаешь ценить подобное удобство. Если не ударяться в крайности, то читаемость ощутимо выигрывает.
С чего бы это? Вот определение списка:
Ну вся соль задачи что аллокаций памяти в куче не производится,
и используется O(1) доп. памяти. Такое возможно реализовать на хаскелле?
Ну если вы старой версией не пользуетесь то компилято вполне вероятно соптимизирует это в мутабельную игру указателями. Но если пользуетесь, то без доп. памяти офк никак. Реверс в данном случае это List Reverse(List)
а не void Reverse(List)
. С ситуацией когда оптимизатор может вернуть аргумент в качестве результата.
А считать первый ответ «хэш-таблица» неправильным на вопрос «Как устроен тип map» — ну, такое.
Ну вообще вопрос понятен и такой ответ говорит о том, что человек не знает, что там под капотом. Почему это важно? Наводящий вопрос: map[int]TStruct или map[int]*TStruct? Почему? В если их миллион? Почему? Правильного ответа нет. Но выбрать без понимания — ударить себя лопатой (я самоударенный, я туповат и учусь прыгая с разбегу на грабли)
Для питон разработчиков я обычно задавал вопрос "допустим мы храним телефоны как строки (а если это плохо, то как раз можно объяснить, почему), причем храним только телефоны 8-800 и 8-499. Лучше использовать хэшмап или массив, и почему тот или иной вариант".
Опечатался, имел в виду "телефоны как числа" наоборот, в противовес обычному "как строки".
Для хранения лучше массив — меньше памяти займёт. А других задач не обозначено :)
Если хранить как массив то диапазон от 0 до 8-800 будут содержать нуллы. Не очень-то хорошо получается.
В смысле? Как-то непонятна задача. для меня хранить телефоны в массиве значит:
[
88001234567,
88007654321,
84991234567,
84997654321,
]
какие нуллы в каком диапазоне?
Сори, я на память задачу вспоминал, криво назвал. См. ниже, суть в том, чтобы хранить список номер телефона-имя пользователя, и иметь О(1) доступ к этому самому имени. То есть
phones = [...., "VolCh", "PsyHaSTe", ....]
volchPhone = phones[88001234567]
psyPhone = phones[88001234568]
В изначальной формулировке офк этого косяка нет, это я когда по памяти писал выше неправильно вспомнил точную постановку.
Теперь понятно. В такой постановке классический массив сложно представить когда оптимальным выбором будет, а реализациях разряженных в которые вникал под капотом хэшмапа была и на этих языках классических массивов толком и нет в принципе.
чисто любопытства ради.
- хранится список номеров телефонов или номер телефона это ключ к записи? в чём вообще суть задачи?
- "хэшмап или массив" если бы мне на собесе про питон упомянули что-то такое, я бы сказал "пардон, я кажется ошибся адресом", развернулся и ушёл. Как бы есть словарь и список (ну может быть дикт и лист), но хешмап и массив, это какие-то дельфи или я не знаю. Если человек не использует привычную терминологию, что-то значит не то в конторе.
хранится список номеров телефонов или номер телефона это ключ к записи? в чём вообще суть задачи?
Суть задачи — как лучше хранить привязку номер телефона — имя пользователя. Или Map<Int, String>
или просто String[]
"хэшмап или массив" если бы мне на собесе про питон упомянули что-то такое, я бы сказал "пардон, я кажется ошибся адресом", развернулся и ушёл. Как бы есть словарь и список (ну может быть дикт и лист), но хешмап и массив, это какие-то дельфи или я не знаю. Если человек не использует привычную терминологию, что-то значит не то в конторе.
Ну если вы не знаете что такое хэшмап то наверное действительно стоит развернуться и уйти. Если вопрос "хэшмапа… В смысле дикт?" То можно просто получить утвердительный ответ и пойти дальше. Знакомые программисты вообще в одном предложении могут использовать оба термина, все же понимают, что речь об одном и том же. "Какие-то дельфи" — да нет, ваще-то почти во всех языках принято так называть. Кругозор "знаю больше 1 языка" тоже приветствуется и является бонусом.
"Какие-то дельфи" — да нет, ваще-то почти во всех языках принято так называть
Скажем так, во многих языках они так называются, если называются явно, хотя могут быть нюансы. Вон вы же пишите Map<Int, String>
, а не HashMap<Int, String>
:)
Суть задачи — как лучше хранить привязку номер телефона — имя пользователя. Или Map<Int, String> или просто String[]
очевидно зависит от того — какие операции потом будут производиться? Например, поиск имени по номеру телефона (строим какой-нибудь АОН) или наоборот — по ФИО ищем телефон (как в какой-нибудь адресной базе)
Суть задачи — как лучше хранить привязку номер телефона — имя пользователя. Или Map<Int, String> или просто String[]
тогда не очень понятно, в чём заключается доп.условие что номера только 8-800 и 8-499. Если мы храним номер как 10-значный int, то это одно. Если мы храним его как 7-значный инт плюс префикс 800/499 (может быть и бред, но мало ли кому что в голову взбредёт) то одним интом не отделаешься.
если вы не знаете что такое хэшмап
я знаю, что такое хэшмап. Но если вы называете тип данных dict
хэшмапом, то я очень сомневаюсь, что вы знаете, где вы находитесь. Если вы используете in для проверки наличия ключа в питоновском дикте так:
if "x" in the_dict.keys()
то да, так можно делать. Но если вы мне предлагаете должность сеньора и при этом утверждаете, что так правильно делать, то извините.
Map<Int, String> или просто String[]
вот о чём я и говорил, к питону это не имеет никакого отношения.
"Какие-то дельфи" — да нет, ваще-то почти во всех языках принято так называть.
если вы считаете, что жавовская термонология уместна во всех языках, я не думаю, что мне с вами по пути, потому что в таком случае с вероятностью 100% вы будете использовать и другие жавовские приёмы. Если вы пишете на жаве, пишите на жаве. Не надо писать жавовскими идиомами ни на питоне ни на дельфях. Вы же не говорите по-английски, используя дословный перевод с русского.
Так вот, в питоне нет типа данных "хэшмап". И если вы имеете в виду дикт, то я развернусь и уйду. Если же это какой-то самописный class HashMap
, то возможно ещё подумаю, хотя необходимость такого в питоне сомнительна.
Кругозор "знаю больше 1 языка" тоже приветствуется и является бонусом.
Я знаю довольно много языков, как ЯП, так и человеческих. И именно поэтому, для меня важна точность терминологии. Называть хэшмапом дикт в питоне, это то же самое, что называть машину в английском "machine". Да, формально "car" и "auto" это тоже machine, но люди так не говорят. Просто сразу видно, что вы не местный. Ничего личного, но если вы при этом работаете в фирме переводов, то досвидос. Так же и со словарями и списками в питоне. Ничего личного, я уважаю Жаву как язык. Но работаю на питоне.
тогда не очень понятно, в чём заключается доп.условие что номера только 8-800 и 8-499. Если мы храним номер как 10-значный int, то это одно. Если мы храним его как 7-значный инт плюс префикс 800/499 (может быть и бред, но мало ли кому что в голову взбредёт) то одним интом не отделаешься.
Храним как 10-значный инт
я знаю, что такое хэшмап. Но если вы называете тип данных dict хэшмапом, то я очень сомневаюсь, что вы знаете, где вы находитесь.
Не понимаю, почему это должно кого-то смущать. Если знаете > 1 языка то точно проблем никаких не будет. Если не знаете — не беда, переформулирую.
Если вы используете in для проверки наличия ключа в питоновском дикте так:
if "x" in the_dict.keys()ё
то да, так можно делать. Но если вы мне предлагаете должность сеньора и при этом утверждаете, что так правильно делать, то извините.
Я никакой x in dict.keys()
нигде даже близко не писал. Вы точно на тот комментарий отвечаете?
вот о чём я и говорил, к питону это не имеет никакого отношения.
Конкретно к питону офк не имеет, но обычно срашиваю на япе который собеседуемый знает.
если вы считаете, что жавовская термонология уместна во всех языках, я не думаю, что мне с вами по пути, потому что в таком случае с вероятностью 100% вы будете использовать и другие жавовские приёмы. Если вы пишете на жаве, пишите на жаве. Не надо писать жавовскими идиомами ни на питоне ни на дельфях.
Логика уровня /b/. Впрочем, склонен согласиться, что не по пути))
Вы же не говорите по-английски, используя дословный перевод с русского.
Конечно говорю. Трейт, тайпкласс, имплементировать, инвестигейт, багтрекер,… Как и большинство коллег, с которыми общаюсь.
Я знаю довольно много языков, как ЯП, так и человеческих. И именно поэтому, для меня важна точность терминологии. Называть хэшмапом дикт в питоне, это то же самое, что называть машину в английском "machine". Да, формально "car" и "auto" это тоже machine, но люди так не говорят. Просто сразу видно, что вы не местный. Ничего личного, но если вы при этом работаете в фирме переводов, то досвидос. Так же и со словарями и списками в питоне. Ничего личного, я уважаю Жаву как язык. Но работаю на питоне.
Ну значит вы "питон разработчик". Ничего личного, но в моей личной системе координат это уровень ниже нежели просто "разработчик", наравне с "сишарп разработчик", "раст разработчик" и так далее.
Я никакой x in dict.keys() нигде даже близко не писал
а что, примеры уже нельзя приводить? :) я просто хочу показать, что идиомы из одних мест они не всегда уместны в других.
Логика уровня /b/.
скажите, что не так в этой логике. Иначе, это выглядит как логика уровня 0. Я хотя бы аргументировал, вы же просто ляпнули.
Вы же не говорите по-английски, используя дословный перевод с русского.
Конечно говорю. Трейт, тайпкласс, имплементировать, инвестигейт, багтрекер
пардон вы ошиблись — во-первых, здесь нет перевода. Трейт — это англоязычный термин, который не переведён, а взят как есть, перевод был бы "особенность", "черта". Во-вторых, это общепринятая практика, например слово "танк" это тоже заимствование из английского, без перевода (перевод — "бочка"). Впрочем, кому я объясняю, вы это и сам прекрасно знаете. И либо вы понимаете ошибку в вашей логике и намеренно её делаете, либо не понимаете, тогда увы о чём разговор про логику уровня /b/.
Ну значит вы "питон разработчик".
Да, когда работаешь на питоне, наиболее эффективно работать используя подходы, принятые в питоне. Пиша на Жаве — подходы, принятые в Жаве. Если вы считаете, что на всех языках одинаковые идиомы одинаково эффективны, вы не "просто разработчик", а просто не разработчик. (Не имея в виду лично вас.)
Я не хочу вас оскорблять, я вас не знаю, вы меня не знаете. Кто и что в вашей системе координат на каком уровне, меня также не оскорбляет. Я просто указываю вам на те вещи, в которых, на мой взгляд, вы ошибаетесь. А уж как вам к этому относиться, я на это никак повлиять не могу.
а что, примеры уже нельзя приводить? :) я просто хочу показать, что идиомы из одних мест они не всегда уместны в других.
И откуда эта идиома?
скажите, что не так в этой логике. Иначе, это выглядит как логика уровня 0. Я хотя бы аргументировал, вы же просто ляпнули.
Если я использую распространенную терминологию это не значит что я на питоне пишу как на джаве. Я на каждом языке собственно пишу так, как в нем принято. В чужой монастырь, как говорится.
пардон вы ошиблись — во-первых, здесь нет перевода. Трейт — это англоязычный термин, который не переведён, а взят как есть, перевод был бы "особенность", "черта". Во-вторых, это общепринятая практика, например слово "танк" это тоже заимствование из английского, без перевода (перевод — "бочка"). Впрочем, кому я объясняю, вы это и сам прекрасно знаете. И либо вы понимаете ошибку в вашей логике и намеренно её делаете, либо не понимаете, тогда увы о чём разговор про логику уровня /b/.
А "хэшмап" — это перевод какого слова?
Да, когда работаешь на питоне, наиболее эффективно работать используя подходы, принятые в питоне. Пиша на Жаве — подходы, принятые в Жаве. Если вы считаете, что на всех языках одинаковые идиомы одинаково эффективны, вы не "просто разработчик", а просто не разработчик. (Не имея в виду лично вас.)
Но есть общие вещи. Например "хэшмап" реализован +- одинаково и в питоне, и в жабе, и в расте, и где угодно ещё. От того что где-то его называют "словарём" (как в моем основном сишарпе, к примеру) ничего не меняет. А если вы так прикипели к конкретной терминологии, это как раз скорее для меня сигнал про неготовность к развитию. Для человека по-хорошему должно быть неважно даже на каком языке писать, не то, что какими синонимами описывать происходящее в ней.
И откуда эта идиома?
да, подумав, пожалуй не в тему =)
Если я использую распространенную терминологию
я не соглашусь, что она распространённая. Конкретно HashMap, Array — типы данных из Жавы. Честно, за 11 лет работы ни разу не слышал слова "хэшмап" в контексте питона. Map
, Mapping
может быть ещё более-менее, хотя в первом случае путается с функцией map(), а во втором — с collections.abc.Mapping
. Конечно, я пойму, о чём идёт речь, если кто вдруг выскажется, но всё-таки предпочитаю называть лопату лопатой (call a spade a spade) :)
С другой стороны YMMV — я не работал везде, и сказать что никто не использует слова "хэшмап" вместо дикта/словаря и "массив" (прям-таки Pascal :)) вместо листа/списка, тоже не могу.
В чужой монастырь, как говорится.
вот и я о том же, просто терминология для меня показатель. На чём пишешь, так и говоришь ...
А "хэшмап" — это перевод какого слова?
HashMap как тип в Жаве соответствует dict как типу в питоне. Т.е. перевод HashMap на язык питона — dict. :) В примере с языками я всего лишь хотел подчеркнуть, что если речь идёт о питоне, то пользоваться стоит питоновскими терминами.
От того что где-то его называют "словарём" (как в моем основном сишарпе, к примеру) ничего не меняет
Окей, обратный пример. Я прихожу на собеседование Java Senior Dev и говорю, если ключик в словаре ("in") is None..., или напишем лямбда функцию возвращающую списочек ...
Есть ли вероятность, что я бы прошёл собеседование дальше этих фраз? Даже если я бы мог написать код на жаве правильно, это всё равно выдаёт человека, которому Жава не настолько близка, чтобы он выражался принятой в ней терминологией. Ибо поработав с языком -дцать лет, ты уже не думаешь, что в теории дикт и хэшмап это одно и то же, а говоришь то, что видишь чаще всего. С другой стороны, мне вряд ли вообще пришло бы в голову назвать java.util.HashMap диктом — просто потому, что он называется HashMap, а дикт, это вроде вполне конкретный тип в питоне...
Хотя возможно я и переоцениваю влияние языка (ЯП) на язык (которым выражаешься) и обратно.
я не соглашусь, что она распространённая. Конкретно HashMap, Array — типы данных из Жавы.
А ещё из хаскеля. И из С++. И из раста. И из котлина. И из дарта. И из ...
Почему сразу считаете, что это "тип из джавы"?
Окей, обратный пример. Я прихожу на собеседование Java Senior Dev и говорю, если ключик в словаре ("in") is None..., или напишем лямбда функцию возвращающую списочек ...
Ну и нормально, говорите :)
Хотя возможно я и переоцениваю влияние языка (ЯП) на язык (которым выражаешься) и обратно.
Вот. Именно это я и хотел донести.
. хранится список номеров телефонов или номер телефона это ключ к записи? в чём вообще суть задачи?
Оооо. Дружище, задав такой вопрос вы вот прям вот без штанов вот вышли в публичное место. Прям вот камиинг аут
Было похожее собеседование недавно на senior php.
- паттерны проектирования знаем? — нет
- explain в sql для чего нужен? — не знаю
- какие виды архитектуры знаем? — не силен в теории
- как работает DI? — человек плавает, говорит какую-то чушь про service provider
- как с docker? — никак использую vagrant
- с *nix как? — только основы
После чего у человека уточняют на какую сумму он рассчитывает и он называет медиану по рынку для сеньора…
На что спрашивается рассчитывал ?
В php в этом вообще печаль-беда — куча web мастеров с портфолио на 50+ проектов на готовых движках, но задашь что-нибудь не стандартное и все человек выпучил глаза и тупит. Я лучше еще одного junior возьму и буду обучать...
Слишком демпниговать тоже не стоит, можно получить эффект "как-то он слишком мало хочет. Наверное какой-то стрёмный. Ну нафиг".
Или чётко обозначивать "готов работать за еду некоторое время ради получения опыта коммерческой разработки". Тут, главное, соглашаться только туда, где будет эффективно приходить востребованный в дальнейшем опыт.
Но если посмотреть на компании типа Ланита, которые продают джунов по цене сениоров, то там уже шансы выше. Я сам как раз на 15к туда устраивался в 2013м, по схожим соображениям. В 2012 пробовал в каспера, но не захотели они меня даже на собес звать.
А так: опенсорс, разработка, все дела. У меня щас в тематическом канале в телеге сидит школьник-10классник, который уже и идрис выучил, и на расте бодренько шпарит (один из коллабораторов библиотеки teloxide), и запилил свой язык на макросах поверх С, с АДТ, тайплевелом и прочими вкусностями. Хотя казалось бы — 18 лет нет человеку… Такого я б даже может взял, несмотря на наши правила)
Ну это от организации зависит. В текущей например мы действительно джунов даже не рассматриваем, потому что 1 джун это обычно не плюс 1 разработчик, а минус 0,5.
Но если посмотреть на компании типа Ланита, которые продают джунов по цене сениоров, то там уже шансы выше. Я сам как раз на 15к туда устраивался в 2013м, по схожим соображениям. В 2012 пробовал в каспера, но не захотели они меня даже на собес звать.
Дело всего лишь в возможностях организации процесса работы.
В маленьких конторах каждый человек на счету, и да, минус 0.5 запросто может быть и это маленькая организация не всегда может себе позволить.
Перешел на файрфокс, хабр тормозить перестал. Чего и вам желаю.
Вот из-за таких комментариев джуны боятся вопросы задавать и сидят пилят что-то несуразное, что миддлы-сеньоры-лиды должны потом переписывать явно или в процессе код-ревью.
Задача нормального менеджера убедить и джуна, и коллег, что джун, получая ответы на свои вопросы от них, ни у кого время не ворует, что менеджер заложил "минус 0.5 разработчика" на время, как минимум, онбординга джуна и уменьшил свои ожидания от всей команды на этой время, оплачивая коллегам обучение джуна.
На прошлой работе был такой слушай, приехал человек из узбекистана самому 30 лет, знает html/css и немного php готов работать на опыт. Месяц поработал вообще без оклада, 2 с окладом джуна.
За пол года дорос до крепкого мидла, после этого отработал год и гордо ушел в закат.
После чего на одной конфе встретился со знакомым и узнал что этот дядя освоил ruby on rails и сидит себе сапортит legacy монолит в крупной компании и счастлив.
Говорите за себя. У нас сейчас 5 джунов, 3 уже делают успехи. Еще один дорос до мидла и платим ему норм зп, еще одна уже ушла в спорт и получает зп оператора.
С джунов просим 2 вещи — стремление развиваться и умение писать код (на уровне fizzbuzz). Первые месяцы джуны сидят в офисе и проходят онлайн курсы, если есть вопросы — то спрашивают мидлов. После чего включаем в работу постепенно допуская все к более сложным задачам. Вот неделю назад буквально одному из них доверил собирать dev-сборки
Что-то сомневаюсь, потому что судя по вопросам — нужен миддлакак минимум.
Если готовы к переезду в наш регион одной из стран бывшего СССР. К местным зп которые на уровне московских — ну такое себе, плюс качество жизни чуть пониже — тогда добро пожаловать в личку )))
Вы хотите найти людей, которым нравится Go. И которым нравится писать на Go.
Почему-то мне не кажется, что это особо обширная группа людей. Язык, придуманный с ненавистью к быдлу (чтобы не выделывались, а писали как сказали), язык, придуманный для того, чтобы разгрузить сеньёров (они там пишут как хотят, а нам легко ревьюить).
И почему это никому не нравится инвестировать энтузиазм в Go?
Может, стоит попробовать Rust? Я уверен, там будет много людей, которым нравится разбираться в языке и его особенностях, потому что rust — любят. А go — не любят.
Ну мне, например. Скажем, потому что мне не хочется учитывать уйму подводных камней Go.
Скажем, потому что мне не хочется учитывать уйму подводных камней Go.
Вы привели в пример довольно-таки ангажированный список. Там есть некоторое количество подводных камней, но в реальности их гораздо меньше, чем в упомянутой вами статье.
Смотрите что там написано:
Пункт 1) Достоинство выдаваемое за недостаток. В других языка заводят специальные большие документы по code style и пишут дополнительные утилиты, чтобы избежать проблемы, которой в Go нет из коробки. И уж чем, чем, а именно подводным камнем не является, так как вам не удастся сделать это незаметно, компилятор вам не даст.
Пункт 2) Позволяет уменьшить количество ошибок в коде. Это достоинство языка, опять таки, выдаваемое за недостаток. Но автор статьи с непонятных причин выставляет это как недостаток. Подводным камнем не является, так как вам не удастся сделать это незаметно, компилятор вам не даст.
Пункт 3) Достоинство языка, выдаваемое за недостаток, то же что и пункт 2. Подводным камнем не является, так как вам не удастся сделать это незаметно, компилятор вам не даст.
Пункт 4) Вкусовщина. Подводным камнем не является, так как вам не удастся сделать это незаметно, компилятор вам не даст.
Пункт 5) Вот мы добрались до первого подводного камня. Пятым в списке претензий к языку обнаружился первый подводный камень, что говорит нам о низком качестве проработки «претензий» в упомянутой вами статье.
Пункт 6) Вкусовщина. Подводным камнем не является, так как вам не удастся сделать это незаметно, компилятор вам не даст.
Пункт 7) Можно засчитать как половина подводного камня, так как это зачастую даже нужно самому программисту. Хотя да, приходится быть внимательнее. Решается включением статического анализатора.
Пункт 8) Автор статьи требует нарушить принципы языка Go — делать вещи по возможности явными.
Пункт 9) Ну так то речь вообще о разных вещах. Автор ожидает что и у функции и у простого присваивания будет одинаковое поведение. Что? Проблема в голове автора.
Пункт 10) Это второй однозначно подводный камень. Он идет 10-ым в списке претензий. Что показывает притянутость за уши большей части претензий.
Пункт 11) Совершенно логично сделано в языке.
Ну и так далее в том же духе.
Реальных подводных камней в статье приведено раз-два и обчелся.
Остальные претензии автора — или личная вкусовщина автора той статьи или, даже, он достоинства языка выставляет за недостатки.
Причем подавляющая часть претензий к тому, что «компилятор не дает так делать». Но, позвольте, такое поведение уж к подводным-то (незаметным) камням отнести никак нельзя.
Вы напрасно ссылаетесь на тот список, как на какой-то авторитет.
Все пункты спорны, но вот про 2 и 3 откомментирую: когда я игрался с кодом на Go то любое экспериментирование в стиле "давайте закомментируем использование этой переменной и попробуем всесто неё использовать константу" приводило к лавинообразному "неиспользуется там/неиспользуется здесь". В итоге я по 5 минут занимался тем, чтобы комментировать разные куски кода, или тем паче его редактировать, а потом после игрищ нужно было как-то помержить результат исследования с изначальным видом кода.
В других языках отформатированный код лежит в репозитории, а на машине разработчика он может делать что угодно. Потому что не нужно поддерживать "0 ворнингов" ПОСТОЯННО, достаточно чтобы на момент коммита было так. А это легко решается вызовом форматтера на стороне гит сервера, который проверит, что код корректно написан. Вы правда думаете, что дописать одну проверку сложно?
А это легко решается вызовом форматтера на стороне гит сервера, который проверит, что код корректно написан. Вы правда думаете, что дописать одну проверку сложно?
Я правда думаю, что этого никто делать не будет. Если не принуждать.
За очень редкими исключениями предприятий высокой культуры коды.
Я правда думаю, что этого никто делать не будет, как мы это видим в других языках программирования, несмотря на наличие для них code style и соответствующих утилит.
В результате мы имеем очень разномастный код в других языках в публичных пакетах/библиотека.
Чем это плохо? Глазу нужно время чтобы настроится.
А код на Go читается гораздо легче и быстрее всегда, там глаз всегда настроен на одно и то же, потому что авторы языка Go продавили определенный стандарт на code style немножко насильно.
К слову: автор утилиты go fmt даже сам не был согласен с конкретными правилами code style, принятыми для Go. Но при этом он понимал, что всё равно эти правила должны быть едиными для всех, независимо от его личного вкуса.
Ну вот возьмите исходный код на расте, где нет никакого "Обязательного форматирования". Но почему-то весь код в публичных репозиториях оформлен в одном стиле, ничего выбивающегося я из десятков реп что открывал не припомню. Получается, заставлять под дулом пистолета все же нен адо?
ничего выбивающегося я из десятков реп что открывал не припомню
Если вы про rustfmt, то у Go это тоже такое же добровольное как и go fmt.
Выдаете желаемое за действительное.
Это технически затруднительно — чтобы у всех было одинаково.
Тут даже не человеческая лень тому причиной (а лень при нас всегда).
Даже живя в соседних государствах — Канада и США, в одном маленьком государстве совсем рядом — Англия и Шотландия — мы имеем разный английский.
Расхождения начинают проявляться сами по себе, это особенность человеческого мозга. Мы имеем индивидуальные особенности и предпочтения всегда.
Да блин даже по сути одинаковые смартфоны, но должны быть у нас немножко разными.
Получается, заставлять под дулом пистолета все же нен адо?
Служители Rust — элита, осознающие что нужно придерживаться code style?
А пишущие на Java, JavaScript, Python, PHP, С++ и пр. форматируют кто в лес, кто по дрова, ибо они все сплошь быдлокодеры?
Просто языки разного поколения. Можно видеть, что чем дальше в прошлое, тем ниже культура оформления кода в среднем. У сишников лучше чем у алголовцев, а у го/раста лучше чем у сишников. Выдавать это за илитарность или нет решайте сами :shrug:
А для Rust специальных «чистых» программистов родили просто?
Глобально это одни и те же люди.
Причина, имхо, всего лишь в наличии легкодоступного (не нужно что-то искать и что-то ставить дополнительно) встроенного rustfmt. То есть в наличие стандарта, «навязанного» разработчиками Rust.
Нет, просто множество программистов на сишарпе и расте меньше, чем просто на сишарпе. Поэтому даже если программисты, получив опыт раста (или го) запилили у себя в попенсор сишарп проекте форматтер или линтер, то это не окажет большого влияния на процент проектов на гитхабе с настроенным форматированием. У меня вот на всех проектах оно стоит, а у моих коллег которые с растом/го не знакомы и не пользовались консольным форматтером (а только тем, что предоставляет ИДЕ) — нет.
Но косяки касаются и свеженаписанного кода
Вот есть у нас условно 5% разработчиков сишарпа, которые познакомились с линтерами в других япах. И теперь на 5% нового кода с линтерами будет приходиться 95% НОВОГО кода но без линтеров. Про старый я вообще молчу, там триллионы строк кода написанного по-старому.
И это если эти 5% стали использовать линтеры во всём своём коде. Хотя, если часть из них сможет продвинуть линтеры на свои проекты, на свои команды, то конечный результат непредсказуем :)
Вот есть у нас условно 5% разработчиков сишарпа, которые познакомились с линтерами в других япах.
Острейшая необходимость в линтере есть как раз в древнем от рождения С++.
В таких свежих языках как Rust и Go необходимость в линтерах меньше. Просто потому что сам компилятор проверяет суровее.
Все пункты спорны, но вот про 2 и 3 откомментирую: когда я игрался с кодом на Go то любое экспериментирование в стиле «давайте закомментируем использование этой переменной и попробуем всесто неё использовать константу» приводило к лавинообразному «неиспользуется там/неиспользуется здесь». В итоге я по 5 минут занимался тем, чтобы комментировать разные куски кода, или тем паче его редактировать, а потом после игрищ нужно было как-то помержить результат исследования с изначальным видом кода.
Совершенно согласен, что это раздражает.
Но при этом я кучи незаметных ошибок избежал (переменную подготовил, задумал её использовать, а потом ушел в другое место программы и забыл про эту переменную; но умница компилятор подсказал; оказывается, всё правильно он мне подсказал, нужно было эту переменную использовать; компилятор помог не допустить логической ошибки в программе), так что как бы не раздражало, но смысл в этих проверках есть.
Тут можно привести пример Хаскеля, где подобные вещи на порядок более жестко проверяются. И, в шутку или в серьезно про программу на Хаскеле можно сказать так: «если ваша программа на Хаскеле вообще смогла скомпилироваться, то она, с большой вероятность и задачу вашу решит корректно».
Так вот все эти доп. проверки в Go позволяют избежать некорректно работающих программ не только в техническом смысле, а и в смысле уменьшения количества ошибок для целей решения конечной задачи, ради которой программа и была создана.
Ну как пример обратный:
Тот же С позволяют и ногу себе отстрелить.
Но на сегодня сложные проекты целесообразнее создавать на Rust, где компилятор делает кучу дополнительных проверок, чтобы уменьшить вероятность остаться без ноги.
Да это раздражает, пока прорываешься через сообщения компилятора.
Но лучше иметь эти сообщения.
Эти доп. проверки основываются на "разработчик дурак, мы за него решим как лучше". Этакий эппл от мира разработки. Я считаю, что это вредно. Мало того, что разработчик не понимает, ПОЧЕМУ так сделано, это ещё и ставит палки в колёса тем, кто понимает. Проверок на уровне создания коммита или даже PR более чем достаточно для поддержания чистой кодовой базы.
Эти доп. проверки основываются на «разработчик дурак, мы за него решим как лучше». Этакий эппл от мира разработки. Я считаю, что это вредно. Мало того, что разработчик не понимает, ПОЧЕМУ так сделано, это ещё и ставит палки в колёса тем, кто понимает.
Вы серьезно?
То, что компилятор указывает вам на потенциальные ошибки вы считаете минусом? Предлагаете откатиться во времена С?
Да нет проблем, вы и сейчас можете писать на С. Но зачем требовать от нового языка программирования повторения ошибок архитектуры старого языка программирования?
При этом тут же рядом вы приводите примером «хорошего» Rust, где компилятор ограничивает ни в пример больше (тот же каскад сообщений с borrow).
Имхо, вы пишете каждый раз так как вам удобно в данном конкретном аргументе, не придерживаетесь последовательной точки зрения. Спасибо, но не интересно.
То, что компилятор указывает вам на потенциальные ошибки вы считаете минусом? Предлагаете откатиться во времена С?
Ложная дихотомия, давайте без этих приемчиков, выглядит некрасиво.
если я написал print("Hello world")
а потом закомментировал его я НЕ ХОЧУ получать ошибку что у меня неиспользуемый fmt — я ЗНАЮ, я закомментировал его на одну секунду проверить одну идею. После того как скомпилируется я его раскоммнетирую. Я не хочу иметь из-за этого ошибку. Варнинг — ещё ладно, но ошибку точно нет. Перед коммитом в репозиторий я конечно почищу все варнинги, но сейчас-то я не хочу тратить время на это.
При этом тут же рядом вы приводите примером «хорошего» Rust, где компилятор ограничивает ни в пример больше (тот же каскад сообщений с borrow).
Пока что по опыту гошный линтер ограничивает меня куда больше.
Ну так не запускайте линтер при записи файла. gofmt/goimports/gofumports — другое дело, но они на такое не ругаются. Поддерживать одинаковое форматирование кода всегда, включая процесс активного редактирования кода — это одно, и это действительно очень полезно, потому что глаз привыкает и проще читать код. Гонять жёсткие линтеры каждые несколько минут и поддерживать требуемую ими чистоту кода во время активного редактирования — это уже какой-то мазохизм. Линтер надо запускать в идеале перед коммитом, очень желательно перед отправкой PR, и обязательно на CI, которая этот PR проверяет.
Поддерживать одинаковое форматирование кода всегда, включая процесс активного редактирования кода — это одно, и это действительно очень полезно, потому что глаз привыкает и проще читать код.
Я часто использую нарушение форматирования для временных решений типа отладочного вывода или комментирования куска кода. Как раз чтобы глаз резало, чтобы не забыть убрать.
Для этого есть более эффективные средства, вроде комментариев FIXME/DEBUG — на которые обучен ругаться линтер, благодаря чему отпадает субъективный фактор "режет глаз", который может сработать далеко не всегда (особенно если задачу пилит больше одного человека, или просто если отвлекся и не просмотрел внимательно git diff перед коммитом).
По какой метрике считаем эффективность? )
Если затраты на настройку линтера и введение его обязательным шагом в процесс околонулевые, то возможно.
Околонулевые. Более того — линтер всё-равно надо подключить и настроить, без вариантов, на любом проекте, включая личные мелкие пет-проекты. Так что даже если бы затраты были более значительными чем скопировать .golangci.yml
из предыдущего проекта и добавить вызов линтера в конфиг CI — их всё-равно пришлось бы делать.
Ну вот я сейчас оцениваю затраты на подключение линтера как часов 60 моего времени. Из них часов 30 на настройку самого линтера и часов 30 на автоматизацию CI на базе ранее не встречавшегося мне и непонятного Teamcity. Речь не про Go если что, банальный PHP.
В 60 — не верю, простите. Я настраивал немало разных линтеров для разных языков и CI, столько на это не нужно. На линтер максимум часа 2-3, это если это монстр мета-линтер содержащий десятки других линтеров и его надо заточить под особенности текущего проекта. Изучение нового сервиса CI может занять много времени, но линтер тут не виноват. А подключить линтер к уже настроенному CI — дело пяти минут, максимум получаса.
Но главное вовсе не то, что это можно сделать быстро, а то, что это достаточно научиться делать один раз и подключение этого же набора в следующем проекте займёт реально минуты.
Особенности текущего проекта:
- линтеров не было никогда
- навскидку используется три код-стайла в нашем основном коде, причём не строго в даже рамках одного файла.
- куча стороннего кода, причём после трёх месяцев на проекте я ещё не знаю точно где наш, а где сторонний — только по истории коммитов смотреть надо, добавлялся он одним куском или постепенно писался. Там тоже с код-стайлом не очень
- код на фреймворке с кучей магии, позволяющей использовать необъявленные переменные. надо как-то прикрутить проверку обязательности хотя бы аннотаций в комментариях. Выглядит как написание своего модуля для линтера. В идеале с проверкой наличия столбцов в базе для магии слоя доступа к ней.
- тестов нет, чтоб с чистой совестью прогнать автоисправление
- в исходниках код на пяти языках не считая SQL в строках, плюс файлы сочетающие код на нескольких языках (.ini подобные разделители секций)
Ну и сама CI с GUI невнятным. В теории можно писать пайплайны на Kotlin, но пока для меня эта возможность заблокирована.
Тяжёлая ситуация, но это же ничего не меняет в моих оценках. Просто надо разделять разные виды работ: подключить линтер к проекту, и почистить весь код проекта так, чтобы линтер на него не ругался — это же очень разные вещи. Я оценивал первое. Второе может занять сколько угодно времени, в зависимости от размеров и запущенности проекта.
Из хороших новостей: некоторые линтеры поддерживают режим "проверять только новый код", т.е. проверяться будут только те строчки, которые изменились/добавились в текущем PR. Это позволяет намного быстрее начать пользоваться линтером. Но даже если такой стиль не поддерживается, то всё-равно можно, например, за день-два отрефакторить проект так, чтобы весь, условно, старый код жил в каталоге old/ и линтер туда не совался, а все новые фичи писались в другом каталоге, который линтер проверяет максимально тщательно. Ну и дальше в том же духе можно покрутить, как сделать так, чтобы по старому коду линтер проверял самый минимум или вообще ничего, а по новому работал в полную силу. И дальше уже постепенно, по одной, активировать фичи линтера для старого кода, одновременно подчищая этот код — да, этот процесс растянется на месяцы, но зато он не будет блокировать текущую разработку бизнес-фич а код будет постепенно становиться чище.
если я написал print(«Hello world») а потом закомментировал его я НЕ ХОЧУ получать ошибку что у меня неиспользуемый fmt — я ЗНАЮ, я закомментировал его на одну секунду проверить одну идею.
Просто используйте
_ = НенужнаяФункция()
вместо
НужнаяПеременная = НужнаяФункция()
если вам так надо.
В реальности, как показывает куча подключенных ненужных зависимостей в ПО годами уже работающего в production, программисты, конечно, всё знают и всё помнят. Но забывают.
Буквально вчера исправил подобную багу из-за неиспользуемого кода, что жил на сервере года 4-5.
Подобные косяки встречаются чаще, чем вам кажется.
Пока что по опыту гошный линтер ограничивает меня куда больше.
Ну это и есть дело линтера «немножко параноить». Не запускайте его просто. Или настройте до нужно вам уровня паранойи.
Имхо, у вас обычное неприятие нового, что пока мало знакомого. Это нормально для человеческого мозга.
Буквально вчера исправил подобную багу из-за неиспользуемого кода, что жил на сервере года 4-5.
Как этот баг пролезет, если ровно та же рповерка делается, но при мерже?
_ = НенужнаяФункция()
вместо
НужнаяПеременная = НужнаяФункция()
если вам так надо.
А на это я получаю ошибку no new variables on left side of :=
. Видимо подчеркивание считается какой-то магической переменной, которую присваиваем а не инициализируем. Тем более, нужно тогда все := заменять на _ для такого. ИМХО неудобно совершенно.
В го есть форматтеры и импорты добавляются и удаляются ими автоматически. Т.е. в реальной работе нет такой проблемы.
То есть неиспользуемый импорт является ошибкой компиляции без всяких внешних тулов, просто вот в компилятор вшита такая проверка. Что весьма маешает.
То есть неиспользуемый импорт является ошибкой компиляции без всяких внешних тулов, просто вот в компилятор вшита такая проверка. Что весьма маешает.
Современные языки используются всё больше с IDE…
Это формально конечно «внешний тулз». Но он всегда с нами.
В современных языках это ворнинг. Который можно проигнорировать.
Покажите язык, который все потенциальные ошибки считает реальными и не даёт компилировать код?
В современных языках это ворнинг. Который можно проигнорировать.
Вы говорите о нормах конца прошлого начала нынешнего века.
В старых языках — да.
В новых языках — идет обратная тенденция.
Уж очень люди ленивы, уж очень часто программисты забивают на warning.
Rust — старый язык? Idris — старый язык?
Покажите любой язык кроме Go где unused это ошибка компиляции.
Уж очень люди ленивы, уж очень часто программисты забивают на warning.
Нет, это "пользователи нашего языка — идиоты, поэтому мы им запретим всё для их же блага". Я удивлен, что кому-то вообще подобная формулировка не то что не претит, но и даже нравится.
Чтобы в проекте не было ворнингов достаточно использовать куда менее драконовские меры, без потери качества. Но, видимо пока их не продаст гугл, никто про них думать не будет.
Покажите любой язык
Почему в одном языке должны быть те же принципы, что и в другом? Зачем тогда вообще разные языки?
Только ради синтаксической вкусовщины, чтобы у программистов была возможность, например, объявлять переменные по разному?
тип название_переменной;
название_переменной: тип;
название_переменной тип
Разница-то в языках не только в этом.
Чтобы в проекте не было ворнингов достаточно использовать куда менее драконовские меры, без потери качества. Но, видимо пока их не продаст гугл, никто про них думать не будет.
Да ладно вам демонизировать.
Есть же и Python выросший тоже под крылом Google. И он другой.
Просто языки — они разные.
В этом и смысл.
Один язык не обязан следовать принципам принятым в другом языке. Иначе и смысла придумывать разные языки не было бы никакого.
Вы же сами написали, что «в новых языках», а не «в одном конкретном Go».
Угу. Есть такая тенденция.
Сравните хотя бы диагностику GCC и Clang
gcc и clang — новые языки? Или они по умолчанию компилируют с -Werror?
Пример был не про языки, а про тенденцию.
Современная тенденция — больше диагностики.
При этом, когда я прошу «дайте мне больше возможностей описывать свои собственные диагностики и ограничения в виде типов», мне говорят, что это всё не нужно.
Зачем нам совершенно одинаковые по функционалу языки? Зачем повторять другие?
То, что вам надо — есть в других языках.
Выбор языка под задачу — совершенно нормально.
Вот и я не могу понять, зачем [мне] Go. Для каких задач он мне пригодится?
Зависит от того, какого типа у Вас проекты, насколько Вы довольны текущим языком и как сильно Вас достала чрезмерная сложность всего окружающего — от используемого языка до собственного кода.
Я лично перешёл на Go потому, что он хорошо подходит именно для тех проектов, которые я обычно пишу (микросервисы и утилиты), потому, что он очень простой сам по себе, и потому, что код на нём легче читать и поддерживать. Моя жизнь после перехода на Go стала заметно легче — мне нужно прикладывать меньше усилий, чтобы написать качественный и вполне производительный микросервис, и потом его поддерживать.
Диагностика на неиспользуемые переменные была по-моему ещё в паскале. Какие это «новые тенденции»?
Проблема в том, что линтеры существуют, но их ленятся запускать.
Новая тенденция — то, что падает значение отдельного линтера, который поленятся запустить. Нынче всё больше проверок внутри компилятора.
Ну да, а в том, является ли неиспользуемая переменная ошибкой или нет, ага.
Помнится, когда Яву запускали — всех тоже бесила особенность, что нельзя не обрабатывать исключение.
«Мы же умные, мы же сами решим когда их обрабатывать, а когда не обрабатывать».
Ну а авторы языка на момент создания Явы имели жизненный опыт, который говорил им, что программы, в т.ч. и тщательно отлаженные, вроде бы. А все равно могут неожиданно «падать в кору» из-за того, что программисты всё же забывают обрабатывать исключительные ситуации. И они решили принудить.
И обмазали Яву с ног до головы необходимостью всё декларировать.
Именно потому что программисты, вроде бы, и знают как нужно правильно делать, но не делают этого в реальности.
И при этом я всё равно считаю, что делать неиспользуемую переменную ошибкой компиляции — не нужно.
А я считаю, что крайне полезно. Это уже сэкономило мне кучу времени. Как ни парадоксально звучит.
На самом деле этой проблемы не существует. Она шокирует в момент знакомства с языком, это да. Я помню, тоже впечатлился в своё время. Но при ежедневном использовании она проблем практически не доставляет.
Иногда, особенно при временном комментировании куска кода, приходится вместо него добавлять "заглушку" вроде строки:
_, _ = varA, varB
И хотя, на первый взгляд, сейчас самое время воскликнуть "вот! видите!!! яжеговорил, оно мешает!!!", но на практике это не отнимает ни времени, ни внимания, делается абсолютно механически, и нужда в этом возникает примерно раз в неделю (и обычно — в тестах). Я не говорю, что я счастлив, что приходится это делать в принципе, но это действительно не является реальной проблемой, и это далеко не самый серьёзный недостаток Go.
Помнится, когда Яву запускали — всех тоже бесила особенность, что нельзя не обрабатывать исключение.
Да, в итоге когда все поняли что это неюзабельная хрень в язык добавили unchecked exceptions и про эту проблему забыли как страшный сон.
Помнится, когда Яву запускали — всех тоже бесила особенность, что нельзя не обрабатывать исключение.
Да, в итоге когда все поняли что это неюзабельная хрень в язык добавили unchecked exceptions и про эту проблему забыли как страшный сон.
Напомните, в каком это произошло году?
А в каком году появилась Ява?
Если сравнить первую Яву и нынешнюю — там очень много изменений. Вплоть до невозможности просто перекомпилировать без исправлений сколько-нибудь сложный проект так чтобы в итоге ничего не сломалось.
Причём не взлетело не столько потому, что сама по себе идея плохая, столько потому, что отсутствовал полиморфизм по спискам возможных исключений.
Как IDE помогает удалять неиспользуемые импорты?
Ну, понятно всякие фичи рефакторинга — но это опять ВРЕМЯ
Подсвечивает, как минимум.
Плюс Code > Optimize imports у JetBrains
Как IDE помогает удалять неиспользуемые импорты?
Погуглите функционал goimports
В Intellij можно поставить галочку "оптимизировать импорты" во время выполнения форматирования кода. Не знаю, как все, а я часто прожимаю этот шорткат на автомате (прямо как Ctrl+S некоторые).
У меня в Vim при записи запускается автоматически и добавление/удаление импортов, и переформатирование, и проверка на ошибки. Всё это выполняется практически моментально. Вручную импорты мне приходится добавлять где-то раз в пару недель, когда тулза ошибается. Удалять импорты вручную не приходится вообще никогда. Иными словами — Вы не правы, никому ничего не мешает.
Вот у вас есть использование форматирования в WriteLine. Вы закомментили этот код. Вам IDE автоматически импорт удалит? ПОтому что если нет то в го у вас теперь код не компилируется, ведь есть неиспользуемый импорт!
Как сам удалит, так сам и вернёт, когда я раскомментирую строку. Он сам с собой в это добавление/удаление импортов играет, по сути, я туда обычно даже не смотрю (за исключением редких ситуаций, когда есть высокая вероятность, что он автоматически подсунет импорт не той библиотеке, вроде math/rand вместо crypt/rand, или первую версию вместо /v2, etc. — но это бывает редко).
Спрашивается, и зачем тогда эти импорты в файле, если программист их не вводит и даже не смотрит на них..
Действительно, получается requirements или package.json достаточно....
Он есть — go.mod
. И да, я тоже думаю, что тулзе было бы неплохо обращать на него больше внимания при поиске подходящих импортов. Но есть нюансы: иногда добавляется новая зависимость, и это делается прямо в коде, не отвлекаясь на добавление её сначала в go.mod
(ибо она туда добавится автоматом сама чуть позже), иногда это стандартная библиотека, как в примере с math/rand vs crypt/rand, которую в go.mod не добавляют, иногда (редко) в go.mod подключены две мажорные версии одного пакета, соответственно какая из них нужна конкретно в этом месте кода тулза сама может не разобраться. В общем, тут явно есть, что улучшать, но вот прям сходу вообще выкинуть импорты из кода "в связи с их очевидностью" пока не получится.
Затем, что иногда тулза ошибается.
Спрашивается, и зачем тогда эти импорты в файле, если программист их не вводит и даже не смотрит на них..
Потому что иногда программисту нужно иметь возможность на импорты влиять вручную. Компьютеры, всё же, пока еще не пишут программы полностью за программистов.
Например, в случае одноименных пакетов. В частности IDE Jetbrains подключает импорты молча, если они однозначные. И задает вопрос, если есть сходные имена (как выше с примером rand)
в случае одноименных пакетов
мне кажется, что их проще банить на уровне принятия в репо пакетовв. Или на уровне конвенций об именах делать их униками (ну, как, в джаве — com.gitlab.component.my — многословно, но этот код автогенерируется IDE)
в случае одноименных пакетов
мне кажется, что их проще банить на уровне принятия в репо пакетовв. Или на уровне конвенций об именах делать их униками (ну, как, в джаве — com.gitlab.component.my — многословно, но этот код автогенерируется IDE)
Полное имя пакета — да, уникальное.
И в импорте указывается именно оно.
Но в основной части кода при обращении к объекту из этого пакета указывается только последняя часть.
В вашем примере это будет:
my.A()
my.B
my.C{}
И если есть пакет
com.gitlab.other_component.my
то в нем могут быть ровное все те же:
my.A()
my.B
my.C{}
А как оно будет работать если функция в двух подключенных пакетах есть? Пример из жизни, у меня есть микросервис, который опрашивает 5 других микросервисов. Каждый из которых выставляет типа ServiceA.Error, ServiceB.Error,… Как эта штука будет определять, какой именно Error я имел в виду в закомментированной строке?
См. выше: тулза иногда ошибается. Нередко есть другая тулза, которая помогает с этим бороться: линтер depguard, например, который следит чтобы в проекте не появлялись определённые импорты (чаще всего — посторонние логгеры, у них всех очень похожий API и ошибки при их импорте встречаются чаще других, что и мотивирует автоматизировать борьбу с такими ошибками через линтер).
Мне это видится проблемами с ветряными мельницами. Слишком умный тул, который ошибается, поэтому есть второй тул… А можно было просто не делать неиспользуемый импорт ошибкой компиляции.
Кстати, а неиспользуемые переменные оно тоже так подставляет? Потому что импорты-импортами, но это общее правило. Закомментил переменную А. Перестали использоваться B, C. закомментил и их. Перетали быть нужы D, E, F. Закоментил их — теперь функция не использует входные параметры. Закомментил их — теперь нужно поправить все места, которые эту функцию вызывают… Хотя наверное я зря на это ругаюсь, и через _ это решается (и замену := на =), но все же.
Мне это видится проблемами с ветряными мельницами. Слишком умный тул, который ошибается, поэтому есть второй тул… А можно было просто не делать неиспользуемый импорт ошибкой компиляции.
Это чисто архитектурное решение.
Принципы unix — каждая утилита имеет свою узкую область ответственности, а полностью решение осуществляется группой утилит.
Вы об этом узнали просто потому что с вами поделился опытом человек, использующий vim, а там да, нужно самому поставить.
В реальной развитой IDE все эти вещи глубоко под капотом.
А можно было просто не делать неиспользуемый импорт ошибкой компиляции.
Вы же не думаете, что об этом забыли позаботиться?
Это осознанное решение разработчиков язык.
Неиспользуемые куски кода сигнализируют о потенциальных ошибках.
Лично меня уже неоднократно выручали такие сообщения. Смотрю и ошибку и понимаю, ба, действительно тут косяк.
Неиспользуемые куски кода сигнализируют о потенциальных ошибках.
Знаете в чем разница между потенциальной ошибкой и просто ошибкой? Тем, что потенциальная ошибка не всегда ошибка. А отказываться компилировать программу в которой нет ошибок это свинство
А как оно будет работать если функция в двух подключенных пакетах есть? Пример из жизни, у меня есть микросервис, который опрашивает 5 других микросервисов. Каждый из которых выставляет типа ServiceA.Error, ServiceB.Error,… Как эта штука будет определять, какой именно Error я имел в виду в закомментированной строке?
Поскольку Go это язык со статической типизацией — у IDE довольно-много информации, чтобы решить самой.
Ибо кроме имени функции есть еще её сигнатура.
Таким образом, реальные дубли, где можно ошибиться автоматики и нужно спрашивать человека — относительно редко встречающиеся ситуации.
Тут 2 варианта что делать при наличие дублей:
1) Или каждый раз спрашивать у человека.
2) Или запоминать последнее используемое.
А при чем тут сигнатура? Вот я пишу
Error Foo() { }
Где Error
— красным подсвечен. Сейчас в том же сишарпе тул предложит импортировать Error и на выбор выдаст все пакеты, откуда он может быть получен. Автоматически это решить просто невозможно.
И это не так редко бывает, чтобы на это закрыть глаза. С другой стороны список импортов в начале файла кому-то доставляет много неудобства? Какую проблему в итоге решаем-то?
Сейчас в том же сишарпе тул предложит импортировать Error и на выбор выдаст все пакеты, откуда он может быть получен. Автоматически это решить просто невозможно.
В Go — аналогично.
Если не однозначно, то IDE вас спросит.
Если однозначно — сама подставит.
И кстати, да, в Go у вас было бы не так как в вашем примере, а так:
module1.Error Foo() { }
Ибо внешние объекты в Go указываются вместе с именем пакета.
А это уже упрощает получение подсказок/автоимпорта от IDE.
То есть в коде уже есть подсказка на вероятный правильный модуль.
Интересные аллюзии :) В смысле иронии :) В том смысле, что у С и Go одни авторы )
В том смысле, что у С и Go одни авторы
это интересный тезис и я бы переформулировал его, чтобы он был более точный. "Часть разработчиков языка С является разработчиками языка Go"
Там все пересчитываются пальцами рук человка ))) Но примерно да. Но включая Ритчи, так что без разницы
Не уверен насчёт верхней цитаты в колонке 2013, но нижняя совершенно точно относится к временам задолго до гугла — она является одним из принципов заложенных в OS Inferno.
Кстати о картинке. Гугл не является родиной Go :)
P.S. В контексте философий, а не формальностей, конечно
Интересные аллюзии :) В смысле иронии :) В том смысле, что у С и Go одни авторы )
Между языками сколько десятилетий?
По сути это уже совсем другой человек.
Человеку свойственно меняться очень сильно. Тем более за десятилетия.
То, что компилятор указывает вам на потенциальные ошибки вы считаете минусом?
То, что указывает на потенциальные ошибки — плюс.
То, что считает потенциальные ошибки реальными и отказывается компилировать — скорее минус, чем плюс.
То, что считает потенциальные ошибки реальными и отказывается компилировать — скорее минус, чем плюс.
Warning — гуд только в идеальном мире. Ибо человек ленив. И попросту пропускает их.
Как показала моя практика компиляции библиотек, написанных на С, С++ — разработчики изначально проигнорировали миллион warning, что в результате привело к невозможности использования этих библиотек.
К сожалению, человека нужно иногда заставлять.
Да, это «унижает человеческое достоинство, да что они о себе возомнили, мы же не идиоты, а это рассчитано на идиотов».
На практике все же 80% разработчиков именно что идиоты/ленивы.
И если разрешить выбирать оставшимся 20% умных/ответственных самостоятельно определять уровень warning — оставшиеся 80% просто первым делом будут отключать warning навсегда. Что значительно снизит общее качество ПО.
С варнингами мне нравится когда их можно подавлять только на уровне конкретного срабатывания конкретного правила.
На практике все же 80% разработчиков именно что идиоты/ленивы.
Очень жаль, что у вас все так печально. Только вот как я уже сказал, вы лечите проблему головной боли гильотиной. Кто мешает на CI проверять отсутствие варнингов? В итоге имеем лучшее двух миров: разработчик их видит но может временно игнорировать, а CI обеспечивает именно временность и то, что в гите не хранятся все эти "Рыбу заворачивал".
Разрабочтик-идиот найдет как вам жизнь попротить и с линтером. От того, что говнокод будет красиво отформатирован жить легче не станет. Вывод простой: лучше иметь немного нормальных разработчиков, чем толпу идиотов.
Ну, то есть, вы делаете язык для ленивых идиотов
Вы так пишете, как будто в других языках по другому…
Есть же прямо противоположенные примеры:
Для той же цели разрабатывался как и усложненный Java, так и упрощенный Go.
Впрочем, я считаю что причина иная: на заре компьютерной эры было не до линтеров и форматтеров… До всего этого относительно недавно только руки дошли.
Да откуда вы все берете, что Go делали для идиотов? Ритчи, Томпсон, Керниган, Кокс и Пайк не идиоты. Зачем они для себя делали что-то как для идиотов? Или идиоты?
Загуглите, пожалуйста. Хуже не будет. Просто чтобы это прозвучало из уст хотя бы одного из разрабов. Вообще Гугль большой — ему можно, а система зависимостей в «старом» go просто ужасна. Сейчас стало получше, но все равно завязка на публичные репозитории — этапять.
Правда в том, что когда они начали его разрабатывать, Гугла даже в проекте не было, а Брин наверное ещё в Lego играл. И слова такого не было "микросервисы". Они не могли это делать для выпускников вузов, которых надо было сажать чтото там писать. Несомненно, они одними из первых подошли к снаряду микросервисов, но развить его не смогли тогда. Но теперь у нас есть UTF-8, /procfs и Golang
Дедфуд, это ты что ли? Ну камон, ты же знаешь эту историю. Я лет 10 назад в жуйке всех достал вроде
Так скажем в последней, уже гуглевых времен, редакции в Go появились только интерфейсы как концепт. В основном это были подходы к снаряду реализации и борьбы с копирайтами
Наверное потому что авторы Go одни из первопроходцев микросервисов. Когда это ещё не было модным. Это не везение, это целенаправленное движение
Я и не настаивал. Я настаивал на том, что история создания Go вообще к гуглю имеет опосредованное отношение. И это точно не было "для студентов за 50р". Это была внутренняя игрушка вполне определенного отдела BellLabs. И если cfront, utf-8 и /procfs "взлетели" тогда, то прародитель Go шёл долгим путем любимой игрушки бывших сотрудников Bell Labs
игрушка получилась так себе
Путь так скажем был тернист. Но проблема там была не в синтаксисе и конструкциях. Хотя… Хотя дженерики вот они выпилили
и выстрелила только в условиях гугла
Несомненно
выстрелила только в условиях гугла и охапок студентов
Да ладно.
Полным полно широкораспространенного ПО, созданного с использованием Go.
Да хоть Docker.
Но только потому что Гугл прокачал
Но только потому что Гугл прокачал
Ну да, а Яву прокачал почивший в бозе Sun
ЯваСкрипт был прокачан Netscape Communications Corporation
Python опять Гугль прокачал.
C# — проделки MS.
А вот неплохой вроде D не взлетел — ибо за ним никого влиятельного не стояло.
P.S.:
Хотя если взглянуть внимательнее:
Docker
Проект начат как внутренняя собственническая разработка компании dotCloud, основанной Соломоном Хайксом (Solomon Hykes) в 2008 году с целью построения публичной PaaS-платформы с поддержкой различных языков программирования
Разработка Go началась в сентябре 2007 года, его непосредственным проектированием занимались Роберт Гризмер, Роб Пайк и Кен Томпсон[5], занимавшиеся до этого проектом разработки операционной системы Inferno. Официально язык был представлен в ноябре 2009 года.
Всё из Википедии.
Чтобы докер взял Go должно было что-то случиться. Про игрушку создателей UNIX/C конечно же знало какое-то количество людей. Я даже нашёл В РОССИИ несколько человек, реально что-то делавших на одной из тупиковой веток предшественников Go. Кстати это интересно, Docker это про микросервисы. Это прямо то, с чего начался путь Go. "make mainframe great again" — это Пайк/Ритчи/Керниган конца 80-ых. Несмотря на то, что когда я увидел docker, я чуть кофе не подавился, я не считал docker идеологическим наследником Go-way. Но сейчас задумался. Надо покопаться и найти, кто у них был фаном команды Bell labs и их изделий
одной из тупиковой веток предшественников Go
Если это намёк на Limbo, то я бы не сказал, что это тупик. Вложили бы в него столько ресурсов, сколько в Go — результат был бы намного круче.
Если это намёк на Limbo, то я бы не сказал, что это тупик. Вложили бы в него столько ресурсов, сколько в Go — результат был бы намного круче.
У истории нет сослагательного наклонения.
Назови 10 отличий Limbo от Go.
Если очень надо, то, наверное, я их назову. Но, если честно, мне лень — я Limbo уже несколько лет вообще не использовал, к сожалению, так что придётся сначала поднять собственные же статьи, чтобы вспомнить и назвать, и за пять минут это сделать не получится.
Но главное в том, что 10 отличий и не нужно — потому что на практике значение имеет ровно одно: Go писался под POSIX (и позднее дорабатывался под винду), что позволило использовать его в привычных условиях, освоив буквально пару необычных концепций (горутины и интерфейсы). Порог входа в Limbo на пару порядков выше.
Ну да, синтаксически за основу взят предшественник Limbo. Выкинуто лишнее, типа дженериков, и добавлен рантайм, обкатанный на dis-машине в Limbo. И некоторые синтаксические конструкции типа перевернутого определения переменных и сигнатур функций. Про 10 отличий я спросил потому что Go довольно мало взял в себя чего-то супернового. Точнее, в нем есть новые концепты, но основа у него уже была
Год назад, мы кстати уже говорили про Limbo :) Это я был )) Я спрашивал про дженерики в функциях
Про 10 отличий я спросил потому что Go довольно мало взял в себя чего-то супернового.
Ну авторы Go и не скрывают, что там еще идеи Хоара. А они — 197x-е годов.
В этом Go не одинок:
habr.com/ru/company/oleg-bunin/blog/516218
У разных гуру, как обычно, разные мнения. Разработчики объектных языков говорят о принципиальных новшествах, для реализации которых они сделали свои языки. Это Бьерн Страуструп, разрабатывавший в 1979-1986 первый вариант языка C++. Практически параллельно с ним работал Бред Кокс, автор Objective-C (1982), Бертран Майер, разработавший Eiffel (1985) с концепцией design by contract, и другие.
Однако, рассказывая историю языков, статьи вики всячески подчеркивают, что это были не оригинальные идеи, они уже были в ранее разработанных языках, и авторы концептов не просто были с ними знакомы, а использовали эти языки. Этого же мнения придерживаются некоторые гуру, разрабатывавшие структурное программирование. Например, Николаус Вирт, работавший над Алголом, а позднее разработавший Паскаль. Он полагает, что в Алголе объекты «почти были», а С++ и другие объектные языки ничего принципиально нового они не принесли.
Мы привыкли, что каждые пару лет — по новой версии Andoroid да по новому iPhone.
В других отраслях все не так быстро происходит.
Вон тормозной механизм в моем автомобиле сконструирован 30 лет назад и сохраняется сквозная совместимость со всеми моделями этого производителя, выпущенными за 30 лет.
От языка программирования тоже не следует ожидать, что он «прямо-таки уникальной-новый». Принципы подавляющего большинства мейнстримовых языков тянутся аж и 196x-198x годов
Там не совсем просто "идеи". Там совершенно конкретная история развития совершенно конкретного языка совершенно конкретной команды с совершенно определенными вехами. Одна идея. Одна команда. Один вождь. В 2009 мы узнали это как Go.
Я люблю рассказывать — я видел живой cfront. Реально. На одном дистрибутивном диске с прародителем Go
Да, я это понял ещё с твоих первых комментов тут. Я резко заинтересовался, кто это тут знает такие исторические подробности, полез в профиль — ба, да это Фил! :) Кстати, я смотрел твой доклад по теме нашей беседы и в полном восторге, спасибо!
Утверждение, что докер про микросервисы — очень спорное. Про изоляцию (не 100%, но хоть какую) — да. Про удобство разработки — да. Про микросервисы — спорно.
Про изоляцию неймспейсы. Он конечно про пакетизацию и управление запуском. И про эксплуатацию. И именно он разогрел тему микросервисов. Ну так кажется. Потому что в том же 2010 теми же cgroups было ещё невозможно пользоваться
были солярки и фрибсд ) с зонами и тюрьмами (jails). Да и параллельно с докером очень подтянулся системди
Зоны ещё туда-сюда, а джейлы вообще так себе практическое использование имели. Докер идеи подтягивал похоже из премордиального go-way :)
были солярки и фрибсд ) с зонами и тюрьмами (jails). Да и параллельно с докером очень подтянулся системди
Про Солярку не скажу. А на FreeBSDшную тюрьму Докер переплюнул довольно быстро. За пару лет.
"было бы"? Да оно и было все 15 до. На том самом уровне. О нём кто-то знал, но и всё
«было бы»? Да оно и было все 15 до. На том самом уровне. О нём кто-то знал, но и всё
Вы про себя? Ну дык не значит что так было у всех.
У нас, к примеру, активная разработка, ведущаяся прежде всего на Go, уже лет 7. До этого присматривались и экспериментировали года три.
статья о том, что вокруг много хороших спецов с сеньерским СV, которы не дали себе труда разобраться со своим инструментом, и потому не пригодны для сеньерской позиции.
А в расте с борроучекером не будет таких же лавинных эффектов (правда, по другой причине)?
А в пайтоне и js с async / sync вызовами?
А в с++ с модификатором const?
С борровчекером не бывает, потому что можно на время экспериментов поставить 'static и забыть про лайфтаймы. С асинк — можно накостылить запуск без ожидания и thread.sleep, но там да, бывает сквозное изменение. Но как правило оно целенаправленное, а не просто "играюсь с кодом", поэтому и проблем с этим бывает меньше.
Пункт 9) Ну так то речь вообще о разных вещах. Автор ожидает что и у функции и у простого присваивания будет одинаковое поведение. Что? Проблема в голове автора.
slice = append(slice, item)
и map[key] = value
выполняют в какой-то степени одну и ту же операцию: добавляет элемент в коллекцию. Только почему-то в первом случае это можно сделать с nil-коллекцией, а во втором — нет. И, кстати, append не совсем некорректно называть функцией, вы сами такую написать не сможете.
Может, стоит попробовать Rust?Вот не уверен, что на Rust можно написать обращение односвязного списка за 5 минут. И даже за 10.
rust-unofficial.github.io/too-many-lists
Up: Не успел
Ёлки-палки, зачем вам там сырые указатели потребовались?Готовы продемонстрировать эффективную реализацию reverse для списка без сырых указателей?
Я уж молчу о том, что у вас там память течёт.А еще нельзя узнать ни одного значения из списка. Задача была реализовать reverse, а не весь linked list. Как реализовать Drop я думаю и так понятно.
Готовы продемонстрировать эффективную реализацию reverse для списка без сырых указателей?
Уже выложил тут
Но с двухсвязными так уже не сработает.
Так у двусвязных списков нет "владельца", очевидно. Потому что вам нужно прийти к концепции, владеет prev нода или next, что при выборе любого варианта приведет к противоречию. Поэтому да, без указателей и борровинга, в стиле си.
Но правда двусвязные списки ещё реже чем обычные. Так что у вас можно сказать уникальная задача.
Берёшь и пишешь
Связнаые списки в Rust это задача примерно уровня "создать объект с гарантированным методом удаления из памяти в любом ЯП с GC". Есть вещи, которые просто не делатся легко в некоторых языках.
Учитывая что связаные списки на практике я все ещё нигде в работе не вижу, даже те которые предоставляют снаружи списочный интерфейс внутри устроенны на ресайзящихся массивах, хэшмапах или ещё чем, то наверное это не так страшно.
Из стандартных структур такое не скрутишь. Но у меня все поверх Vec работает, без unsafe.
Для любой реальной ситуации есть библиотека. Например, понадобилось нам как-то держать мапу с локфри доступом и возможностью обновления. Ну я напутил прототип на arc_swap с обычной мапой. Когда нужно обновить данные — готовим мапу с новыми данными, атомарно заменяем, профит. Но оказалось, что с таким подходом мы дублируем количество используемой памяти (старая копия + новая в какой-то момент существуют параллельно), при том, что обновления обычно происходят над 1-2% структуры. Коллега пару дней попробовал руками что-то намутить, но конечно же борровчекер надавал по рукам, потому что нормально гарантировать что мы мутируем мапу на которую уже нет ссылок нет — ведь в любой момент может прийти HTTP зарпос или старый ещё только отдает данные и ему нужна копия данных.
В итоге просто взяли evmap, почитали немного документации и всё заработало. Под капотом там наверняка всякий ансейф и прочее, но нам это не очень интересно, бенчи показывают успех, бизнес доволен. Так же и для связных списков, и для деревьев, и для всего остального, есть крейты со стабильными реализациями этих структур, а т.к. больше 1 раза их реализовывать не надо, то и сложность их написания не очень важна… Если только нет цели показать, что структуры данных которые элементарно делаются в одних языках сложно выразить в других. Может и так, но их выразили, и их можно подключить одной строчкой и пользоваться, как и везде. А сколько там страдали авторы прежде чем его родили — любопытно, но не более того.
Но стоп, кому то приходится эти структуры писать. Хорошо что не нам конечно =)
Ну их не невозможно написать, просто сложно. А дальше вступает правило, что в любом достаточно развитом языке всё уже написано до нас, нужно только склеить правильно. Изредка поконтрибьютить куда-нибудь в зависимости. Мне вот недавно монгодрайвер пришлось форкать, чтобы некоторый функционал нужный мне завезли. Но остальные 99% кода которые там есть я с удовольствием переиспользовал.
Уже да, нам там линейные типы завезли.
А заимствование — нет.
Да не, я просто не хочу делать линейные функции, в которые прокидывается и возвращается одно и тоже значение, особенно если это значение точно не меняется.
Можно врубить unsafe, и написать как на сях. Только тогда приходит осознание, что на сях простая реализация не такая уж и правильная, а правильная везде сложная.
Строго говоря, когда его придумывали, никаких сеньоров ещё не было...
Вы хотите найти людей, которым нравится Go. И которым нравится писать на Go.
Есть часть людей, что на работе работают прежде всего потому что им нравится.
Но большая часть всё же работает просто за деньги.
Есть люди, которые занимаются своим делом за деньги, а есть готовые заниматься почти чем угодно ради денег.
А на первый вопрос я бы без зарения совести попросил напомнить, в чём отличие императивного от декларативного языка, и дальше бы уже ответил. Думаю почти все каандидаты когда-то читали и знали отличие, но без явного напоминания на практике оно же улетучивается.
p.s. могу ошибаться, но я бы не был столь категоричен относительно lock-free структур в Go. Вы уверен, что они там всегда есть?
чтение из sync.Map — lock free, по большей части: golang.org/src/sync/map.go?s=1149:2596#L104
правда, чтобы было так, надо, чтобы записей в мапу оказалось достаточное количество: golang.org/src/sync/map.go?s=1149:2596#53
Ну не, так низя говорить. По большей части тогда и спинлоки можно считать lock-free при низком контеншне :)
Ваще с темой lock free я был бы очень осторожен. Может оказаться, что ответ "нет" не совсем неверный. В отрыве от архитектуры, в общем случае, в go нет lock free структур. Пакет atomic гарантирует атомарность, но нигде не гарантирует её без блокировок. Вроде на arm он использует локи.
Или вы думаете, что каджый сеньер — магистр компьютерных наук идеально знающий свой язык? Да таких на весь мир единицы в каждой области. И их имена на слуху. Разговариваете с сеньером, имени которого никогда не слышали? Ну так он обычный специалист, просто не идиот и с большим опытом.
Да и к тому же, декларативный это или императивный язык, да какая разница, по большому счету? Или там как изнутри устроен тип мап, или чем стек отличается от кучи.
Не, поймите меня правильно, я не против технических вопросов. Но приходишь ты такой на собеседование, перед тобой усаживаются 5 человек и начинают гонять по вопросам с листочка, как будто ты устраиваешься на позицию разработчика какого-нибудь компилятора. А потом принимаешь оффер и оказывается, что всё что от тебя требуется — это гонять джейсоны от одной апишечки к другой. И спрашивается — нафига было проводить такой отсев и искать человека несколько месяцев, если с этой работой любая обезьяна справится?
Так разберёмся. Главное в подготовке к собесу — это угадать, что спрашивать будут.
Даю подсказку: будут спрашивать про технологии, с которыми придется работать.
Я про, например, PHP могут на день вопросов подготовить, минимум. Но на собеседованиях на позиции где PHP на первом месте в технологиях меня лично о PHP практически не спрашивают. Самый распространённый, пожалуй, "что больше всего запомнилось, понравилось в изменениях самого PHP?" и после ответа "появилось ООП в 4 (1999 для справки) и к 5.3 (2009) стало юзабельным", разве что "а в 7.*(2015-2020)?" ещё уточняющий и больше по языку вопросов нет.
Судя по вопросам выше, кандидату предстоит целыми днями разворачивать списки и имплементировать хэш-таблицы. Ну такое)
В описании вакансии написано с чем работать будете. Не написано в описании, трясите рекрутера. Рекрутер ее признактся трясите интервьюера
С чем работать — это одно. Что будут спрашивать — совсем другое. Ожидания от реальных знаний и навыков — вообще третье.
если спрашивают о чем то другом, смотрите так внимательно в описание вакансии и спрашиваете, простите а вот тут у вас написано Php и css, а вы спрашиваете про микроконтроллеры, н емогли бы вы рассказать о связи, мне очень интересно. и все.
Некоторые связи довольно очевидны без вопросов. Например, если на позицию PHP-разраба спрашивают по HTML и JS в некоторых компаниях/проектах без упоминания их в вакансии. Зато спрашивают про OpenAPI, который тоже не упоминался. Объединение множеств "очевидных" смежных технологий я могу на сотню пунктов набросать навскидку. Угадать конкретное подмножество практически нереально.
ну, не упоминался, значит есть возможность поговорить о нем. ведь что такое OpenAPI вы знаете? слышали для чего он? спросите как он используется в проекте, почему именно OpenAPI а не собственная аутентификация? начните разговор, не тупите
список, кстати, можно делать не только на указателях, но и на индексах массива. что решает проблему кешироания.
А мог бы просто оставить комментарий // this is obviously correct
и пойти дальше, как принято в "настоящей разработке". Хотя в мейнстриме для такого даже комментарий не принято писать.
Да, неприятно. С другой стороны для меня агда это что-то вроде J, только с привкусом TeX, так что меня это не особо затрагивает, прикосаться к нему желания нет. А вот на идрисе я бы чего интересного пописал, жаль экосистема отсутствует. А самому её делать — ну не знаю даж… В последние несколько месяцев мотивация подупала.
ну для меня записи вроде последней это просто тарабарщина какая-то. Но людям с математическим бекграундом видимо удобно, не первый пример вижу. Так что рад, что подходит. Но я бы таким пользоваться не стал, и уж тем более не назову больше 1 человека из окружения который бы смог.
Вот как назвать переменную Γ⊢[x↦ε]τ чистой латиницей?
Да не знаю :) я не научрук и не шарю в теории типов, у меня матан кончился на 3 курсе универа вместе с алгорифмами маркова, машинами тьюринга и прочей матлогикой. Для разработчика второе имя куда проще, хоть и потеряло видимо точность. Не говоря про то, что подозреваю автокомплиту будет с ней куда проще работать.
О, судя по коду, Агда умеет в затенение переменных?
И тогда у меня возникает вопрос: зачем в такую компанию идти, которая кривые архитектуры решает умными олимпиадными задачами и гордиться собой при этом?
я сделаю это за неопределенное время
это прекрасный ответ, но на другой вопрос. soft skills, конечно, overrated, но заполучить в команду человека, да не линейным программистом, а лидом, который так будет реагировать на задачи в трекере — мало кто хочет.
ну и отдельно доставляет, конечно, отнесение разворачивания списка к олимпиадным задачам…
поэтому я сделаю это за неопределенное время.
За фиксированную зарплату?
Или зарплата должна быть пропорциональной потраченному времени?
Для самоутверждения это делается. Я задрот, а вы нет, ха-ха-ха.
А потом оказывается, что такого супер специалиста ищут годами. А если бы он действительно был нужен, то нашли бы за пару месяцев, потому что бизнес не дал бы в эти игры играть.
А ещё есть синьоры в Гугле и вот у нас в провинции. И я думаю, разница в зп у них — это не случайность.
Бизнесу рапортуется, что на рынке нет кандидатов. Нормальных. А все нормальные уже в гугле. Как говорится, принимайте решение — либо делаем из говна и палок и выращиваем своих специалистов, либо хантим за стопицот денег рокстаров из гугла (это возможно). Только вот у обычного бизнеса нет таких задач, где нужны настолько крутые спецы. Srsly, json’ы гонять туда-сюда много ума не надо. Но при этом никаких «прорывов» и не будет.
Я думаю, что Вы плохо понимаете, что такое "бизнес". Если бизнес не имеет уверенного представления о кандидате, у меня плохие новости. И да, бизнес сознательно выбирает — то или он готов тратиться на риски и эксплуатацию, то ли он готов тратиться на квалификацию. И вот это всё между. Действительно, многие бизнесы выбирают первое, факт. Но это не значит, что нет каких-то других бизнесов и они ущербны.
Вот кстати яркий пример такой стратегии — Гугл и Golang. Вместо изобретения чего-то на коленке пятком хипстеров, они взяли деда с его друзьями дедами с их уже подпротухшей игрушкой, и выдали ресурсы и время.
Надо различать ИТ-бизнес, который создаёт и продаёт ИТ-продукты, и обычный, где ИТ лишь одно из подразделений, обслуживающих основной бизнес. Может сокращать затраты, оптимизировать бизнес-процессы и т. п. В лучшем для него случае может давать возможность вести бизнес вообще. Но вот само денег не приносит.
Несомненно
Я к тому, что обычный бизнес обычно не может уверенно сформулировать требования к разработчику на уровне задачи для HR/ОК, пока не найдёт человека, который ожидания бизнеса от ИТ-подразделения (пускай из одного человека) не сможет конвертировать в типовую вакансию и методологию проверки кандидата на соотвествие.
Спрашиваете про прометеус? А может быть, он знает TICK стек. Или работал со спланком. Или у него на предыдущем проекте было хитрое ТЗ, но он виртуозно кладет метрики по UDP? Ничего из этого вы не узнаете. Вы ткнете своим очень узким вопросом и скажете «ок, хорошо». Или «нус, как такого можно не знать сеньору, давайте дальше». Максимум, что вы проверите — умеет ли человек в: «фак, я не знаю, но ладно, порассуждаем». Большинство же кандидатов такой вопрос переведет в состояние: «блин, интервью провалено, интересно, долго ли еще мучиться». Проиграете здесь вы.
Что делать?
Можно провести глубокое техническое интервью открытыми и уточняющими вопросами, совместно работая над задачей, похожей на ту, что кандидат умеет решать, а еще лучше — на знакомой кодбазе (опенсорс или тестовое). Так он почувствует, что у него «пошло» и покажет сильные стороны.
Очень не советую «тащить список вопросов себе», если вы хотите нанимать. Уверен, это просто быстрый способ ЧСВшнуть и оскорбиться «ужасным состоянием рынка».
Можно, я приду к вам на собеседование? С целью обмена опытом
Трансляция будет?
Мне кажется, нормальный собес именно на мидла почти никто из сениоров не тянет, разве что кроме тех, которые совсем недавно ещё были мидлами. У мидлов спрашивают обычно столько конкретики по используемым инструментам/фреймворкам, сколько ни один сениор в голове держать никогда не будет в принципе.
Это если считать "не тянет" как "не может ответить точно".
Не понимаю, как можно не знать "конкретику". Ну какие-то совсем детали типа "как реализуются разные уровни транзакцийй в СУБД" ещё могу понять, то вот историю пару лет назад что чувак собесился на сениор сишарп вакансию и не смог ответить зачем нужен кейворд virtual… По-моему это как езда на велосипеде. Когда на собеседовании на программиста неиронично спрашивают физзбазз мне даже интересно, кто эти люди с опытом работы программистом в резюме которые его не могут написать...
Попробовал как-то проехать на велосипеде после 20 лет перерыва. Минут 5 ушло на то, чтобы первые 50 метров проехать с торможением и поворотом. Да и потом навык явно не полноценно восстановился.
10 лет не катался на велосипеде, со школы. Когда появилась работа в паре км от дома, решил что пешком ходить далеко, а на ОТ ездить — близко. Купил велосипед, сел, поехал. Никаких проблем :shrug:. Первые буквально пару метров немного неловко ехал, потом нормально. Конеш старых трюков типа "захеать на высокий бордюр" сходу делать будет опасно, но ездить проблем никаких.
Да элементарно можно конкретику не знать. Конечно, то, что я ежедневно использую — я знаю. Но, в отличие от миддлов, я редко пишу однотипные задачи, поэтому то, что я использую сегодня обычно не имеет почти ничего общего с тем, что я использовал три дня назад и неделю назад. И, разумеется, я не держу всю эту фигню в голове.
Кстати, очень прикольно наблюдать глаза рядом сидящего джуна в процессе его обучения, когда я очень быстро набираю рабочий код, и при этом он видит, что я даже названий используемых функций толком не знаю. Ну т.е. я понимаю принципы работы, и из этого следует, что "скорее всего именно в этом пакете должна быть функция примерно с таким именем, egro: набираем имя наугад, параметры по логике она должна ожидать примерно такие, сохраняемся, если ошибки компиляции нет — значит угадал, идём дальше; если ошибка есть — делается прыг в доку на три секунды, поиск по ключевым словам в доке, ага, вот как они её назвали, нуок, переименовал и поехали дальше". Набранное имя я забуду примерно через минут 15, ну через пару дней точно, если больше не попадётся. И на собесе я не смогу сказать, как точно называется эта функция и в какой точно она библиотеке, потому что мне не надо этого помнить чтобы ей пользоваться, мне достаточно понимать принцип, что какая-то функция с таким поведением обязательно должна быть в такого рода библиотеках.
Типичный пример — я отлично знаю что такое MIME, как устроены соответствующие HTTP-заголовки, какие бывают грабли и почему лучше ручками такие заголовки не парсить, и что в стандартной библиотеке есть для этого готовые функции. Но я совершенно не помню, в каком именно они пакете и как называются. Помню, что не очень очевидно они называются, и нахожу я их там обычно не с первой попытки, что бесит. И всё. Фокус в том, что когда сениор этого не знает — это норм, потому что он при этом знает как всё это устроено и когда понадобится найдёт нужную функцию очень быстро. А вот когда миддл этого не знает — это обычно говорит о том, что он вообще ничего по этой теме не знает, и когда в работе возникнет соответствующая задача попытается работать с этими заголовками ручками, как со всеми остальными, наступая при этом на все типовые грабли. Именно поэтому у миддла на собесе обычно спрашивают конкретику, а у сениора общее понимание.
Не, я не про конкретные фунцкии конкретных библиотек, тут конеш снимаю шляпу, помнить все нереально. Но несколько десятков ключевых слов языка по которому ты "сениор" знать-то можно? Что можно сказать про сениора который не знает что такое for
?
for — это не конкретика. Хотя синтаксис этого самого for я вполне себе позволяю не помнить, особенно если приходится одновременно писать на 3-4 языках. Я знаю, что он бывает в стиле while по условию, бывает в стиле C с инициализацией и постусловием, и бывает в стиле range/итератора. Сколько из этих стилей поддерживает текущий язык и через какую пунктуацию они в нём записываются — я могу и не помнить, и это норм. А вот если такое не помнит миддл, который обычно пишет на одном языке — это сразу заставляет заподозрить, что он этого языка вообще не знает (либо, что более вероятно, он дико волнуется на собесе и надо переключить разговор на отвлечённые темы чтобы он успокоился, а потом вернуться к вопросу про for).
набираем имя наугад, параметры по логике она должна ожидать примерно такие, сохраняемся, если ошибки компиляции нет — значит угадал, идём дальше;
А потом выясняется, что вы перепутали два параметра с одинаковыми типами, и теперь у вас программа компилируется, но делает не то.
Я и в своём коде стараюсь не писать функции, принимающие подряд два параметра одного типа (исключая ситуации когда порядок реально очевиден — вроде x,y или login,pass — и нет нормального способа этого избежать), и в чужом к таким отношусь крайне настороженно, именно по указанной Вами причине. Так что нет, фокус с набором кода наугад я в таких ситуациях не применяю.
А на случай, если такая ошибка всё-таки прокрадётся в код — у меня есть привычка покрывать код юнит-тестами практически полностью, так что шансы что такая грубая и легко обнаружимая ошибка доживёт до PR — стремятся к нулю.
(исключая ситуации когда порядок реально очевиден — вроде x,y или login,pass — и нет нормального способа этого избежать)
У вас логин и пароль имеют одинаковый тип?
А на случай, если такая ошибка всё-таки прокрадётся в код — у меня есть привычка покрывать код юнит-тестами практически полностью, так что шансы что такая грубая и легко обнаружимая ошибка доживёт до PR — стремятся к нулю.
Юнит-тесты покрывают ровно те случаи, на которые хватило фантазии у автора теста. А подобные баги могут вскрываться только на взаимодействии функций.
Так задача провести энное количество интервью или таки найти кандидата на вакансию? Или быть такого не может, что после предварительно отбора хорошими hr, прям вот первый пришедший окажется способным решать ваши задачи?
он, фактически, выдает тестовое типа «почитать код», и просит покодить в реальном времени.
а у вас как устроено?
Как знать, может человек в таком гугле работает, что нужны хотя бы вопрос про люки чтобы отсеять уж слишком большой поток кандидатов по надуманным критерям.
Ну как в примере с чтением из закрытого канала
Оно вроде бы как и важно, но по сути столкнувшись с этим первый раз — второй уже будешь работать через v, ok на автомате, если вообще стоит вопрос о закрытых каналах. А что именно там происходит в v < — closed из памяти вполне и выпасть может…
Если речь обо всех из них — ну вполне может попасться «академик», теорию знает очень хорошо, на практике не может связать три строчки между собой. К слову я не считаю их бесполезными, несколько спросить стоит. Но походу дела
Что такое реальные задачки? Я себя взял за правило, если что-то пишу и вдруг обращаю внимание на то «этож классика, но 15 лет назад я бы задумался» — там кроется хороший вопрос, который никак не связан с конкретным языком.
Конкретно про go, из простых, полезных вопросов что задаю — напишите прорамку, которая принимает из stdin int, по одному на строчку, запускает некую обработку, для примера — рандомальный sleep, не больше 128 паралельных исполнений.
Чаще всего очень быстро приходится дополнить — без дополнительных библиотек, только stdlib, без гугла, без документации.
Бонус — по ctrl-c дождаться завершения бегущей обработки, не запускать новые. В целом от хорошего кандидата ожидаю и этого, грузить сразу не хочу дополнительными подробностями. Если скажет что не помнит сигналы и где они находится, но знает что они ему нужны — ок, гугли.
Тому кто могёт — дел на 5 минут, тому кто нет — все сразу ясно. В результате покрывается достаточно большое кол-во тем, включая контекст(которого к слову в вашем списке нет, а стоило бы)
ЗЫ, к слову о rust vs go
Есть проект, который мне достался в наследство, на который тоже ищу кандидатов, он написан на rust. Я его называю SSAS, Stupid simple api service. Утрирую, но ничего заоблоачного там нет и на мой взгляд rust не оправдан.
Искал месяца 2 на позицую на rust. С кандидами в целом было плохо, тех кто утверждали что знают раст вообще единицы. Задачку выше на расте никто не решил и за половину времени.
А даже те кто вообщем то действительно как-то раст знали, запутались в трейтах, что можно, что нельзя, почему некая стороняя библиотека(на раст разрешал делать что угодно, хоть с stackoveflow скопипастить) не работает с аргументами комманды(там я просил аргументы, а не stdin) и много чего еще. В общем это была боль.
В конечном счете я решил просто переписать на go и искать соответствующе. Стало проще. Ибо не готов я повторять эти поиски кандидатов на rust, в отличии от go, такой ряд теоретических вопросов становится намного важней, а найти и так сложно.
Ну как в примере с чтением из закрытого канала
Оно вроде бы как и важно, но по сути столкнувшись с этим первый раз — второй уже будешь работать через v, ok на автомате, если вообще стоит вопрос о закрытых каналах, либо что еще более вероятно — range. А что именно там происходит в v < — closed из памяти вполне и выпасть может…
Если речь обо всех из них — ну вполне может попасться «академик», теорию знает очень хорошо, на практике не может связать три строчки между собой. К слову я не считаю их бесполезными, несколько спросить стоит. Но походу дела
Что такое реальные задачки? Я себя взял за правило, если что-то пишу и вдруг обращаю внимание на то «этож классика, но 15 лет назад я бы задумался» — там кроется хороший вопрос, который никак не связан с конкретным языком.
Конкретно про go, из простых, полезных вопросов что задаю — напишите прорамку, которая принимает из stdin int, по одному на строчку, запускает некую обработку, для примера — рандомальный sleep, не больше 128 паралельных исполнений.
Чаще всего очень быстро приходится дополнить — без дополнительных библиотек, только stdlib, без гугла, без документации.
Бонус — по ctrl-c дождаться завершения бегущей обработки, не запускать новые. В целом от хорошего кандидата ожидаю и этого, грузить сразу не хочу дополнительными подробностями. Если скажет что не помнит сигналы и где они находится, но знает что они ему нужны — ок, гугли.
Тому кто могёт — дел на 5 минут, тому кто нет — все сразу ясно. В результате покрывается достаточно большое кол-во тем, включая контекст(которого к слову в вашем списке нет, а стоило бы)
ЗЫ, к слову о rust vs go
Есть проект, который мне достался в наследство, на который тоже ищу кандидатов, он написан на rust. Я его называю SSAS, Stupid simple api service. Утрирую, но ничего заоблоачного там нет и на мой взгляд rust не оправдан.
Искал месяца 2 на позицую на rust. С кандидами в целом было плохо, тех кто утверждали что знают раст вообще единицы. Задачку выше на расте никто не решил.
А даже те кто вообщем то действительно как-то раст знали, запутались в трейтах, что можно, что нельзя, почему некая стороняя библиотека(на раст разрешал делать что угодно, хоть с stackoveflow скопипастить) не работает с аргументами комманды(там я просил аргументы, а не stdin) и много чего еще. В общем это была боль.
В конечном счете я решил просто переписать на go и искать соответствующе. Стало проще. Ибо не готов я повторять эти поиски кандидатов на rust, в отличии от go, такой ряд теоретических вопросов становится намного важней, а найти и так сложно.
А разница между уровнями кандидитов я для себя определил не самой возможностью решать задачки, решить должны все. А тем как быстро и качественно, и кол-во задачек которые успел задать на интервью
Тому кто могёт — дел на 5 минут, тому кто нет — все сразу ясно.
А на Сях принимается? :)
А на Сях принимается? :)
Начинать в наше время новый проект на С — это должны быть аргументы.
Это же не про проект, а про решение тестовой задачи. Мне вот нравится подход, когда тестовые задачи на "общий кругозор" (алгоритмические, системные и т. п.) можно решать на любом известном кандидату языке. На целевом языке, например, он никогда не работал с сигналами, нужды не было. А вот в "прошлой жизни" или на пет-проекте постоянно. Чтобы начать писать продакшен код работы с сигналами на целевом языке ему надо лишь изучить возможности экосистемы этого языка для работы с ними, но не нужно изучать вообще концепцию сигналов и их общие подводные камни.
Добавил в закладки. Если ещё раз придётся писать что-то на Go, то пройдусь по списку.
P.S. Или ему скажут, что здесь и здесь используется это и он должен, при необходимости, справиться с поддержкой этого кода вне зависимости владеет ли он GO при этом?
(понимаю, что это маркетинго-рекламная статья и дальше интервьюреюмый будет заселён на необитаемый остров для кодинга без всяkих Github и.т.д ресурсов в условиях IT посакколапсиса :)
Всё равно, кого бы не было принято решение на наём в контору оно не будет «идеальным».
Ну, имхо базовые структуры данных знать надо. Потому что на ревью у нас регулярно бывает, что человек создает массивчик из 10 констант и потом делает if (MyConsts.Contains(thisValue)) { ... }
. Регулярно прошу сделать вместо массива хэшмап. Объясняю, что одно вычисления хэша (no-op для энума который обычно просто int) и доступ по индексу куда быстрее итерирования по многим элементам коллекции. Не столько потому, что я люблю микрооптимизации, а сколько для прививания привычки "Contains можно делать только на множествах". Помогает потом не делать Contains на каком-нибудь вычисляемом поле в БД.
- я практически уверен, что шарповый джит это не съест. Собсна да
- подобная привычка может и не дает особого выигрыша на маленьких массивах, но там на самом деле не так важно, 100нс или 200нс занял поиск. Зато минимизирует риск сделать Contains на массиве из миллиона элементов (не раз такое наблюдал).
А сколько это в наносекундах? Потому что это правило не про то, как оптимизировать список из 40 элементов, а как не искать за линию в множестве из миллиона.
С вашим общим правилом я согласен, но если надо поискать миллиард раз в списках из 10 элементов, то я бы задумался.
К тому же, часто бывает так что элементы изначально заданы в виде чего-то типа вектора. В таком случае, если мы точно знаем что их всегда маленькое количество и нет corner cases, то преобразовывать вектор в хешмапу ради поиска это overkill.
Тоже самое касается случая, когда нужно проверить на вхождение один раз – перебор будет дешевле преобразования в хешмапу.
Так что на любое правило есть исключения.
С вашим общим правилом я согласен, но если надо поискать миллиард раз в списках из 10 элементов, то я бы задумался.
А такие вещи мы бенчим, и подобные алгоритм недавно пережил 3 переписывания, в последний раз на расте, в обнимку с vtune, с оптимизациями вплоть до ручной простановки префетча конкретных элементов в кэш. Но это уже исключения и очень специфические ситуации. Общие правила на то и общие, что направлены на общий случай)
Тоже самое касается случая, когда нужно проверить на вхождение один раз – перебор будет дешевле преобразования в хешмапу.
Речь о том, когда у нас есть выбор, хранить массив или хэшмапу. Даже если в текущей версии приложения мапа дергается один раз, это может измениться в любой момент. И на это завязываться думаю не стоит.
А что в значениях хэшмапы? Что с памятью?
Нет. Как минимум потому что любые логи — сами по себе «тормозят». А включение логов может изначальную картинку вообще перевернуть с ног на голову (как в квантовой механике — измерение влияет на объект измерения)
У нас никакого HFT, но при этом логгирование в консоль просаживало RPS сервиса авторизации в 10 раз. Не нужно недооценивать роль инструментации в оверхеде на производительность.
Вы синхронно в логи что ли пишите? Или пишете туда целые эпопеи?
Синхронно, но в консоль. По крайней мере стандартный логгер Serilog так реализован. Но оказывается, что даже лок на стдаут это уже достаточно сильный оверхед для некоторых сервисов.
Ну так, логи надо в отдельный тред через wait-free буфер сбрасывать, чтобы не влияло на перфоманс.
Надо, возможно будем форкать и исправлять. Но это был ответ про "логи только в хфт замедляют". Вообще ни разу.
А потом буфер переполняется и логи теряются… Типичный кейс из жизни. Да, это проблема. Но решаемая
А запись метрик, разумеется, никакие локи не берёт и информацию ни в какие буферы не складывает.
Полностью поддержу, что метрики не "бесплатные", но почти бесплатные ) и, конечно, надо думать головой всегда
Атомики всё ещё медленнее обычных load/store
А по логам зачастую "тормозит везде" и логи ничем не помогают. Помогает понимание где какие лишние действия происходят.
А по логам просто нельзя посмотреть где тормозит?
В лоб — нет, не увидите.
Читать логи (а также в них грамотно писать) тоже нужно уметь.
Или, к примеру, это множество быстрых событий, но тормозит из-за того что их множество — тем более не просто. Суммарное торможение видно только если просуммировать время этого множества быстрых событий. Вам часто приходилось суммировать записи в логах (да еще и по определенному фильтру), вы и инструменты сходу назовете, которыми это будет сделать удобно?
Ответ на все 28 вопросов давно дал Александр Чистяков, alexclear, я думаю вам знакомо это имя.
Цитирую:
Ну а смысл быть сеньором за пять кусков, когда можно быть джуниором за три?
Меня это всегда удивляло.
Сеньор — 5, джуниор — 3, это что, один сеньор приносит конторе меньше пользы, чем два джуниора?
***но это тогда, а не контора.
Или сеньор ***но.
Или Москва.
(источник alexclear.livejournal.com/489205.html )
Это был 2013 год.
Не знаю кто там джуном сметал, я в 2013 на 15к полставки устраивался и считал, что мне повезло, мог с универом совмещать. К 2016 я вырос до 100к.
ИМХО зарплаты не особо поменялись за последнее время в долларах. Сениоры как получали порядка 4к долларов, так и сейчас получают. А то на одной чаше весов я вижу комментарии лдей у которых 5к не деньги, и у которорых джуны по 3к получают, а с другой статистика моего круга где медианная ЗП разработчиков в РФ — 108к.
Уж не ложная ли это память?
В 2013 г. средняя зарплата российских специалистов по разработке ПО, включая менеджеров, составила $2645 или около 80 тыс. руб., говорится в предварительных итогах уходящего года отраслевой ассоциации «Руссофт».
По данным этого некоммерческого партнерства рост зарплат в 2013 г. составил в среднем 15%. «В 2012 г. этот показатель проседал до 7-8%, а по итогам 2011 г. рост был сопоставим с показателями 2013 года — 18%», — говорится в отчете ассоциации. Данные для аналитики подавали ее участники: около 70 компаний, в штате которых состоит порядка 17 тыс. сотрудников.
Это просто рубль улетел в жопу, сейчас джуны должны получать соответственно 300к, а сеньёры - 500-1000к.
не хочу регаться в ЖЖ
(ворчливо) Вот и выросло поколение, которое не знает, что существуют сайты, где не обязательно регистрироваться для комментирования.
но, когда мы на прошлой неделе разговаривали — он все еще был сеньером :)
Самый популярный неправильный ответ: «Это хеш-таблица». Да, это хеш-таблица.
Самый популярный неправильный ответ: «Вернется ошибка». Да, вернется.
Самый популярный неправильный ответ: «Я не пользуюсь стандартным логгером». И никто не пользуется, сюрприз! Но почему?
Самый популярный неправильный ответ: «Можно, если защитить его мьютексом». Я признаю, это плохой вопрос, недостаточно показательный. Но зачем же давать на него хоть и формально правильный, но бесполезный ответ?
Самый популярный неправильный ответ: «Gorm, вроде, неплох». Конкурирует с ответом «Я всё пишу руками». Я даже согласен с обоими ответами
После слов «неправильный ответ» вы пишете «Да», «формально правильный, но бесполезный ответ» или «Я даже согласен с обоими ответами». В лучшем случае у вас не лучший стиль написания статей, в худшем — проблемы с логикой…
Даниил, огорчаете! Нанимать нужно не только по "hard skills" (то есть чисто по знаниям, особенно таким, которые легко нагуглить), а ещё и по soft skills и смотря на то, как человек решает реальные задачи. Давайте на всякий случай постараюсь упростить жизнь тем, кто к Вам приходит собеседоваться, чтобы не тратить зря своё и чужое время, и отвечу на все эти вопросы (надеюсь, что плюс-минус правильно :)).
Go — императивный или декларативный? А в чем разница?
Императивный. Разница в том, что декларативные языки обычно никто не понимает :).
Что такое type switch?
switch variable.(type), позволяет обработать разные типы одной переменной удобным способом.
Как сообщить компилятору, что наш тип реализует интерфейс?
var _ interfaceName = &typeName{} // если typeName это структура
Вот только делать этого обычно не нужно.
Как работает append?
Просто вставляет в конец слайса, пока есть место (capacity), и увеличивает его в N раз (вроде 1.5, но могу ошибаться), когда место кончается.
Какое у slice zero value? Какие операции над ним возможны?
Полностью эквивалентен слайсу нулевой длины и емкости за исключением того, что при сравнении на nil будет true, а не false.
Как устроен тип map?
Сами-то знаете ответ на этот вопрос :)? Мне кажется, здесь как раз не стоит углубляться и ответ «это хеш-таблица» должен быть достаточен. Спрашивать про то, какие бывают хеш-таблицы — на Ваше усмотрение.
Каков порядок перебора map?
Случайный.
Что будет, если читать из закрытого канала?
Хз. Знаю, что можно делать range по каналу, и итерация остановится, когда канал закроют. Видимо, вернется nil value, но я в реальном коде такого не видел.
Что будет, если писать в закрытый канал?
Паника.
Как вы отсортируете массив структур по алфавиту по полю Name?
sort.Slice(arr, func(i, j int) bool { return arr[i].Name < arr[j].Name })
Что такое сериализация? Зачем она нужна?
Превращение сложной структуры в массив байт, который можно передать куда-нибудь по сети или записать на диск и потом восстановить обратно.
Сколько времени в минутах займет у вас написание процедуры обращения односвязного списка?
Одну, потому что я скопирую этот код из Stack Overflow. Ну и давайте серьезно, никто в Go односвязные списки всё равно не использует.
Где следует поместить описание интерфейса: в пакете с реализацией или в пакете, где этот интерфейс используется? Почему?
Там, где интерфейс используется, или же в отдельном пакете. Интерфейсы позволяют таким образом разрешать циклические зависимости, например.
Предположим, ваша функция должна возвращать детализированные Recoverable и Fatal ошибки. Как это реализовано в пакете net? Как это надо делать в современном Go?
Да кто ж его знает, как она в пакете net реализована :)? Можете использовать errors.Wrap(), errors.Is() и прочее, но так вроде мало кто делает пока что.
Главный недостаток стандартного логгера?
Нормальный стандартный логгер, не надо на него валить. Да, он не умеет в разные уровни ошибок, но я пока ещё не видел, чтобы их правильно кто-то выставлял, если честно.
Есть ли для Go хороший orm? Ответ обоснуйте.
Вряд ли. ORM вообще не бывают хорошими.
Какой у вас любимый линтер?
go vet
Можно ли использовать один и тот же буфер []byte в нескольких горутинах?
Если только для чтения — можно. Для чтения и записи — нельзя.
Какие типы мьютексов предоставляет stdlib?
Что за дурацкие вопросы? Вроде есть Mutex и RWMutex. Что дает это знание :)? Есть ещё ведь как минимум атомики и каналы, но это не мьютексы.
Что такое lock-free структуры данных, и есть ли в Go такие?
Структуры, не опирающиеся на мьютексы (наверное?). В Go таких нет. В Go даже sync.Map использует мьютексы для записи.
Способы поиска проблем производительности на проде?
Обычный линуксовый perf прекрасно работает, начиная с 1.5 вроде. Ну и pprof, конечно же.
Стандартный набор метрик prometheus в Go -программе?
Вот вообще без понятия. Не все используют prometheus, и не очень понятно, почему должны :).
Как встроить стандартный профайлер в свое приложение?
import _ "net/pprof" или как-то так.
Overhead от стандартного профайлера?
Зависит от приложения. Обычно не очень большой, от силы должен быть 10-20%, но я видел и в несколько раз замедление как-то.
Почему встраивание — не наследование?
Потому что это разные концепции, очевидно :). Не знаю, что ещё тут сказать.
Какие средства обобщенного программирования есть в Go?
До Go2 таких средств нет. Кодогенерация не в счёт. Интерфейсы тем более.
Какие технологические преимущества языка Go вы можете назвать?
Да, горутины и простота языка, позволяющая легко начать на нём программировать и понимать написанный другими код.
Какие технологические недостатки языка Go вы можете назвать?
Объектная модель, по сути, отсутствует, и для тех же GUI приложений это печалька. Ну и GC есть, а значит есть оверхед и по CPU и по памяти, а также иногда всё-таки бывают паузы при сборке мусора.
элементарщина же? элементарщина!
Как работает append?
Просто вставляет в конец слайса, пока есть место (capacity), и увеличивает его в N раз (вроде 1.5, но могу ошибаться), когда место кончается.
Вы ещё забыли упомянуть восхитительный подводный камень append: она меняет переданный слайс in-place, если это возможно, а если нет — выделяет новый, в который копирует содержимое старого. В обоих случаях возвращается тот слайс, в котором лежит добавленный элемент(ы), из-за чего банальный vec.push(item)/vec.push_back(item) в других языках программирования превращается в
slice = append(slice, item)
, вынуждая повторять путь до слайса дважды.
Какие технологические преимущества языка Go вы можете назвать?
Да, горутины и простота языка, позволяющая легко начать на нём программировать и понимать написанный другими код.
Как-то странно записывать в технологические преимущества простоту и криво реализованную фичу, которую в других языках спокойно используют в виде библиотеки.
криво реализованную фичу, которую в других языках спокойно используют в виде библиотеки.
я вот недавно выяснил, как реализовано это в виде библиотеки на rust (tokio). и оказалось, что, если ты хочешь, чтобы оно нормально работало, весь IO тебе надо делать на tokio, и всю синхронизацию на tokio, и все таймеры на tokio.
в этом свете решение внести эту функциональность прямо в runtime уже не выглядит таким уж кривым.
Я, сказать честно, вообще не понял, почему товарищ считает, что горутины реализованы криво. Они как раз реализованы правильно — ввод-вывод всегда асинхронный и не нужно думать о том, что весь поток заблокируется из-за каких-то синхронных вызовов, потому что этим управляет рантайм языка. Причём я лично больше не знаю (не функциональных) языков, где так же легко было бы писать эффективный сетевой код именно по этой причине.
Я не вижу сложности писать любой асинхронный код на любом языке с асинк-авейт в принципе. Это как раз в го я умудрился задедлочиться на ровном месте.
Сложностей нет ровно до тех пор, пока вы контролируете 100% кода, который исполняется. То есть, как правильно заметил Даниил, весь код должен быть асинхронным и написанным с помощью этой библиотеки, иначе можно случайно, грубо говоря, вызвать какой-нибудь библиотечный метод, который начнет писать в файл или делать какие-нибудь синхронные сетевые вызовы (условно, в DNS сходить или что-нибудь такое), и отследить это бывает очень сложно. В Go же можно на эту тему особо не переживать и весь библиотечный код будет гарантированно асинхронным. Он может содержать другие сюрпризы, например паники в горутинах, которые Вы не контролируете, но это уже другой разговор.
Сложностей нет ровно до тех пор, пока вы контролируете 100% кода, который исполняется. То есть, как правильно заметил Даниил, весь код должен быть асинхронным и написанным с помощью этой библиотеки, иначе можно случайно, грубо говоря, вызвать какой-нибудь библиотечный метод, который начнет писать в файл или делать какие-нибудь синхронные сетевые вызовы (условно, в DNS сходить или что-нибудь такое), и отследить это бывает очень сложно.
В нормальных системах типов это ловится и при попытке так сделать код просто не скомпилируется. В хреновых, но более-менее рапространенных (жаба, сишарп) библиотеки подобным не промышляют. Максимум пишут лог куда-то, причем конфигурируемо.
В шарпе иметь функцию которая в фоне какое-то блокирующее ИО внезапно запускает это адовый баг. Наоборот, имеется тенденция делать асинхронным всё подряд.
В итоге разница между го и другими япами остается в наличие ключевого слова await, да необходимости использовать вейтгруппы явно там, где в шарпе можно просто попросить стд собрать результаты многих гринтредов в массив.
читать эту лапшу — вт что трудно
Я, сказать честно, вообще не понял, почему товарищ считает, что горутины реализованы криво.
Композируются они в Go фигово. Как мне дождаться конца работы горутины? Заводить отдельный канал и его прокидывать? Удобно, ничего не скажешь.
А ещё можно легко забыть, что рантайм за вас горутину переключать не будет, если у вас там какие-то чисто вычислительные задачи, которые не трогают ничего из whitelist-а известных языку асинхронных операций.
Композируются они в Go фигово. Как мне дождаться конца работы горутины? Заводить отдельный канал и его прокидывать? Удобно, ничего не скажешь.
Да, жизненный цикл горутин Вы определяете сами. Не знаю, если честно, хорошо это или плохо.
А ещё можно легко забыть, что рантайм за вас горутину переключать не будет, если у вас там какие-то чисто вычислительные задачи, которые не трогают ничего из whitelist-а известных языку асинхронных операций.
Это в целом больше не является правдой с введением асинхронного вытеснения горутин в одной из последних версий (1.14 вроде): https://medium.com/a-journey-with-go/go-asynchronous-preemption-b5194227371c
Да, жизненный цикл горутин Вы определяете сами. Не знаю, если честно, хорошо это или плохо.
Я немного о другом: если мне нужна операция "дождаться результата горутины", то мне туда надо пихать какой-то код помимо бизнес-логики, а я бы хотел саму запускаемую функцию не менять. Собственно, в том же tokio функция для запуска асинхронных задач возвращает ручку к этой задаче, на которой я могу вызвать .await
, чтобы получить то, что функция вернула, причём я могу это сделать не сразу, а положить в какую-нибудь коллекцию, а достать и дождаться исполнения уже позже, или вообще положить в FuturesUnordered, чтобы дождаться нескольких задач сразу.
Кажется, запись в буферизованный канал решит проблему
Так я опять прибиваю гвоздями горутину к конкретному каналу, не говоря уже о том, что мне приходится в запускаемую функцию писать внешнюю, вообще говоря, по отношению к ней логику.
а дождаться — точно так же, как и в любом другом языке.
Неправда. Точно помню, что я использовал токийный таймер на actix-rt, например. Да и в целом, асинхронные примитивы в расте построенны больше вокруг общей инфраструктуры std::future::Future, а дальше есть tokio/romio/async-std/… хз какие там ещё придумали, мне в целом токио хватает. Но я вижу ценность в том, что это библиотека, а не стд. Токио 0.1 и 0.3 отличаются разительно, 0.2 вообще проскочили потому что там прототипировали просто адски. В итоге 0.3 это сплав из 0.1 и 0.2, в парой любопытных идей.
Если бы это было в СТД, то мы бы никогда не увидели нормального интерфейса, костыли 0.1 тащили бы до скончания веков. Так что подход "библиотеки, а не язык" я считаю более чем правильным. Вот пошли на поводу и асинк-авейт сделали на уровне языка — ну всё, теперь там пин/анпин и прочая хрень, которую невозможно запомнить. Я пару раз пробовал, и бросил — гиблое дело. Просто не пользуюсь пинами вообще, зато регулярно читаю плач людей которым оно позарез надо.
Так что функциональность в рантайме — та ещё проблема.
если я хочу, чтобы мои корутины работали нормально — я должен обеспечить им работу в одном шедулере. один шедулер — это как раз и есть tokio, насколько я понял.
использовать токийный таймер на actix-rt ничто не мешает, но не появится ли у нас от этого два event loop в программе? я не в курсе, но, насколько я понял — это конкурирующие реализации экзекутора.
в go же доступ к шедулеру ограничен оператором
go
. внутри можно перепахивать все очень серьезно — например, в 1.14 появилась вытесняющая многозадачность — и на коде это не отразится никак.использовать токийный таймер на actix-rt ничто не мешает, но не появится ли у нас от этого два event loop в программе? я не в курсе, но, насколько я понял — это конкурирующие реализации экзекутора.
Не появится, экзекутор ровно один, и причем конфигурируется.
если я хочу, чтобы мои корутины работали нормально — я должен обеспечить им работу в одном шедулере. один шедулер — это как раз и есть tokio, насколько я понял.
Можно делать корутиы которые работают с любым шедулером, а потом подсовывать тот который хочется. Собственно все асинк функции в расте так и работают: они описывают последовательность шагов и причинность, а дальше вы вольны выбирать на каком шедулере это всё крутить.
в этом свете решение внести эту функциональность прямо в runtime уже не выглядит таким уж кривым.
Проблема в том, что внесение асинхронности в рантайм языка подразумевает, что рантайм в любой момент времени есть только один. А это не обязательно должно быть так: если у нас работа параллелится и не требует обмена данными между единицами работы, мы можем настрогать несколько потоков ОС, а на каждом из них запустить свой однопоточный рантайм, на котором уже все задачи спавнятся. actix, например, так и работает, и производительность у него замечательная.
А ещё явное наличие рантайма означает, что мы можем его настроить, причём до создания. Какие там ручки у рантайма есть в Go? GOMAXPROCS, GOGC и… Всё?
настрогать несколько потоков ОС, а на каждом из них запустить свой однопоточный рантайм
а зачем это может быть нужно?
Какие там ручки у рантайма есть в Go? GOMAXPROCS, GOGC и… Всё?
а что бы вам хотелось понастраивать?
я и эти-то ручки не кручу со времен 1.5
а зачем это может быть нужно?
Вы нарочно проигнорировали следующее предложение?
а что бы вам хотелось понастраивать?
Ну, например, интервал времени между безусловными сканами сборщика мусора. Из-за невозможности настроить это в принципе Discord в итоге свой read states переписал с Go на Rust.
что же до дискорда — уже ко времени переписывания проблема, на которую они жаловались, более не наблюдалась. они там все на довольно старой гошке гоняли…
я ничего не проигнорировал, но процитировал по минимуму. так зачем это может быть нужно?
Чтобы избежать оверхеда на синхронизацию, который неизбежно есть у рантайма, поддерживающего запуск задач из разных потоков.
onokonem выше немного заминусовали за "навскидку — 6+", но ошибки ведь действительно есть, и их не одна или две:
Разница в том, что декларативные языки обычно никто не понимает :).
Это не ошибка, конечно, но шутка не самая удачная, учитывая что очень многие всё ещё много и часто работают с SQL, не испытывая особых проблем с его пониманием.
var _ interfaceName = &typeName{} // если typeName это структура
Тоже не ошибка, я сам в первый момент хотел так ответить, но суть вопроса про то, что в Го компилятору это объяснять вообще не нужно. Это становится очевидно, есть медленнее перечитать вопрос, а не бросаться отвечать услышав пару ключевых слов из вопроса.
Просто вставляет в конец слайса, пока есть место (capacity), и увеличивает его в N раз (вроде 1.5, но могу ошибаться), когда место кончается.
Опять не ошибка. Но здесь важнее упомянуть что именно стоит за словом "увеличивает" и как это может внезапно сказываться на производительности и приводить к out of memory.
Видимо, вернется nil value, но я в реальном коде такого не видел.
Да, вернётся zero value, но суть вопроса-то не в этом, а в том как отличить чтение zero value записанное в канал от zero value считанное в связи с закрытием канала.
sort.Slice(arr, func(i, j int) bool { return arr[i].Name < arr[j].Name })
Снова ситуация, когда ответ выдаётся недослушав вопрос: вопрос был про массив, а не срез.
Одну, потому что я скопирую этот код из Stack Overflow. Ну и давайте серьезно, никто в Go односвязные списки всё равно не использует.
Такой ответ на собесе демонстрирует, что голову кандидат тоже старается лишний раз не использовать. Давайте серьёзно, да, списки обычно никто не использует, но голову-то использовать надо часто, и увидеть что кандидат привык использовать в работе — голову или SO как раз и помогают такие вопросы.
Интерфейсы позволяют таким образом разрешать циклические зависимости, например.
Эмм. Ладно, замнём для ясности, иначе тут ещё и по этому поводу холивар начнётся. Интерфейсы в го, почему-то, многие понимают и используют совершенно не так, как это было задумано при разработке языка, но это — очень отдельная тема.
Да кто ж его знает, как она в пакете net реализована :)? Можете использовать errors.Wrap(), errors.Is() и прочее, но так вроде мало кто делает пока что.
Плохо, что не знает. И очень плохо, что мало кто делает. Ошибки случаются в каждой второй строчке кода, их корректная и наглядная обработка и логирование крайне важная часть нашей работы (и значительная часть строчек кода конкретно в случае Go), в этой теме необходимо ориентироваться "на ять" даже джуну, если он хочет стать миддлом.
Да, он не умеет в разные уровни ошибок, но я пока ещё не видел, чтобы их правильно кто-то выставлял, если честно.
За честность — пять, но за кадром остался вопрос умеете ли их правильно выставлять лично Вы… и как это влияет на Ваш выбор логгера, при наличии возможности его выбирать.
go vet
Хорошо, что Вы про него знаете и используете. Не очень хорошо, что это не golangci-lint с конфигом включающим абсолютное большинство встроенных линтеров. (Или хотя бы gometalinter, если Вы немного отстали от прогресса.)
Что дает это знание :)? Есть ещё ведь как минимум атомики и каналы, но это не мьютексы.
Знание даёт, как обычно, силу. :) А конкретнее, когда нужно выбрать механизм синхронизации для конкретной задачи, хорошо бы знать, что помимо sync.Mutex и sync.RWMutex есть и другие варианты. И они существуют именно потому, что вышеупомянутые мьютексы хороши далеко не во всех ситуациях. (И, кстати, каналы — это тоже мьютексы, в том смысле, что реализованы с использованием мьютекса.)
В Go даже sync.Map использует мьютексы для записи.
Не всегда, в этом и смысл его существования. При правильном использовании sync.Map будет работать практически lock-free.
Зависит от приложения. Обычно не очень большой, от силы должен быть 10-20%, но я видел и в несколько раз замедление как-то.
Вопрос был с подвохом — просто добавление профайлера (тот самый import, который Вы не совсем верно написали, но это как раз не важно) никак не влияет на производительность.
Если добавить к вышеупомянутому пару вопросов, которые Вы замяли или отшутились — как раз 6+ и набегает, если по-честному. Другое дело, что лично я бы человека отвечающего как Вы — в команду взял бы моментально. Не на роль евангелиста, конечно, как поставлена задача в статье, но сеньорный уровень, безусловно, эти ответы подтверждают.
У вас один момент упущен, как в видео, так и в тексте.
Вы построили граф завистемостей по бизнес-части и вывели из него граф релевантных технических доменов для вашего бизнеса. И начали выкидывать из опросника некоторые темы, чтобы формат интервью укладывался в заветные 45 минут. Калибровка проводилась за счет интервьюирования текущих сотрудников.
Окей, видите проблему?
Есть мнение, что вы подогнали опросник под те заветные 8+ баллов для сеньора, экспертиза по которым уже есть в компании и релевантна только для узкого круга опрошенных.
То есть, с помощью интервью вы хотите нанаять сотрудника, чтобы улучшить экспертизу (bar raiser) в компании за счет тех доменов, в которых и так уже все хорошо. При этом те домены, которые являются сильными сторонами интервьюируемого вы сознательно (?) выкинули из процесса.
Понятное дело, что вы не можете выйти на публику и сказать, что в некой компании медианная экспертиза по технологии состовляет 4-5 баллов, а заветные 8 — где-то в районе 95 процентиля.
Но таки давайте быть немного честнее и начинать не c 3.3 для людей из вне, а с 4.5 для людей внутри? ;)
так что — да, опросник подогнан под имеющуюся экспертизу.
Ваш опросник годится только для того, чтобы оценить насколько хорошо кандидат умеет в квизы.
Почти все вопросы — это либо какой-то бред из методички (вроде append, map, мьютексов из stdlib), либо какие-то частности вроде prometheus, линтеров и прочая вкусовщина.
Никто не размышляет "а как же работает append" или "какие мьютексы есть в stdlib". Именно это знать не обязательно. Потому что абсолютно не важно.
А что важно — это какие мьютексы применять, когда у вас соотношение R/W — 50/50 или 99/1.
Или что будет со слайсом снаружи, если он передаётся в функцию, а внутри вызывается append.
Как отражает готовность работать зубрёжка метрик прометеуса, которые можно в официальной доке за минуту глянуть? А если ты пользовался не прометеусом, то всё, пока? Исходя из предположения, что окружение для сбора метрик в проекте настроено и работает, въехать в сбор метрик — это совсем не проблема. А если вообще никакого окружения нет — то и разницы никакой.
Наводящие вопросы: как получить одно случайное значение из map
Если я правильно понял наводку, то range по map не честно случайный.
Во всяком случае не был таковым пару лет назад.
Он специально слегка «размешивается» чтобы пользователи языка не полагались на порядок, но до честного нормального распределения очень далеко при мапе большого размера.
А сид этого "размешивания" можно проставлять? Или го прямо запрещает писать детерминированный софт? Да, я могу вставить принудительный .sort или что-нибудь такое, но все же это выглядит как очередное проявление отношения разработчиков языка к пользоветелям как к глупым сусликам, которых нужно направлять и ни в коем случае не делать отхожее место рядом с кормушкой.
А сид этого «размешивания» можно проставлять?
Насколько мне известно нет. Его же специально добавили, чтобы никто не полагался на порядок. И даже тест на это есть.
github.com/golang/go/blob/f979d072d339a24e4938d46588c153587d61af19/src/runtime/map_test.go#L507
очередное проявление отношения разработчиков языка к пользоветелям как к глупым сусликам
Не могу отвечать за создателей go, но скорее они решили себе «постелить соломки».
Если указать что порядок специфицирован, то в новых версиях языка сложнее изменить внутренюю организацию map.
А так ребята явно говорят: порядок не гарантирован, хотите гарантированный — пожалуйста, заведите себе slice с ключами рядышком. (https://blog.golang.org/maps Iteration Order)
Еще и специально сбивают порядок, чтобы кто-то случайно не завязался. Забота. :-)
Если указать что порядок специфицирован, то в новых версиях языка сложнее изменить внутренюю организацию map.
Не обязательно его уточнять, достаточно просто сказать, что итерации по мапе, которую не меняют, выдают один и тот же порядок. И да, я не понимаю причин для рандомизации. Ну вот от чего эта фича защищает?
Ах да, в гошке же всё может быть расшарено. Каюсь, забыл.
Означает что её "не меняют"
Однопоточное мышление detected.
Менять мапу может, например, GC.
Люди даже жалуются, что он это мало делает — большие мапы не уменьшаются в размерах после массированного удаления. Это баг, и его фиксят.
Так что вопрос мой заслуживает более пристального внимания.
И да, я не понимаю причин для рандомизации. Ну вот от чего эта фича защищает?От denial of service via collision attack. Если злоумышленник контролирует значения добавляемых ключей, он может легко выродить хеш таблицу в вектор, нагнув вашу систему.
Это-то понятно, но как это связано с рандомизацией порядка обхода?
Это означает, что получив примерно 4 миллиарда отображений итерирования, можно вычислить seed, и затем устроить DoS. (см. комментарий ниже)
Реализовано это за счет случайного сдвига начального индекса для каждого бакета и каждой итерации.
Можно было бы конечно увеличить размер сида до 64 бит, но сдается мне что эта «фича» была реализована скорее из-за заботы о горе-разработчиках, которые полагаются на упорядоченность хеш таблиц.
В мапе код который рандомно выбирает первый бакет с которого начинается итерация, а дальше как кольцевой буфер обходится: https://github.com/golang/go/blob/f89d05eb7ba1885474d03bb62f0a36a2d3cf56ea/src/runtime/map.go#L832
Вы случаем не знаете какой размер хеша используется в Go?
Ну вот от чего эта фича защищает?
Опять же, я не разрабатываю Go, спросите Роба Пайка. :-)
Могу только предположить, что от того, что кто-то завяжется на это в коде, а потом начнет создавать issue и жаловаться, что ему сломали back compatibility в новой версии.
Исходя из этого же предположения
достаточно просто сказать, что итерации по мапе, которую не меняют, выдают один и тот же порядок
Вроде бы нет смысла давать гарантии, если их можно не давать.
Ну вот от чего эта фича защищает?
Да, можно говорить про "отношения … как к глупым сусликам". Но суровая правда в том, что все суслики делают ошибки, и умные, и глупые. И техники, которые позволяют эти ошибки дешевле обнаруживать — это очень нужные и полезные штуки. Лично я не раз видел, как "внезапно" проваливающийся тест на CI (который дома прошёл один раз перед отправкой PR) помогал найти проблему… чаще всего в тесте, но и в коде — тоже случалось. Очень дёшево найти, обращаю внимание, что ценно.
допустим я сделаю мапу из объектов [1,2,3,4,5,0]
. Теперь я делаю
int count = 0;
for i in map {
print(10/i);
if (count++ == 3) { break; }
}
И теперь этот код будет то работать, то не работать. Понимаете, я не собираюсь завязываться на порядок перебора элементов, но мне нужно чтобы результат выполнения одного и того же кода был детерминирован. Спасибо конеш за такую "Заботу", теперь баг с прода может не воспроизводиться ни при каких условиях. Один раз на миллион рандом выдаст такую последовательность обхода мапы, что всё поломается, и потом никогда не найдете, в чем была причина. До следующего падения через месяц. Удобно, ничего не скзаать. А ещё если учесть, что в тесте мапа из 4 элементов, то судя по реализации в 25% случаев тест должен падать. Весьма удобно.
Видите ли. Когда возникает конфликт между "мне нужно A" и "язык делает B" — нужно или язык менять, или свои нужды подстраивать под используемый язык.
Приведённый Вами код — в принципе некорректный для Go. Именно потому, что в спеке Go ясно сказано, что порядок range по map не детерминирован. И то, что Go ещё и дополнительно рандомизирует этот порядок, всего-лишь помогает нам поймать такие ошибки намного раньше — а чем раньше выявится ошибка, тем обычно дешевле её исправить.
По сути, Вы жалуетесь на то, что язык мешает Вам закопать неявную ошибку под ковёр и отложить её обнаружение (при удачных для Вас обстоятельствах) на год-другой, когда она станет уже не Вашей (в связи со сменой места работы), а чьей-то другой проблемой.
По сути, Вы жалуетесь на то, что язык мешает Вам закопать неявную ошибку под ковёр и отложить её обнаружение (при удачных для Вас обстоятельствах) на год-другой, когда она станет уже не Вашей (в связи со сменой места работы), а чьей-то другой проблемой.
PsyHaSTe утверждает вообще-то строго обратное. Вместо ДЕТЕРМИНИРОВАННОЙ ошибки — он получает рандом, который может стрельнуть, а может не стрельнуть.
Приведённый Вами код — в принципе некорректный для Go.Прошу прощения, что вмешиваюсь в ваш разговор, но если этот код в принципе некорректный для го, то почему же компилятор меня не остановил?
play.golang.org/p/jJveuIrmJY8
Или он может только мне палки в колеса совать, когда мне это нафиг не надо, вроде «unused import»?
Это, в общем-то, главная проблема языка. Разработчики думают, что лучше меня знают, как мне писать мой код. Это же надо додуматься, специально дополнительно рандомизировать перебор мапы.
Это же надо додуматься, специально дополнительно рандомизировать перебор мапы.
на самом деле в долгосроке это возможно правильное решение, т.к. позволяет избежать т.н. side channel attack. Но это должно быть явно задекларированным свойством алгоритма. Т.е. даете рандомизированный перебор — давайте и нормальный, детерминированный перебор. И возможность выбора.
В расте есть такая рандомизация. Только эта рандомизация работает на вставку, и во-первых настраивается параметром генерика (хех) S и её можно отключить, а во-вторых как раз и обеспечивает воспроизводимость чтений из мапы.
То есть тут кмк скорее не забота о пользователях, а скорее гццшное "а давайте на УБ запускать арканоид, ведь согласно спецификации мы имеем на это право". То есть такой "ах, вы попробовали завязаться на деталь реализации? Нате вам неприятный сюрприз. Получили? То-то, будете в будущем читать документацию внимательно!"
Звучит по-детски и глупо.
Я кстати знал и забыл
А можно и вообще простенькое задать, типа как развернуть по диагонали вот эту матрицу:
10011110
00110111
01111001
10111001
01111111
01001010
01111100
00010110
в вот эту:
10010000
00101110
01111010
11111011
10111110
11001011
11001101
01111000
И сделать это за одну операцию.
Так вы легко поймете — начинал ли испытуемый читать Кнута. Только какой в этом толк в подавляющем большинстве случаев… За всю жизнь мне это только один раз пригодилось.
Сорян, за две операции
Это биты? То есть матрица задана как 8 байт? Хммм, а из какого множества операций можно выбирать?
Гугл мне в помощь. Спасибо, что вы пример прям скопировали. Вобщем, это действительно биты и эти 64 бита составляют октабайт в терминологии Кнута. Вобщем, решение предлагается искать среди команд MMIX — придуманного самим же Кунтом (так и не реализован в железе). Для решения нужны команды перемножения матриц октабайтов. Интересно, есть ли такие операции в современных процессорах…
6. Как устроен тип map?
- Что я хочу оценить: насколько интересно кандидату, как именно ложатся в память наши байтики. Map, возможно, самая важная из стандартных структур данных, и весьма замысловато устроенная. Она сложная, она эффективная, она обладает встроенным race condition детектором… Неужели не любопытно?!
- Самый популярный неправильный ответ: «Это хеш-таблица». Да, это хеш-таблица. Как устроена хеш-таблица?
Представляю что подумает прораб когда у него спросят о количестве линз в обычном нивелире и можно ли поменять призму для повышения точности, а на резко округлившиеся глаза получит ответ в стиле: «Неужели вы никогда не задумывались? Разве вам не было интересно?»
Да, соглашусь, с большинством вопросов у кандидата не должно возникать сложностей, но как минимум пара точно лишние. Хотя тут претензия не столько к вопросам которые задаются, сколько к вашим ожиданиям от ответов на них.
P.S. Возможно я не понял для какой цели ищется кандидат, бизнес действительно подразумевал найм:
человека, который сможет задать и поддерживать высокий уровень профессионализма в применении языка GoЭдакого гуру задача которого не кодить а рассуждать о качестве кода и духе Go. Если так то вопросы сразу отпадают.
программист, который тупо делает, как научили, и не задумывается над смыслом — будет очень плохим программистом.
Правда вот совсем не уверен что те для кого вы занимаетесь их наймом солидарны с вами в таких суждениях.
Как вы отсортируете массив структур
Да никак. За меня это сделает import «sort». И никаких велосипедов изобретать не надо в 99% случаев. Может у вас, как раз, регулярно возникает оставшийся 1%? Ок, тогда у меня три встречных вопроса: почему они возникают, почему этих велосипедов нет в проектных библиотеках и почему эти ситуации не вынесены на собеседование?
А если хотите порассуждать о пузырке и прочих мерже/квик сортах — спросите прямо. В чем проблема?
Да никак. За меня это сделает import «sort».
ответ на 9, едем дальше
Тогда вы просто ищете токсиков, которые могут в ответ "нахамить". Потому что когда вопрос поставлен таким образом, то подразумевается, что реализовывать надо, и что варианты "взять из библиотеки"/… уже отметены по каким-то причинам. Возможно, этим причины соискатель может уточнить, но это необязательно и принимается на веру.
А что что вы на 9 оцениваете соискателей за ответы "никак не буду делать, импортирую"/"так никто не делает"/..., но при этом на единичку тех, кто говорит "не знаю, импортирую"/"не знаю, так никто не делает" весьма иронично.
А что что вы на 9 оцениваете соискателей за ответы «никак не буду делать, импортирую»/«так никто не делает»/..., но при этом на единичку тех, кто говорит «не знаю, импортирую»/«не знаю, так никто не делает» весьма иронично.
смысл этого пассажа ускользает от меня :(
вообще — я ровно «воспользуюсь стандартной библиотекой» и хочу услышать.
если кандидат говорит «погуглю» — я предлагаю погуглить прямо сейчас. только мало кто говорит «погуглю» :(
Они же палец о палец не ударят лишний раз. Поэтому, ваш вопрос, именно что читается, как регулярные нестандартные ситуации. И ответ «заюзаю стандартную либу» не подразумевается вообще никак. )
и я ничего не выдумал — странные ответы на этот вопрос я получаю довольно часто.
Сколько времени в минутах займет у вас написание процедуры обращения односвязного списка?
Я хотел бы, чтобы каждый интервьер, который задает этот вопрос вне контекста функциональных языков в аду только и делал, что кодил используя односвязные списки.
Вот серьёзно, список — это ужасная структура данных, которая не нужна ни в каких задачах, кроме «разверни-ка этот список» или «объедини-ка эти два списка» (опять же, речь про императивные языки в духе го).
Каким образом тут функциональные языки появились? А одно- или дву-связные списки полезны для некоторых задач. Например, операция вставки элемента в список — очень дешёвая. Или операция конкатенации списков. Если вам не встречалось таких задач, это не значит, что их нет. Да, в современном мире вычислительные ресурсы стали весьма дёшевы и раскидываются налево и направо, но это не отменяет знания программистом основных структур данных.
Каким образом тут функциональные языки появились?
В функциональных языках списки важны/нужны, поэтому я уточнил, что речь идет о списках и императивных языках.
Например, операция вставки элемента в список — очень дешёвая
А вы не подскажете, насколько долго искать место вставки?
Если вам не встречалось таких задач, это не значит, что их нет.
Приведите, пожалуйста, пример. Желательно с односвязным списком. Не нужно «реальную» задачу, можно просто «олимпиадно-алгоритмическую».
в современном мире вычислительные ресурсы стали весьма дёшевы и раскидываются налево и направо, но это не отменяет знания программистом основных структур данных.
Так в том-то и суть, что знающий программист знает, что производительность обычных списков неудовлетворительна в 99 процентах ситуаций.
Приведите, пожалуйста, пример. Желательно с односвязным списком. Не нужно «реальную» задачу, можно просто «олимпиадно-алгоритмическую».
С двусвязными, конечно, но:
- простейший LRU-кэш обычно реализуется через хэш-мапу и список
- цепочки буферов обычно строятся на основе списков
- очередь тоже часто на основе списка
- Простейший LRU реализуется как import LRU from something
- Цепочки буферов на практике видел только внутри какого-нибудь malloc, а не юзер коде
- Очереди уже везде реализованы, второй раз делать этого не надо
Вы сейчас точно в том треде отвечаете? Этот тред про то, что список — негодная структура данных:
Вот серьёзно, список — это ужасная структура данных, которая не нужна ни в каких задачах, кроме «разверни-ка этот список» или «объедини-ка эти два списка»
А, ну если так брать, то всё уже написано до нас. Просто надо найти подходящий модуль и пользоваться им. Так и односвязные списки тоже импортировать можно, зачем же их писать...
простейший LRU-кэш обычно реализуется через хэш-мапу и список
Ладно, хороший пример. С другой стороны, в виду статичности размера «списка» более эффективно его интерфейс реализовать с помощью массива, особенно когда кэш небольшой.
цепочки буферов обычно строятся на основе списков
Не уверен, что понимаю о чем речь. Сколько обычно буферов?
очередь тоже часто на основе списка
Но часто и нет. В С++ вот на основе массива. С большой вероятностью это более эффективно.
Ладно, хороший пример. С другой стороны, в виду статичности размера «списка» более эффективно его интерфейс реализовать с помощью массива, особенно когда кэш небольшой.
А как вы, простите, будете делать перемещение элемента из середины массива в его начало? Копировать каждый раз? Список то именно ради этой операции и применяется.
Не уверен, что понимаю о чем речь. Сколько обычно буферов?
Например, в ядре линукса skb в цепочку выстраиваются, могут быть сотни структур в цепочке.
Но часто и нет. В С++ вот на основе массива. С большой вероятностью это более эффективно.
В libstdc+++ через деку, а не через массив: https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_queue.h#L75
Потому что нужна эффективная операция снятия элемента с начала цепочки элементов, а в массиве такого не сделать. Вот если бы очередь была фиксированной длины, да элементы одинакового размера, тогда можно было бы говорить о кольцевом буфере на непрерывном куске памяти.
Предлагаю вам такую разминку для ума: попробуйте придумать, когда сортировка пузырьком будет существенно эффективней квиксорта. В реальной жизни такое бывает при рендеринге сцен в играх.
Простой пример — DOM. Пользователь может перемещать любые узлы в любое место дерева вида "после этого" или "внутри этого". Плюс несколько пользователей могут делать это одновременно и вам нужно все их правки на сливать лету. Двусвязные списки тут отлично работают.
Автору поста: напишите книгу с ответами на эти вопросы и разбором best practices. Я серьезно. Может получиться очень хорошо.
не понимать, что интервьюер имеет в виду под «развернуть» — нормально, и задать уточняющий вопрос тоже.
на вопрос «что такое односвязанный список» я тоже отвечаю, просто задаю чуть больше вопросов по алгоритму.
короче — нарисованная вами печальная картина в реальности не наблюдается :)
Я думаю любой лид или техлид или хороший синьер в начале своего пути интервьюирования создавал себе такой список, судорожно спрашивал и «охал» и «ахал» о том «Ну как же этого можно не знать!!!». Все проходили через такое. Автор просто не опытный, но опыт не коррелирует с должностью в рогах и копытах и уж точно не с «годами». Все проходили через эти списки, вопросы по языку, хеш-мапы, строки числа, табличные значения и тп.
Но с временем и опытом приходишь к выводу, что умный человек впитает это все за недели, и будет кодить лучше чем «5 лет опыта» но не обладающий нужным интеллектом и высокой способностью к обучению. Языки меняются, функции переименовываются, технологии умирают и рождаются. Важен не язык, важно не знание го, питона, джавы, пыхи, важен общий опыт, скилл, ум и способность быстро впитать что надо и накидать рабочий код, сбегать в соседний отдел и родить решение блокирующей задачи.
Если хотите нанимать нормально — как писали выше, общайтесь о опыте, о задачах проектах.
Если затащите как гугл — или фаанг, спрашивайте литкод, давайте задачи, просите проектировать.
Автор выучил го и нанимает тех, кто выучил го, копни влево, вправо, в питон, в пых — срок задачи пойдет на +1 месяц. Язык это инструмент, не нанимай уборщика плиток, найми того, кто не сольется при виде паркета, а впитает как его мыть и сделает лучше.
вот вы интервьюируете людей для сторонней компании. вас пригласили, как эксперта.
скорее всего, если вы твердо скажете «вот этого нанимайте» — его наймут, потому, что если уж ты позвал эксперта, его надо слушать.
если не скажете — точно не наймут. но будут задавать вопрос «а почему мы его не нанимаем»
и вот вы такой «общаетесь об опыте, о задачах, проектах».
и вам надо сказать «нанимайте», или «не нанимайте, потому что...», по результатам общания. и сказав «нанимайте» вы ставите на кон свою репутацию.
я, оказавшись пару раз в такой ситуации, решил свой опыт обобщить и формализовать.
а вы — обобщили и формализовали, или полагаетесь на интуицию?
если обобщили и формализовали — я очень хочу ознакомиться с результатами. потому, что собственная правота меня вообще не интересует, а интересует меня делать свою работу хорошо.
Есть принцип, согласно которому лучше не нанять мудака гения, чем нормального в общении середнячка. Каким образом это можно отсеять на тех интервью? По манере ответов? Сомнительно. Поэтому — да, концептуально лучше не нанять человека, чем облажаться с его наймом. Но это какой-то перекос в строго одну сторону
Составляется карта с ранжированием от 1 до 10 (например) и по каждому пункту проставляются варианты. Оценка принятия 5-6 (средняя по всем показателям)
Нельзя сделать шкалу где джун-3, миддли-6, сеньор-9
У вас должно быть 3 шкалы с уровнем принятия 5-6.
Все другие подходы не являются «экспертными», веет отсебятиной без знания матчасти.
а где глянуть ваш, правильно составленный?
ну, я пришел к тому, что имею два опросника, фактически, на мидла и на сеньера.
Нет, не вы, а мировая практика, которой уже больше 50ти лет.
а где глянуть ваш, правильно составленный?
в любом учебнике по управлению персоналом :)
Дальше по вкусу, можно боинг посмотреть, можно в сторону тойоты.
По собеседованиям и персоналу нужно иметь такой же бекграунд, который вы требуете в своих опросниках.
Больше скажу, каждый опросник строится под конкретную организацию, нельзя с одним опросником набирать в разные организации. (см спираль гибели возможностей конвея как референс).
По поводу оценок, я не препод и не имею энциклопедических знаний
Описание находится в теории принятия решения, экспертное мнение, экспертная система. И в материалах по теории систем.
Спасибо за статью. Очень много спорных моментов с апломбом выдаётся за абсолютную истину. Я помню так первую статью про то, как делить строки по словам писал на хабр, с формулировочками "пациент не понимает, что слова — это то, что состоит из букв, а не то, что не является разделителем". Надо ли удивляться, что от такого "старта" мне в первую неделю пришлось пользоваться кнопкой обнуления кармы. В общем, бесплатно делюсь своим опытом.
Статья на тему, как собеседовать сотрудников в виде строгого учителя. Такое ощущение, что вы не коллег нанимаете, а спрашиваете нудный зачет в виде теста. Причем правильный ответ который не предполагается тестом не засчитывается. Да и сама манера выставлять баллы, и т.п. настораживает.
Что я хочу оценить: насколько интересно кандидату, как именно ложатся в память наши байтики. Map, возможно, самая важная из стандартных структур данных, и весьма замысловато устроенная. Она сложная, она эффективная, она обладает встроенным race condition детектором… Неужели не любопытно?!
Неужели каждое обращение к каждой мапе триггерит некоторый детектор? Даже если у меня однопоточное приложение, но с кучей этих самых мап? Как-то не очень весело получается...
А вообще я думал, что го — простой, каждый разработчик который открыл tour de Go уже может писать в прод и вот это всё. А тут вопросы с подковыркой, всякие nil-слайсы и прочее. Не знаю, как можно всё это держать в голове и при этом одновременно считать какие-нибудь генерики сложными.
Неужели каждое обращение к каждой мапе триггерит некоторый детектор?
триггерит, да. детектор тривиальный, поэтому проблем не создает. но попытка чтения из map, в которую прямо сейчас происходит запись, закончится паникой. и это очень хорошо.
Статья на тему, как собеседовать сотрудников в виде строгого учителя. Такое ощущение, что вы не коллег нанимаете, а спрашиваете нудный зачет в виде теста.
Есть такое ощущение, да. Но когда я почитал что ему отвечают — у меня всё резко стало на свои места: если бы мне на интервью пришлось выслушивать много ответов а-ля "Самый популярный неправильный ответ" — я бы тоже от безысходности пришёл к похожему стилю, наверное (лично мне пока везло, и я обычно собеседовал коллег, которые меня до такой степени не огорчали). Иными словами — легко быть добрым и приветливым когда тебя окружают идеальные люди.
Причем правильный ответ который не предполагается тестом не засчитывается.
Это не так, и об этом много говорилось и в статье и в комментариях.
Да и сама манера выставлять баллы, и т.п. настораживает.
Эмм. А что ещё делать, если наше субъективное впечатление имеет тенденцию ярко запоминать одно и при этом напрочь забывать другое? Удачный ответ на один вопрос может заставить забыть пару крайне неудачных ответов на другие… как и наоборот. Баллы позволяют принять более справедливое решение, учтя все ответы наравне. Нужна ли эта справедливость в данном конкретном случае — другой вопрос, но в самом подходе ничего плохого нет, на нём вся современная наука держится.
Тогда надо не собес проводить, а требовать «сертификацию программистов». Для админов испокон веков существовали всякие CCNA… вот и пора вводить сертификацию «Golang senior programmer v1.13». Этим может заняться какой-то отдельный комитет. Представьте себе какая экономия времени — если у человека есть такая бумажка и подтверждённый опыт — можно сразу скраивать время на техсобес и спрашивать более интересные вещи, чем про стандартную библиотеку или односвязные списки
onokonem Ваши 200 вопросов — первая заявка на такое. Проблема только в том, что ответы должны быть однозначные )))
Интересно почему в сис админстве эти вещи присуствуют, а в dev нету. Может не выгодно?
Очередная версия языка — использовать её или нет это выбор самого программиста.
Хороший пример как держится legacy — программы написанные на старых версиях Java не переписываются долго-долго на новые, ибо много работы. А работает и так, зачем трогать?
Новые фичи можно и на старой версии реализовать.
С админством не так. Если вам нужна новая фича — нельзя оставаться в старой версии ПО. Нужно обновлять. А что потянет за собой обновление? За код-то админ, в отличие от разработчика не отвечает, он и починить не может и даже посмотреть не всегда может что там. Поэтому привязка сертификации к версии ПО важна.
Ну и вторая причина, которая, имхо, важнее:
К сертификации админов имеют отношения организации, выпустившие ПО.
А кто имеет отношение к сертификации разработчиков под языки программирования?
Вообще существует какая-то серьезная сертификация под язык программирования, кроме языка Ada и т.п.?
В стиле автора:
- Усилия автора по поиску go сеньоров
Что я хочу оценить: Насколько автор вообще настроен именно найти человека, а не просто потешить ЧСВ
Самый популярный неправильный ответ: «Я им даю вот этот задачник. А потом бомблю с ответов». Очень жаль, что ты простой quiz, %USERNAME%. Если бы ты хотел искать сеньоров, а большинство кандидатов не знали бы ответа на первый вопрос, ты бы разобрался как они ищутся, а не просто сидел как бот и спрашивал тех, кого дают.
Наводящие вопросы: Откуда уверенность что тебе подают именно сеньоров? Усилия хэдхантеров как-то оцениваются? Хоть раз-то проверял, какие резюме попадают к тебе, а какие — в мусорку?
- Вопросы
Что я хочу оценить: Умение автора задать вопрос
Самый популярный неправильный вопрос: «Что такое Х?». На ответ "Х это Y" начинается вонь и глумление. Оказывается надо было понять, что автор хочет узнать не что такое Х, а как работают Z и как устроен W из которых состоит Y. При этом заботливо стоит пункт "что я хочу услышать", но он отделен от вопроса. Зачем спрашивать то что ты хочешь услышать, если есть тупой и некорректный вопрос? Молодец, автор! Так держать!
Наводящие вопросы: Почему не говорить кандидатам сразу пункт "что я хочу услышать"
Хочу сказать, что на результат собеседования сильно влияет опыт хождения на собеседования и анализ, как их эффективней пройти. Не опытные в плане собеседований соискатели не спросят, что хочет услышать интервьюер.
А устроившись на работу и получив непонятную задачу этот человек задаст наводящие вопросы? Или он сразу бросится воевать с ветряными мельницами?
Тут больше экзамен и психологически воспринимается по другому. Часто студенты спрашивают, что хочет услышать в ответ экзаменатор? Я ни разу не видел, чтобы кто-то спросил.
пусть учится. записывается на собесы и учится. за спрос же денег не берут и на собесах же не рубят рук
- При том что я знаю, что поменялось в 1.13 в месте с ошибками (и знал), я не понял вопроса. Т.е. из вопроса я узнал, что есть теперь стандартная практика
- Я бы вставил "моржика". Он зараза хитрый
- Я понимаю, что вшивый о бане. Но вопросы паттернов ООП прямо вот странные. Да, я понимаю, что зная паттерны довольно легко выяснить понимание встраивания. Просто стравив его с наследованием. Но есть много людей, которые с ООП столкнулись лет 20 назад и потом нет. Я про наследование года три назад специально повторял, потому что вопросы задолбали. Есть масса людей, которые вообще не сталкивались с ООП. А из тех, кто думает, что прямо весь в ООП — многие глубоко заблуждаются. Но паттерны конечно отщелкает. Я бы скорее что-нибудь про замыкания спрашивал. Почему нет? Чем они провинились перед полиморфизмом? )
- Или вот sync.Map. Единственный смысл спросить об этом — это узнать, помнит ли человек о таком. Я сейчас третий раз прочитал и вероятно третий раз забуду. А вот тема тредов и процессов пропущена. Вот где открытий нас много ждет
в опроснике — он опубликован, ты в курсе — есть призовая игра, еще 30 вопросов. но их я задаю, только если кандидат бодро отвечает на эти 30.
Ну да, это спор о том, что попало в призовую игру. Ну ок. Предположим я не знаю, что такое линтер (ну очень интуитивно только), но довольно недурно отличаю процессы, треды и сопрограммы. Посыплюсь только на вопросе асинхронности дискового i/o. Без гугла я думаю, что там имитация асинхронности путем вынесения в отдельный тред. Это хорошо или плохо? Я считаю управление программой более базовым, а линтер — премиальным знанием. Или вот аллокации. Я плаваю в этой теме и это плохо. Вокруг этого бы всё обойти: https://golang.org/ref/mem
вообще, я пытаюсь тестировать не конкретные знания, а связи в голове между фактами. хорошо у меня получается, или нет — это вопрос открытый.
то, что опросник не полная лажа, я проверил, прогнав по нему некоторых знакомых сеньеров. и пару мидлов.
рекорд — 8.3 за 20 минут.
отдельные вопросы могут быть неудачными/нерелевантными/неочевидными, но у меня никогда и не было задачи написать «идеальный код».
Мне кажется, ваш потенциальный кандидат, довольно редкая птица, и места ее обитания вполне известны. Например многие ответы на вопросы из вашего опросника я получил в ходе участия в HighloadCup, где надо копаться во внутренностях языка чтобы понять, а что можно выжать еще. А вот эта сортировка стандартная на моем наборе данных работает оптимально, или вот тут я другую использую и она быстрее будет. Многие получают этот опыт в больших компаниях с большими нагрузками, где замена алгоритма сортировки сэкономит XXX рабочих инстансов, и такое копание в деталях — имеет бизнес-значение.
Большинство же backend разработчиков (подавляющее) в основном решают другого уровня задачи, как тут верно писали в комментариях — гонять данные туда-сюда, и скорее больше фокусируются на самом бизнесе, который может быть довольно широк, отсюда и ваш вывод про — задача сделана, идем дальше, времени мало. Больше ценятся работа в команде, софт скилы, знания бизнес процессов и т.п. Плюс добавтье сюда то, что зоопарк технологий растет очень быстро, сейчас нет просто физической возможности копаться в сорцах каждого инструмента, который разработчик использует, плюс какой смысл? Среднее время работы программиста в компаниях сейчас довольно маленькое, ну изучишь ты один инструмент от и до, как ты этот опыт перенесешь на другого работодателя? Но это не означает, что при необходимости большинство разработчиков этого не сможет сделать.
и скорее больше фокусируются на самом бизнесе,
Я обычно не прохожу даже на 50% опросники топикастера. Ну, потому что я не настоящий сварщик в том числе. Но процитированное — это кодовое слово, чтобы я например молча встал и ушел. Потому что если это не оговорка — это путь в никуда. Для таких разработчиков в аду есть специальный котел
Нет конечно. Я считаю, что они должны довольно четко понимать инструмент, которым пользуются
Реальная история. 1995 год. Игра Wizardry 7. У меня компа не было. Я пришёл поиграть в гости, а то завидно, пока все на кухне пили. Прихожу как-то посреди ночи на кухню к друзьям и рассказываю, что меня вынесли крысы, а самое мощное заклинание, которое у меня было — "KNOCK-KNOCK" — не эффективно.
Эта история про фокусировании на бизнесе
Не все вопросы я бы взял, что-то бы переформулировал, но расширил бы ваш список вопросами это точно:
а) контекст — человек должен прекрасно понимать что это и зачем.
б) как выделяется память в Go программе
в) как работает сборщик мусора
г) дебагер — как делаете отладку локально. Почему это важно? Потому что очень много людей выводят дампы в консоль через println или spew.Dump. Скажем так это не совсем то что нужно, если мы за культуру разработки :)
д) вопросы про принципы построение библиотек, про design patterns применительно именно к Go. У вас есть вопрос про интерфейсы, и при желании из него можно выйти, но мне кажется, что этого не достаточно, для оценки специалиста, на котором будет ответственность за качество Go кода.
Возможно ли взглянуть этот полный список? Чисто себя поверить.
полный оформлен так, что только мне и полезен, так что — нет :(
можно на mindmap глянуть, то самое "дерево знаний"
г) дебагер — как делаете отладку локально. Почему это важно? Потому что очень много людей выводят дампы в консоль через println или spew.Dump. Скажем так это не совсем то что нужно, если мы за культуру разработки :)
Очень субъективно. Пожалуйста обоснуйте. Что это за культура такая, что дебагер — хорошо, а отладка по логам — плохо?
Да просто быстрее получается обычно, поскольку возможностей у отладчика больше. Если, конечно же, говорить про графический отладчик, а не про утилиту из серии foodb, где даже точку останова поставить — уже приключение.
Для себя вопрос давно закрыл — логирование удобнее, потому что А — автоматизация: глазам не надо страдать отслеживая баг вручную прыгая по окошкам отладчика — просто один грамотно оформленный вывод в лог на одну гипотезу.
Ваш пример с циклом не очень удачный. Даже когда использовал отладчик, мне приходилось добавлять условие средствами отладчика, чтобы он остановился только на брейкпойнте только при определенном условии, чтобы не скакать в цикле по брейкпойнтам и не дергать лишний раз глаза. Так зачем спрашивается так мучиться, если проще автоматизировать через лог?
for ... {
if(val != expectedVal) {
print oops/trace/stack/whatever
break
}
}
Все хуже — отладчик можно запустить только на локальной машине. Когда у тебя 100500 микросервисов — удачной отладки в тесте и на проде. Только логи и метрики спасают ((((
Формально говоря и на удалённой машине можно некоторые отладчики запускать. Правда часто нужны танцы типа поднять отдельный инстанс для отладки, перенастроить LB, чтобы только помеченные как-то запросы на этот инстанс слал и т. п.
У нас как-то разработчик на прод заатачился к процессу, поставил брейкпоинт, потом его отвлекли, он пошел ужинать и лег спать.
Просыпыается, а весь рабочий чат завален воплями, что прод не работает. Такие дела.
Ну вон выше предлагают же. А если не прод то 90% что там баг не воспроизводится дебажть там нечего.
Правда часто нужны танцы типа поднять отдельный инстанс для отладки, перенастроить LB, чтобы только помеченные как-то запросы на этот инстанс слал
Как-то сложно. Лог проще :)
Если заранее нет понимания какие гипотезы требуется проверить — то вам для сбора логов потребуется 5-10 раз передеплоить весь прод. Ну или сделать всё то же самое, что было предложено делать для подключения отладчика...
Идея в том, что разработчик на функционал который делает изначально пишет логи. Ну как вы тестами покрываете чтобы понять, что программа работает, так же и естественно получается писать лог, чтобы самому понять, выполняется ли логика или нет. Просто обычно как это происходит: разработчик расставляет отладочную печать (предположим, что он не использует дебаггер по каким-либо причинам), отлаживает, и когда программа правильно работает удаляет все эти дебьаг принты и отправляет в прод.
Идея в том, чтобы никогда не удалять подобные записи, а просто менять их уровень логгирования на verbose. Тогда при необходимости проверить гипотезу достаточно просто включить подробное логгирование в нужном компоненте (хотя бы компонент который подозревается в дурной работе обычно известен, если нет, то это определяется очень быстро), и дальше просто смотреть на ворнинги и прочие аномалии. Нашли проблему, починили/добавили логов, выключили логи до следующего происшествия.
Ну вот как есть TDD, так видимо есть и LDD
А подход с логами к слову работает в средах, где дебаг сложен или невозможен: в SQL, в ленивых контекстах, в функциональных языках, и так далее.
Если бы всё было так просто… Вот в примере выше отладочная печать стоит в ситуации когда val != expectedVal
. Но если expectedVal
известна — зачем вообще вычислять val
? Вполне возможно, что проверяет эта проверка лишь частный тестовый случай, и включать её в общем случае — полностью бесполезно.
затем если val это признак чего-либо, а не полноценное значение само по себе. например if responseStatus != ResponseStatus.Ok
— можно ли выкинуть такую проверку? не стоит ли заллогировать ответ если условие истинно?
Но я не вижу каким образом при проверке if responseStatus != ResponseStatus.Ok
пригодится трассировка стека. При таких проверках, как правило, и без того понятно где она произошла...
Кроме того, запись в логах о неуспешном запросе пригодится не только при отладке, но и при эксплуатации, проверка подобного рода никак не попадает в категорию отладочных.
Ну вот например я недавно функционал писал, вот эти логи в итоге помогли найти проблему.
Я просто проверил, что начиная с какого-то момента в логах писалось не то, что я ожидал и поправил. Дебажить такое трудно, потому что тут завязаны очереди, другие компоненты и т.п. Отключать всё это даже на тестовом стенде и заводить на разработческую машину долго. Кроме того, эти логи пригодястя в будущем, если меня собъет машина и система будет странно себя вести, по этим логам любой человек сможет понять "хмм, а почему тут эти два поля равны, Хотя по тесткейсу не должны и должны были обновиться?.."
Внимательно выслушаю предложения по улучшению
Не видя полностью код и не зная полностью контекста и задачи сложно. Вообще у PickapTimeSlot есть свой тип добавить в этот тип PickapTimeSlotOfset сравнение по полям From и To. Дальше уже в условии проверять через вызов этого метода. Не делать выставление через вложенный if а просто сделать метод и возвращать нужный pickupTimeOffset. Сделать проверку в начале и в начале запись в лог и прерывание метода. Тогда не будет вложенных if и сразу понятно что с этого место дальше просто уже ничего не выполняется. Добавить в PickapTimeSlotOfset доп конструтор который принимает другой объект и вот эти timeZone, LocaleFrom. В общем мелочи такие всякие. Ну это так, возможные улучшения на первый взгляд.
Вообще у PickapTimeSlot есть свой тип добавить в этот тип PickapTimeSlotOfset сравнение по полям From и To.
Они не всегда должны так сравниваться. Именно в таком виде они сравниваются тут в одном месте. Зачем пихать сравнение в базовый класс? Хотя, возможно, имеет смысл.
Не делать выставление через вложенный if а просто сделать метод и возвращать нужный pickupTimeOffset. Сделать проверку в начале и в начале запись в лог и прерывание метода.
Не понимаю, давай код.
Тогда не будет вложенных if и сразу понятно что с этого место дальше просто уже ничего не выполняется.
Только дальше как раз всё выполняется, тут 3 ветки при которых выставляется picupTimeSlotOffset в определенное значение.
Добавить в PickapTimeSlotOfset доп конструтор который принимает другой объект и вот эти timeZone, LocaleFrom. В общем мелочи такие всякие. Ну это так, возможные улучшения на первый взгляд.
А вот это с моей тз не улучшение, а ухудшение. Констуктор принимает минимум информации который ему нужен, про вот эти LocaleFrom он не знает и знать не должен, это вообще не его зона ответственности.
Хм, тогда почему у конструктора уже есть параметр localeFrom?
Так просто превратить весь этот кусок кода в функцию которая возвращает это офсет как свой результат. Вместо того чтобы в этом куске кода в нескольких места его устанавливать. Я так понял это не сработает потому что ниже и выше он и опять высталяется или что-то в этом роде. Не видя всего кода сложно сказать.
Тривиальный Extract method? возможно это было бы улучшением (хотя это спорно), но на "фу говнокод" это не тянет.
Тут еще у вас логи странные. Надо тесты писать. Логи пиши на выходе из вне (сеть файл) либо при отправке результата во вне (сеть файл) внутри самой системы это странно потому что и так можно зафиксировать результаты при известных входных данных через тесты. Нужен тесто что при таких вот входных данных вот такой вот итоговый результат получаем. Ну и новый разраб что придет увиде что вот тест говорит что если вот так то так а не будет по странным логам которые по середине логики торчат бродить.
Это как раз пример "логов вместо отладки" который я говорил. Когда хочется в логах видеть, как идет флоу и в какой момент он пошел не так, как должен был. Юнит тесты тут вообще не при чем, эта функциональность на регрессе проверяется.
Ты чего такой токсичный? Если там этот кусок кода для тебя был как родной и тебя эта моя фигня сильно задела то прости. Забей вообще на мой комментарий. Люблю тебя.
Код вообще не мой, я только логи расставлял, когда эта штука не работала. И потом по ним понял, что сломалось.
Это как раз пример «логов вместо отладки» который я говорил. Когда хочется в логах видеть, как идет флоу и в какой момент он пошел не так, как должен был. Юнит тесты тут вообще не при чем, эта функциональность на регрессе проверяется.
Так тестами можно было этот флоу описать. Что если вот так то должно делаться вот так. Если есть входные и выходные данные из логов то можно было реально с ними продебажить в специально созданном тесте — просто в моки и стабы данные нужные выставить и дебажить. Ну как тест — это уже просто экспериментальный запуск. Хотя там такое, я всего кода не вижу. Может там дофига внешнего взаимодействия и написать моки/стабы был бы дикий гемморой.
Нельзя было это тестом покрыть, тут очереди, вебсокеты и вся петрушка в один узел завязано. То есть, в теории, конечно, тестами покрыть можно, но по факту ресурсы ограничены, и было выбрано тестами покрыть другой функционал, а этот оставить на откуп ручникам
Почему нельзя замокать веб сокет и прочую петрушку?
Нельзя проверить работу с Х, замокав сам Х. Это будет уже проверка работы с моком.
Ты чего такой токсичный? Если там этот кусок кода для тебя был как родной и тебя эта моя фигня сильно задела то прости. Забей вообще на мой комментарий. Люблю тебя.
Кажется, тут вовсе не ваш оппонент токсичен...
Но я специально не затрагивал тему продакшена, потому что в этой ветке обсуждается отладка именно в девелопмент окружении. А также некая мистическая культура с этим связанная.
А что вам мешает автоматизировать всё что нужно в отладчике?
вашей «культуры».
Вы писали, что логи лучше отладчика, потому что логи можно автоматизировать, а в отладчике придётся все вручную делать. Вот я вас и спрашиваю, что же мешает автоматизировать все что требуется в отладчике.
Если уж вы влезли, то приводите корректные аргументы, а не соломенные чучела. Ну или не жалуйтесь на минусы.
Почему мне лучше:
— Автоматизация напрямую в коде. Я фильтрую в коде всё лишнее для проверки гипотезы. Мне не нужно изучать отдельный инструмент (тонкости автоматизации под конкретный дебаггер)
— В многопоточном приложении во время отладки можно не получить те же результаты, что при реальной работе приложения из-за точек останова.
Мне не нужно изучать отдельный инструмент (тонкости автоматизации под конкретный дебаггер)
То есть когда дебаггер вам именно что понадобится (а он вам понадобится как только вы по какой-то причине не можете изменить код в нужном месте — например если это библиотечный код) — вам он окажется незнаком.
В многопоточном приложении во время отладки можно не получить те же результаты, что при реальной работе приложения из-за точек останова.
С логами та же ерунда выходит...
То есть когда дебаггер вам именно что понадобится (а он вам понадобится как только вы по какой-то причине не можете изменить код в нужном месте — например если это библиотечный код) — вам он окажется незнаком.
Возможно мне когда-то и понадобится для такого случая отладчик. Но не факт. Я уже лет 7 как отказался от дебаггера и ни разу не возникало такой потребности, хотя пару раз за это время и были проблемы с внешними компонентами, было достаточно знать, что ошибка внешняя.
С логами та же ерунда выходит...
Нет, я о детерминированном баге, который стабильно проявляется и замечательно отслеживается при логировании, но может не возникнуть именно из-за остановки на брейкпойнте (когда этот поток стоит).
Если баг детерминирован — то он и в отладчике вылезет. А если нет — то помешать ему вылезти может что угодно. Если логи не мешают — значит, вам просто повезло.
логи этот ход не нарушают
с чего бы?
Но логи добавляют лишнюю синхронизацию потоков, которая также может помешать воспроизвести баг независимо от затраченного на логи времени.
А ещё иногда логи могут тормозить...
Ну а вот моя статистика: при отладке через логи, по ощущениям, нужно в среднем пять итераций гипотез. Т.е. программу надо перекомпилировать и перезапустить 5 раз, в то время как при использовании отладчика достаточно 1 раз попасть в нужную точку останова. Так что именно в сравнении с отладчиком мне логи не помогли ни разу.
А вот тот случай, когда логи тормозили и мешали, я буду помнить долго...
в то время как при использовании отладчика достаточно 1 раз попасть в нужную точку останова
Или не попасть или расставлять слишком много брейкпоинтов, чтобы попасть, особенно с асинхронным/многопоточным кодом. Что по затратам примерно равноценно выводу сразу нескольких гипотез в лог за одну компиляцию.
У меня противоположный опыт. Но я покрайней мере не топлю за то, чтобы все использовали логирование. Я за то, чтобы не дискриминировали тех, кто предпочитает логи. Потому что пока вижу только субъективные аргументы.
Я чуть ниже писал. Логи можно и с прода собирать, а дебажить прод не оч. Так же логи собираются автоматически, а что автоматизировать в дебаггере мне не очень понятно, это инструмент чисто ручной.
Я такую привычку поставил бы скорее в плюс нежели минус. Надо только приучить
- вместо печати в консоль писать в лог
- НЕ УДАЛЯТЬ эту отладочную печать перед тем как коммитить в прод
Это два простых правила, которые были одной из немногочисленных полезных вещей почерпнутых на туче конференций.
for i := range slice{
...
... { spew.Dump(i, slice[i]) }
...
}
Такое можно с учетом вашего пункта 1 писать в лог отформатировано и красиво. Но в какой-то момент у нас туда вообще всё будет писаться. Считаю, что в логи писать всё что тебе пришлось отлаживать не имеет смысла.
Человек приходит и говорит — у меня nil pointer exception. Он идет и расставляет по коду spew.Dump ( или вывод в лог) что бы понять где и в каком месте у него значение не присвоилось. Имеет ли смысл такое оставлять и писать в логи? Нет.
Такое можно с учетом вашего пункта 1 писать в лог отформатировано и красиво. Но в какой-то момент у нас туда вообще всё будет писаться. Считаю, что в логи писать всё что тебе пришлось отлаживать не имеет смысла.
Так и должно быть. А дальше скоупами/уровнями логгирования просто не выводить что не нужно.
Ну вот простой пример. у вас ВДРУГ в этом месте прод начал ломаться. В одном случае у вас уже есть логи, вам достаточно просто написать в конфиге "мне все подробные логи которые пишет этот компонент пожалуйста" и посмотреть что происходит. А если логи после дебага поудаляли — то куда смотреть? Новые писать? Так это ещё надо разобраться, куда и что писать.
Подобные дампы которые пишет сам разработчик когда пытается понять, работает правильно или нет его софт — идеальные кандидаты на подобное. ЧТобы не засирать эластик мусором конечно всё подряд туда писать по-умолчанию не стоит, но удалять такие места ни в коем случае нельзя.
Как устроен тип map?
Что я хочу оценить: насколько интересно кандидату, как именно ложатся в память наши байтики. Map, возможно, самая важная из стандартных структур данных, и весьма замысловато устроенная. Она сложная, она эффективная, она обладает встроенным race condition детектором… Неужели не любопытно?!
Самый популярный неправильный ответ: «Это хеш-таблица». Да, это хеш-таблица. Как устроена хеш-таблица?
Я не понял, так это правильный ответ или неправильный? Сначала пишите, что неправильный, потом, что «да, это хэш-таблица», т.е. правильный. Прямо шиза какая-то в одном предложении, или если выражаться политкорректно, противоречие.
- Господи! Народ — говно!
- Но другого у меня нет для тебя Моисей. Проповедуй в этом.
В какой-то мере я согласен с тем, что знать нужно все о своем инструменте. Но, как известно, продавец об инструменте "знает" больше мастера, который его покупает. Проблема в том, что продавец не умеет им пользоваться.
И ничего удивительного нет в том, что те вещи, которые не используются каждый день — забываются. Я уверен, что все это было прочитано и забыто.
Лично я совершенно без проблем даю пользоваться гуглом на собеседовании. Конечно, это снижает мое мнение. Но, гугл сегодня инструмент разработки. Более того, он очень важный инструмент. Избавляющий от уймы велосипедов.
Так вот. Если кадидат низкого уровня, нагуглит ответ, он в любом случае не поймет его сути. Если уровень высок, кандидат быстро встроит пазл в общую картину и даст развернутый ответ.
Я перед собой также не ставлю задачи таскать все в голове. У меня есть что-то типа "закладок". Я знаю как я найду ответ. И в зависимости от того, что я делаю последнее время, у меня накапливаются одни детали и "выветриваются" другие.
Но да, их регулярно спрашивают, поэтому приходится перед собеседованиями подымать теорию. Но потом вне зависимости от позиции, ты в в 98% случаев делаешь вещи типичные для твоего языка и никак не связанные с этими вопросами, поэтому уже через месяц вся подготовка снова выветривается.
Но автор статьи спросит: «а оставшиеся-то два процента?». А очень просто: я знаю где поискать. И это не обязательно будет копипаста со stackoverflow, я примерно помню как должна называться стоящая проблема в википедии.
Но вот беда, объяснить это на собеседовании порой невозможно, потому что вопрошающий боится потерять лицо, так как он не будет знать как вести интервью не гоняя по списку вопросов.
Выехать на общей эрудиции и здравом смысле может человек в хорошем настроении с хорошо подвешенным языком и умением рассуждать вслух. В среднестатистическому случае на интервью мы имеем интроверта в полустрессовой ситуации с плохими навыками рассуждать вслух.
Хотя именно под ваш случай этот человек и не подходит, но очень часто требования едины даже для перекладывальщика json в sql.
Но за список вопросов спасибо. Надоже периодически готовиться к интервью с людьми вашего типа.
Собственно, большую часть задач мы решаем в режиме разведки, проверяя чужие смелые бизнес-гипотезы.
Приветствую! Я как продуктолог имею такое мнение на этот счет. ИТ-индустрия испытывает большое давление со стороны общества и бизнеса — задач и планов явно больше, чем грамотных специалистов, способных их реализовать правильно.
И это рождает другую проблему — популяризированный «старатперский» подход к ведению бизнеса. Важно «быстро протестить» MVP, чтобы понять, будут там деньги или нет. Потому как ч/ч разработчиков очень дорогие, реклама — дорогая, конкуренты и мега-корпорации жарко дышат в копчик, чтобы съесть тебя или твой продукт.
Поэтому, когда индустрия варится в ситуации, когда нужно Быстро и Дешево, страдает качество. А следом и уровень понимания фундаментальных основ технологий.
Но читать было интересно, теперь, если когда-либо буду в него погружаться, обязательно вернусь к этому тексту!
На самом деле, с теми или иными оговорками, список вопросов проецируется практически на любой язык, только вот ответы в зависимости от этого будут разные.
Все просто, те, кто правильно ответит на большинство вопросов, скорее всего, не имеют нужного опыта. А опытные не так часто сталкиваются в подобными проблемами, чтобы помнить ответы
Это общие вопросы. Я вчера испытал некий стыд за то, что мне на ответы пришлось гуглить (что-то я не помнил, до чего-то руки не дошли). Да, мне не стыдно за последнюю треть вопросов, я не разработчик, я в душе не знаю что такое линтер. Но первые две трети это база. И это провал
В результате лучшие кадры приучаются делать только то, что им поручено, ничего, кроме того, что им поручено, и необходимый минимум того, что им поручено. И этот подход, я предполагаю, незаметно и неосознанно эти кадры распространяют и на свое обучение. Разработчик изучает только то, что ему нужно по текущей задаче: ничего, кроме этого, и ограничивается минимально возможным набором знаний. Моё скромное мнение — так нельзя! Образование — это игра в долгую, и подходить к нему надо с другими критериями, нежели к очередному «Проверим идейку MVP».
И я тоже согласен, что это плохо.
Когда только начинал и игрался только с персональными проектами, изучал что ни попадя. Всё было интересно и было много времени.
Но теперь, когда работаю, увы, от нас хотят, чтобы мы фигачили задачки, делали это быстро. А если требуется поднабраться опыта — это тоже мы должны делать быстро. Совместно с изучением других технологий, которые нам лично интересны или нужны для пет-проектов. Голова набекрень, и поэтому приходится ставить приоритеты и выбирать, что изучать. В результате, время и силы остаются только на самое необходимое (или желаемое, что зачастую не нужно для работы в компании).
А вопросник в принципе неплохой. Честно скажу: даже при том, что официально senior, я с полпинка и на половину этих вопросов не ответил бы хорошо, если бы меня вот прям щас посадили и начали их задавать. Во-первых, часть этих знаний в рабочей практике не нужна почти совсем. Во-вторых, многие ответы существуют на уровне интуиции и мы можем не суметь их с ходу вербализовать, но, оказавшись в ситуации, где это знание (может быть) нужно, просто за счёт опыта выбираем правильное решение.
С другой стороны, ответы на эти вопросы найти довольно легко, поэтому этот и любой другой вопросник можно использовать для гугления и запоминания ответов. Как раз, при подготовке к собеседованию чаще всего возникает проблема не в том, что я чего-то не знаю или не могу узнать (практически всегда можно), а в том, что я не знаю, чего хотят, чтобы я знал. Поэтому такие списки вопросов для меня лично даже полезнее, чем непосредственные ответы на них. Автору спасибо 8)
P.S. "не знаю" можно также заменить на "не помню". Когда я искал работу полтора года назад, я это всё как орешки щёлкал. А сейчас банально часть вещей забыл, ибо у мозга (по крайней мере, моего), очень эффективный garbage collector. XD
А мне кажется это закономерным.
Мы, когда изучаем любую новую технологию — начинаем с минимального числа абстракций для прикладного применения. Т.е. условно «вставляешь это сюда, а это сюда и оно работает», но при этом все, что под капотом — это «магия».
Уже позже, когда в голове эти знания перешли в долговременную память — мы можем углубиться и разобрать, как оно внутри работает. Это, несомненно, открывает больше вариантов использования. Но абсолютно невозможно на первом этапе.
Объем знаний в ИТ расширяется невероятными темпами — вполне закономерно, что у нас не хватает времени на глубокое понимание везде и мы переходим к поверхностному.
И этот процесс будет и дальше продолжаться. Единственное, что ему можно противопоставить — это деление на более узкие специализации, но у него куча своих проблем.
Поэтому все менее полезными становятся глубокие фундаментальные знания алгоритмов — они итак чаще всего уже лежат в каких-то библиотеках и для их использования достаточно помнить их ограничения и применимость, а вовсе не реализацию.
На каком-то бесконечно далёком собеседовании на должность программиста меня начали гонять по порядку аргументов в редких процедурах-функциях, вплоть до winapi. Были очень удивлены моей реакцией, которая была не «не знаю» или «не помню», а «да мне в общем-то пох какой там порядок».
Это я к чему — с таким вашим подходом лично я завалю любого кандидата на собеседовании по любому мало-мальски известному мне языку. Ну может кроме сеньора из сеньоров, но его и без этого видно практически сразу.
И да, я честно опросник дочитал примерно до середины — реально годный вопрос номер 12 и с оговорками 8-9 (если это реально используется в ваших проектах).
Когда вас собеседуют — что за вопросы они задают.
Круговорот неоправданных ожиданий.
Но почему даже после отсева к вам попадают люди с средним баллом 3,3, а не с 8+ как вы хотите?
Почему вы со своим предложением не интересны людям с 8+?
Почему ваши ожидания, что Senior должен знать на 8+, так расходятся с реальностью?
Я бы с удовольствием послушал такой курс, или доклад, или хотя бы статью почитал.
Но вот что меня удивляет: 28 тривиальных вопросов стали вдруг мучением для программиста. Как это произошло? Когда?
или в чем поинт?
У вас хороший список вопросов, но очень неправильно преподнесен подход и ожидаемы ответы. Человек должен рассуждать, выдавать свои знания, а не совпадения своих знаний с вашими. Т.е. про хеш и порядок можно уточнять
что за функция, почему дерево, почему не дерево, почему не двоичное, почему двоичное, что такое дерево, какие типы деревьев знаете, почему тут хешь это набор связанных списков, а не деревьев, нужно ли его балансировать или с этой задачей и так поплывем, а если у нас хеш на 10 элементов, а если на 100млн, есть разница?
Вот в чем поинт, а не просто ждать «ну потому что в Go придумали так».
Не нужно. Можно. Можно менять ожидания, и нередко это верный подход. А можно пытаться эту реальность изменить. И если никогда даже не пытаться делать последнее, и ждать пока "хорошо" для тебя сделает кто-то другой — высока вероятность никогда этого не дождаться.
Вот реально — 28 тривиальных вопросов теперь у нас считаются завышенными ожиданиями?
до того — каждый пользуется той методикой, которую придумал и обкатал.
если у вас конкурс прыжков в мешках — я вас не критикую.
если у меня вопросы, на которые можно дать простые ответы, если массив материала усвоен, а если не усвоен — трудно дать и сложные, то я ими пользуюсь, а вы критикуете.
ок?
лучшие кадры приучаются делать только то, что им поручено
Лучшие кадры не тратят своё время на бессмысленную копипасту — они программируют на более выразительных языках. А вот программировать на Go идут как раз такие люди, как вы описали — им сказали, что дженерики не нужны, а с ошибками надо работать через жопу — они уши развесили и пошли копипастить или обмазываться годогенерацией.
или обмазываться годогенерацией.
Осмелюсь предположить, что вы не пробовали лично, не вникали в суть, а просто повторяете чужие ошибочные слова. Кодогенерация в Go используется настолько редко, что почти никогда.
Но в качестве аргументов её приводят часто. И повторяют за другими и копируют это заблуждение.
Мне за последние 7 лет в Go встречалась одна-единственная библиотека, что предполагает кодогенерацию. Но не для генериков, а кодогенерацию объектов соответствующих конкретной схеме базы данных.
Map, возможно, самая важная из стандартных структур данных, и весьма замысловато устроенная.
Для тех, кто не знает ответа, есть вариант сделать "ход конем". Спросить интервьюера, мол, а Вы в курсе, что из-за неэффективности хранения большого количества пар ключ-значение Discord переписал одно из приложений на Rust? А те, кто имеет дело с реальным highload препочитает "использование slices вместо maps для хранения key->value значений".
Но, в принципе, считаю вопросы вполне "годными". Я сам люблю задавать на собеседовании вопросы типа "зачем нужен виртуальный деструктор". Пусть даже этот сценарий вытеснен из "горячей памяти", пусть даже мне нужен разработчик на Java (где этого нет) — мне интересен поиск ответа на него и количество требуемых подсказок.
- Какие технологические недостатки языка Go вы можете назвать?
Непригодность встроенного типа map для highload :)
Там не собственно в map было дело, а в его взаимодействии с GC.
И это починили, даже раньше, чем Дискорд переписался...
Возможно, я что-то пропустил. Разве интенсивная работа с map не вызывает больше фрагментации памяти? Разве циклом сборки мусора теперь можно пренебречь?
Ради интереса запустил https://www.komu.engineer/blogs/go-gc-maps
go version go1.14.6 windows/amd64
With a map of strings, GC took: 1.3960798s
With map of strings(that are hashed to ints), GC took:: 11.0006ms
Программа создает словарь размером 30E6 а затем запускает runtime.GC()
Интересно. По какому критерию Вы определили, что цикл GC при наличии в памяти обновляемого словаря размером в 30E6 элементов влияет на производительность в допустимых пределах?
А те, кто имеет дело с реальным highload препочитает «использование slices вместо maps для хранения key->value значений».
Особенно если им нужен частый поиск по ключу.
Ну да, конечно.
Забавно. Почти на всё есть ответ в книге "Язык программирования Go". Неужели не все go-разработчики её читают?
Есть ценные вопросы, бесспорно, особенно про обработку ошибок, но по хорошему, вопросы нужно разбить по категориям, т.е. архитектура, мониторинг, и тд.
В комментариях, было очень ценно замечено, что продавец все знает о том, что продает, но не умеет пользоваться. Имхо, сначала нужно поставить задачу, которая подразумевает себя проверку всех этих знаний, где они и в правду потребуются, для её решения.
Но с автором соглашусь, в том, что это немного огорчает, т.к. сейчас у всех свои понятия о том, кто же этот рыцарь сеньор помидор. По опыту собеседования людей на такие позиции, все разбивается даже не об знание языка, а об решения проблем. Сложись такое впечатление, что сейчас кроме CRUD сервисов ничего нету, у всех одни и те же кейсы решения задач, но как только проблема становится не типичной, то все, у меня лапки.
Ну и в добавку, вот мой любимый вопрос, который отсеивает джунов, да и вообще, людей, которые не понимают, что не все задачи решаются технически.
Как сохранить 10ГБ на диск объемом в 1ГБ?
Почему-то, люди начинают и в правду решать эту задачу. Самый лучший ответ, который я слышал, это сохранять в /dev/null :))
Как сохранить 10ГБ на диск объемом в 1ГБ?
Ответ "если в заархивированном виде не влезает, то никак" принимается?
Нет, можно с потерями сохранить :)
Как создать /dev/null объёмом 1 Гб?
Что-то в стиле "сейчас работаю над распаковщиком".
Но задачка хорошая, чтобы проверить как кандидат будет уточнять ее.
Ну и еще наброшу из реальных собесов по гошечке: medium.com/@gotzmann/so-you-think-you-know-go-c5164b0d0511
сильный программист, которому интересно разбираться во внутренностях языка на уровне знания конкретных хеш-функций в мапах
Это отнюдь не показатель «сильного программиста».
Сильного олимпиадника, возможно.
Но если бы говорим о повседневной коммерческой разработке, то тебе нужно представлять, по сути, только классы структур, а в нюансы типа конкретных видов хэша — вникать только в конкретных случаях, если приспичит (но, скорее всего, никогда в жизни не приспичит, если вы не разработчик базовых библиотек).
неизвестной галеры типа Evrone?
действительно! Не чета какому-нибудь https://andersenlab.com/ или EPAM/Luxoft!
Ну и еще наброшу из реальных собесов по гошечке
А в чем ктсати сложность? А то там статья про некий surprise при том, что примеры тривиальные и результат тоже предсказуем.
Что, даже четвёртый?
Присмотрелся повнимательнее — да, в последнем какая-то дичь. Причем если заменить a = append(a, 5) на a = a
то поведение программы совершенно меняется. Судя по всему что-то с реаллокацией происходит, но на сторонний взгляд выглядит как баг.
a = append(a, 5) расширяет слайс не на один элемент, а с запасом.
в результате второй append, который 6 элемент добавляет, не приводит к переаллокации.
Я понимаю как работают списки на массивах, вопрос немного в другом. Поведение программы
package main
import "fmt"
func surprise(a []int) {
a = append(a, 5)
for i := range(a) {
a[i] = 5
}
fmt.Println(a)
}
// Quiz #4
func main() {
a := []int{1, 2}
a = append(a, 0)
surprise(a)
fmt.Println(a)
}
и
package main
import "fmt"
func surprise(a []int) {
a = append(a, 5)
for i := range(a) {
a[i] = 5
}
fmt.Println(a)
}
// Quiz #4
func main() {
a := []int{1}
a = append(a, 0)
surprise(a)
fmt.Println(a)
}
Совершенно различается! Получается, у вас весь флоу программы без единого условного оператора зависит от реального значения, которое написано в a
! Это же жесть.
package main
import "fmt"
func surprise(a []int) []int {
a = append(a, 5)
for i := range(a) {
a[i] = 5
}
fmt.Println(a)
return a
}
// Quiz #4
func main() {
a := []int{1, 2}
a = append(a, 0)
a = surprise(a)
fmt.Println(a)
}
он вполне однозначный. и об этом много где написано
ну или еще вот так можно, тоже все однозначно
package main
import "fmt"
func surprise(a []int) {
a = append(a, 5)
for i := range(a) {
a[i] = 5
}
fmt.Println(a)
}
// Quiz #4
func main() {
a := []int{1, 2}
a = append(a, 0)
surprise(append(([]int)(nil), a...))
fmt.Println(a)
}
Что значит "правильный флоу"? Это корректный код на Go? Если нет то вопрос, почему нет ворнингов. Если да, то мне непонятно, почему изменение контента влияет на поведение. Потому что получается, что у вас например с консоли массив читается, а дальше в зависимости от того что ввел пользователь семантика совершенно различается. Либо это УБ, тогда вопросов нет (разве что откуда в современном языке с ГЦ взялось УБ)
surprise(append(([]int)(nil), a...))
Я ведь правильно понимаю, что если бы у нас был слайс слайсов, то это сделало бы поверхностное копирование вложенных слайсов?
это документированное поведение.
Менее ногострельным оно от этого не становится. Причём, строго говоря, корректный ответ на четвёртый вопрос дать нельзя, потому что спецификация языка не говорит о том, какая стратегия роста ёмкости у встроенных слайсов.
Не знаю почему, но прямо вопрос про логгер номер один в рейтинге. Прямо очень красиво. Мне конечно пришлось заглянуть в доку, но хватило 10 секунд, чтобы вспомнить почему нет. Мимими
Получается, интервьюера огорчает, что на языке, предназначенном для казуалов, внезапно нанимаются писать казуалы.
Вдобавок эти вопросы можно зазубрить и отхакать интервью по полной.
Не совсем понятно, что такое "язык для казуалов" и почему Go именно он? Ритчи, Томпсон, Керниган люди скромные, но вряд ли они считали себя прямо вот казуалами, делая себе игрушку
А при чем тут они? Они си делали, и для других целей совсем.
В смысле причём тут они? Вы не знали, что в разработке Cи и Go (и кстати, частично C++) участвовали одни и те же люди? Вы же не думаете, что Go 11 лет?
Go 11 лет. А то так можно приплести что тайпскрипт это такой Паскаль, ведь Хейслберг пилил. И ему 50 лет
Ммм… мне трудно рассуждать про Тайпскрипт, я ничего про это не знаю. Но с Go историческая ситуация довольно публичная и известная.
Никогда в живой природе cfront не видели, кстати? А я видел. На одном диске с позапрошлой версией Go. А знаете что объединяет Go и UTF-8? Они созданы друг для друга. Это не философское утверждение
А знаете что объединяет Go и UTF-8? Они созданы друг для друга.
Настолько созданы, что строки в Go не имеют никакой кодировки и могут содержать невалидные с точки зрения UTF-8 последовательности.
Настолько созданы, что строки в Go не имеют никакой кодировки и могут содержать невалидные с точки зрения UTF-8 последовательности.
Это нормально.
Ну мало ли зачем программисты используют строки… Это довольно удобная структура.
Если нужна валидность — проверят отдельно.
P.S.:
Уже не говоря о том, что строка может быть прочитана из внешнего ресурса и должна быть передана на другой внешний без изменений.
Автоматическая валидация тут будет только мешать.
Это не строка, извините, а bytearray или что там у вас является аналогом в языке
Это не строка, это набор байт. И в Go не используют повсеместно байтовые слайсы только потому, что строка — единственный (кроме всяких численных типов, разумеется) неизменяемый тип данных в языке.
Это не строка, это набор байт.
Это не строка, извините, а bytearray или что там у вас является аналогом в языке
Э… нет, господа.
Это именно строка, но пришедшая из внешнего источника. Он нас не зависящая.
Например, строка из файла-шаблона для формирования HTML.
Если это значение пришло извне, то у него совершенно точно нет никаких ограничений на содержимое, так что строкой это называть некорректно.
От внешнего источника не может прийти UTF-8 строка, может прийти только набор байт. А в строку её надо парсить. Причем парсинг может очевидно завершиться неудачно.
А в строку её надо парсить.
Имеет смысл парзить, если вам нужно её парзить.
Ну а если не нужно?
Если нужно просто сделать что то типа «внешняя строка»+«мои данные»+«другая внешняя строка» = записать в файл?
И что там было во «внешней строке» нас не интересует.
Если это значение пришло извне, то у него совершенно точно нет никаких ограничений на содержимое, так что строкой это называть некорректно.
Мы то работаем с ней как со строкой — см. выше.
Понятно, что входные данные нужно проверять, по уму. Но мы же с вами знаем, что это делают далеко не всегда. Иначе бы программы давно бы уже не падали вовсе.
Уже не говоря о том что не всегда возможно сообщить об ошибке во входных данных, ибо это может быть ответственность другой части системы.
Имеет смысл парзить, если вам нужно её парзить.
Ну а если не нужно?
Тогда это не строка :shrug:
Понятно, что входные данные нужно проверять, по уму. Но мы же с вами знаем, что это делают далеко не всегда. Иначе бы программы давно бы уже не падали вовсе.
Так вы уж определитесь — "современные языки заставляют проверять кейсы" и "ну мы-то люди, не проверяем нихрена".
А то с моей колокольни это все больше напоминает карго-культ, где с одной стороны в компиляторе встроена проверка не ниспользуемые переменные и форматирование, а с другой херак-херак, непроверяемые строки (но надеемся что там всё ок), interface{} через interface{} и прочее. В итоге бамбуковый аэропорт совсем как настоящий, но почему-то не работает.
Если нужно просто сделать что то типа «внешняя строка»+«мои данные»+«другая внешняя строка» = записать в файл?
И что там было во «внешней строке» нас не интересует.
ну, так и работайте тогда с bytearray? Считали bytearray, взяли свою строку, конвертнули ее в поток байтов (это может происходить в языках автомагически, незаметно для разраба), склеили, запихнули получившийся bytearray в выходной поток (=файл). Где тут работа со строками?
ну, так и работайте тогда с bytearray? Считали bytearray, взяли свою строку, конвертнули ее в поток байтов (это может происходить в языках автомагически, незаметно для разраба), склеили, запихнули получившийся bytearray в выходной поток (=файл). Где тут работа со строками?
Мы же о Go?
byteA:= []byte("aaa")
byteB:= []byte("bbb")
byteC:= byteA + byteB // а так нельзя
byteC:= append(byteA, byteB...) // можно так
strA:= string(byteA)
strB:= string(byteB)
strC:= strA + strB // а так мне нравится больше
Поэтому я довольно часто байты в строку загоняю и никакая неправильная кодировка мне не мешает. Ну разумеется, если исходные строки были корректны.
Потому что это не те строки. Но с UTF-8 с некоторым допущениями исторический факт. Спецуево за два дня
а предыдущий — пару лет.
пока никто не хакнул ни тот, ни другой.
думаю, это потому, что хакать его нет никакого смысла
Для позиции
найти человека, который сможет задать и поддерживать высокий уровень профессионализма в применении языка Go
Совершенно адекватное интервью. Я бы сказал, что позиция, скорее, на tech lead, поскольку нужно "задать" высокий уровень, чем senior. Но я не совсем понял
средний балл по опроснику — 3.3 по шкале 0-9. 3.3, Карл! 3.3 — это, с моей точки зрения, уровень junior. Middle должен набирать, я считаю, 5+. Senior — 8+.
По всей видимости, плохо отработали HR или те, кто просматривал резюме — нужно было более серьезных людей пропускать на собеседование.
Возможно, и проблема с деньгами — люди, кто могут показать 8+ просто не особо шли. Впрочем, их и очевидно просто мало.
Считать среднее вообще не имеет смысла. Это нормальная статистика, что, чтобы нанять одного разработчика нужно провести около 10 собеседований. И это при хорошем фильтре резюме, как для mid, так и senior. Соответственно, да: 9 из 10 мидов попадают под <5, 9 из 10 сеньоров под <8.
По всей видимости, плохо отработали HR или те, кто просматривал резюме — нужно было более серьезных людей пропускать на собеседование.
в том и боль, что по резюме кандидаты были подходящие.
более того, по беседе об опыте и текущей позиции тоже вполне.
но когда дело дошло до более общих вещей — оказалось, что слишком узкие спецы.
— Как в одном комментарии было верно подмечено, Автор по сути ищет академического лектора по заданной теме. Что есть самостоятельная профессия! Нужно видимо осознать, что человек умеющий все это — зачем ему программистом то идти, если он может пойти в учебной учреждение на более «белую» работу, где не нужно впахивать, больше статуса, авторитета, шире и разноплановее рынок труда, больше соц.гарантий?
— А кто ищет Сеньора Go? Собственник бизнеса или руководитель отдела, просто не ясно, где Сеньор Экономики в этом вопросе. Экономика говорит о том, что выигрывает тот, у кого средство производства при прочих равных дешевле. Просто с этой колокольни это выглядит так: «мы ищем пахаря за еду и ценнейшие опыт, который мы ему дадим в нашем колхозе». В этом смысле, эффективнее, и это тоже звучит в комментариях, у Пахаря интересоваться общим состоянием здоровья, целостностью зубов и общим развитием мускулатуры. Готовностью в конце концов пахать до ночи в сезон урожая. А инструкцию к плугу он прямо во время первой смены освоит или ему подскажут старшие товарищи.
— Не знаю, оригинально ли звучит — максимальный профит Нанимателю всегда приносит «работящий» работник, способный взять больше и унести дальше. А все на что вы водит Анкетник вообще ничего общего не имеет с выявлением этого.
Вот из моего опыта: код на go, но sql запросы совершенно не дружат с постоянными подключениями, не используются prepared (убивать за это пора уже), параметры подставляются конкатенацией с сомнительным экранированием (sql инъекции в 2020 году, уау). То есть по сути — весь код в помойку, потому что под нормальное использование подготовленных запросов его не так то просто будет переписать.
Как вы со своим опросником помогаете отсеять людей делающих такие вещи я даже не представляю.
И самое забавное, что совершенно неважно, понимает ли он как реализовано взаимодействие со структурами данных или нет, потому что на подготовленных запросов он может сэкономить такое жуткое количество времени выполнения, которое перекроет любые низкоуровневые нюансы и еще останется.
Я могу ошибаться, но вроде prepare хорош только вне транзакций, а с транзакциями (в которых обычно такой запрос один на транзакцию) от него больше вреда, чем пользы — нет?
Кроме того как приятный бонус: разделение текста запроса и его параметров.
ЗЫ про вред не слышал
Что же экономится-то, если в каждой следующей транзакции необходимо повторять prepare этого же запроса? А вред в том, что prepare+execute это 2 запроса вместо одного. Почитайте исходники, там звёзды должны сойтись чтобы в транзакции не пришлось повторять prepare: ранее подготовленный stmt не должен в этот момент использоваться в другой транзакции, должен уже быть ранее подготовлен именно на этом соединении с БД… Я пару раз когда-то делал бенчмарки на коленке — без prepare внутри транзакции бегало заметно быстрее, а при отсутствии транзакций — наоборот (впрочем, охотно допускаю, что проблема была в самом бенчмарке, я не очень сильно на него заморачивался).
Наверное, если заранее подготовить пул stmt в которых подготовлен одинаковый запрос и ручками распределять их между текущими транзакциями, плюс уделить внимание вопросу сколько у нас живут соединения с БД и постараться продлить их жизнь — очень может быть что и получится получить выигрыш в производительности… только я вот такого в полном объёме ни в одном проекте не видел пока. И, сказать честно, обычно тормоза реляционной БД решаются вовсе не благодаря prepare — если конечно у нас не тот самый очевидный кейс, когда один запрос многократно выполняется с разными параметрами подряд кучу раз в рамках обработки одного ответа юзеру.
Все остальные ваши утверждения как то не сходятся с документацией.
Я вообще ничего не говорил «тормозах бд» я говорил об экономии времени выполнения. Вы суммарно хотя бы за день посчитайте сколько вы запросов выполняете.
Вот под рукой как раз запрос оказался, пачка юнионов, расчет количества элементов по табам в конкретном разделе. Отношение чтения к записи для этих списков ну как минимум 10к1 я бы даже сказал много больше.
Выполняем:
Planning Time: 5.939 ms
Execution Time: 3.437 ms
Planning Time: 4.540 ms
Execution Time: 3.030 ms
итд
Теперь Prepare, execute:
Planning Time: 0.189 ms
Execution Time: 2.818 ms
Planning Time: 0.050 ms
Execution Time: 3.809 ms
Да не для всех запросов это так, иногда мы меняем скорость подготовки на скорость выполнения, но например в случае с Jit все интересней. Да и кроме всего прочего заметьте, что меня куда больше смешение параметров с текстом запроса напрягает.
Не поймите неправильно. Я охотно допускаю, что не прав — собственно, я с этого данную ветку и начал (давно не сталкивался с высокими нагрузками на реляционную БД, стараюсь проектировать системы так, чтобы такая ситуация не возникала в принципе). Тем не менее, я не вижу в указанной Вами доке конфликтов с тем, что говорю я. Плюс, как бы не работал постгрес, но между нашим кодом и постгресом находится database/sql (мы здесь ведь Go обсуждаем), а он работает именно так, как я описал — сходите по ссылке выше и убедитесь. А поведение определяемое постгресом наступает уже потом.
Возможно я Вас неправильно понял, но Ваш первый комментарий прозвучал так, как будто использование prepare является обязательным в любых ситуациях, и его отсутствие это смертный грех. Я всего лишь уточнил, что существуют ситуации, в которых это может быть не так. С Вашим конкретным примером, где prepare полезен, я спорить и не думал — конечно, он нередко очень полезен. Но бездумно делать prepare для каждого запроса в любой системе, не обращая внимания ни на то, что это за проект, ни что у него за запросы, ни что за БД используется — не выглядит оптимальным подходом.
Здесь по-моему очень похожая ситуация. Правильные теоретические вопросы о которых редко задумываются в реальных проектах. Если стоит задача нанять внутреннего эксперта по Go, то вопросы правильные. Но тогда надо искать среди спикеров конференций и других увлеченных теоретической информатикой людей. Если кандидату предстоит вести реальные проекты, то лучше проводить case-интервью. А как вы решали такую проблему, а чем лучше/хуже было бы сделать так… На примере предыдущих проектов кандидата, либо на реальных задачах из своей компании. Получается достаточно показательно.
Сколько людей набрали 8 и больше баллов, не считая ваших знакомых, с которыми вы работали или работаете?
У кандидатов, набравших высокий бал, проводились ли на их прежней работе постоянные экзамены? Если нет, сколько собеседований у них было перед вашим или сколько месяцев они готовились? Но, вы это конечно вряд ли спрашивали и мы это не узнаем.
В результате лучшие кадры приучаются делать только то, что им поручено, ничего, кроме того, что им поручено, и необходимый минимум того, что им поручено. И этот подход, я предполагаю, незаметно и неосознанно эти кадры распространяют и на свое обучение. Разработчик изучает только то, что ему нужно по текущей задаче: ничего, кроме этого, и ограничивается минимально возможным набором знаний.По большей части согласен. Что с этим можно сделать? Да ничего. Чтобы хорошо справляться со своей работой, обычно глубоких познаний в теории не нужно. Много кому нужен начитанный разработчик, от которого профит будет больше на 0-20%, но зарплата которого в 2-3 раза больше? Бизнесу это обычно не нужно и это нужно принять. Если было бы очень нужно, тогда из 8 часов выделяли бы несколько не на работу, а на обучение.
Почему так? Почему опытные, квалифицированные разработчики набирают такой низкий балл?Помимо вашего предположения, есть еще и другие причины:
- в их обязанности на работе не входит сдача экзаменов) Они не заучивают и не перечитывают прочитанное в прошлом, если им это не нужно.
Отсутствие глубокого познания теории, которые не используешь или используешь редко — это одна проблема. Вторая проблема — что большую часть рабочего времени пишешь код, а не рассказываешь, объясняешь что-либо, и эти навыки у многих деградируют, не развиваются. - позиция — бэкендера, а кандидат фуллстэк. Кандидат широкопрофильный специалист, а собеседуют, как узкопрофильного. Он знает больше технологий, но в лучшем случае на среднем уровне.
- собеседования обычно проходят так, как будто интервьюер собеседует сам себя. То есть спрашивает то, в чем он хорошо разобрался. Без учета, что у других разработчиков свои знания, свой опыт, обычно сильно отличающиеся от знаний и опыта интервьюера. Программисты обычно заносчивы и уперты. Большинство считают, что все обязаны знать именно то, что знают они.
Даже если ограничиться одним стеком, возможных технологий и знаний будет слишком много, чтобы их все знал один человек. Плюс технологии быстро меняются. Также разработчик может сменить стек. - они не перечитывают годами одни и те же книжки по языку и структурам данных, а изучают что-то новое, что может пригодиться в работе. На самообучение этому в течении 10 лет итак у большинства уходят тысячи часов личного времени.
- со временем набираются опыта, меняются ценности в жизни. Приходит понимание, что технические знания особо не улучшат качество их жизни, и если развивать что-то, то эффективней точно не их. Вырастают из этих игр в крутого разработчика и вместо траты свободного времени на обучение по работе, тратят больше времени на себя и своих близких. Стать счастливым или стать крутым специалистом? Я думаю, выбор очевиден)
- может зарплата маленькая, вот и пришли кандидаты, у кого зарплата меньше. А спецы в теории уже получше работу нашли.
6. Как устроен тип map?Ну, мне например такое уже не интересно. Все эти постоянные дедлайны, ограничения по времени на задачу, попадание в проекты с плохим кодом, привело к тому, что мне интереснее то, что может помочь сделать проект быстрее и код читабельней, гибче.
Что я хочу оценить: насколько интересно кандидату, как именно ложатся в память наши байтики. … Неужели не любопытно?!
Ну а вообще, кому-то интересно строить, кому-то разбирать. Нет же профессии археолог-строитель?) Так и здесь. Программисты тоже разные бывают. Кому-то интересно в «кишках» копаться, кому-то интересно изучать, как сделать код более масштабируемым, третьему нравится c 3rd party решениями разбираться.
26. Какие средства обобщенного программирования есть в Go?Если вы хотите оценить знакомство с основными парадигмами, то и вопрос должен звучать: «какие парадигмы вам известны ...?»
Что я хочу оценить: знакомство с основными парадигмами современного программирования и границами их применимости в Go.
А этим вопросом вы только про одну спрашиваете. Хорошо, если вы скажете, что именно вы хотите оценить. В таком случае вы можете получить ответ не «я не знаю», а «именно эту я не знаю, но могу рассказать про другие».
вопрос должен звучать: «какие парадигмы вам известны ...?»
прямые вопросы не работают :(
я понимаю, что сложно в это поверить, но мой опросник составлен так, чтобы кандидат мог рассказать, что он знает.
на любой вопрос можно зайти минимум с двух сторон, и даже со стороны «да это все не важно»
многие кандидаты просто ленятся подумать, о чем же спрашивает интервьер. на позицию линейного программиста это не очень важно, но вот эта позиция была не для лентяев.
"они не перечитывают годами одни и те же книжки по языку и структурам данных, а изучают что-то новое,"
Мап — это одна из основных структур данных в большинстве языков. Можно забыть все, что угодно, но это в работе постоянно. Нельзя даже отвертеться "я в работе мапы не использую".
А самое главное — не надо ничего зубрить, нужно один раз понять. Потом всегда можно вывести логически.
Знать в деталях, как реализована каждая основная структура данных в языке (особенно если это уже где-то 5-ый язык, с которым ты работаешь) — это совсем другое, и на практике практически никогда не используется и теряется в море других знаний. Естественно, что чем дольше работаешь, тем хуже знаком с такими вещами. И естественно, что без повторения сеньоры валятся на таких вопросах гораздо чаще джунов, недавно изучивших язык.
Всего 28 вопросов, но сколько боли и недоумения они мне принесли! Но и не задавать их я не могу — это моя работа
Можете. Это я Вам говорю как нанимающий менеджер.
Просто в Вашей отрасли почему-то принято устраивать из собеседования экзамен и глумиться над кандидатами.
Я нанимаю схемотехников и конструкторов печатных плат. Технические вопросы (один или два — достаточно простых) я задаю в одном из двух случаев:
— когда кандидат прям форсит что вот этот вот аспект он прям знает знает;
— когда из его «рассказа о себе» вообще ничего толком не понятно.
Хотя я мог бы спрашивать что-нибудь типа «а чем перекрестная помеха на внешних слоях принципиально отличается от перекрестной помехи на внутренних». Это базовый, простой и основополагающий вопрос, требующий небольшого понимания теории (Вы даже не являясь специалистом скорее всего быстро нагуглите ответ и даже поймете почему так) — тока на него мало кто сможет ответить кроме меня вот так с ходу (а уж тем более стрессуя на собеседовании). Ну просто это священное знание на практике не нужно. Но зато, я как интервьюер мог бы блеснуть своим интеллектом и самоутвердиться.
Ни один из нанятых мной людей — еще не был уволен.
Я допускаю что у Вас программистов какая-то своя кухня, но ИМХО — Вас просто слишком много и Вы просто не знаете как по формальным признакам фильтровать кандидатов.
Я допускаю что у Вас программистов какая-то своя кухня, но ИМХО — Вас просто слишком много и Вы просто не знаете как по формальным признаком фильтровать кандидатов.
это, конечно, так и есть — никто не знает, что такое «хороший программист»
четвертый, наверное, человек прихидит сюда в комменты рассказать, что автор просто не умеет нанимать людей, а вот комментатор-то — ого-го.
ценной информацией пока поделился только Matvey-Kuk. Оказалось — он отправляет кандидатов изучать некий код еще до собеса.
Тоже так буду делать теперь :) Скорее всего — полыхание не только не утихнет, но станет жарче.
четвертый, наверное, человек прихидит сюда в комменты рассказать, что автор просто не умеет нанимать людей, а вот комментатор-то — ого-го.
Я этого не говорил. Более того — выразился максимально абстрактно о всей Вашей отрасли в целом. Просто увидев Ваш список аж 28 вопросов я мягко говоря выпал в осадок.
ценной информацией пока поделился только
А какая ценная информация Вас интересует? Чем я руководствуюсь?
Я просто смотрю на то, что человек делал по резюме, а если этой информации нет — прошу рассказать о самых сложных устройствах которые он проектировал. И задаю вопросы, позволяющие мне оценить их сложность с моей точки зрения и прояснить с какими областями знаний он при этом имел дело. Ну например — «а к чему у Вас там была подключена память, а какая? а код контроллера памяти Вы сами писали? а как отлаживались? были ли проблемы? какие? как решали?»
У меня раньше был опросник с кучей умных вопросов с двойным дном. Я заменил их несколькими, которые не имеют правильного ответа а скорее провоцируют кандидата порассуждать на техническую тему. Пример такого вопроса «если бы Вам досталась чужая плата на проверку — что бы Вы там проверяли и на что обращали внимание».
Я уверен что в Вашей отрасли тоже можно собеседование из экзамена превратить в рассказ кандидата о себе, просто напрявляя его повествование в интересное для себя русло и прося раскрыть какие-то детали. Люди любят рассказывать о себе и любят детально рассказывать о том что знают — сами. Стресса меньше, меньше людей будут считать Вас плохим человеком и картинка получится вероятно более объективной.
У меня даже был случай, когда одна женщина (ранее работала в NVidia, сейчас в Intel — моделирует чипы ихние на Signal/Power Integrity) просто пошатнула мою картину мира. Сначала мне показалось что она говорит какую-то дичь, а через пару уточняющих вопросов (в духе — «это почему это вдруг?») я понял, что она на голову выше меня по квалификации просто. Если не вдаваться в детали, я с ней беседовал об интерфейсах до 10G, а она со мной — от 40G — просто контекст не почувствовала. Я употребил термин «высокочастотные интерфейсы», а в ее мире планка «высокочастотности» сильно выше оказалась. Получил массу новой информации в голову.
Ну все же уже глумятся над Вашими (не персонально Вашими, а в целом в отрасли) экзекуциями при найме.
возможно, такая постановка задачи не имеет смысла, но пока эксперимент продолжается.
Ну все же уже глумятся над Вашими (не персонально Вашими, а в целом в отрасли) экзекуциями при найме.
я довольно часто слышу «спасибо, было интересно» после интервью. так что, все же, не экзекуции.
После этого месяц страдал от собственной ничтожности, а еще через 3 месяца мне оттуда позвонили и сделали оффер, так как этот человек (в целом кстати очень хороший и я рад знакомству с ним — просто вот так он проводит собеседования) за 4 месяца не смог никого нанять.
Обычно это просто вежливость. Ну и некая последняя попытка расположить Вас к себе. Ну типа — «спасибо что указали мне мое место, согласен что я никчемен но готов учиться».
месяц страдал от собственной ничтожности
у нас страдать некогда, у нас ажиотажный спрос на спецов.
Если так, то почему не закрываете вакансии? Значит, спрос не такой и высокий? Или попросту платить столько не можете, чтобы затаскивать к себе рокстаров?
Или Вы имеете в виду, что у Вас не спрос ажиотажный, а кандидатов овер возможности их собесить и нанимать? В целом, наверное, справедливо, что каждый уже мнит себя вайтишником.
Позвольте тогда узнать: какова воронка (количество исходных заявок кандидатов, кол-во кандидатов после отсева HR), среднее время на поиск нужного кандидата, коэффициент, отражающий текучку успешного кандидата (не прошел испытательный срок/слился в течение года-полутора-трех).
Кстати, общался с коллегами HRами. Те, которые работают как агенства — берут деньги, только в случае успешного прохождения испытательного срока (это дает гарантии для работодателя, что кандидат ТОТ, а не какой-то самозванец). У Вас есть такая практика?
Т.е. у Вас не возникает вопроса, почему входной фильтр так плохо работает? И не жалко своего времени?
у меня есть ответ, но он никому не понравится
Кажется в чьей-то организации не хватает троллей.
Ну вот, например, я как-то думал дать HR чёткую инструкцию какие резюме отсеивать, а какие нет, имея перед глазами несколько десятков откликов от кандидатов, половину из которых я собеседовал потом и отсеял бОльшую часть как "какой сеньор?! ему год минимум в нашей команде работать под чуткой опёкой, чтобы миддлом стать"
Сдулся после, когда "инструкция" на 10-й лист полезла, а имеющиеся резюме стали попадать в не те классификации.
+1. Последний пример. Приходил паренёк. На прошлом месте якобы тимлид, распределение задач и все такое. По техническому интервью никогда бы не «вывел его на чистую воду», т.к. кандидат достаточно компетентен, но тимлидство было указано только лишь чтобы набить себе цену. А вот вопросы за жизнь, за организацию работы, за задачи — то что надо!
никто не знает, что такое «хороший программист»
много кто знает. Сеньеористый программер это тот которому можно дать посредственно сформулированную задачу и получить вопросы, читаемый код и отсутствие необходимости за ним переделывать.
четвертый, наверное, человек прихидит сюда в комменты рассказать, что автор просто не умеет нанимать людей
Возможно потому, что каждый проходил таких собеседований вагон? И скорее всего, выяснил, что с реальной работой такие опросники коррелируют примерно никак?
ценной информацией пока поделился только
Желаете ценной информации? Пройдитесь по опыту соискателя. Знаний можно почерпнуть сколько угодно.
Примеры:
Человек отвечает что написал много крутых клиентских библиотек для REST API: можно спросить о недостатках, даже подсказать про уровень транспорта и приложения, да даже прямо намекнуть про коды ошибок, если не упомянет про 401,403,404,500, то я склонен сомневаться в его опыте.
Знает vue.js? Да самое простое, отличие computed/functions, data/props. Хуки жизненного цикла (те что помнит). Если не ответит значит не работал с vue, если ответит то по сути всe, особо спрашивать там больше нечего.
Любит ORM? Да еще доктрину? Спросим про мэппинг кастомных запросов.
Обожает фреймворки? Ок, пройдемся по компонентам фреймворка и зачем они вообще то нужны.
Пишет запросы: select, join, group by, having, with (cte), partition over(window functions) и смотрим где сознается или замнется и уже понятен уровень.
И дальше идем уже по самим проектам и уточняем важные нам детали. Ну например, если человек работал над сайтом по продаже недвижимости, то можно выяснить как хранили и нормализовывали адреса, где добывали географическую информацию и как с ней работали.
Плюс пара тройка вопросов по важным моментам в ваших текущих проектах, которые явно не прослеживаются в резюме соискателя.
Собственно все, через час такой беседы вы будете уже знать все что вам нужно.
а заказчику интервью я что скажу? «я поговорил, норм чел»?
а в ответ на «ты с тремя поговорил, какого берем»?
через час такой беседы вы будете уже знать все что вам нужно
я и через час беседы по опроснику знаю все, что нужно. и еще у меня будет измеримая метрика.
или вам все кажется, что я прекрасных кандидатов сливаю? так ведь нет, знать-то они больше не начнут.
или вам кажется, что и не надо все это знать, можно так, без знаний кодить? так ведь нет, нельзя.
«я поговорил, норм чел»
Кандидат вам подходит, способен эффективно выполнять пул указанных задач.
«ты с тремя поговорил, какого берем»
Этот более силен вот в этом и этом, а у этого больше опыт в такой то сфере, а у этого признаки будущего техлида.
и еще у меня будет измеримая метрика.
метрика чего? Чтения документации? Вам тогда либо выпускников либо их преподавателей нанимать нужно, вот только обе категории — работники так себе.
Мне вот резюме джунов с метриками приходили, по разделам, удобная штука, но только для джунов, от остальных мне нужно совсем другое.
вам все кажется, что я прекрасных кандидатов сливаю
Не кажется, я уверен, если только вы не супертоповая компания с зп значительно выше рынка, тогда топовые кандидаты к вашему собеседованию готовиться начнут.
так ведь нет, знать-то они больше не начнут
о тонкостях реализации нюансов языка они будут знать меньше, о предметной сфере — много больше.
или вам кажется, что и не надо все это знать, можно так, без знаний кодить? так ведь нет, нельзя
Можно и в большинстве случаев так оно и есть. Да о чем вы, я прекрасно знаком с уровнем разработчиков одной финтех компании, софт которой используют все банки страны, скажем так: я не в восторге.
ЗЫ я вот прочел вакансию которую вы линканули, читаем «Знания и опыт использования баз данных не только через ORM (у нас есть PostgreSQL, Tarantool и Redis)». Значит разработчики сами пишут запросы, значит умение их писать весьма важно (прямо в основном блоке), у вас по этому делу — ни одного вопроса. Но уверен если бы были вы наверняка бы спрашивали устройство b-tree, gist индексов, wal, буферизацию и это вот все и это как раз то что интересно в последнюю очередь.
ЗыЗы на самом деле доказывать что либо мне вам не очень интересно, если вас так напрягают мои комментарии. Но по идее, я как раз таки тот для кого вы и проводите такие собеседования.
Вот эта мысль, что я что-то нетривиальное спрашиваю — она откуда? :(
То есть — я спрашиваю тривиальное, Но кандидаты не могут ответить?
Наглядно: если бы вы собеседовали меня, я бы ушел уже на 7ом вопросе, если вместе со мной, я бы на этом же вопросе(upd хотя не, на 5ом, если только вы не задаете их супер дружелюбным тоном от которого разработчикам легко и комфортно) перехватил у вас инициативу и дальше беседовал сам(хотя если разработчик очевидно нравится можно было бы еще несколько, если нет, зачем мучать), если для меня… оставим пока эту тему)
По-моему Вы немного забыли постановку задачи. Если бы это был собес на сениора — один разговор. Сениор должен уметь ровно то, что уже много раз упомянули в комментариях, а не то, о чём статья (но отличный сениор не будет этим себя ограничивать, и сможет справиться с большинством вопросов не напрягаясь). Но в статье чётко сказано: «найти человека, который сможет задать и поддерживать высокий уровень профессионализма в применении языка Go». Вы где-то здесь между строк прочитали слово "сениор"? Перечитайте, его там нет.
Искали либо евангелиста, либо принципала, но точно не рядового сениора таски пилить. И если сениор действительно может позволить себе не знать элементарных вещей описанных в статье и при этом быть вполне эффективным в своей роли, то для евангелиста/принципала всё упомянутое в статье знать необходимо, и многое другое тоже (в статье на самом деле далеко не все вопросы упомянуты, а только те, которые реально стыдно не ответить более-менее терпимо даже для сильного сениора).
P.S. Лично меня тоже огорчает тот факт, что сейчас вполне нормально работать сениором и даже хорошо справляться со своей работой, и при этом не знать ответы на такие вопросы. От найма таких сениоров меня это не остановит (как не останавливает и onokonem — если нанять нужно именно сениора), потому что доучить их при необходимости не сложно, но… всё-равно это огорчает. Возможно дело в том, что когда я начинал более 30 лет назад — мне было интересно само программирование, а не "таски пилить" или "крутая зарплата". И до сих пор мне интересно само программирование — поэтому я им занимаюсь вне зависимости от того, платят ли мне в данный момент, или нет. И поэтому я плохо представляю себе как можно называть себя сениором и при этом не знать элементарных вещей, описанных в статье. Ну т.е. мне — было бы стыдно. Для выполнения типичной работы сениора — да, можно многого из этого не знать. Но самому искренне считать себя "старшим разработчиком", учить других, и при этом не быть в состоянии ответить… я этого просто не понимаю, честно.
По-моему Вы немного забыли постановку задачи
Нет не забыл, я сходил по ссылочке из коментария, прочел вакансию, нашел компанию на hh и хабр карьере, посмотрел ставку и сделал выводы.
Вы где-то здесь между строк прочитали слово «сениор»? Перечитайте, его там нет.
так же нету и евенгелиста, и уровень зп на него не сильно то и намекает.
Но самому искренне считать себя «старшим разработчиком», учить других, и при этом не быть в состоянии ответить… я этого просто не понимаю, честно.
Не у всех память работает в условия стресса так как мы этого хотим. Не все способны к ответам вне контекста. Суть то как раз в том что знания эти вторичны. Я очень много встречал ребяток которые вот такие вещи знают, а нормальный код написать не могут. Да далеко ходить не нужно, я такой дичи в базах понавидался, что мне даже не смешно уже, но алгоритмы и структуры данных знают, да…
ЗЫ поймите меня правильно, я сам в ужасе от того какие прикольные люди просят с порога по 200 тысяч, но поймите так же и тот факт, что действительно крутые ребяты уж точно не будут рады допросам с пристрастием, я сам через это проходил и больше у меня нет никакого желания (делаем еще скидку на тон и формат с которым это делается). В том числе потому что я оглядываюсь вокруг и вижу кто как работает и я так же знаю как трудно найти хорошего специалиста. У меня даже есть личный подбор примеров веселых проектов вроде интернет магазина за 40 месяцев или баз данных которые еле ползают. И среди авторов этой дичи очень много людей которые легко проходят такие собеседования, а у меня от их кода facepalm непрерывно случается. Посему когда я нанимаюсь разработчиком, выбирать буду я и выбирать придирчиво, начиная с избегания вот таких допросов и очень многие разработчики которых я бы хотел нанять сделают ровно также.
ЗЫЗЫ Ну и средний 3.3 смущает дальше некуда. Знаете как говорят: «если на вопрос ответили все, это легкий вопрос, если никто — тупой». Если _средний_ показатель настолько низок то вы ищете либо не так (что тут уже попытались объяснить), либо не там (уровень зарплаты я бы не назвал мечтой).
Нет не забыл, я сходил по ссылочке из коментария, прочел вакансию, нашел компанию на hh и хабр карьере, посмотрел ставку и сделал выводы.
+1
Я лично не HH, но поспрашивал знакомую, вполне квалифицированную (я работал с теми, кого она подбирала, и мне понравилось с ними работать). Она однозначно сказала, что если открыто указать, что нужен евангелист и большую з/п — пойдёт поток самоуверенных фриков (если что, она выразилась более мягко, но я понял именно так, и здесь пишу как есть, чтобы не запутывать обсуждение ещё сильнее), которые много мнят о себе но на практике выполнять эту роль не в состоянии, а вот большинство подходящих кандидатов решит, что они этого не достойны и даже не попытаются. Поэтому такие вакансии однозначно стоит писать под сильного сениора и не более того, а реальную ситуацию и з/п описывать уже когда кандидат заинтересовался. Не могу сказать, насколько это распространённая практика или её личный подход.
Лично для меня этот подход звучит вполне здраво и вполне объясняет то, что Вы прочитали в вакансии. Синдром самозванца ещё никто не отменял, и многие крутые сениоры действительно не знают себе настоящую цену.
Кроме того «пойдёт поток самоуверенных фриков» это сейчас вообще про любую вакансию. И решение выглядит как нежелание делать свою работу, уж извините.
Сейчас икать не в столицах на позиции middle+ долго дорого и сложно. А уж какое веселье искать тимлида/cto ууух… Будет еще хуже. Потому что даже у самых упертых патриотов или особо привязанных к месту/родне/окружению начинают сдавать нервы.
В статье одно, а в вакансии — сеньор. Чем заниматься будет разработчик — не понятно. Может компания галера и разработчик будет пилить небольшие стартапы, а может поддерживать и развивать продукты с многомилионной аудиторией.
«Найти человека, который сможет задать и поддерживать высокий уровень профессионализма в применении языка Go». Мы не знаем, уточнял ли автор статьи, что под этим подразумевается, каким видит подходящего кандидата заказчик. Может автор понял по своему.
Дана задача — «найти такого-то разработчика». Деньги и время тратятся, но человек с задачей не справляется. Ладно, почему? Где анализ возможных причин? Что можно сделать, чтобы ее выполнить? Может предлагаемая зарплата низкая, может текст вакансии надо исправить?
Если же вместо анализа проблемы и предложений решения, получаем ответ вроде «причина не во мне, а в том, что все кандидаты плохие», то лично мне это говорит о том, что задачу доверили не тому человеку.
или вам кажется, что и не надо все это знать, можно так, без знаний кодить? так ведь нет, нельзя.
кодить — можно, эффективно кодить — вряд ли, разрабатывать — невозможно
или вам все кажется, что я прекрасных кандидатов сливаю? так ведь нет, знать-то они больше не начнут.
Есть в покере такой термин как Calling station. Известная штука, когда игрок все время колл делает, если у него только не супер слабая рука. И просто по частоте коллов оппоненты могут судить о том, что игрок — новичок, и плохо играет, даже не заглядывая в карты. Потому что просто статистически невозможно такое количество хороших карт. Поэтому на сайтах с покером когда люди серьезно готовятся к игре с рандомами, они смотрят % коллов, и если он большой то понимают, что парня можно развести на деньги.
Так и в вашем случае, если вам никто не подходит, но чисто статистически по крайней мере иногда должны приходить нормальные кандидаты, значит вы их отсеиваете, значит механизм отсева фиговый. Это не значит, что мы знаем как сделать лучше, это означает только что можно оценить качество отсева не статистически, не имея на руках альтернатив "что исправить".
никто не знает, что такое «хороший программист»
много кто знает. Сеньеористый программер это тот которому можно дать посредственно сформулированную задачу и получить вопросы, читаемый код и отсутствие необходимости за ним переделывать.
Это разница между джуном и миддлом.
Не про сеньора.
Чтобы спрашивать такое — нужно иметь кругозор не меньше, чем у кандидата, не так ли?
Не обязательно прямо знать все в глубину, можно понять насколько кандидат хорош по уверенности его ответов. Наверное. Понятно, что в таком случае "уверенные самозванцы" тоже пройдут. Но наверняка есть способы их тоже срезать.
Опять же — для меня главный вопрос — как не нанять токсичного мудака. Потому что ТМ может быть реально гением или рокстаром, знать все от а до я, но при этом работать с ним будет попросту невозможно.
Чтобы спрашивать такое — нужно иметь кругозор не меньше, чем у кандидата, не так ли?
конечно
Понятно, что в таком случае «уверенные самозванцы» тоже пройдут
Нет, если задать несколько вопросов вглубь.
Могу простой пример привести. Кандидат рассказывает что переводили весь проект на graphQL, ярко так, убедительно. Прошу рассказать нюансы, что доставило боль, что гереоически решили — тон уже менее уверенный. Через 10 минут спрашиваю в лоб почему не выкинули бек и не запустили graphQL прямо на Postgresql: в следующие 5 минут приходим к тому что за последний год их отдел занимался ничем. Это говорит о том, что человек делал мелкие задания без понимания зачем и почему.
и не запустили graphQL прямо на Postgresql
А что, так можно было? Вот в голову бы просто не пришло при рисече гуглить "можно ли запустить graphQL на РСУБД".
Через 10 минут спрашиваю в лоб почему не выкинули бек и не запустили graphQL прямо на Postgresql: в следующие 5 минут приходим к тому что за последний год их отдел занимался ничем
Могут быть доводы и против.
Например, нельзя напрямую отдавать наружу GraphQL из соображений безопасности — чтобы нехорошие люди не положили по сути прямыми запросами в СУБД через API GraphQL всю производительность СУБД в 0.
Другое дело, что не на уровне того человека было принимать такие решения…
Другое дело, что не на уровне того человека было принимать такие решения…
если он — член Команды, а не просто Исполнитель — он участвовал бы в обсуждении "почему так, а не иначе". Или хотя бы для успокоения своей инженерной совести разузнал это....
Собственно ваш аргумент или свой я и ожидал услышать. Выше хороший коммент с которым я согласен.
когда из его «рассказа о себе» вообще ничего толком не понятно.
Из рассказа любого айтишника мне будет вообще ничего не понятно. 2020 год, даже похожие области очень разные. Как что-то понять без специальных вопросов мне не ясно. Возможно мы с Нилом просто старые пердуны
Но тем не менее каждый из Вас работает с ограниченным набором инструментов, стэков и прочего. Утрирую, вы можете спросить кандидата как он реализовал какой-то алгоритм, уточнить детали, понять какие у него могли бы возникнуть проблемы связанные с его реализацией (вы же тоже профессионал — должны понимать предмет) — поинтересоваться возникли ли, почему по его мнению, как он их решал.
Он Вам сам все и расскажет. А если не расскажет — то это не Ваш человек.
Ну. Он работает с ограниченным набором, я работаю с ограниченным набором. И они не пересеклись. У нас только и точки пересечения — языки и возможно базовые инструменты для самых базовых вещей. Ну вот я решил с ним обсудить k8s, а он с ним не сталкивался. Тупик.
ИМХО — это дает Вам абсолютный 0 информации.
Я бы в такой ситуации оценивал человека по следующему принципу:
— посмотрел бы что за компания в которой он работал, что за продукты она выпускает, насколько они качественны и успешны (я всегда гуглю последнее место работы кандидата и смотрю что делает эта компания как минимум);
— спросил бы о его роли в разработке — что конкретно он делал. Вы же вполне способны оценить качественно — сложно это и круто, или полная ерунда и перед Вами просто юнец который рад, что смог зажечь зеленую лампочку;
— в конце концов просто пообщался бы на отвлеченные темы, чтобы понять — а как вообще, я смогу этого человека каждый день видеть на работе-то?
Попробуйте выключить учебник и использовать джедайскую силу в общем. У Вас же большой поток кандидатов вероятно — можно и поэкспериментировать.
Когда у Вас нет общих точек, то единственное что Вы можете оценить — некий общий IQ и адекватность, не более того.
если нет — пофиг, но перестаньте, пожалуйста, делать предположения о том, что именно я проверяю, и сколько это дает информации
А во-вторых, меня сложно назвать Вашим коллегой — о чем я Вас уведомил в своем первом сообщении. Я столь же далек от Вашей специфики, сколь Вы от влияния структуры плетения препрега на распространение сигнала. Поэтому переходить в позу «да кто ты такой?» — странно что ли. Тем более если Вам пофиг.
Просто вся эта возня с опросниками да еще в форме «как Вы можете не знать того что знаю я — это же азы» — выглядит, ну скажем странной.
Но мне совершенно искренне интересно какую практическую пользу для бизнеса Вы при этом извлекаете.
Во, пример из моей жизни. Я хочу обсудить разбор XML на Go и map[int]TStruct vs map[int]*Struct в применении к списку Роскомнадзора. И поговорить сразу станет не с кем. А вот топикастер не сможет поговорить со мной про линтер, я хз что это. Ну и так далее
150Mb и я хотел таки ловить его и раз в три минуты на VDS до 20$. Это оказалось не так просто. А да. Я держу его в памяти и раздаю своему боту по protobuf. Основная проблема была в 2млн IP (сейчас их нет)
Проверять на принадлежность. Выдавать метаданные согласно принадлежности. Метаданных около 200k записей. Никаких диапазонов. Разреженный массив
Да вот та прога: https://github.com/usher2/u2ckdump
Там в res два примера
И рядом лежит чем использую: https://github.com/usher2/u2ckbot
А да. 150Mb — это XML. Я хочу и быстро апдейтить. Апдейты небольшие, но мне прилетает просто новая версия в 150Mb
Мммм… И дольше, и жрет. Но легче делать. Это был первый вариант архитектуры. Я сделал иначе — там просто куча строк с уникальными Id. Я сравниваю контрольные суммы старых и новых, и делаю списки тех id, что изменились. Те id, что не появились в новом — удаляю. Те, что не нашлось в старом — распарсиваю. Те, что изменились — распарсиваю заново и заменяю на новую версию
контрольные суммы старых и новых,
контрольная сумма априори может генерировать коллизии. И не нужно говорить, что они статистически маловероятны. Корректный алгоритм vs вроде как работающий в 99% случаев.
вот поэтому. Вопросы и баллы остались в институте. А на работе задачи другие…
Мне это напомнило тестирование на сайте учебного центра «Специалист» на владение виндой. Выглядело примерно так: «какие 10 способов переноса файла с дискеты в папку вы знаете?»
Почему так? Почему опытные, квалифицированные разработчики набирают такой низкий балл?
Потому что опросник очень плохой, очевидно, других ответов тут быть не может.
Нету. Сделать хороший подобный опросник — это очень сложная задача, которая потребует длительной работы полноценного исследовательского коллектива с нехилыми бюджетами. Если решать ее методом "бездумно наговнякаю что-нибудь на коленке за пять минут" — то итог закономерен. Вместо того, чтобы проверять профессиональные навыки кандидата, опросник будет проверять кандидата на соответствие некоторой сферической в вакууме идеальной модели из головы автора опросника, каковое соответствие в общем случае с этими навыками не слишком-то и коррелирует.
https://roadmap.sh/ — неплохой ресурс оказался, кстати. Примеряю на себя и действительно — идея хорошая — определить на каком этапе такого роадмапа "к экспертности" находится кандидат.
Смотрю там на фронтенд — сплошные глупости.
Ну, поправьте — там есть гитхаб и можно сделать коррективы )
Между "предложить пулреквест" и "сделать коррективы" — пропасть.
Ага, создай свой сайт, потом сам пропиарь как следует и всё это ради… чего, собственно?
roadmap.sh — неплохой ресурс оказался, кстати. Примеряю на себя и действительно — идея хорошая — определить на каком этапе такого роадмапа «к экспертности» находится кандидат.
Посмотрел backend — это максимум для миддла.
То есть по сути для джуна чтобы видеть к чему стремиться.
Можно поправить ) Но все равно, повторяю, что это хорошая стартовая точка
там есть раздел Contribute — дерзайте
Для потенциального сеньора это не полезный ресурс.
Готовый к выходу на этот уровень уже сам представляет, без подобных сайтов. Иначе он еще не готов стать сеньором.
P.S.:
Сейчас не рассматриваю ситуацию, когда лычку сеньора тебе дают через 3 года с начала программирования просто потому чтобы твоё тщеславие побаловать, а зарплату не добавлять.
сделайте его полезным для тех, что в будущем станет сеньором
> Готовый к выходу на этот уровень уже сам представляет, без подобных сайтов.
когда есть карта в руках легче двигаться к цели
сделайте его полезным
Ради чего? Если я не согласен со всей концепцией этого сайта для сеньора.
ну тогда создайте сайт с правильной концепуией для сеньора
Вот ведь какой вы любитель халявы…
Зачем мне на это тратить ресурсы?
Ради вас?
Незачем.
если вы так дорожите своими ресурсами, то почему вы их в пустую тратите на комменты?
Это несравнимо:
1) Я потратил на коммент 10 секунд.
Вы же теперь утверждаете: «ты потратил 10 секунд, то потрать и 5 дней на разработку роадмапов — это же одно и то же».
Вы серьезно?
2) Может быть вы и работаете бесплатно. А я не практикую такое.
В комментах идет оплата эмоциями: я получаю удовольствие от прямого общения.
А чем вы мне оплатите за роадмапы?
P.S.:
Как и любой человек халяву я тоже люблю как и вы.
Но при этом терпеть не могу халявщиков наглых. Которые не просто берут то, что им добровольно предлагают. А еще и носом воротят и что-то требуют зарвавшись в своей наглости, что мол им «должны» дать ништяки независимо от желанию дающего.
Пользоваться источниками, которые вам добровольно предоставляет автор — это одно.
А требовать, чтобы кто-то для вас что-то сделал бесплатно — это совсем другое.
вам не надо 5 дней на разработку роадмапов
>> Вы же теперь утверждаете: «ты потратил 10 секунд, то потрать и 5 дней на разработку роадмапов — это же одно и то же».
вам не надо 5 дней на разработку роадмапов
Ну так если вы это настолько точно знаете — то вы и составьте.
Не?
Другие все должны для вас делать? Ваша работа только царственным слогом написать приказ «сделай»?
а не занимаюсь ни фронтендом ни бэкэндом
а не занимаюсь ни фронтендом ни бэкэндом
Но надо полагать по своей области вы уже составили роадмап для желающих? Где его можно посмотреть?
ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B5%D1%82%D1%8C%D1%8F_%D0%9F%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0_%D0%9A%D0%9F%D0%A1%D0%A1
Вот так удобнее см. ту ссылку, что вы привели: Третья Программа КПСС, 1961 г.
Тег «a href» здесь комментах можно использовать.
но я работаю над этим!
Образование — это игра в долгую, и подходить к нему надо с другими критериями, нежели к очередному «Проверим идейку MVP».Казалось бы, при чём здесь образование…
Наверное об этом уже писали:) С июля нет человека, но опрос продолжается) не хочу показаться грубым, но им вообще нужно чтобы человек работал или им важно чтобы когда-то к ним пришёл го-гуру? ну и наверное вы знаете много людей, которые подходят под эту вакансию, но они почему-то не бегут аплаиться. Наверное что-то тут не так)
проблема вероятно не в квалификации в целом, а в завышенном ЧСВ у кандидатов — по крайней мере действительно многие переоценивают свои возможности, но это не отменяет существование ПРОФИ и ПРОФИ, которые недооценивают себя (таких тоже знаю). Это раз. Два — выше, как говорили, для решения большинства бизнес-задач знание проблематики вышеупомянутых вопросов, к сожалению, не нужно, и будучи эффективными в работе, разрабы могут не пройти Ваш тест. Коллеги это уже неоднократно отмечали.
но я лично не думаю, что у кандидатов что-то завышенное и/или неадекватное.
со своей работой они справляются ведь? справляются!
а вот то, что они мой тест пройти не могут — свидетельствует о перекосах в системе знаний, которые хорошо бы ликвидировать. благо, это не трудно.
ну или трудно, потому, что требует смены парадигмы самообраовательной
Вопрос кто должен этот перекос ликвидировать. А сначала детектировать.
Пост подразумевает, кажется, что и выявление перекоса и его ликвидация — ответственность самого разработчика. И уж точно не работодателя, его собеседующего. Топикстартера огорчает, что ему приходится констатировать наличие перекосов.
ликвидировать должен кандидат — больше-то ни у кого доступа нет.
А представляете себе подобный автоматический онлайн-детектор? Чтобы в вакансии бросить сыслку на него и дописать "если не можете пройти на 80 из 100, то не тратье своё и наше время?"
именно эту автоматизировать, скорее всего, не удастся (и я говорю об этом в докладе)
У компании уменьшилось бы количество неподходящих кандидатов. А кандидаты смогли бы сэкономить время, оценив адекватные ли вопросы у компании или там спрашивают всякую чушь, которая или никогда не пригодится или которую помнить нереально.
А есть какой-то стандарт, что должен знать сеньор? Хотел бы на него посмотреть) в одной компании сеньор может быть мидлом в другой. Разные задачи же. И люди хотят расти и аплаятся на вакансию выше рангом, что тоже хорошо. В общем из какой-то выборки интервью в одной компании сделать вывод о том, что вокруг нет знаний как-то немного преждевременно, мне кажется. Может просто никто не хочет туда идти из тех, кто мог бы:)
а сеньор в какой области?
Да в любой ит-шной.
В любой, которая меняется, ладно:) хочется опровергнуть чтоли и найти область, в которой есть золотой стандарт?:) да в целом мне все равно даже если такая есть) не вижу смысла спора)
en.wikipedia.org/wiki/Software_Engineering_Body_of_Knowledge
Супер! Наверное как раз оттуда были все вопросы в данной статье:) и каждый на собесе это спрашивает, «стандарт» же!
Профессиональные стандарты, разве что.
А есть какой-то стандарт, что должен знать сеньор?
это тема отдельной большой статьи.
если коротко, то — да, есть набор знаний, умений и навыков, который обязателен для любого сеньера. и, по моим оценкам, на 70% это один и тот же набор для любого языка.
но формализованного описания я пока не видел. возможно — про это будет следующая статья :)
Что же до выборки и выводов — я делаю вывод только о неудачном для нанимателя и кандидата перекосе в системе знаний кандидата.
опросник не создавался для выявления перекоса, но, как оказалось, довольно чутко на него реагирует.
Простите, коллега, но практическая польза конкретно от этого списка, хоть в качестве роадмап для обучения, хоть в качестве проверки уровня знаний, если брать по 10-ти балльной шкале — в районе абсолютного нуля (т.е. −273).
А потом ещё и performance review раз в квартал, а то вдруг забыл чего. И ещё каких-нибудь проверок знаний и чтоб не менее одного выступления на конференции. С процессами всегда все хорошо, это с квалификацией всегда проблемы:)
Одновременно и грустно и смешно.
Я бы скорее назвал статью "коллеги, мне грустно от того, что вы в массе своей плохо умеете готовиться к собеседованиям" ;))
Я себя не позициюнирую как Go разработчика, не работаю Go разработчиком, хотя считаю, что на уровень Middle претендовать вполне могу (несколько pet проектов именно на go, в том числе и с задачами на производительность).
Так вот, на 2/3 вопросов в режиме "здесь и сейчас" я ответить не смогу. На подкорке мгновенно мозг ответил только про каналы, sync.map, профайлер, да про логгер.
А что самое интересное — почти по всем вопросам я в своё время детально разбирался (разве что во внутренности структур не лез руками, но читал про них), очень многие вещи есть в моём коде, который я осознанно писал.
Ну то есть я готов дать осознанный ответ, но если мне дадут на каждый вопрос несколько минут покопаться в собственном коде и повспоминать ;))
Вот даже про подключение профайлера — не помню я, как его подключать, хотя подключал и использовал.
Единственная разумная мысль — разработчикам очень сложно держать открытый контекст по огромному объёму знаний. У большинства кандидатов нужные знания, как мне кажется, есть, но они убраны на дальнюю полку и вернутся только в случае, когда они реально нужны. Если у меня встанет вопрос сделать нечто производительное, то извините, но мне нужен минимум час (а скорее всего заметно больше), чтобы накидать на бумаге нужные схемы, архитектуру и в процессе нужные знания подтянутся.
p.s. Даже вопрос про доступ из нескольких горутин к []byte тоже спорный — да, лучше, к примеру, каналами, но если представить, что это общий вопрос, то на месте []byte может оказаться мапа, к которой нередко нужен доступ из множества горутин (и не всегда тут синкмапа подойдёт). И тогда кандидаты будут отвечать не на вопрос "нафига вообще лезть к []byte", а на вопрос "как обеспечить одновременный доступ к разным объектам, если считаем, что такой доступ точно нужен".
Роб Пайк недоволен опом, ведь он разрабатывал язык для макак, которые не задаются вопросами типа "Есть ли для Go хороший orm" или "Какой у вас любимый линтер". там 100 страниц спецификации и 50 бест практис, это все что нужно знать.
7. Каков порядок перебора map?
Самый популярный неправильный ответ: «В порядке вставки». Хеш-таблица, которая сортирует элементы в порядке вставки, ага. А как в ней происходит выборка по ключу в таком случае?
Если взять для примера Java с его JVM, то одна версия отдает обход по дереву, а другая отдает по вставке, вне зависимости от формирования дерева. Один и тот же обход map на мобилке и десктопе будет работать по разному.
Возможно в Go есть подобные штуки.
Так что это вопрос из серии «угол заточки стамески».
Возможно, она поможет вам лучше подготовиться следующему собеседованию.
а смысл, если ответы на вопросы выше гуглятся за 5 минут при нормальной техбазе. У вас вопросы по Go, а не по тех базе специлаиста.
Стандартный набор метрик prometheus в Go -программе?
кто бы помнил, 1 раз делается дашборд и носится из проекта в проект, а смотрят в этот дашборд уже как раз «эти девопрсы».
смотрите, эти вопросы я придумал как раз для проверки нормальности техбазы. если кандидат хочет что-то погуглить во время собеса — я никогда не против. просто задам чуть больше вопросов именно на базу.
дашборд — это вообще не про это (и это часть вопроса)
7. Каков порядок перебора map?
Самый популярный неправильный ответ: «В порядке вставки». Хеш-таблица, которая сортирует элементы в порядке вставки, ага. А как в ней происходит выборка по ключу в таком случае?
Если взять для примера Java с его JVM, то одна версия отдает обход по дереву, а другая отдает по вставке, вне зависимости от формирования дерева. Один и тот же обход map на мобилке и десктопе будет работать по разному.
Возможно в Go есть подобные штуки.
Так что это вопрос из серии «угол заточки стамески».
Правильный ответ — порядок не гарантируемый, полагаться на него нельзя.
Я как-то думал есть там закономерность или нет.
Проверил.
Оказалось, что при обращении к одному и тому же мапу порядок перебора может меняться.
Деталей не помню, то ли после перезапуска программы то ли еще какая погода на Луне влияет.
Но в спецификации языка порядок вам не гарантирован. И так оно и есть.
Гарантировано только что вы можете обойти весь мап.
Так что это вопрос из серии «угол заточки стамески».
Вы вот напрасно так пренебрежительно.
Угол заточки принципиально важен.
Из того, с чем вы можете лично столкнуться: посмотрите форму свёрел по металлу, по дереву и по бетону. Они сильно разные. Одно сверло вообще не способно решить вашу проблему в другой ситуации.
С поиском далеко не всегда всё так плохо. Чаще опирается только в оценки О(). То есть вы можете использовать и другой алгоритм. Просто он будет медленным.
Другое сверло вы использовать не сможете, вообще никак.
Собеседование сениора это обычно разговор по душам и предложение спроектировать пару-тройку сервисов. А спрашивать "на какой странице документации описана вторая перегрузка третьего логгера" во-первых некрасиво, во-вторых глупо, если это гуглится за 5 наносекунд. А оно всё примерно за это время и гуглится. С другой стороны "какой трейдоф при проектировании распределенной международной системы с учетом пиков чтений вот с такой периодичностью и таким соотношением чтений/записи, при необходимости собирать такие-то метрики" за минуту в гугле не найти.
А в данном случае, насколько я понял автора, требовалось оценить именно объём погружения в конкретную технологию
Так вот в дискуссии я выявляется уровень знаний хорошо. Ответы на классические вопросы можно и заучить, а вот полноценно обсудить достоинства и недостатки и опыт нужен, и качественные знания. Уровень задачи на "поговорить" можно брать разный, например, чтоб в конкретную технологию помещалась.
Как выше написали, имено дисскуссия и является собеседованием. А не ответы из решебника.
Ещё веселее если собеседуемый пришёл из другой области, и слабо знаком с устоявшимися практиками (хотя тут можно порассуждать о том, правильно ли нанимать такого сениора)
Из какой другой? Вопрос как я выше сформулировал можно задать для любого стека и любого яызка, тут вообще ничего языко-специфического нет. Если же под "другой сферой" имеете в виду из слесарей, то тогда наверное трудно без подготовки сразу в сениор девелоперов прыгать.
Как выше написали, имено дисскуссия и является собеседованием. А не ответы из решебника.
Это звучит как аксиома, но на самом деле не является таковой. Всё определяется условиями, и в каких-то случаях именно вопросы на понимание инструмента и знание деталей его реализации актуальнее дискуссии
Из какой другой? Вопрос как я выше сформулировал можно задать для любого стека и любого яызка, тут вообще ничего языко-специфического нет.
Из геймдева, например. Или человек драйвера писал. Ну не было у него распределённых систем. Вроде не слесарь при этом
Что я хочу оценить: насколько кандидат склонен к написанию «велосипедов».
Я верно понимаю, что 9 на вопрос
Сколько времени в минутах займет у вас написание процедуры обращения односвязного списка?
можно получить за ответ «0,47 секунды — за столько гугл выдает мне невелосипедное решение»?
2. можно попробовать. за сколько вы реально это нагуглите? и что вы нагуглите? хронометрируйте, показывайте, будем смотреть
Я это реально загуглил за 0,47 секунды. Не верите джентльменам на слово?
Я бы, честно, воспользовался первой же ссылкой, но интересно будет услышать Ваше мнение по, например, вот этому варианту.
Это я специально ограничения соблюдал с нагуглить. Для велосипедов у меня отдельная закладка есть (считаем время за 0?). Можете и ее прокомментировать, очень любопытно.
вариант хороший
а закладка вообще шикарная.
и то, и другое потянет на 9
p.s. Рад, что закладка понравилась. Всегда делюсь ей с удовольствием!
- Где следует поместить описание интерфейса: в пакете с реализацией или в пакете, где этот интерфейс используется? Почему?
Оба варианта плохи, если нет какой-то специфики у Go, красиво решающую ситуацию "много пакетов с реализацией интерфейса, ещё больше пакетов использующих этот интерфейс с реализаций, которую клиент или бутстрап предоставит.
P.S. Прочитал вакансию. Выглядит так, что, с учётом этого поста, можно подготовиться за пару месяцев по вечерам и віходным на такого сеньора, если немного покривить душой и сказать, что опыт на Go есть. Или убедить начальство попробовать Go для сервиса-другого и сильно переинженерив их. Главное туториал хороший найти по "ентерпрайз" разработке на Go. Я в своё время не смог. Вообще, кажется неудачное время выбрал для входа в Go, как раз выход модульной системы новой, как я понимаю.
go не про энтерпрайз разработку. go — про смузи-хипстеров и 20-летних синьоров
Ну, у Go такая специфика как раз есть, в виде отсутствия явной директивы реализации интерфейса. Поэтому, если интерфейс используется всего в одном пакете — ему самое место именно там и быть объявленным.
Третий пакет понадобится только в том случае, когда у интерфейса несколько потребителей, либо если вы собираетесь в пакет с реализацией добавить тест на соответствие реализации интерфейсу. Но последний вариант противоречит идеологии языка Go, и если появилось желание так сделать — пора задуматься от переходе на какой-нибудь Rust или хотя бы C# :-)
Но последний вариант противоречит идеологии языка Go,
Не совсем. Надо — добавляйте. Просто никто не заставляет клиентов использовать именно то объявление интерфейса, которое Вы добавили в пакете с реализацией. Плюс, если надо проверить соответствие реализации интерфейсу — никто не мешает тип интерфейса сделать не экспортируемым, раз это чисто для самопроверки, и никто его даже не увидит.
Делать его неэкспортируемым смысла нет никакого, потому что цель проверки — гарантировать что у пакета-потребителя не будет проблем с использованием интерфейса, а для этого пакет-потребитель к интерфейсу должен иметь доступ.
В Go не так. Пакет-потребитель не должен иметь доступа ни к каким интерфейсам, ему нужен доступ только к реализации. Интерфейс, подходящий для этой реализации, пакет-потребитель в состоянии нарисовать себе сам, более того, именно это рекомендуется делать в большинстве случаев (в основном — с целью максимально сузить интерфейс до реально используемого данным потребителем).
Не то, чтобы лично я видел много смысла в вышеупомянутой самопроверке на соответствие интерфейсу, но вреда от неё ровно ноль, так что если кому-то для самоуспокоения она кажется необходимой — он может её реализовать. И если в то же время он не хочет выставлять реализованный интерфейс наружу, напр. потому, что ему кажется что это "противоречит идеологии Go", то он может сделать его не экспортируемым и не выставлять. Да, всё это больше психологические моменты, а не технические, но мы же люди, а не роботы, так что такое тоже иногда полезно.
Вы издеваетесь, или правда не замечаете, что в одном комментарии дали два совета, которые взаимоотменяют друг друга?
Нет совершенно никакого смысла в проверке соответствия неэкспортируемому интерфейсу! Эта проверка имеет смысл ровно в одном случае — когда есть гарантия, что "проверочный" интерфейс совпадает с требуемым.
Вот мне больше делать нечего, кроме как издеваться, ага.
Никаких противоречий тут нет. В Go никто не ожидает, что пользователь библиотеки будет использовать именно тот интерфейс, который объявлен в самой библиотеке (более того, в большинстве случаев в библиотеке никто этот интерфейс даже не заморачивается объявлять). Библиотека может предоставить этот интерфейс, чисто как опциональную фичу для удобства некоторых пользователей.
Тем не менее, особенно учитывая тот факт, что интерфейс в самой библиотеке может и не быть объявлен вообще, авторы библиотеки вполне могут хотеть иметь гарантию, что она реализует вполне определённые интерфейсы — как свои собственные, так и чужие (для совместимости — напр. хочется чтобы моя библиотека логгера была совместима по интерфейсу с логгером из стандартной библиотеки). Или, другой пример, нужна совместимость с определённым внешним API, реализация которого может быть в другом пакете/репо, и хочется чтобы джун нечаянно её не сломал — в таком случае объявить локально "желаемый" интерфейс, которому должна соответствовать наша реализация — вполне может быть удобно. Делать его при этом экспортируемым — вовсе не обязательно, всё-равно он никому снаружи может быть не нужен.
По факту все эти объявления интерфейсов не делают вообще ничего, помимо того, что при попытке их нарушить мы моментально получим ошибку компиляции. И всё. Считайте, это просто такой линтер. Добровольный. Не имеющий никакого отношения к пользователям библиотеки.
Вот есть снаружи интерфейс:
type Foo interface {
bar(name string)
}
Я в библиотеке пишу его реализацию:
type Baz struct { }
func (*Baz) bar(id int) { }
И, чтобы убедиться что я реализовал интерфейс правильно, делаю как вы сказали:
type Foo interface {
bar(id int)
}
...
var _ Foo = new(Baz)
Ну и внимание вопрос: нафига была эта проверка, если ошибку она не отловила?
То есть каждый потребитель рисует сам себе интерфейс, который нарисован и в каждой реализации? Допустим, что интерфейс и так минимальный и используется потребителями по принципу всё или ничего.
Зачастую — да. Но не обязательно. Библиотека может предоставить интерфейс. Пользователь библиотеки может им воспользоваться, чтобы не писать его ручками, а может и проигнорировать и написать ручками.
Причина игнорировать предоставленный библиотекой интерфейс в том, чтобы избежать прямой зависимости от пакета библиотеки.
А если как в других языках, общие интерфейсы, у которых заведомо много реализаций будет (DBAL например), выносить в отдельные пакеты? Совсем не go-way?
Go-way здесь заключается в том, что:
- Интерфейс не привязан к реализации, вообще никак. Это важно и круто. Язык даёт нам это из коробки, и go-way тут в том, чтобы не пытаться прибивать их обратно гвоздями друг к другу ручками, по привычке из других языков.
- Пользователям рекомендуется принимать внешние зависимости в виде минимального интерфейса, описывающего только то, что реально использует данный конкретный пользователь (что зачастую понимают как "пользователь должен сам объявить нужный ему интерфейс", но это не так — если где-то уже объявлен подходящий, то его использование ничем не противоречит go-way).
Конкретные примеры из стандартной библиотеки:
- минимальные интерфейсы (буквально из одного метода) вроде io.Reader уже объявлены и рекомендованы к использованию (хотя объявить свой такой же никто не мешает, и он ничем не будет отличаться в использовании от стандартного, но это просто лишняя бессмысленная работа и так обычно никто не делает);
- а вот например библиотка log никакого интерфейса не объявляет, хотя очевидно же, что всем нужен логгер, причём полезно иметь возможность его подменять или мокать, а для этого очень бы пригодился интерфейс — потому что большинству её пользователей обычно нужны не все её методы, и даже не большинство, а один-два (и, соответственно, альтернативному логгеру обычно достаточно реализовать для совместимости со стандартным логгером только часть методов — да, это не сделает его 100% совместимым, но для большинства пользователей логгера — которые, в соответствии с go-way, принимают параметром минималистичный интерфейс логгера содержащий только нужные им методы — такой сторонний логгер окажется вполне совместимым со стандартным).
общие интерфейсы, у которых заведомо много реализаций будет (DBAL например), выносить в отдельные пакеты?
Прошу прощения, отвечая на последний вопрос я упустил из виду предыдущий.
Выносить в отдельный пакет такие интерфейсы можно. Но так обычно не делают, не потому, что "не go-way", а потому, что просто не нужно:
- Одна из основных причин вынести такие интерфейсы в отдельный пакет в том, чтобы можно было импортировать пакет с интерфейсами, не создавая при этом зависимости от пакета с реализацией. Но в Go, в большинстве случаев, пакет это часть модуля, а модуль это одно репо, и импортируя пакет мы получаем зависимость от всего модуля/репо. Соответственно, чтобы в этом подходе был реальный смысл, нам нужно целый отдельный репо завести под такой "общий интерфейс".
- Чтобы имело смысл так заморачиваться, нужно чтобы импортировать этот пакет ради интерфейса было заметно проще, чем набрать этот интерфейс ручками по месту использования. А это подразумевает, что интерфейс этот — большой и сложный. Что таки уже начинает противоречить go-way, если пользователь реально использует только подмножество этого интерфейса, как чаще всего и бывает.
Самый популярный неправильный ответ: «Встроенный в Goland». Come on!, там нет линтера, там — тривиальный syntax checker!
Вот сейчас обидно было...
то, что находит goland, полезно и важно.
но и половину не перекрывает того, что находит правильно настроенный golangci-lint
в первую очередь потому, что goland должен быть быстрым
И да, и нет. Большинство проверок в линтерах достаточно просты, и при правильной реализации на производительность не влияют. В то же время, мы никогда не ставили своей целью перетащить к себе все. Обычно мы стараемся добавлять наиболее полезные инспекции, к которым можно сделать квикфиксы. И мы всегда рады фидбеку, чего именно не хватает ;) В любом случае, наличие control flow, data flow и nilness анализаторов позволяется мне не согласится с утверждением про "тривиальный syntax checker".
а про «тривиальный чекер» — это я в полемическом запале, да :)
хотите — дам где-нибудь опровержение?
чем не знать, что бывают простые реализации хеш-таблиц, которые итерируются в порядке вставки
И правда. Не поделитесь ссылочкой на такую реализацию? Вот чтобы прям как вставляли элементы, в том же порядке их обратно получить… и чтобы при этом это не массив/список был, а таки хеш… и реализация чтобы простая.
Но ведь это же не хеш. Если я правильно понял, то по сути мы в хеш вставляем элементы linked list, плюс ещё отдельно храним указатели на голову/хвост этого linked list. Да, этот linked list формируется на лету операциями добавления/удаления из "хеша", но, по сути, мы просто держим элементы в двух, никак не связанных между собой, структурах данных. Я к тому, что операция "итерирования по хешу" работает вовсе не по хешу. И я бы не стал называть такую реализацию "простой" — потому что некорректно называть "простым хешем" то, что является "обычным хешем" плюс ещё одной структурой данных в довесок.
Лакмусовая бумажка, позволяющая убедиться, что это две несвязанные структуры: если мы выкидываем саму хеш-таблицу (массив корзин), то все наши элементы по-прежнему доступны, можно их добавлять/удалять/итерировать через те самые "две ссылки"; если мы выкидываем эти "две ссылки", то мы имеем ту же картину, все элементы доступны, можно их добавлять/удалять/итерировать (только уже в неопределённом порядке).
Вообще наш человек так воспитывается со школы: включай смекалку, учись списывать, не забивай лишним голову. В школе ещё полностью учатся профильные предметы, т.к. по ним будет конкуренция при поступление в вуз, но в вузе можно уже на всё забить кроме программухи, ведь оценки у нас никто не смотрит нигде. На западе ситуация иная, там не понимают когда человек списывает, учит только то, что ему сейчас нравится и диплом в котором 90% троек на руки не дают. В итоге имеем то, что имеем, самых смекалистых синьёр стекоферфлоу девелоперов, которые с удовольствием поучатся азам за счёт заказчика при необходимости, необходимость эта конечно может растянутся на многие месяцы переделок. Мне бы на месте заказчика такое конечно не очень то и нравилось.
Есть вопрос по поводу пункту 14, а именно Fatal ошибки. Под fatal подразумевается deadlock, out of memory , out of index и тд или просто серьезные ошибки, после которых надо закончить функцию/горутину?
Так как если это именно fatal ошибка (например deadlock), то как вообще можно делать какой-то дополнительный детализированный вывод помимо стандартного?
Собесите разработчика на языке, для которого самый подходящий девиз - "просто бери и пиши бизнес-логику не думая о том как оно работает", и удивляетесь что разработчики не знают как оно работает.
Пока вы теорию учили, они компаниям деньги зарабатывали
Была с двух сторон баррикад. Собесила людей с 5ти летним опытом разработки, которые при онлайн кодинге гуглили как написать конструкцию switch. Поэтому согласна, что нужно спрашивать теорию. Не сильно погружаться в кишки, но определенный уровень знаний должен быть. Но до их пор против задач с LeetCode.
По сути собеседование я уже давно воспринимаю как экзамен. И да - я сама с ходу не пройду собес. Обычно 1-3 собеса идут как тестовые, чтобы понять что сейчас в тренде по вопросам.
Конструкция switch во всех языках примерно одинаково выглядит.
Но собеседование это не экзамен!
Да, это так. Но как я и написала - к сожалению сейчас это так. И мне тоже не нравится, когда меня собесят, то вынимают всю душу. Все что я знаю и не знаю.
У нас нет такого понятия как разряды. Нет оф. экзаменов, например, как у учителей и у врачей, чтобы присвоить определенный разряд. И он был бы общим для всех работодателей.
Именно что примерно, там бывают незначительные отличия которые всё портят. И ещё бывают IDE, которые своей "помощью" не оставляют шансов вспомнить нужный синтаксис методом тыка.
А когда в языке есть одновременно switch expression и switch statement с разными синтаксисами — то и вовсе забыть одно из них совершенно нормально.
А если человек привык пользоваться if/else if/else, а не switch?
Я и такое встречала. 5 или 6 if/else подряд. Согласитесь это слишком.
Ну и довольно часто приходится использовать switch. Это наоборот как-то странно, если человек его не использует совсем.
По мнению ряда разработчиков, switch - антипаттерн, который нужно заменять полиморфизмом. Но при лайвкодинге полиморфный код особо не получится писать, поэтому могут использовать if-ы, как более привычные.
Ничего странного, учитывая что вложенные else-if прекрасно вытягиваются в цепочку на большинстве языков, и дают скорость не хуже switch в общем случае (а частный случай, когда switch и правда важен, наступает раз в 5 лет).
Не согласимся, 5 или 6 if/else подряд проще понятнее и безопаснее.
Офигенный вопрос кстати. Прямо к опроснику выше. И ведь на него есть ответ. Ответите?
Не уточнила - это был онлайн кодинг и он сам начал писать такую конструкцию. По сути его никто не заставлял.
где-то выше есть коммент трехлетней давности про то, что собес должен выявлять не слабые, а сильные стороны кандидата.
в этом смысле этот опросник не очень хорош (я в нем разочаровался за эти годы :) )
но никаких подходов лучше я пока не придумал
в том же разумном комменте выше изложен их подход к собесу, и их собес - дико дорогой, массовый найм с их подходом обеспечить невозможно.
Парни, вы издеваетесь? Я специально набросал Вам план по подготовке, а Вам лень даже дойти до ближайшего собеса?
найти человека, который сможет задать и поддерживать высокий уровень профессионализма в применении языка Go
Я считаю, что профессионал не откликнется на такую вакансию, так как подразумеваемый результат не имеет никакой практической ценности. Это, извините, какой-то онанизм. Профессионал должен решать задачи, а не поддерживать навыки владения одним инструментом.
В этом месяце у меня было наверное одно из лучших технических интервью - на позицию Senior/Техлид примерно.
Сколько было технических вопросов? - 0.
Поговорили просто про мой опыт в других компаниях на протяжении около 15 лет - что где и как делал.
Раз уж этот пост внезапно всплыл через несколько лет, то
Каков порядок перебора map? Самый популярный неправильный ответ: «В порядке вставки». Хеш-таблица, которая сортирует элементы в порядке вставки, ага.
Ага, а вот в JavaScript именно так: есть map, который
как минимум в одной из реализаций (V8), когда я последний раз туда смотрел, реализован на hash-таблице,
и перебирается в порядке вставки т.к. спецификация явно этого требует: https://262.ecma-international.org/6.0/#sec-map.prototype.foreach "Map.prototype.forEach ... Repeat for each Record ... in original key insertion order"
Описание алгоритма реализации такого hashmap: https://wiki.mozilla.org/User:Jorend/Deterministic_hash_tables
как мы понимаем - это не map, а более сложная структура данных, которая включает в себя собственно map и linked list
"Собственно map" уже включает в себя какое-то количество (по числу бакетов) linked list или вообще деревьев, как в https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/HashMap.java
Конечно, сложность - субъективная оценка, и формально добавление одного linked list - это усложнение структуры, но IMHO в конкретно этом контексте нет смысла писать "это более сложная структура данных, там ведь ещё и linked list".
Имхо, если интервьюер не может на основании разговора о предыдущем опыте выяснить что может и понимает кандидат, где у того пробелы, подходит ли тот по уровню для проекта и команды или нет, то это слабый интервьюер (к сожалению, таких очень много). Все эти многочисленные вопросы чисто теоретические и показывают лишь насколько кандидат готовился к собеседованию, и хорошо подходят лишь для джунов.
вот что лишь для джунов - это правда
но когда кандидат в сеньеры не может на джуновые вопросы ответить - это тоже что-то значит
но когда кандидат в сеньеры не может на джуновые вопросы ответить - это тоже что-то значит
Обычно это значит что интервьюер мудак.
Обычно у каждого интервьюера в голове свой список вопросов, которые считать джуновыми. И так как, в отличие от экзамена, официальной программы нигде нет, то всегда можно попасть на такое незнание или забывание по причине неиспользования даже у мегасеньора.
"найти человека, который сможет задать и поддерживать высокий уровень профессионализма в применении языка Go"
Звучит (в купе с содержимым и размером опросника), как поиск человека не на конкретные проекты, а в так называемый "Офис языка GO" по аналогии с "Проектным офисом", который не реализует конкретные проекты, а следит за корректностью и (возможно?) эффективностью применения практик управления проектами.
В своей практике найма я разделял разработчиков на "инженеров", которые могут решать задачи клиентов, системно мыслить, и на "кодеров", которым нравится именно кодить решения, искать "красивые" в их понимании формы записи решений на языке программирования. Совмещение и того и другого в одном человеке не так уж редко, но бывает. Опросник в этой статье больше подходит для отбора "кодеров", на мой взгляд.
кажется, я так и написал в преамбуле: нужен был человек, который задаст планку для гоферов в компании
Согласен. Я старался ответить тем, кто в комментариях выражал разочарованность Вашим разочарованием, которое, в свою очередь, мне показалось преувеличенным, так как "кодеров" нужно существенно меньше, чем "инженеров".
Ощущение такое, что получилось "из пушки по воробьям". Но качество Ваших опросника и статьи меня восхитили!
Думаю, численность "Офиса языка GO", может состоять из 1-2 человек, проводящих семинары для "инженеров" и, возможно, ревью кода. И тогда им нужно обладать еще массой других качеств, уже даже не технических.
Автор статьи, имхо, мог просто написать, что ему нужны реинкарнации Майка Росса из сериала Форс-мажоры.
Кажется дело в том, что это Go, он специально создан чтобы бацать не думая и обучать программистов как можно меньше. И сделан сам по себе (дизайнерски) абы как
Программировать на нём всерьёз сложно, потому что ну как можно сделать недо-С с сборщиком мусора и продвигать это как современное решение всех проблем?
О да, Пайк, Керниган и Ритчи известны своим подходом "абы как" к продуктам. И языкам в частности :) Ну хоть немного за речью-то следите :)
Аппеляция к авторитетам, которые к тому же неособо причастны к созданию этого языка. Которым всем по 90 лет и всё что они делали это что-то связанное с unix на С и собственно сам язык С, как же у них мог выйти полу-С с сборщиком мусора...
https://youtu.be/ql-uncsqoAU?si=7hdmkd3ttc6X7IrE
в смысле - вы просто не в курсе, коллега
Я на самом деле согласен, что просто апелляция в авторитетам - это чушь полная. Но я намекаю, что за этой апелляцией стоит целая предыстория.
средний балл по опроснику — 3.3 по шкале 0-9
Таки а шо вы хотели? Последние годы из всех утюгов вещают "качайте софт-скилы". Сейчас чтобы работать программистом, уровень английского хотят C1 -- рынок требует софтскиловых 3.14-здунков
Есть ещё один момент. Я некоторое время наблюдаю оду анскилу (раз, два, дальше лень, но такого навалом). Статьи об этой тенденции я ещё не видел
Короче, дальше лучше не будет. Может, пора писать статьи "Как выйти из айти"?
В каментах, кстати, проскакивает правильная мысль, что язык - это всего-лишь инструмент. И программист просто им пользуется. Коллеги, а вы по инструменту, по которому у вас "горячие" знания сможете ответить на подобный опросник? Как в вашем последнем инструменте устроена мапа? Инструменты абстрактного программирования? Параллельное и конкурентное программирование? Пакеты? Какой линтер и почему? Вы вообще что-нибудь знаете об отвёртках в своём строительном чемоданчике кроме названий брендов?
Можно своё мнение прибавить, как взгляд с соседней колокольни? По ходу работы постоянно сталкиваюсь с разработчиками и с результатами их труда. Это основная часть моей работы. Сам себя разработчиком не считаю, хотя постоянно пишу тот или иной код (HCL, CI/CD, скрипты автоматизации), изучаю техническую литературу, которая иногда заходит в область разработки. Каюсь, периодически пишу на Go. Этим всего лишь хочу сказать, что совсем не далёк от темы разработки и подробностями, связанными с этим.
Уже который месяц подряд наблюдаю как команда с дюжину разработчиков пытается осилить проект на описываемом языке программирования. И вот что вынес в качестве наблюдений за командой разработки:
Go — императивный или декларативный?
Не поверите, многие уверены что функциональный
Что будет, если читать из закрытого канала?
Что будет, если писать в закрытый канал?
У нас проект пока в стадии разработки, поэтому пока не до каналов и что с этим связано. Если надо, будем потом необходимое внедрять (с)
Главный недостаток стандартного логгера?
Стандартный логгер для некоторых был открытием
Есть ли для Go хороший orm?
Короче, есть GORM, его берём. (с)
На попытки уточнить данный выбор относительно других, был просто проигнорирован. Мало ли чего знаю, им виднее
Какой у вас любимый линтер?
С большим трудом своей командой протолкнули линтер в CI. Но жить ему там похоже не долго
Способы поиска проблем производительности на проде?
Ну что за вопросы? Для этого есть специальная команда эксплуатации. И с данным мнением встречаюсь вообще на протяжении многих проектов
Стандартный набор метрик prometheus в Go -программе?
Прометей это вотчина девопсов или команды эксплуатации либо мониторинга, если таковая есть
Какие технологические преимущества языка Go вы можете назвать?
Наводящие вопросы: чем отличается goroutine от OS thread?
Тут мы попадаем на очень зыбкую почву многопоточности, и всеми связанными с этим познаниями. Что такое поток исполнения, где именно он исполняется и отличие его от процесса. Отдельная тема (неплохо раскрытая Тоненбаумом) варианты реализации многопоточности (в контексте пользователя, в контексте ОС, гибридная). И то что многопоточность и асинхронность это совершенно разные вещи. Но это уже отдельная боль.
И когда по тому или иному поводу (обычно связанному с потреблением аппаратных ресурсов) начинается разговор про потоки исполнения, то выясняется, что для многих они тождественны процессам ОС
Какие технологические недостатки языка Go вы можете назвать?
Нет классов, наследования, полиморфизма, перегрузки. Очень сильно не хватает точки запятой в конце строк
Коллеги, вы меня огорчаете