Собеседование junior iOS разработчик

Подготовка к собеседованию на iOS Developer

Транскрипция видео:

  • Привет Владимир Вова Да сегодня у нас собеседование на позицию жуниор АС разработчика и наверное первым предоставлю слово тебе Расскажи немного о себе почему вообще вообще iOS Как сюда пришёл да ещё раз Привет Меня зовут Вова действительно OS Я пришёл не то чтобы прям сразу Такой путь как бы как такая исходная точка была по сути физмат школа какие-то первые первый язык программирования там был Паскаль по сути а потом уже начался университет где мы как бы проходили больше c+ Plus окончил Ну так сказать проходил обучение в

    00:00:00 - 00:01:31

  • санкт-петербургском государственном университете на направлении фундаментальной информатика информационной технологии и то есть да основной упор был на c+ долгое время но потом проанализировав разные направления в it как-то так получилось что интереснее всего именно iOS разработка там Apple очень интересно оказалось И постепенно постепенно начал именно в этом направлении развиваться вот Ну и дальше начал уже так сказать основная деятельность бы как выполнение некоторых зака Вот в общем такая основная тема у меня

    00:00:53 - 00:02:13

  • была понял ну то есть я услышал база у тебя была е Ну плюсов вот может быть по сравнению с плюсами что-то в свифте тебе прям больше понравилось кстати или может что-то не понравилось если у тебя есть как раз с чем сравнивать Да как говорится иначе бы не остался на плюсах потому что [музыка] кие то что очень удобно Можно короткие строчки кода писать которые очень функциональные тем не менее хоть и плюсы говорят они Да там оптимизация хорошая но мне как-то вот оказалось ближе Swift более читаемый код

    00:01:34 - 00:02:49

  • я бы сказал валидно согласен вот хотел спросить стать такой небольшой вопрос у нас и Swift и плюсы насколько я знаю это языки компилируемые знаешь ли разницу там между компи Интер языками В чём у них там плюсы минусы есть м Ну так а компилируемые языки да Я полагаю что действительно Swift он как раз-таки и Ну как и обк все они вот все родом из какой-то общей си семейства и у них действительно что-то общее есть А компилируемые ну то есть соответственно код компилируется м так глубоко прямо как-то не копал в

    00:02:15 - 00:03:44

  • эту сторону не надо это я просто так скаж на интерес опять же Т не докам пря До мелочей Вот хорошо я услышал что у тебя база c+ у нас ещ будет где про это вспомнить Вот но давай Наверно с классического вопроса вот одного из классических это принципы Sol что-нибудь слышал о них вообще влом тореко разработчику не только iOS вообще любому чтобы код был так сказать более читаемым лучше воспринимался другими программистами то что также правильное выстраивание каких-то структур классов в своём приложении Именно для этого нужен

    00:02:58 - 00:04:33

  • Sol чтобы так сказать не было у нас проблем потом с этим в будущем закладывание хорошим фундаментом хорошо хороший фундамент хорошее слово а вот например если по буквам пройтись Ну какой-нибудь классической там буква О например что там она как расшифровывается Для чего она вообще нужна о ЧМ говорить конкретно о буква буква О ну если прямо конкретно не вспомнишь это нормально это вот Open открытости закрытости принцип про что может скажешь да Как раз таки исходя из названия что если вот как правильно помню что долж

    00:03:49 - 00:05:11

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

    00:04:30 - 00:05:47

  • воздействовали да Да всё правильно всё правильно А вот и послед сшу буква с которая сама первая идёт она сразу говорю она о ЧМ она нам говорит вообще по Су с английского су единствен ответственность сть вот каждый класс отвечает каждый метод отвечает за какую-то одну задачу класс отвечает одной задаче и нам не нужно сказать несколько задач выполнять в рамках одной какой-то вот сущности Да да да всё верно всё так вот Хорошо тогда мы перейдём немного с абстракции чуть к другим абстракциям самый базовый вопрос который тоже часто

    00:05:08 - 00:06:37

  • встречается мы от него тоже никуда не денемся есть val Type есть reference Type у нас в чём их различие там кто к кому относится вот прям вот рассказывай вот всё что помнишь что знаешь я что остановлю действительно на этом как бы вообще основан там очень важная часть Свифта отте никуда и мы в основном подразделяется как раз кфн тапу и журы в том числе А вот к у нас относятся я намы и структуры Вот это разделять Да по основным типом данных также вместе с этим стоит очень важно отметить что структура это сразу они в стеке хранятся

    00:05:56 - 00:07:34

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

    00:06:46 - 00:08:09

  • классы они наследуются и от протоколов тоже в том числе Вот Но тем не менее Apple всё равно рекомендует лучше со структурами работать а они так сказать потому что стек он более быстрый чем куча Ну да это это правда А хотто вот спросить ты говорил про value refer ty сделаем чу-чуть шаг назад а вот у нас знаешь ли ты у нас что есть какие-то стандартные коллекции в свифте Да знаю действительно там ма они являются кем вообще базового или тайми вот вообще с ними Какая история они насколько я правильно понимаю

    00:07:27 - 00:08:55

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

    00:08:11 - 00:09:31

  • на куче его элементы при этом так сказать ссылка она будет рано храни на ссылка на эти Так сказать элементы Абсолютно верно Да как-то так в основном с массивами происходит Хорошо Да А кстати вот ты говорил какие-то исключения А это вот например какие то есть классы у нас Тай структура у нас тайпа А бывают ли какие-то исключения Когда например структура Может уползти в кучу то есть Ну как раз-таки я и хоте сказать осном про коррекции то что вот у них такая фишка существует что может действительно быть вроде как

    00:08:51 - 00:10:20

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

    00:09:37 - 00:11:02

  • ИТ можем вво Возможно ли такое у какой-то действительно На мой взгляд нестандартный кейс обычно бывает что если мы указываем вот в классе это как силтон будет выглядеть то со структурами как правило так не действует но мне кажется э м мне кажется что так можно написать но так не делают обычно Ну короче я скорректируйте во-первых как ты сказал такой случай не Самый классический Вот и вряд ли ты где-то увидишь такое в коде потому что ну во-первых у нас компилятор ругается на это почему объясню потому что опять

    00:10:24 - 00:12:01

  • же структура это val ty вот даже если логически подумать мы у тайпа должны заранее так как у нас стек понимать Ну примерно сколько на него памяти хотя бы выделяется Вот а если мы в свойстве указываем тип структуры у нас получается рекурсия Вот и для это неприемлемо Вот и у нас Поэтому будет ошибка компиляции Вот потому что у нас не скомпилированный но это не критично но просто да вот такой вот момент действительно есть Да это бы необычно кстати вот ещё знаком ли ты с таким понятием как Да действительно C Вот как раз оно

    00:11:14 - 00:12:39

  • да знакомо Но вот как раз массивы такой яркий пример когда это случается есть Copy on Right и Cop on assignment что Мы производим так сказать копирование только при изменении этого массива например при добавлении нового элемента в массив соответственно на это очень удобная штука для оптимизации нашего приложения потому что мы выделяем ресурсы вот тока в момент изменения А пока мы делаем допустим просто копирование одного массива в другой новый массив мы C делать не будем и у нас будет просто ссылка на эту же старую область памяти

    00:11:56 - 00:13:12

  • Угу Да да Всё всё верно всё так а хорошо так про это сказали на это кстати возможно я хотел бы дать вот одну сейчас задачку Сейчас я тебе скину ссылку угу Там просто скажешь что напечатается условно говоря и ничего такого прям чески сложного Вот так я ссылку кинул в чат сейчас я закину сам код чуть-чуть просто порассуждаем Кстати если не сложно сможешь пошарить экран сейчас когда вот зайдёшь там всё сделаешь Угу Так сечас так а тебе нужно разрешить походу Ну ты как од а разрешить дадада да Всё я

    00:12:33 - 00:14:03

  • сделал разрешил [музыка] угу так вот видно что-нибудь так Да видно сейчас я закину сам код так я его прокомментируй Наверное чтобы тебе сечас было попроще смотри у нас просто есть какой-то класс у нас Переса его тамр это чтобы просто чась у им в примерах показа ниже что просто что указали оно бы печаталось вот и создали класс дальше мы создаём первый массив надо поправить некритично пом и дальше просто примеры того что у нас если мы затим у нас за Ватан если мы Прим у нас при тоже ва Никита Андрей дальше Мы производим такую

    00:13:23 - 00:15:32

  • манипуляцию там Ладно уже не стал править Ну понятно у мы вызываем мед он удаляет последний элемент внм что у нас выведет с консоли Сейчас подумаю немного можешь рассуждать как-то Вот то есть там про ко ты что-то говорил может с этим связано да действительно Да вот как если я сказал что поскольку мы ага Да мы всё-таки произвели изменения в нашем Первом массиве и значит к первому массиву уже присваивается новое значение без пластового значит вот Андре без Андрея значит там будет Ваня и Никита в Первом

    00:14:44 - 00:16:20

  • массиве находиться А насколько я понимаю что он остался таким же и в таком случае яже действительно прав вот я не буду всякие там ты точно уверен Ну да это правда потому что нас эти грубо говоря они в данном случае не зависит от того что мы сделали попла хорошо И вот на следующей строчке мы делаем ещё одну манипуляцию с First Mass мы Обращаемся к последнему элементу вот к его полю name и меняем его на Игорь угу вот а поменяется ли что-то в данном случае при принте Second M угу так или всё останется

    00:15:40 - 00:17:14

  • прежде м так ну соответственно значит First ма уже состоит из двух элементов потому что я так полагаю вот этот метод по Blast он по сути говоря уже изменил этот же сам массив Да действительно да значит в ф массе У нас сейчас находится Ваня и Никита и теперь ластово ф масе у нас значит будет Никита значит вместо Никиты там становится Значит Ваня и Игорь получается в целом Вот Но мы действительно так и не затрагивая поэтому мне кажется что будет такой же результат как и в первый раз СН массом Хорошо я тебя услышал Ну в общем

    00:16:37 - 00:18:12

  • это такое немного как раз вот примерно Понимание где у на ссылке где по значению в первом случае Да действительно у нас всё остаётся так как прежде потому что никак не связано просто мы грубо говоря значени обращались А вот когда мы мы во втором случае обратились конкретно уже к классу который у нас является референс тапом мы мы взаимодействи грубо говоря не с массивом а именно вот в данном случае с классом и мы поменяли поле у класса то есть поменяли то что лежит там по ссылке у наму ВМ с Ир адре у види нается именно вот тот

    00:17:24 - 00:18:48

  • класс который Ну которо мы обращались Вот то есть поем конкретно по ссылке значение пость будет ва Игорь Андрей А почему тогда [музыка] действительно СБО пото потому что опять же как ты говорил что у нас семантика что когда мы манипуру с самим массивом Мы манипуру как с типом действительно вот за исключением там вот то есть что у нас есть это да Вот но когда во втом случае обем комен обем те и у меняем есть не смотрим на массив мы смотрим конт обект класса вот конкретного объекта класса мы поменяли

    00:18:06 - 00:20:03

  • поле Вот и теперь Просто теперь Гру говоря не существует такого класса как ну с по Никита если мы зано заведём Вот потому что ну всё Мы у него поменяли его просто в принципе нестм Об угу понятно автоматически будет и меняться тоже да ну потому что у него хранятся как бы ссылки ссылки у него те же вот то есть это как бы массив где у нас как раз сохранятся вот эти вот самые ссылочные типы Угу Да я понял да стоит буду знать теперь хорошо Может сейчас пока выключать демонстрацию экрана пока Продолжим что без без

    00:19:10 - 00:20:41

  • этого вот так хорошо Мы проговорили про коллекцию проговорили про C хорошо такой опциональный вопрос знаком ли ты с понятием диспетчеризации диспетчеризация Ну как-то так особо пока не сталкивалась Вот с таким понятием А ну ладно хорошо вот просто на будущее Можешь почитать что такое вот там как раз у классов структуры есть различия и там На это тоже бывают какието задачки Иногда я так полагаю не путать это другое другое там вот есть Ну это статическая динамическая и диспетчеризация на сообщениях которые

    00:19:57 - 00:21:38

  • токо вот поэтому это отдельная тема кото може просто почитать нас помогает оптимизировать скорость там работы твоей программы Ладно Хорошо Окей хорошо у нас в свифте есть такая классная штука классная штука Как опциона Да во-первых вот если не вдаваясь какие-то подробности там как оно устроено вообще для чего как думаешь они нужны в свифте и вот где они Может там используются например они могут использоваться в работе с сетью когда мы допустим так сказать получаем какие-то данные сети мы може мы не можем

    00:20:49 - 00:22:22

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

    00:21:37 - 00:23:08

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

    00:22:27 - 00:23:57

  • нас приложение билди или в ран тайме Когда уже Мы там что-то тыкаем работаем в ран тайме да Да действительно просто этим как раз и плохо что у тебя именно в ран тайме всё крашится это очень неприятно для юзера Да иногда не сразу можно отследить этот баг а только уже большое приложение его потом ещё искать придётся Ты кстати заделал дженерики Может расскажешь вообще для чего они нужны где мых используем может [музыка] быть дженерики это действительно особенность Свифта а достаточно такая такая тема Она

    00:23:24 - 00:24:40

  • позволяет нам удобно работать допустим если нам нужно писать много каких-то однотипных функций Куда нужно помещать например то string то Double то int и вместо того чтобы писать 10 разных функций можно через дженерики сделать одну универсальную функцию это вот основная мысль когда будет удобно использовать дженерики вот хорошо а вот ты знаешь Кстати на этапе во-первых Что происходит с дженериками Да так скажу на этапе компиляции как у нас всё-таки воспринимает наш компилятор то что мы написали дженерики то есть ну он как-то

    00:24:05 - 00:25:23

  • шаблонный Код Да что вот происходит с ним дальше это такой опциональный вопрос просто тут знаешь не знаешь так тут пока пока Зару отве най вопрос Если интересно они просто там на этапе компиляции грубо говоря пишутся конкретные реализации просто уже под необходимые параметры которые есть где-то в коде то есть анализирует код смотрит когда мы их используем и уже конкретно реализации нам предоставляет для этого поэтому кстати если у нас там условно много дженериков их 12 разных реализаций у нас увеличивается

    00:24:44 - 00:26:09

  • количество получается создания функций и может увеличиться к время компиляции изза это есть всё-таки они на как ты сказал на этапе компиляции они получаются создаются конкрет реализация ком всё хорошо Ладно всё верно хорошо тогда блок по свифту наверно мы закрываем такой абстрактны перейм наверно к И вообще там как расшифровывается как применяется что считается не считается Да действительно одна из важнейших вещей в свифте потому что оно связано как раз coun он был таким уже предшественником Man C который был в но теперь именно

    00:25:29 - 00:27:16

  • используется и он достаточно важен потому что крайне важно вте работать с памятью потому что могут происходить утечки памяти и этот механизм он как раз при хорошем обращении с ним позволяет их избежать то есть основная суть заключается в том что у нас есть три вида ссылок это вот Strong ссылки ссылки UN ссылки и всё завязано на увеличение или уменьшение счётчика ссылок то есть когда количество НГ ссылок У нас например один или больше то тогда объект существует когда и становится равным нулю значит объект он освобождается из

    00:26:22 - 00:27:41

  • памяти основная мысль такая важно не допускать создание ретей сайлов это может как раз приводить к большим утечкам памяти же это цикл Строн ссылка может ещё называться Угу всё это достаточно Хороший ответ хотел бы вот ещё услышать наверное про у нас да со строгом понятно То есть основной СК с у нас е есть такие ссылки как например может быть знаешь какие-то у них различия Может там какие-то ещё интересные штуки возникают Когда у нас возникают ссылки слышал может что-нибудь Да действительно в так сказать и они

    00:27:04 - 00:28:36

  • немножко особняком стоят потому что они Нет с они вот поэтому немножко Уникальны этим самым к он работает именно когда дело касается Вот опциона потому что Wi он по сути создаёт опционально значение а unown не опционально значение и unowned использует с одной стороны эффективнее с точки зрения оптимизации а с другой стороны и более опасно то есть стоит быть очень так сказать уверенным в том что там Значение будет потому что если не будет то можно ошибку ш приложения получить если обратиться к если там не будет

    00:27:50 - 00:29:05

  • значения также ском связано то что создаётся S Table Да как раз-таки если раньше в свифте не было такого понятия как S Table то и и они могли находиться в некой одной таблице то Потом вышли новые версии Свифта где уже пошёл Сай и это тоже очень удобная веь для оптимизации в плане в плане памяти ресурсов вообще приложения потому что как раз-таки там будут храняться храниться вот эти ссылки в сайле Угу хорошо А кстати вот ты говоришь толь А у нас в этой S Table хранятся только в их ссылке или может ещё там например

    00:28:30 - 00:30:03

  • затрагиваются или или только в их ссылке а там только ссылки находится Но вот но там хранятся Ну такой скажем карный немного вопрос потому что там хранятся в общем и и и они в общем все туда переезжают все счётчики Вот но как бы но ты сказал на самом деле вот для ответ был достаточно хороший Вот тут я прямо скажу про наверное у меня прям таких вопросов ещё нет только один вот есть есть такое понятие как Cap что можешь сказать про него вообще как как ты его понимаешь для чего он нужен Да вот как capture L он например один из

    00:29:16 - 00:30:53

  • популярных кейсов это когда допустим То есть он работает с классами что вот когда мы можем в capture L поместить какое-либо значение то даже если класс впоследствии будет производиться изменение в этом классе В объекте этого класа то Cap он уже зафиксирует значение этого объекта вот оно не будет больше там то есть в кжу останется Вот только это значение определённое и всё также в Cap листе может ещё быть такое как употребляться очень популярная вещь связаная как раз с сетевыми запросами он нам как раз также очень как

    00:30:09 - 00:31:36

  • раз один из хороших механизмов для предотвращения Вот такая вот вещь да Угу Хорошо тогда вот по поводу этого скажем так по поводу этой темы Я вот ещё одну задачу по той же ссылке я там её добавил Просто если не сложно Поша экран Да сейчас так сейчас перейду тогда по ссылочки к Угу Так вот ш вот вопрос простой что у нас за принти Угу сейчас момент Значит у нас тут код сюда [музыка] угу так Ага ну Я полагаю что действительно поскольку Да у нас в переменной Language было значение Swift ринговая и мы

    00:30:53 - 00:32:42

  • захватываем вот это значение значит то что мы потом Его изменили это уже не будет играть роли в нашем в нашем кжу Значит мы будем принти именно Swift Да это действительно верно а поменяется ли что-то Если вот мы вот просто удалим ли поменяется ли что-то так да В таком случае тогда будет obc а почему как как как вот мы Ну то как у нас происходит тут взаимодействие с ндм почему она поменялось М ну то есть уже как бы на этапе на этапе компиляции этот кжу уже словит значение что вот вот вот вот это финальное objective C оно

    00:31:55 - 00:33:32

  • будет принти Вот сюда в этот кжу м потому что ну то есть короче что типа про ссылку наверное то что ты хотел сказать что мы там грубо говоря захватили а не значение Да и что вот когда мы поменяли значение Мы же захватывали ссылку не явно захватили то есть по сути у нав типа вот и поэтому мы конечно Прим Да потому что мы изменили вс-таки [музыка] зада сся прекрасно Давай тогда может да сейчас убирать демонстрацию Угу хорошо дальше мы пойдём по многопоточность и сталкивался ли ты с нем действительно Да многопоточность она

    00:32:47 - 00:34:16

  • вте аое представлена несколькими разными фреймворка То есть если ВС начина трев потом то всё в итоге пришло к тому что современные методы как раз gcd и то есть в основном в основном конечно же пользовался gcd наверно как многие Ну так сказать тоже имел некоторый опыт ещ и с другими то есть примерно понимаю в чём отличие как раз таки о какое тогда вообще вообще сейчас какое различие в понятиях между многопоточность и асинхронность [музыка] угу так сказать Да многопоточность она как раз-таки предусматривает что у вас будет

    00:33:51 - 00:35:30

  • несколько потоков которые например могут выполняться параллельно то в случае с асинхронность задачи могут это может быть кстати не обязательно именно Гоп точка В случае с асинхронность как Например если речь идёт о главной очереди и главном потоке он может быть один и это будет по сути один поток но он будет выполняться асинхронно как вот знаменитый dispatch M dispatch Q maining А вот и да то есть эти понятия немного разные они так что ещё про них сказать то что м ну можешь кстати не вдаваться Вот ты на

    00:34:47 - 00:36:03

  • самом деле я основное что хотел услышал то есть что действительно ты понимаешь разницу между просто ну глобальную между этими двумя понятиями и Да что у нас на одной грубо говоря можем просто в асинхронно запихивать задачи Вот А у нас есть очереди очереди в свою очередь делятся там на си и conc в чём основное различие этих двух видов очередей Да действительно значит такая последовательное будет выполнение тасков задач А в кон Они как раз параллельно выполняются то есть одновременно могут выполняться эти эти

    00:35:25 - 00:36:53

  • задачи наверное вот основное отличие ещё хотел добавить что конты они как раз могут подразделяться там в зависимости от of они их там бывает несколько разных видов GL очереди бывают хорошо А у нас ещё есть такое понятие Как там ан да то есть это грубо говоря способы добавления задач в очередь вот и что например произойдёт когда мы в conc очередь добавляем с помощью какую-то задачу в ЧМ основная суть да Значит это будет синхронное выполнение задачи то есть Значит в этой очереди задача должна выполняться когда

    00:36:08 - 00:37:53

  • и новая задача не будет начата до тех пор пока старая задача не выполнила это вот основная была суть как [музыка] раз метода вот в же немного по-другому там как раз таки они могут закончится в разное время там результат может быть Немного более непредсказуемым в случае и но при этом он наиболее эффективный по времени ресурсам выполняется Ну и и в целом достаточно умный механизм то есть мы можем например как раз сделать диспет И большинство пробле Бут решены как ки вот связа с точностью Ну как-то вот так то

    00:37:08 - 00:38:56

  • есть я услышал решает проблемы с многопоточность Ну не совсем просто понял в чём посыл предложения Почему решает Да скорее мне стоит добавить добавить что ну то есть да логично что UI реализацию нужно всю выкладывать на M Угу Ну и также соответственно мы можем допустим какие-то тяжеловесные задачи поставить на Global там Граунд поток И это тоже поможет нам чтобы это если асинхронно будет выполняться то так будет так сказать эффективнее Ну хорошо Да действительно какие-то задачи можно там убрать в

    00:38:01 - 00:39:38

  • Global которые не связа с пото что Да весь U действительно у нас делается по хорошо а вот в связи там многопоточность это всё классно А какие у нас есть проблемы с многопоточность вот может быть известные знаешь Да действительно есть известные Проблемы такие как например такие как например [музыка] или также е несколько других эти самые таки извест локе например может быть такая ситуация что у нас есть допустим поток А и поток б и поток а он так сказать захватывает ресурс X а и а в то же время поток B

    00:38:49 - 00:40:24

  • захватывает ресурс Y и но при этом потоку А в какой-то момент понадобится ресурс Y а соотвественно потоку б понадобится ресурс X но они окажутся заблокированы Они не смогут получить доступ к этому ресурсу они будут бесконечно пытаться это сделать но это будет такой конфликт образо Ну то есть всё время короче друг друга Они ждут да да акой самый яркий пример наверное в айосе знаешь лока так в [музыка] айосе так [музыка] Ага сейчас как-то прям так не вспомню но был какой-то действительно приме которые связаны слоком их лучше

    00:39:40 - 00:41:08

  • конечно же всё-таки сразу не допускать как раз правильно выстраивать синхронизацию потоков с помощью некоторых разных методов мы это делаем и лучше не доводить до этого изначально Вот но прямо сейчас так вспомнить не могу конкретный случай Ну ладно Но нет это не проблема хорошо ещё вот хотел такой один теоретический вопрос и пойдём одну задачку решим вот у нас есть какие-то говорил про gcd С какими там может быть инструментами Ты работал То есть у нас есть там M Global вот а какие ещё там слышал ли

    00:40:28 - 00:41:48

  • что-то про семафоры про диспач группы Да действительно есть такие семафоры и диспач группы например диспач Груп достаточно эффективный способ Если у нас например такая ситуация что приходит большое количество там допустим 100 картинок и мы их все скачиваем с сети потом мы не хотим чтобы они в разное время появлялись А чтобы они все вот в одно определённое время появились и диспач группа - это как раз идеальный способ решить вот эту проблему вот семафор э семафоры барьеры также есть ещё Да в gcd А как раз например вот

    00:41:07 - 00:42:20

  • и барьер ещё есть который тоже эффективно позволяет нам решить такую проблему что мы хотим поставить барьер некий и чтобы мы конкретно дожидались выполнения одной задачи и и только когда она завершится мы пропустим через этот барьер уже другие задачи чтобы они тоже выполнились вот с семафором же немножко другая история Что там у нас как раз есть два таких метода Signal и Wait мы будем Сначала мы указываем какое-то число допустимых потоков которые будут работать над какой-то задаче и мы это решаем оно

    00:41:45 - 00:43:03

  • может быть равно единице Там двойке и так далее и в зависимости Вот как раз эти два метода си они либо повышают этот счётчик семафора либо уменьшают его это можно тоже использовать в своих задачах в своей работе прекрасный ответ ещё такое уточнение слышал ли Ты что такое мьютексы А ну да мьютексы Как раз таки это такие предшественники семафором Они тоже по сути блокируют один поток но основная наверно Суть в том что они могут работать только с одним потоком а не с множеством потоков как в случае с

    00:42:24 - 00:43:41

  • семафорами по сути что-то подобно Да всё вот этот ответ был прекрасный что это по сути семафор - это усовершенствованный ютекс в своём роде вот можешь перейти по ссылке там есть достаточно стандартная задача там по шар экран вот я думаю если ты что-то смотрел Вот про какие-то задачки Наверняка ты эту задачу видел а Позволь это снова надо доступ дать мне для Это для рения всё да коне ждал Угу [музыка] се Да действительно такая классическая задача м О'кей dispatch Q Global cos User initiated assn м Я полагаю

    00:43:02 - 00:44:36

  • что не так принципиально какой у нас qu здесь Действительно это не особо Смотри да и Мо там ниже сразу писать просто Что у тебя прин там вот грубо говоря две строчки отступить И просто писать чтобы не зать А да Хорошо о'кей тогда мм Ну да практически однозначно что у нас единица будет первой а потом мне кажется будет м потом мне кажется будет 10 А потом мне кажется будет 10 Да вот а дальше уже дальше уже Немного более детальнее стоит посмотреть как раз таки тут у нас вроде как двойка стоит ещё сразу посмотреть на вот

    00:43:52 - 00:45:30

  • эти вот методы а снова Да здесь Вполне может случиться вероятность дедка поэтому стоит тоже быть внимательным тут Также сейчас сейчас попробуем тогда мне Да здесь тоже проблем быть не должно должна двойка всё-таки запри Я полагаю дальше идём тут три мы пока не делаем ничего дальше 4 полагаю Здесь должна быть четыре после двойки Так а здесь здесь уже синхронное выполнение задачи так Окей значит шесть тоже То есть те кто не связаны с диспач очередью они выполняются Ну значит и девятка должна м так сказать тоже

    00:44:41 - 00:46:31

  • принти потом п а да здесь уже немножко посложнее конечно М немножко посложнее так м так так так а тройка Так у нас осталась получается тройка пятка и 78 7 3 5 78 значит 3 5 Кстати да я не обратил сразу внимание везде везде просто только даде глобала значит наверное это попроще ситуация так хорошо хороо послед воп так вот по-моему там вот либо п либо ри вот сейчас так немножко неоднозначно нуши по думаешь может зависит от последовательности Да а потом обязательно долж выполниться как вот мы предусматривали что

    00:45:36 - 00:47:51

  • синхронно Ага значит тут синхронно запускаем се оно вот вроде как сейчас должно выполниться и потом ещё это по-моему как раз вот здесь может и делок сейчас случиться если вот это не ошибаюсь как раз на этом этапе Да на Мейн потоке асинхронно и тут мей поток синхронно то есть мы хотим выполнить эту задачу но у нас ещ тут задача более приоритетная висит это может привести Мне кажется Вот как раз на этом и всё то есть дальше ничего не напечатается Да полагаю так хорошо давай я такую сделаю корректировку смотри у

    00:46:55 - 00:48:21

  • нас действительно сначала напечатается единица потом напечатается десятка потом мы переходим в на M то есть до это были на глобале най асинхронно закидываем в стерильную очеред двойку Всё у нас закинула двойка потом мы асинхронно ещ закинули тройку то есть действительно напечатается двойка тройку мы закинули куда-то там она ждёт своего часа доходим до четвёрки четвёрку печатаем и вот на этом моменте возникает у нас первый дедлок потому что на самом деле то есть ты его увидел вот здесь вот то есть вот ты его

    00:47:38 - 00:48:52

  • увидел и по сути на самом деле Вот он же здесь и есть Вот то есть на самом деле напечатается четвёрка и на этом дальше ничего не напечатается потому что за дочи и мы дальше никуда не пойдём Но Давай попробуем обойти этот момент мы напишем Global А давай там без коса просто ан м тогда у нас напечатается действительно двойка четвёрка А и что будет дальше Вот как думаешь что-то поменяется так Ага теперь у нас Global Угу так двойка четвёрка Окей идём дальше пятёрка должна синхронно реализоваться но она на Main очереди А

    00:48:14 - 00:49:56

  • тут вообще Global и в принципе пятёрка так а нет у нас же ещё шестёрка есть Окей Так а это это А вот кстати тут не совсем понятно шестёрка или пятёрка начнётся раньше выполняться потому что э очереди разные но тут мей очередь всё-таки она более главная чем Global Значит всё-таки тут пятёрка будет тогда и только потом шестёрка Хорошо давай тогда сразу поправлю В общем смотри тут з такая тоже Ловушка такая заранее была сделана смотри у нас сначала печатается двойка потом что мы делаем мы на Мейн в

    00:49:05 - 00:50:34

  • мей очередь она же серийная как-то асинхронно закинули тройку да запом это потом мы переходим принти четвёрку тут всё нормально и дальше мы говорим диспа всё так как тут мы не можем пойти дальше нам нужно выполнить этот Принт но нужно помнить что до этого мы закинули ещё тройку сюда то есть у нас поэтому сначала напечатается тройка потом напечатается пятёрка и только потом напечатается шестёрка Как ты говорил действительно потом девятка а Да и потом у нас вот этот вот момент Но тут единственное не всё прямо

    00:49:50 - 00:51:13

  • упадёт у тебя напечатается всё же короче семёрка и вот на моменте когда мы дойдём до диспач Main syn у нас действительно упадёт и восьмёрка и напечатается то есть у нас напечатается всё кроме восьмёрки Вот в такой последовательности м угу вот ну такой да пример не самый простой Вот Но раскрывающие все моменты и слока и за синка и просто нужно действительно быть просто внимательные вот да хорошо Нет всё равно молодец размышлял м увидел Deadlock Это хорошо просто нужно было его чуть больше грубо говоря в общем случае увидеть то есть

    00:50:31 - 00:51:50

  • это нормально действительно так хорошо можешь выключать демонстрацию экрана Угу Так О'кей ещё Давай наверное перейдём к юаю Вот наконец-таки и пойдём насколько я знаю Ты работал только с китом правильно Да да В основном с ним хорошо тогда давай по нему стандартный достаточно вопрос там Расскажи мне жизненный цикл в контроллера Но перед тем Кстати как ты его расскажешь скажи вызывается ли он при инициализации вю контроллера или нужно конкретно что-то сделать чтобы вызвать так насколько я понимаю жизненный цикл

    00:51:10 - 00:52:39

  • контроллера он обрис ситуацию то есть мы пишем не знаю мы инициализирован вызове там как раз отметить что нас будет вьюшка Как раз таки фигурировать и именно в таком случае у нас пойдёт Всё выполнение жизненного цикла и вообще мы это всё должны прописать также вте как раз пометить вот какой у нас будет Вот наш именно в таком случае у нас будет запуска Ну то есть в общем при инициализации не запускается жизненный цикл да Ну да это действительно верно вот скажем так остановимся на этом что это это утверждение верно Вот хорошо

    00:52:05 - 00:53:39

  • давай жизненный цикл контролера всё же расскажи какие там есть методы основные Да основные методы начинается всё с инита потом идёт как раз таки VI и уже дальше VI такой самый наверно популярный А после него уже например идут VI Will appear VI did layout Sub views тоже может быть VI Will потом VI VI Will disar и VI dis и всё заканчивается де итом в конечном счёте Угу а Слыш ли Ты кстати что-то про метод который там как-то отвечает когда у нас память как там что-то утекает короче проблемы с памятью когда

    00:53:09 - 00:54:44

  • возникают метод просто сложно вызывается грубо говоря синтетически Вы просто слыша по действительно вот я как-то да наблюдал что вот как раз в старых в старом экс коде Если не ошибаюсь как раз по дефолту вызывался там связанный с мемори как раз таки не совсем помню как он точно назывался этот метод но его сейчас можно тоже вызвать даже в новом Ико Но это он так сказать неча используются насколько я понимаю Хорошо да хорошо услышал перейдём тогда к вёрстке у нас есть автолейаут что это вообще Ну само

    00:53:56 - 00:55:14

  • по себе что это из себя представляет то есть авто - это как раз такой механизм в основном основанный на констрейнт приходилось именно верстать фреймами более старые времена то сейчас наиболее такой метод это именно через автолейаут и констрейнт о там связано с энкомия Это для того чтобы например очень удобно было размещать наши вьюшки на разных устройствах независимо от того это маленький iPhone SE или большой iPhone Pro Max а autolayout позволяет нам как раз всё что было читаемо нормально а вот Извини сейчас перебью

    00:54:38 - 00:56:02

  • вот Извини а что вообще само под капотом такое что такое автолейаут что что там считается может быть или делается вообще Откуда возникают э все цифры это всё Как устроена как система линейных уравнений э как раз эти констрейнт э также там можно ещё добавить например приоритеты например hing приорити или compression Resistance priority оно тоже как раз будет влиять впоследствии на эти линейные уравнения и всё вместе как раз в итоге будут констрейнт которые всё это делают Угу прекрасный ответ хорошо

    00:55:21 - 00:56:40

  • А есть такое ещё понятие кстати вот как раз Ну когда мы пишем там не знаю чем отличается Left от leading знаешь ли есть Понятно типа левая левая сторона экрана вот чем отличается ф от лидин А да они могут быть с одной стороны очень похожие на первый взгляд и ледень лифты вроде как одно и то же но я знал такой вот кейс что бывают например некоторые там страны где там читают например не слева направо а справа налево и как раз это может вызывать некоторые проблемы и поэтому лидинг он более предпочтительный для использования

    00:56:00 - 00:57:22

  • чем Left потому что как раз лидинг ведущий А трейлинг замыкающий и на этом как раз если мы хотим закон слева и справа луше ис лидинг и трейлинг как раз констрейнт Вот Угу хорошо так тогда действительно правильно наверное тоже классический вопрос фй и банс В чём отличие А да Фрей и банс они на первый взгляд могут быть крайне похожи и они могут действительно даже в общем и целом равны быть а то есть если фрейм он больше он завязан на как раз в зависимости от родительского так сказать координаты строятся

    00:56:42 - 00:58:15

  • а при при балансах координаты строятся рассмотрение При рассмотрении собственной системы координат то есть внутренняя система координат используется там и они могут быть различны при ситуации например Когда происходит вращение какой-то вю там наглядно видно как у нас различаются например фреймы Как различаются баунс в такой ситуации Да действительно вращение из вот А например у ба есть в каком случае тогда получается у фрейма Понятно У баун может изменяться значение может быть просто какие-то подскажу так какие-то есть элементы

    00:57:28 - 00:58:53

  • [музыка] когда связано с Bounce и когда вот этот Origin может поменяться Да когда Origin может поменяться мм мм то есть именно какие-то вот э бывают такие кейсы Когда именно меняется баунс да Ну да достаточно такой на самом деле э частый кейс потому что А у нас ну мы часто это можем увидеть на практике ой ещё раз Ну мы часто можем увидеть это на практике потому что у нас да понял на практике угу так Я примерно представляю как это происходит Да трудно пока это немножко сформулировать Насколько часто на

    00:58:22 - 01:00:04

  • практике Ну на практике и баунс можем использовать когда мы допустим как раз хотим А вот у нас есть VI то Bounce мы способ создать какие-то начальные значения для смотри Извини сейчас перебью попробуй тебя вот Ну вот это просто чу-чуть сдвинуть куда на Ну вот есть такой грубо говоря элемент прям в ките прям такой может быть не один Ну просто я вот один который помню который мы прямо часто используем например Когда у нас контент не вмещается например в экран весь Ага контент не вмещается весь в экран

    00:59:13 - 01:00:24

  • А может как раз-таки Это имеется в виду вот этот если об этом илит это немножко другое именно вот там U какой-то элемент а Ага когда не вмещается Сейчас ладно не буду прямо мучить тоже с этим В общем Когда у нас как раз Ну типа дата вся не вмещается в э тме грубо говоря Долина вс-таки дата поменяется Ну наполнение это тако Да просто интересный факт просто не все сразу схода вспоминают об этом У нас ты упоминал У нас есть U и есть CL Назови наверное одно самое главное такое различие междуними которое надо прям

    00:59:50 - 01:01:59

  • учитывать а Да действительно View и cer наверное Ключевое различие в том что UI viw оно как раз-таки предусматривает то что взаимодействие с пользователем когда он будет кликать по этому тапать по этому вю а а а вот как раз-таки cer он будет отвечать за отрисовку и анимации То есть это как раз его поле действия причём причём U viw у неё как раз-таки есть такое свойство р и с помощью него оно может и по сути в иметь все вот эти весь функционал леера на себе хорошо вот ты сказал про обработку нажатий Ну соответственно Знаешь ли ты

    01:00:54 - 01:02:36

  • механизм вот этой обработки нажатий как он происходит примерно Ну да ЕС РЕТ как раз Тен и Chain как раз таки там такая Ключевая вещь что когда пользователь например нажимает на какую-то VI А у нас вот в этой координате куда он тыкнул например есть три viw которые располагаются друг на друге как пирог какой-нибудь и в таком случае и проводятся вот эти расчёты то есть есть метод который который по Су U и этот же метод он будет по сути выяснять на какую VI сейчас нажал пользователь и в дальнейшем у этого же метода там там

    01:01:46 - 01:03:24

  • используется уже Point Insight метод который как раз возвращает значение True или fse и он конкретно уже скажет действительно было ли совершено нажатие или нет на какую-то VI и с помощью этого механизма Мы также Вот будем определять вот там с помощью если какой-то viw имеет механизм обработки этих как раз событий пользовательских назвати и действий которые она будет дальше выполнять тогда оно их выполнит но если нет оно будет дальше по иерархии передавать эту возможность а другим Другим View например вплоть даже

    01:02:35 - 01:03:52

  • до UI viw контроллера А вот так Ну хорошо Да ну в принципе я понял А вот есть такая ситуация что вот у меня вот кнопка я вот на неё нажимаю Но она какая-то очень маленькая кнопка и я по ней мне тяжело попасть вот пальцы такие неказистые как можно с помощью там может быть каких-то методов решить эту ситуацию или может какая-то там вёрстка должна быть особенная Ну чтобы грубо говоря увеличить область нажатия на кнопку да на самом деле в такой ситуации А можно даже если кнопка маленькая всё равно сделать

    01:03:12 - 01:04:26

  • область область прикосновение немножко побольше для пользователя мы можем например как раз-таки вот я упоминал метод Point Insight мы можем его переопределить например в экстен и тогда мы будем там уже наследоваться как раз таки Custom Button у нас будет не просто UI buton а именно C buton с вот этим пере определённым методом и как раз благодаря этому способ там мы можем уже эту область увеличить допустим там мину 50 поставить -50 -50 и у нас уже вот этот сам так сказать диаметр он будет намного больше И можно будет Как

    01:03:53 - 01:05:09

  • раз удобнее кликать на buton у хорошо И вот такой ещё опять вопрос со звёздочкой опциональный у нас ели посмотреть даже стек вызова у нас чаще всего Там сначала будет не какой-то U viw там у нас будет какой-то UI например и вот как Какой механизм Ну есть грубо говоря который помогает нам ловить Вот всё-таки именно вот нажатия которые какие-то внешние возможно ещ он ещё не возможно он ловит ещё таймер и ещё там ряд моментов он ловит может быть понимаешь ли про что я сейчас говорю примерно А ну я примерно понимаю

    01:04:32 - 01:05:52

  • что если вот как UI Скорее всего он сам на себя нажатие наверное не примет а передаст по иерархии Дальше например уже на бан вот это вот если ты передаст как Он передаст Просто воно это такой опять же опциональный если Ну так я могу немного порассуждать что как раз Если не ошибаюсь это как разн в ответе за вот эти вот механизмы передачи вот это функционалу что если не имеет механизмов для работы с этим то теперь Он передаст это другое в которое там вот вышестоящее и она как раз уже обработает это нажатие Поня Ну в общем

    01:05:12 - 01:06:29

  • на самом хорошо рассказал про переписывание прям Это хорошо есть ещё просто один такой механизм это вот тако это грубо говоря бесконечный цикл который всё время пока вот приложение работает он он ловит как раз вот эти вот нажатия какие-то внешние воздействия таймеры и уже потом он грубо говоря передаёт это всё То есть он такой ловит всё и сообщает обо всм Ну это тако просто може тоже почитать про и штука про которую хорошо бы тоже там знать Вот Может в будущем пригодиться Да хорошо Это не критично вот ну наверное наверное всё

    01:05:52 - 01:07:29

  • вот я не буду уж дальше мучить Ты заранее скажу прям хорошо себя показал Вот расскажи можешь расслабиться уже и да Да расскажи вкратце вообще какие у тебя впечатления от собеседования И что тебе там не понравилось там не понравилось показалось сложным может быть или что-то интересным А ну сразу тоже хочу тебя как похвалить Очень приятно было что ты м как бы даже если что-то я не совсем понимал ты мне так сказать помогал додумать эту мысль немножко раскрыть её побольше и в целом в целом не было такого

    01:06:39 - 01:07:58

  • ощущения давления потому что я сначала думал что Собес что-то Там страшно будет но с тобой было очень здорово и в целом тоже было бы интересно послушать и твой фидбек вообще какие моменты ещё можно так улучшить что там дополнительно посмотреть моментами поработать Да всё хорошо спасибо большое Я старался чтобы Да была такая дружеская всё-таки больше беседа нежели собеседования Ну во-первых что конкретно по фи ято Коре я буду горить бло скажем вот что касается Свифта ты достаточно хорошо ВС отвечал

    01:07:20 - 01:08:47

  • ты понимаешь В чём разница между куча что у нас есть там исключения знаешь про механизм и там основные понятия Потому что если мы вс-таки собеседуем на уровень Джуниора даже на уровне не всем это и надо Потому что это уже такая скажем тонкость оптимизации про дженерики Я хорошо услышал про опциона хорошо ВС услышал вот даже под капотом зна что это такое Это вообще прекрасно Это секция прям хорошо про был хороший ответ я тут не буду ничего говорить то есть Вот это очень важно потому что одно дело сказать Другое

    01:08:02 - 01:09:33

  • дело решить Вот тут ты хорошо спра с практикой там опять же была маленькая неточность но на уровне Джуниора Ты прямо даже я бы сказал НИР приближаешься к медлу вот а И кстати про предыдущую задачу которая была в предыдущем блоке про свифту хорошо рассуждал Вот но просто да вот там есть действительно такая тонкость которую просто нужно понимать и может быть просто там стрессовая обстановка может ещё подумал наверное правильно бы и сказал потому что рассуждал достаточно хорошо вот про многопоточность тут я бы посоветовал

    01:08:58 - 01:10:17

  • улучшить навык рассказывания этого всего объяснение потому что я понимал что ты понимаешь Вот но чувствовал что не хватает слов и практики именно рассказать А вот что это такое для чего это нужно потому что там ну конкретный короткий ответ всегда понятен приятен Вот Но твою мысль Я всё равно услышал и она была правильной с задачей Ну задача была действительно с подковыркой там не с одной А с двумя вот Ну тут просто навык нарабатывать то есть там побольше таких задач посмотри порешай там сам Зайди в

    01:09:37 - 01:10:54

  • плейграунд попи там поразвлечься [музыка] про UI про UI Я вообще услышал Всё достаточно хорошо то есть то что я там в конце про спросил Ну это такая опциональная штука которая ну наверное на уровне Джуниора уж точно не понадобится То есть всё-таки тут нам хорошо понимать просто как верстать грамотно что там вызывается что Для чего используется там может я что-то не спросил но опять же мы уже долгом потно и Ям вопросы достаточно хорошие подробный вот у меня в целом приятное впечатление от общения с тобой потому что я услышал

    01:10:15 - 01:11:33

  • когда-то там в начале про Плюсы это тоже неплохая база она не Критична если её нет но если она есть скажем такой плюсик Мне кажется прекрасный вот поэтому у меня впечатление положительное и вопрос там я не знаю прошёл не прошёл интервю Ну скорее я бы сказал Да потому что явно есть понимание явно есть какой-то интерес что-то там читаешь где-то что-то глубже даже знаешь чем нужно сейчас вот где-то там чуть-чуть просто дотянуть попрактиковаться но это хороший ответ на практически все вопросы вот меня приятное

    01:11:02 - 01:12:24

  • вление Спасибо Да действительно очень очень круто то есть подсветить какие-то моменты которые те Поня что особено времени и круто будет вообще Я полагаю Ну да я Говори некоторые вопрос в иню Я даже задавал ть вглубь потому что я видел что ты знаешь вот но в большинстве случаев на скажем так на что ты сейчас шл на это ты отвечал вот то действительно просто по отвечать для себя от [музыка] практика СБО ВМ стрессовая штука вот а проходить его так это гораздо ещё стрессовые поэтому спасибо тебе приятно вление

    01:11:43 - 01:13:19

  • встречи Спасибо тоже за то что позвал было очень интересно тогда окей Давай чтото всё пока пока

    01:12:32 - 01:12:55

Менторы

Специалисты своей области, которые смогут помочь вам

  • Нигма Нурия
    Нигма Нурия

    Middle .Net Developer

  • Сущенко Татьяна
    Сущенко Татьяна

    Senior Product Manager

  • Гудков Денис
    Гудков Денис

    Middle Python Developer

  • Курочкин Константин
    Курочкин Константин

    Ведущий программист

  • Гудман Макс
    Гудман Макс

    Backend Software Engineer (PHP)

  • Гребенкин Антон
    Гребенкин Антон

    Senior .NET/C# developer

  • Ахназаров Фёдор
    Ахназаров Фёдор

    Middle DevOps Engineer | Tbilisi, Georgia

  • Шорохов Дмитрий
    Шорохов Дмитрий

    Middle C# .NET

  • Жуков Александр
    Жуков Александр

    Senior PHP-разработчик

  • Мазикин Павел
    Мазикин Павел

    Middle python developer

© 2024 HireGuru. Сделано в Санкт-Петербурге с hireguru.ru