Александр Ивлев

Александр Ивлев

Неделя
Jan 31, 2021 → Feb 7, 2021
Темы

Архив недели @ivlevAstef

Понедельник


Всем привет. Меня зовут Ивлев Александр. Если не скромничать то "Апостол программирования". Верю в swift и iOS. По званию team/tech lead. И мы переходим с кроссплатформы/ flutter в натив.

Краткий план: Понедельник: моя история. Вторник: олимпиады. Среда: DI, IoC, DIP, DITranqullity. Четверг: архитектура/структура. Пятница: собеседования. Суббота: хороший код. Воскресенье: опционально

Более детально: Понедельник: история жизни, карьеры, апостола. Поверьте тут много интересностей. Вторник: моё отношение к олимпиадному программированию и проф образованию. Среда: DI, IoC, DIP, DITranqullity. Раз уж я автор этой либы, то я не могу пройти эту тему стороной.

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

Писать буду много. Я ещё тот графоман :) но не являюсь активным пользователем твиттера, поэтому всё в новинку пока.

И первый день будет посвящен моей истории, под эгидой судьба или совпадение? Сама история условно будет поделена на три части: как стал программистом, кусочек до армии, после армии. Да, да я был в армии. Но про неё возможно в воскресенье.

И сразу вопрос: "а вы верите в судьбу?"

@mobileunderhood Лаги в кроссплатформе не вылечили или просто переросли ее?
Если честно, то я не любитель кроссплатформы. Не верю в то, что есть. Но был опыт и с xamarin (считаю на текущий момент лучшим решением в этом плане, люблю С#) и с С++, и с JavaScript вариантами. twitter.com/alectogeek/sta…

Ну, начнём. Под этим твитом будет о том как же я попал в эту сферу, и первые шаги в ней. И было это в 2004 году. Тогда мне было 13 лет, и познание компьютера заканчивались умение запустить игру на нём 😅

@mobileunderhood О, а почему в плане нет раскрытия этой истории. Почему переходите, с чем столкнулись, какой опыт был у команды разрабатывавшей кросплатформу и т д?
Ой. Кажется я написал не удачно. Я имел ввиду, что автор прошлой недели писал про flutter. Но немного про кроссплатформу будет. По желанию могу буду описывать опыт с С++ который был не самый как мне кажется удачный, но оно работает. twitter.com/spk_hdj/status…

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

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

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

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

Дальше относительно всё стандартно: Pascal, преподаватель который явно считал меня "средним", и я гипсе не способный нажать одновременно две клавиши 😂 в общем все условия, чтобы бросить это дело.

Но увлекло. Благо гипс сняли и нашлись курсы. Снова Pascal, но писали уже игры. Как же я в те времена хотел умеет две вещи: научиться двигать экран, и иметь больше 16 цветов. Библиотеку на 256 цветов, я так и не осилил подключить...

Это был 9 класс, и преподаватель по Pascal настоял, чтобы меня отдали в Высший колледж информатики. И небольшой факт о первых трёх лет программирования - в тот момент я был так увлечён, что от меня родители прятали компьютерный шнур - мог по 12 часов в сутки писать код.

И тут снова судьба/случайность. Нашёлся друг тоже помешанный на программировании. Не знаю у кого как, а у меня соперничество один из важных мотиваторов развития. А мы с ним "соревновались" во всём. Это дало огромный скачок в росте

А, что для вас является мотиваторов на работе или при саморазвитии?

И почему мне кажется, что я что-то делаю не так... В плане ретвитов. Вроде поток есть, но привязка твитов друг к другу, а не к первому. Постараюсь исправиться. Чесно, честно 🙄

И вроде история успешного человека - все время пишет код, удачные стечения обстоятельств... Но где-то в это же время я узнал о WOW. И "был человек, нет человека" :) или же?

Все играли в Warcraft 3? Так вот на тот момент я смог дойти до 7 миссии за людей и думал, что это конец - так как не был способен её пройти. Всё, что нужно знать о моих игровых способностях на тот момент 😂

И тут wow... Сколько же я убил на него времени. Иногда мне кажется, что в тот период 12 часов я писал код, и 12 я играл в wow. На остальное времени не было. Был период когда я желел о потраченно времени на игры, но кое, что понял.

А понял я две вещи: Игры хорошо развивают реакцию и умении работать с компьютером. Игры стали той зависимостью которую я могу контролировать. Клин клином вышибают - если у меня появляется зависимость, я её перевожу в игру, а потом отказываюсь уже от игры.

В общем если бы не WoW и StarCraft я бы сейчас не умел пользоваться мышкой нормально даже. Ну и клавиатурой. Правда 10 пальцевых набор познал намного позже.

Ваше отношение к играм?

Колледж прошёл весело. Учеба, программы, олимпиады, игры. Но надо думать над универом. Уточню - платно я бы не смог учиться, так-как это дорого было бы. Но и тут судьба/совпадение/удача.

Тут важны детали. Иду я вечером по колледжу. 5 вечера. Не помню чего я так поздно там делал. Подбегает, в коридоре, ко мне преподавать и говорит - "тут через пол часа олимпиада, хочешь поучаствовать?" Уточню: я в колледже занимался олимпиадным программированием.

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

Каково было моё удивление через неделю когда мне говорят: "ты тут в очный этап прошёл, тебе в Уфу ехать теперь". Я даже вначале не понял о чём речь. То был заочный этап и отбирались 30 первых. Чтож ехать так ехать.

Что там я про совпадения писал? :) Теперь самое интересное. В первый день очного этапа все собрались в столовой. Три мальчика сели случайно за один стол. Пообщались, послушали наставления. ничего примечательного. Но запомним этот факт.

В следующих два дня была сама Олимпиада. Олимпиада как Олимпиада, правда среди СУЗов. Занял я в ней третье место, почти второе. Надавали всяких призов, я ещё и самый младший участник был.

А теперь возвращаюсь к трём мальчикам. Эти три мальчика заняли 1,2,3 место на Олимпиаде. Совпадение? ;)

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

"И мы переходим с кроссплатформы/ flutter в натив.". Этот высказывание многие поняли не так как я хотел. Поэтому уточню - тут имелось ввиду, что прошлый автор недели писал о flutter, а не действие моей команды :)

Переходим к университету. Этот поток будет коротким, и связан с универом. Ну и судьбой/совпадением :)

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

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

@mobileunderhood Xamarin уж очень индусский фреймворк, в котором можно однажды случайно сломать проект, что он никогда уже не соберётся.
Так можно о любой технологии сказать. У нас джуны и xcode проекты ломают, так, что только 1 из 100 сеньоров способен починить, не пересоздавая :) Но не буду спорить, что у xamarin много багов. twitter.com/itscanbeblinch…

После сессии моё отношение к учебе "слегка" изменилось. Я стал ходить только на то, что интересно. Раз упорство на экзамены не влияет, то и смысл тратить время? :)

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

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

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

Я вот пошёл. К слову сказать на экзамене крупно повезло, и я сдал на 4. Но главное, что по итогу зимней школы, мы с приятелем создаём свою команду/компанию. У нас есть договор с игровой студией, на написание игры.

Писали мы игры под iOS. На Obj-C/C++. Библиотека для графики cocos2d (на тот момент даже без Х). Вообще про написание игры я могу много чего рассказать. Много было прикольных решений. Хорошее время было - работали у друга дома, на хаккинтош. Я приходил в 8 утра уходил в 12 вечера

В общем просуществовали 2.5 года. Написали 7 игр, выпустили три. За это время я чудом закончил универ. К слову сказать на 3-4 курсе в универе началось программирование и специализация. У меня была "супер компьютеры и архитектура процессоров".

Кто был внимательным заметил - компания 2.5 года. Началась на 3 курсе зимой. Учились уже 4 года. Да я год косил от армии. Поступил в магистратуру, но отчислился сам - было скучно. В итоге компания закрылась, я поработал в другом месте, и армия.

А в ауру вы вы верите? Ну там у одних людей в руках всё ломается, у других чинится?

История. Был баг - воспроизводился у тестера в 100% случаев. Как и положено - никогда у программиста. Пробуем по видео - повторить не можем. Приезжает в офис, даём устройство - повторяется. Тыкаем сами - не повторяется. Перепробовали всё - у него всегда краш, у других никогда.

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

Краткая выжимка: Сломал руку = стал программистом Умный друг = соревнование/развитие Случайная олимпиада = универ Случай+риск = своя компания Слишком много случайностей как по мне, и это только значимые.

Немного фактов по универу: диплом со средним балом ниже 4. Оценки: 5 - связанное с ИТ, 3 всё остальное. Из-за физики я кучу раз чуть не вылет. Был преподаватель-троль, но именно он научил писать коммерческий код, за что я благодарен ему. В универе я бросил WoW :)

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

@mobileunderhood Вы гитом вообще не пользуетесь?
Пользуемся. Но в рамках данного вопроса это равносильно пересоздать проект - всеже откатываются изменения. Да и в случае с xcode есть способы сломать проект локально на компе, но так что в git не будет изменений :) twitter.com/icarumbas/stat…

@mobileunderhood Дальше не менее интересно, замдиректора (Шимановский) пригласил меня к себе и со словами: “с этой бумагой ты можешь продать здание колледжа”, выдал мне доверенность на подписание ЛЮБЫХ документов от имени колледжа в течении недели.
А этого я не знал/забыл :) twitter.com/ad1Dima/status…

По активности людей, явно стоит писать часов с 8 утра по Мск :)

Моя история, том3 :) После своей компании где мы писали игры, до армии я успел немного поработать как С++ программист, и меня забрали. Поток будет о времени после армии. Ну или как я стал iOS программистом и апостолом.

Вот вернулся я из армии, не прошло недели, как я начал искать работу. Ну чтож... Моё самомнение быстро упало ниже плинтуса. Оказывается если тебя год бьют автоматом по голове, и не дают писать код, то всё забывается :)

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

Компания занималась написание аналога AutoCAD. Было много математики, и мало программирования. Продукт конечно интересный, но когда 50 программистов пишут в одну SVN ветку, и релизы создаются из этой же ветки, начинаешь задумываться...

Думал я не долго - три месяца. Пошёл искать работу. Не хочу никого обидеть, но тут как с чиновниками - люди которые ничего не умеют идут в iOS. Это шутка, но в каждой шутке доля правды. Я искал С++ или iOS работу, и офферы я получил только от iOS.

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

Начинал я в компании как Джун, через 2 года ушёл как team lead. Меня это досихпор печалит - 3 года в iOS и ты лид. Какой лид? За такой срок даже кодить то ещё не научиться, не то что программировать, а уже лид. И несмотря на суммарный опыт уже около 8 лет, снова смена компании.

Причин ухода было две: Команда не хотела даже смотреть в сторону swift - их всё устраивало. Проектов снова не было, и на работе протирали штаны. И когда начал искать работу, то быстро появилась третья - оказалось я стою минимум в 1.5 раза больше.

И так. Что происходит в это время: Я начинаю писать свою библиотеку DITranqullity. Цель которой лучше понять язык. Я устраиваюсь в Тензор, где swift 2.2 версии, и где есть опытные разработчики. Окончательно решаю, что не хочу быть С++. Так как влюбляюсь в swift.

Библиотеке будет посвящен целый день. Почему Swift? Я очень люблю строгую типизацию. Мне нравится, что многие ошибки можно обнаружить сразу. Мне зашёл синтаксис языка. Ну и он быстрый - не хуже С++ в производительность. Особенно с unsafe API.

Тензор. Чудесное время. Пока не появился С++ :) проект дал мне многое - хороший опыт в swift. Частично из-за необходимости заменить тайфун в проекте, я вывел свою библиотеку в общество. Опыт управления командой из 7 человек. Я бы и дальше работал, если бы не С++.

С++. Я люблю этот язык. Но то, что произошло в тензоре, это ужас. Намерения понятны - нужна общая логика на iOS и Android. Решений много, но руководство хочет С++. И тут совершается ошибка, которая технически испортила проект - берется С++ ядро с Бэка. 4гига.

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

Функционал входа iOS Джун написал 1.5 года назад. С++ Переписали этот функционал. Влили по тихому - никто даже не знал, до вливания. Итог - пол. года не было возможности войти в приложение. Пол года! С++ сеньоры, не могли сделать то что сделал iOS Джун за месяц.

@mobileunderhood Чую, сейчас будет ещё одно подтверждение, что писать бек и писать клиент - совершенно разные навыки :-)
Именно так. А ещё С++ под одну платформу, и кроссплатформенный С++ требует разного уровня. Для второго стоит читать документацию... Я там как-то ржал с того, как они сортировку открыли для себя - оказалось есть правила к оператору сравнения. Которое UB даёт если не соблюдать. twitter.com/ad1Dima/status…

Так я отошел. пригорает и по сей день, а прошло 3 года :) Из-за подобных казусов я ушел из тензора. Ушел в неизвестную компанию, с полным NDA. Проработал там три месяца. И сейчас вкратце опишу почему.

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

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

После этого я искал место поспокойней, и где должно быть хорошо. И такое место я нашёл. ЦФТ. О этой компании могу писать только в позитивном ключе. В ЦФТ я вел курсы, участвовал в конференциях, писал хороший продукт. И стал апостолом.

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

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

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

Почему же я ушел из ЦФТ? Мне не нравились две вещи: Халявка. Моя скорость разработки, обычно мешала, так как я хотел сделать больше чем надо, и мне приходилось себя замедлять. Я понял, что продукты связанные с банками не моё. На самом деле не знаю... частично жалею о уходе

Ушел я... в тензор. Пробыл там пол. года и снова ушел. За пол. года успел рассказать курс и один (или два) раза выступить. В общем не стоит возвращаться в компании, в надежде, что что-то изменилось. Тем более в большие.

И наконец, где же я работаю сейчас. Я работаю в Tassta. Да у компании есть нюансы, которые мне не нравятся, но есть два важных момента перекрывающих всё: Можно влиять на продукт в целом. При разработке iOS приложения вся ответственность за него, на разработчике.

Ну и третий пункт - я чувствую свою нужность проекту. Сейчас я тут на должности team/tech lead. Team lead назвать себя сложно - команда маленькая пока. Но как tech lead на проекте уже много чего поднято из руин.

@mobileunderhood Я правильно понимаю что если ты Апостол программирования, то кексей - Иисус ios?
😃 К сожалению лично, я с ним ни разу не встречался, но в чате часто читал его. Да возможно его так можно назвать - с его опыты, и с учетом, что он ведет курсы разные, может претендовать на такое звание 🙂 P.S. А разве не эксей... @Exey Как правильно? :) twitter.com/abbath0767/sta…

Это был "краткий" пересказ моей истории. О технических особенностях разных проектов, я еще расскажу в день архитектуры. А сегодня нас еще ждёт: История, как не надо зарабатывать деньги. team lead vs tech lead - отличия должностей. По желанию, могу что-нибудь рассказать.

@mobileunderhood Какие способы самые распространенные?
Каждый раз ломали по разному, и версия xcode меняет варианты. Сейчас можно сломать проект, если неудачно deriveredData почистить, а на проекте swiftPM. Иногда система/юзер случайно *.o файл ломает, и проект перестает собираться. Ну и шалавливые ручки любящие скрипты из инета... twitter.com/mgmzlm/status/…

Ну если отбросить git, то самый распространенный это конечно же конфликты в pbxproj файле. Которые или решают не верно, или автомерж иногда даже ломает.

@mobileunderhood 3. Как ты проводишь досуг и где берешь время, чтобы писать DITranquility?
Про DITranquillity позже, но частично ниже. Про досуг: Жена с дочкой мне придумывают. Иногда я играю на пианино для себя. Пишу код... да 15 лет его пишу, и все равно свободное время трачу на него. Недавно писал на kotline Russian AI Cup. Игры на телефоне. PC редко. twitter.com/SpectralDragon…

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

Хотел бы я написать - "был молод и глуп", но мне было 25... И решил я поиграть на фондовом рынке. Начал я с тинькофф инвестиций, и с маленькой суммы (моя месячная ЗП). И тут у меня все было хорошо - успешно спекулировал.

Через три месяца частично на эмоциях, частично из самоуверенности я взял кредит. Большой кредит. Да конечно я посчитал что в худшем случае я смогу его погасить, но почти не есть не пить придется. Нарушил главное правило инвестиций - использовать только свои средства.

И тут то все и началось. Я очень много раз совершал сделки с большим дневным профитом. Но и не меньшее количество раз ошибался. Вы думаете не повезло? 50/50 и т.д. Как бы не так:

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

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

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

К тому моменту я уже потерял половину первоначальной суммы. Да я упертый... Бота я писал долго, Самое важное что я написал - это умение прогонять бота и сделки используя историю. То есть тестирование. Это кажется легко, но в реальности сделка не делается по шелчку пальца.

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

Собственно говоря бота то я написал. После всех комиссий, и учета плохих сценариев поучилось среднее около 3-5% в месяц. Я даже его запустил. Он даже начал работать. И приносить какую-то прибыль. Но все это не про меня...

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

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

Некоторые выводы из этой истории: Когда дело касается денег, даже логичный человек может вести себя не логично. Спекуляции на рынке возможны, и на этом можно зарабатывать. Спекулировать надо используя свои деньги. Лучшая тактика - следовать одному плану.

Сейчас я рассматриваю это, как очень дорогой урок. Я стал лучше понимать рынок/экономику/политику. Мне пришлось просить повышение ЗП, благо повышали мне её без проблем. До и после этой истории обычно ЗП мне повышали без моего участия.

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

@mobileunderhood Ваш тред в одной картинке: ЗЫ трейдер - это не профессия. https://t.co/KqQXqsIh5j
Да почти так и есть. Только последний пункт слегка не так. Я прекрасно понимаю куда делись деньги :D twitter.com/Dmitry1228/sta…

А сейчас кстати есть прикольная история связанная с рынком и пользователями reddit. Которая показывает логичность рынка :) pikabu.ru/story/birzhevo…

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

Смотрю большинство играющих :) Напишу список любимых игр: Starcraft 1/2, Dota 2, WoW. Игры из прошлого, но в которые я и сейчас не прочь поиграть. Сам пересел на телефон: Clash of Clans, Among us. А вот в настолки почти нет, зато есть это :) twitter.com/mobileunderhoo…
notion image

И на последок: team lead / tech lead. Для меня оба типа лидов ориентированы в команду - их задача отстаивать интересы команды, а не менеджера. При этом оба типа лидов должны общаться с менеджерами - давать оценки, понимать план развития продукта.

Оба типа лидом могут выступать на конференциях. Скорей всего у них будут разные по содержанию доклады, но tech lead это не полный интроверт сидящий в углу и говорящий - тут не соблюден паттерн такой-то.

Если в команде оба типа лидов, то они обязаны коммуницировать. tech lead должен замечать, что программист хуже/лучше пишет код по вторникам, а team lead должен знать почему так происходит.

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

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

Какие проблемы я чаще всего наблюдаю: а. Совмещение этих должностей. В этом нет ничего плохого, кроме как большой разной нагрузки на 1 человека. б. Team lead не следит за мотивацией команды. с. Лиды соглашается на все, что говорит менеджер, не отстаивая даже сроки.

д. Tech lead не адаптирует код/CI/git под размер команды и структуру компании. е. Лиды не занимаются развитием команды. Лекции, занятия и т.п. ф. Расстрельный пункт: Лиды сами не мотивированы делать продукт. г. Лиды сами не пишут код. Это понижает их авторитетность.

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

@mobileunderhood Объясни плиз, как возможно потерять «бесконечность». Если они вложили Х рублей, в теории не могут потерять больше этой суммы. И как можно купить больше акций чем есть в обороте компании?
Начиная с 2008 года, потерять больше чем у тебя есть денег, почти не возможно. Брокеры обязаны за этим следить и закрывать сделки. Но потеря больших сумм возникает из-за "маржинальной торговли"/плеча - это когда ты берешь аналог кредита у брокера. twitter.com/westk0r/status…

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

Пример. У тебя было 100 рублей. Ты воспользовался плечём 1к2. То есть купил акций на 200 рублей. В течении дня цена на акцию упала на 10%. Итого твой убыток минус 20 рублей. Волатильность акции в среднем 20% например. Брокер предполагает - потери не больше 40 рублей у тебя.

Но ночью прошла новость - компания почти банкрот. В итоге при открытии цена на акцию падает на 50%. Брокер на такое не может отреагировать успеть - он тоже живет в рынке, и просто не успевает продать акции. Итого твой минус -20рублей + -100рублей. По итогу ты должен 20 рублей.

@mobileunderhood А ты куда нибудь выкладывал сорцы своего бота?
Нет. На то есть важная причина - кто-то решит им воспользоваться, потеряет например деньги, и виноват буду я. Мне такая головная боль не нужна :) twitter.com/westk0r/status…

@mobileunderhood Тогда ждем тред, как бросить Вов (да и остальные игры тоже)
Ой... Не осилю. Но было сложно :D Ломка была сильная. Да и досихпор есть небольшая. Но я понимаю, что есть другие дела, которые в перспективе мне дадут больше, чем игры. И я не прям бросил - я играю, но очень мало, и периодами. twitter.com/not_ogima/stat…

@mobileunderhood Год назад была же история, когда нефть ушла в минус tjournal.ru/analysis/16196…
О... да... когда это произошло, мой финансовый мир окончательно сломался :D Я сток статей перечитал, чтобы понять как такое вообще возможно - цена на товар отрицательная, и как работают фьючерсы. twitter.com/maratsafi/stat…

О вспомнил просто смешную историю на эту тему. В свое время до слез :) habr.com/ru/company/pro…

@mobileunderhood 3-5% в месяц выглядит весьма привлекательно. какие есть минусы, подводные камни? есть ли какие-то примеры исходников таких ботов, статей как написать бота самому?
Статью я так и не написал, но хотел. И в свое время не нашел. Есть отдельно про апи брокеров, есть алгоритмы описывающие определенные теоретические стратегии. Минусы очевидно - никаких гарантий. За пол. года 3-5% в месяц, не гарантирует, что в будущем будет также. twitter.com/DanVx77/status…

Завтра будет про олимпиады и проф. образование. Надеюсь на активное участие подписчиков. Темы холиварные :) У меня уже 10 вечера - надо готовиться к отдыху :) twitter.com/mobileunderhoo…

@anioutkajarkova @mobileunderhood У лицензии тоже куча багов было. Вроде значений переменных, которые не подсвечиваются по наведении мыши. Периодическая необходимость удаления bin/obj. И проблемы почти с каждым мажорным обновлением. А потом всё это было в swit, что-то до сих пор...
В xcode вообще не подсвечиваются переменные, не то что при наведении в дебаге, а даже просто в IDE то не всегда 😂 twitter.com/ad1Dima/status…

Это не баги, а мелкие неудобства. Вот то что дебаг падал ровно через 5 секунд, вот это да - баг так был :)

@ad1Dima @mobileunderhood Не замечала проблем со Swift, кроме долгого преобразования инструкций одной версии в другую. У Xcode баги бывают. Bin/obj - это баг ещё VS. Не все баги IDE - баги технологии или языка
В xcode со swift я уже понял в чем проблема - во мне 😅. Я слишком быстро меняю код, и он вечно глючит на постоянных обновлениях индекса. Ну и размер проекта влияет ещё. twitter.com/anioutkajarkov…

Вторник


Доброе утро/день :) Сегодня нас ждёт дискуссии о олимпиадах и проф образованию. Я сейчас все дела утренние закончу, и начнём.

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

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

Когда вы последний раз писали сами ну скажем алгоритм сортировки? А не использовали встроенную функцию сортировки?

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

Интересно - много кто не из России оказывается 🤔

В чистом виде на работе все алгоритмы сводятся к выбору - использовать массив/словарь/множество. Хотя кое-что полезное я всеравно использую из алгоритмов - это О-большое, ну или точнее оценку сложности алгоритма. Но и то даже если во всех местах будет O(e^N) это не заметят.

Так. А кто умеет оценивать сложность алгоритма? Тут я уже не могу предсказать распределение заранее :)

И возникает вопрос - и что? Алгоритмы/олимпиады нужны только чтобы собес пройти? И то в Яндекс. И вроде ответ очевиден - не используем, значит не нужно. Да раз в год и палка стреляет - но Google спасёт. И данных на мобиле обычно мало. В общем поток можно закрыть, или?

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

Самый распространенный формат это двух часовой. Ты запираешься от всего мира на два часа, и пытаешься решить 5 задач. Есть второй вариант, но командой из 3 человек. Там задач и времени побольше. Но у этих олимпиад есть одна общая черта:

Это правила сдачи задачи: Задача считается решённой, тогда и только тогда, когда прошла все тесты За неправильное решение штраф/кнут Чем быстрее решил, тем больше пряник Кстати школьные олимпиады имеют другие правила - там баллы считают от количества прошедших тестов.

И эти правила очень важны, так как воспитывают правильное отношение к написанию кода: Прежде чем зарелизить фичу убедись, что она работает во всех кейсах. Если в программе баги, то программиста не погладят. Делаешь больше - ценят больше P.S. на ЗП прямо не влияет :)

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

Чаще всего так происходит в угоду скорости. И если тестирование не увидело, то и пользователей не коснётся. Да и поправить можно же будет ещё. Но тут и кроется ловушка - суммарно скорость разработки падает, а пользователи испытывают дискомфорт, а иногда теряет 9.6лямов :)

Пример: Написали фичу, сразу в тестировании Тестирование нашло N багов Поправили Повторили 2,3 Выпустили Позже нашёлся ещё баг Поправили Выпустили Повторили 6-8

Итог: Пользователю пришлось скачать много раз приложение Пункт 7 != 3 - код забывается, это влияет на время правки. Пункт 3,7 != 1 - код будет хуже, так как будет добавляться, а не учитывать всё сразу. Иногда это приводит к переписыванию фичи целиком

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

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

@mobileunderhood @aarexer > Если команда состоит из олимпиадников - то несмотря на полный ужас в коде, продукт будет работать и развиваться, и не имеет багов. Звучит максимально дико по 2-м причинам (минимум): - программ без багов не бывает - "полный ужас в коде" повышает стоимость развития и поддержания
А вот "программ без багов не бывает" это ложное утверждение. Если отбросить баги обусловленные физическими процессами (радиацией) то программы без багов бывают. Например софт: 5миллионов устройств 5 лет работы - ни одного сбоя. Отсутствие бага это не доказывает, но всеже. twitter.com/Shoonoise/stat…

Тесты писать яб сказал с олимпиадным опытом намного проще, чем без него. В силу наличия навыков декомпозиции любой задачи. А вот гибкость тут да. С другой стороны они перепишут класс, быстрее чем обычный программист поправит одну строчку в нём 😂 twitter.com/aarexer/status…

@mobileunderhood @aarexer Ну во первых еще брукс писал (не зря же я его читал), что 5 талантливых разработчиков могут перформить как 10 обычных. Только это не скалируется, 50 талантливых будут работать как 25 обычных. И дело тут вообще не в олимпиданости. Ну и какие фичи делают в телеге?)
Открой чат телеги с изменениями :) С утверждением согласен, правда пропорции 1/2 кажется сильно заниженным. Возможно тут они лишь условность. twitter.com/tygeddar/statu…

@mobileunderhood Ага, конечно. Учитывая, например, что китайские производители смартофонов любят вносить изюминку в свои устройства, баги появляеются просто от того что они не следуют референсу.
Ну это же тоже баги - просто не в твоей программе, а в системе. Я не утверждаю, что в андройд/iOS можно написать программу без багов. Я даже в это не верю. Я говорю, что программа без багов может быть. В том примере там программа сразу над процессором идёт. twitter.com/caiiiycuk/stat…

Спасибо. Ну я и писал - холивар. А он удался даже больше чем я хотел 😃 Правда год ток начался ;) twitter.com/aarexer/status…

@mobileunderhood О, а расскажи про доказуемость программ с сайд эффектами, было бы очень интересно почитать
Подумаю. Да конечно это идёт больше к промышленной разработке - там где нет слоёв в виде систем, которые имеют баги. Но я сам не участвовал - был джуном на тот момент, но был в команде где это делали, и видел. twitter.com/Shoonoise/stat…

@aarexer @mobileunderhood Звучит так, будто читаемый код - это не что-то, чему учишься. А по умолчанию присутствующий скилл у всех, кроме тех, кто занимался спортивным программированием.
Да. Этот скилл развивается. И олимпиадники тоже учатся ему. Если им это нужно. Я помню случай - человек пишет код, но понятный только ему. Решение - Не будем его пускать в команду, пусть пишет один. А потом - "он не способен работать в команде"... Удивительно 😄 twitter.com/KichatovEvgeni…

Что-то получилось сильно холиварно 😅 пожалуй буду поаккуратней в следующих твитах, а то так времени на работу не хватит. Тему про олимпиады не буду дописывать, чуть попозже начнём про проф образование.

Не был на олимпиаде, не программист! Писать багов, пилить фичи, декомпозировать, да че уже, думать можно только на олимпиаде! P.S.: Я три раза в универе участвовал, занимал первое место каждый раз. До сих пор думаю, что единственная польза от этого занятия это 5ка автоматом) twitter.com/mobileunderhoo…
Чёрт. Ты мне напомнил - главное забы. Хоть я и был призером всероссийской СУЗов, но суммарно в обычных 2 часовых олимпиадах я участвовал раз 30, если учитывать codeforce. Ну и был курс по решению этих задач. В общем я не прям олимпиадник жёсткий. twitter.com/tygeddar/statu…

@aarexer @mobileunderhood Чё? Недавно вот буквально целую библиотеку переписал, и тесты не сломались (и API, разумеется, тоже). Я сразу заворачиваю с CR любые изменения в существующих тестах, не глядя в код даже. Потому что хоть весь проект перепиши, но снаружи этого никто заметить не должен.
В моем мировоззрении вот это то как должно быть у всех :) И, да, это сложно. P.S. Часто переписывать большие куски кода, точно не то к чему надо стремиться. Но если переписывать, то только так :) twitter.com/mudasobwa/stat…

Давайте пока опрос что-ли проведем, пока я работу работаю. Какое у вас образование:

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

Начну я с наблюдения - все чаще замечаю, что в iOS идут люди с экономическим образованием. Видимо чувствую, где денег больше, а требования ниже :)

Дальше про моё мнение. А оно у меня крайне не постоянное :) Когда я закончил универ, мне казалось, что зачем я вообще его закончил? и вроде ФИТ, но что-то данные знания, не очень пересекались с тем, что хотят работадатели.

Ну знаю я эту сетевую модель ISO (ой простите osi), или нам рассказывали про отличия RISC CISC MISC. За 8 лет не пригодилось, второе даже на собеседования не спрашивали. Тем временем на собеседовании, дают кусок кода и говорят: "что в нем плохого"

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

И первых лет 5 я как добросовестный студент, считал, что зря я закончил универ. Но не мог себе это признать, поэтому на собеседования любил спрашивать: Чему будет равно 0xC1 + 0x0B Представление float в памяти компьютера Ну последнее еще хоть как-то полезно.

Что изменилось со временем? А поменялось две вещи: Люди которые даже знали это, не всегда могли писать код. Люди которые способны ответить на эти вопросы, стали появляться все реже и реже. Ну и возраст/опыт.

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

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

И вроде бы на этом моменте я должен сказать "ИТ образование не нужно" идите на курсы, и т.п. Но тогда поток быстро стухнет, и сейчас я считаю, что всеже пользу оно дало, но польза на 4 года не тянет.

Какие же плюсы в проф образовании я вижу: Очевидно корочка. Которую меня пару раз зарубежные компании просили. В 17-19 лет человек редко думает о будущем - хоть чем-то себя занять. Процент людей с моего потока и оставшихся в ИТ это доказывает - около 25%.

От junior в ИТ не мобиле, иногда спрашивают университетские знания. например от С++. UML - то, что я не вижу на курсах, но то что помогает. Если не знаете - советую, помогает коммуницировать при общении о архитектуре/паттернах, иногда даже с заказчиками.

Float - его там вдалбливают. После универа писать floatVar == floatVar2 отпадает на этапе зародыша... Хоть немного, но знание истории ИТ полезно. Просто чтобы осознавать, что ИТ не камнем выбито, а очень динамичная сфера, но при этом ничего нового с 60 годов почти нет.

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

Иногда может повезти с преподавателем. Но тут как и с курсами - повезет не повезет. Универсальность - с проф образованием можно например с iOS легко перейти в F# разработчики, просто за счет того, что в универе давали всё.

И все. То, что я написал это на 1.5 года к сожалению тянет из 4 лет. При этом 1,7 пункт нельзя получить читая интернет. 9 можно, но я не встречал людей которые по собственной воле, берут и учат разные языки и технологи... После вышки иногда да, без нее пока нет.

Ну и немного в сторону. Я слегка преподавал, то там то тут курсы, даже студентам из ИТ. Да похвастаться, что я обучил 1000 человек не могу. Ели как на 50 наскребу. Но на текущий момент, ученица с 30+ возрастом и гуманитарным образованием лучшая кого я учил.

@mobileunderhood 3. Опыт публичных выступлений и публикаций
А вот это хорошее замечание 👍. Про софт скилы я забыл. Еще не для всех, но кому-то сдача экзаменов еще развивает качество "выкручиваться из любых ситуаций", что полезно в любой сфере :) twitter.com/VrednayaVedma/…

Если про образование холивар не зайдет, то напишу сегодня еще про то, где же мне пригождаются знания алгоритмов. Просто алгоритмов, уже не связанное с олимпиадами.

@mobileunderhood Например литература, должна как раз развивать психику и мышление. Это подготовка к философским абстракциям и вероятным научным открытиям. Экономика должа была бы предупредить твою ошибку с торгами. Биология должна бы предотвратить вирусную истерию. И. т.д.
Это зачет. Жалко только "должна была" :( Например школьная литература мне этого не дала, но репетитор по ней за пол. года отлично развил подобное - но из школьной программы он ничего не давал. twitter.com/ad1Dima/status…

Холивар на проф темы зашел слабее. Надо было высказаться менее нейтрально :) Как и обещал 10 алгоритмических задач, которые взяты из коммерческой разработки. Что-то притянуто за уши. Что-то точно не вспомнил.

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

difference(from:by:) - думаю iOS ребята знают, что это. И знаю, что только с iOS 13. Суть функции выдать какие элементы добавились/удалились относительно двух массивов. У меня есть похожая и поддерживающая еще обновление.

Когда-то я делал AR. Задача: есть сообщения с gps координатами. Сообщений много, координаты могут пересекаться. Без сторонних либ на iphone4 сделать показ в реальном времени этих сообщений в AR. На экране окошки сообщений не должны пересекаться.

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

Сделать аналог главного экрана apple, с возможностью менять размеры иконок (не только квадраты). Одной коллекцией тут не обойдешься. Самый главный алгоритм тут - заполнение.
notion image

Когда писал игры. Там много чего: кривые безье, матрицы принятия решений, расчет физики, поиск пути...

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

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

Можно сюда приписать всякие сложные деревья ифов. Когда логика сильно ветвистая почти как алгоритмы пишешь :)

И приписать структуры данных. Тут скорее наоборот - бывает вижу когда код можно написать лаконичней если использовать например Set за место Array.

Пример с детскими книжками - ну а почему бы и нет? :)

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

Напоминаю что завтра день спокойный. Вначале расскажу немного теории, потом историю появление DITranqullity, что это вообще такое, и про то какие трудности были при её написании. Ну и видимо по подробней про быт, и где же я беру время на подобное... twitter.com/mobileunderhoo…

@mobileunderhood А что за софт?) Вымышленный или реальный? Можно часть багов списать на операционку - на pixel пуши приходят, а на сяоми не приходят. Это баг сяоми или приложения? Вопрос философский)
Софт реальный. Это была "система" под американские ТВ приставки. Три года разработки, и релиз на 5 миллион устройства. Меняют раз в 5-7 лет их. Крутилось 7-8 потоков на нём. И например задача получить список каналов это целый квест - это вам не REST API :) twitter.com/sagus_helgy/st…

Был в компании до армии. Но не долго из-за армии. Всего 3-4 месяца. Но в плане подходов к разработке, качеству это совершенно другой опыт. Например всё держалось на код ревью и профессионализме. Тестирование во время разработки не было. Код + самопроверки.

Но там над каждой строчкой думать по дню надо было. Помойму что-то около 50к строк суммарно, за 3 года в 10 человек.

@mobileunderhood Мой негативный опыт с олимпиадниками упирается в подход к решению проблем. Олимпиадники просто не решают проблему. Они не вникают в суть проблемы. Просто делают что бы работало. И обьяснить ценность и важность построения модели проблемы невозможно.
Я такое могу сказать о большинстве разработчиков. Но это скорее вопрос мотивации - какая мотивация у разработчика понимать бизнес? Иногда и по рукам дают за такое... Вообще Tassta первая компания где меня не бьют по рукам за инициативность... twitter.com/daloog/status/…

Среда


Доброе утро/день. Сегодня в программе: Чем занимается DITranqullity Мой досуг, и где я нахожу время Всякая теория близкая по созвучию к библиотеке История библиотеки Что-то ещё, если хватит времени

Начну с краткого описания библиотеки DITranqullity, чтобы все понимали о чём вообще речь. Библиотека занимается внедрение зависимостей в языке Swift. Аналоги есть во многих языках: Java - dagger, C# - autofaq, swift - swinject, Obj-C - typhoon.

Но это аналоги по тому, чем библиотека занимается. Существуют разные способы реализации внедрения зависимостей, можно и без библиотек. По API библиотека схожа с swinject и autofaq, но отличается от Dagger. Если мне подскажут аналог по API в андройде буду благодарен.

На библиотеку я убил много времени за 4года. За последний год я участвовал в telegram конкурсе дважды, в FunCode, в Russian AI cup. При этом я работаю и не всегда ровно 8 часов в день У кого-то то возник вопрос - где я нахожу время на это? Постараюсь ответить

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

Но есть то, что отнимает от саморазвития: Частный дом. Зимой снег, летом помощь в огороде. И куча другого. Семья. Есть дочка. Игры/лень/кино - периодами находит на меня. Ну а ниже постараюсь описать +- из чего состоит моя неделя.

В недели у нас 24*7 = 168 часов. Со сном у меня сложные отношения, но в среднем 8 часов. Иногда 6. Итого остаётся 112. Работа. Для простоты считаем 8 часовой день. В реальности всё сложнее. Итого 72 часа осталось. Эти 72 часа +- есть у всех.

Ем я чаще всего два раза в сутки - день и вечер. Но даже если три, то воспитание сказывается - ем по "армейски". Приблизительно так: 375 мин + погрешность = 130 минут. ceil(130 мин) = 3 часа. Итого 69 часов в запасе.

Частный дом. Сегодня я чистил снег минут 30. Бывает и 2 часа. Весной его надо откидать - почти весь день. Летом картошка отнимает 2-3 дня. ещё есть теплицы. Что-то ломается - чинить. В среднем я думаю за неделю набегает часов 5. Итого 64 часа. И да, я не фанат этого :)

Следующая важная категория - семья. Сейчас из-за твиттера уделяю ей меньше времени. Но это около 1.5-2 часа в будние, и от 4 часов в день в выходные, Иногда все выходные. За неделю минимум 20 часов. Минимум достигается обычно во время олимпиад. Итого 44 часа осталось.

@mobileunderhood По способу объявления зависимостей напомнило Toothpick >_>
Посмотрел. Да он ближе даггера по API, но не полный аналог. В swinject (самая популярная) / DITranqullity, классы программы никак не модифицируются под библиотеку. У toothpick есть использование атрибут. А вот kodein помойму очень похож. twitter.com/evolitist/stat…

Отвлёкся. Следующая категория. Перемещения. Тут я стараюсь экономить как могу, но люблю ходить ногами. На работу, с работы, в магазин. В будние в среднем выходит час. По выходным - это скорее к категории семья. Итого: 44-5 = 39 часов остатка

Игры. Сейчас я играю в clash of clans. Месяц назад не играл. До этого 5 месяцев назад поиграл в WoW пару месяцев. Постоянства тут нет. Когда играю это 1-2 часа в день. Период игры около полу года в год. Поэтому берём среднее: 1 час в день. Итого: 39 - 7 = 32 часа

Кино. И сюда прибавим иногда похоливарить в телеге. В кинотеатры хожу крайне редко - считаю, что туда только ради картинки крутой идти стоит. Чаще смотрю дома. Как и с играми - периодами. В среднем за год я смотрю фильмов 20. 50 часов в год. Итого: 32 - 1 = 31

Хобби/спорт. Играю на Пианино. Около 2-3 часов в неделю. Занятия спортом - 3 часа в неделю. Страдают чем-то не понятным, но очень захватывающим - 1 час в неделю Итого: 31 - 7 = 24

Ленюсь. Периодами. В прочем 30 минут поваляться в кровати не прочь каждый день. Ну и сюда припишем проблемы со сном - долго не могу уснуть, в силу неспособности перестать думать о коде/планах. Это час в день. В период надобности сводится к нулю. Итого: 24 - 7 = 17

@mobileunderhood Тогда, в принципе, если поработать тянет всегда, и от этого ощущается бесконечный кайф, то вопроса "откуда время?" не возникает. В этом случае время всегда найдется, например как у меня поваляться на диване)
Да программирование спустя 15 лет кодинга осталось хобби и по сей день. Хобби за которое ещё деньги платят. Если я не за компом, то вполне способен в голове писать около 200 строчек кода, после чего их восстановить за минуты на компьютере. twitter.com/pomidoroshev/s…

Как мне тут напомнили - естественные процессы. Опять же тут сказывается воспитание - не задерживаюсь в туалете. Но за неделю набегает как бы то не было. Пускай будет час. Итого: 17-1 = 16 часов

Ну и вроде всё. Итого 16 часов - 2 часа спишем на память мою :) В экстренных (олимпиада, ну или ЧП) сокращается лень, убираются игры/кино, иногда снижается коммуникация с семьёй. Последним я не горжусь. 14 часов на себя. Чаще всего это кодинг. Сейчас твиттер ;)

Перейдём к короткой части теория про DI, DIP, IoC. Не знаю зачем это. Мне кажется в наше время все и так уже знаю об этом всё. А пока опрос - знаете что такое DI, DiP, IoC?

О точно - я же люблю поваляться в ванне ещё 😂 вот и два часа забытых которые я в конце написал. А по поводу снимать куртку в лифте. Даже более скажу - я ещё и рашнуровываюсь в лифте 😅 twitter.com/0xfe0d/status/…

О, вот это чудо щас было. пишу код: let deadline = .now() + .seconds(...). Тип переменной не указан. И мне autocompletion достроил .seconds... Потом компилятор опомнился, и начал ругаться, что не знает, что такое .now() без типа. Что это было вообще O_o

Считаю, что время можно экономить гораздо эффективнее. Например: Чистить зубы в душе Бежать на работу. И спортом занимаешься и в офис успеваешь Пить кофе прямо в туалете twitter.com/mobileunderhoo…
Где-то на просторах Китая есть реклама, что ходить по нужде нужно в душе - чтобы воду экономить :) И коллеги рады твоему приходу - надевают прищепки на нос :) Не знаю где тут экономия. Возможно я не пью кофе, чтобы понять прикола. twitter.com/DrKottof/statu…

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

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

Зависимость: когда одна сущность, знает о другой. Если модули: один модуль подключает другой модуль. В языке обычно называется import Если классы: один класс (A), использует на прямую другой класс (B). Обычно это означает, что удалив (B) придется изменить (A).

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

Контроль: когда одна сущность, вызывает какое-либо действие в другой. В ООП можно смело говорить класс, а не сущность. А действие это вызов функции в любом его проявлении. lambda, closure тоже функции.

Первый принцип DI - Dependency Injection. Внедрение зависимостей. Он утверждает, что зависимости не должны создаваться внутри сущностей, а должны передаваться из вне.

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

В чем профит? Проще подменять и контролировать зависимости. Актуально для тестирования. SRP - ответственность за создание зависимостей уходит за пределы класса. Что вроде бы хорошо. Не надо искать зависимости по всему классу - они видны сразу.

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

DIP Dependency Inversion Principle - принцип инверсии зависимостей. Не связан с DI на прямую, хоть и созвучен в названии. Принцип утверждающий, что сущности не должны зависит друг от друга на прямую, а должны зависеть от абстракций.

Своими словами, так и научился объяснять. Ибо ну, что такое абстракция? Интерфейс/протокол? В общем случае абстракцией может быть даже класс, а интерфейс/протокол может не быть абстракцией. Ух надеюсь сейчас не полетят тухлые помидоры.

Но при этом у меня есть пример. Берем кусок какой-то архитектуры: -> Presenter -> Interactor -> Network. Пользователь тыкает кнопку, presenter что-то делает, передает interactor-у, то посылает запрос в сеть. В коде будет import interactor и import network присутсвовать.

А что если мы захотим сделать, чтобы в коде был только import interactor? То есть будет так: presenter -> interactor <- network В этом случае одна зависимость была развернута, относительно первоначального варианта. Как такое сделать чуть попозже.

Окей как разворачивать зависимости вроде бы понятно :D Но как понять какое направление "верное". Возвращаемся к "абстракции". И тут я утверждаю - interactor это абстракция, в отличии от network. Даже если interactor модуль с классами. Почему?

И тут вот и затык. Абстракция, это что-то не реальное. View вроде бы реально - во на телефоне рисуется. Сетевой запрос - ну вроде тоже в какой-то степени реален - вон сервер стоит. А интерактор что такое? Это набор бизнес правил.

Вообще тут есть моя любимая картинка, которая показывает, что абстракции сильно зависят от наблюдателя. То есть физически кошка это один объект, но её абстракция для разного человека разная.
notion image

IoC, Inversion of Control - принцип инверсии контроля/управления. На фоне прошлого выглядит даже простым. Это ситуация когда контроль идет "обратно" направлению зависимостей. Чаще всего достигается паттернами: delegate, callback...

Ну и если рассматривать наш пример из DIP: presenter -> interactor <- network - это зависимости. Но мы по прежнему хотим, чтобы interactor вызывал метод для получения данных. Рассмотрим один из вариантов как это сделать:

Для этого можно рядом с интерактором написать интерфейс/протокол с методом "получить данные" А в модуле network реализовать этот самый интерфейс/протокол. Тем самым interactor будет использовать протокол, но вызывать при этом метод внутри network модуля.

@mobileunderhood Жутко читать про машинный подсчёт траты времени на семью. Особенно "из-за твиттера уделяю семье меньше времени" в то время как другие категории не ужались.
Что-то даже грустно стало. @Tarasminin прав. Написанное мною выглядит не очень красиво по отношению к семье. В своё оправдание, могу лишь сказать - все не так плохо, как может показаться на первый взгляд. В отношении семьи, модель сильно упрощенная и приблизительная. twitter.com/Tarasminin/sta…

Чуть попозже история библиотеки. Надо работу доделать.

Что-то вспомнилось. Текст не влез целиком, поэтому картинкой.
notion image

Мою жизнь разобрали по косточкам, ну ладно :) Надо следовать плана, и все-же рассказать историю появления DITranquillity. Я обещал. Поток про библиотеку.

Библиотека появилась уже давно. Писать я её начал или на swift 2.1 или на swift 2.2 И цели её выкладывать на обозрение не было. Цель была другой - изучить язык, и мне показалось, что подобная библиотека сможет справиться с этой целью

Был это 2016 год если верить гиту. Откуда взялось название. Над названием я наверное думал дольше, чем над тем что бы сделать. Было понимание - хочу назвать библиотеку как-то связано с Typhoon (популярная библиотека для Obj-C)

Вначале я думал о другом виде бедствия - смерчь, ураган, и т.п. Но после понял - так не пойдет. И решил пойти от отрицания. Почему? в Typhoon мне не нравилось одна особенность - неверный граф зависимостей приводил к непонятному крашу в рантайме.

В какой-то момент, не помню уже в какой, было придумано слово "спокойствие" с лозунгом: "пользуйся библиотекой, и будешь спокоен за свои зависимости" :) Так появилось Tranquillity. Приставку DI я добавил от старых привычек добавлять приставку у библиотеки и её классов.

Да подход к разработке библиотеки которую не планировал показывать в свет, конечно глобальный. Почему кстати DI контейнер? Typhoon мне не нравился, а Swinject на тот момент был очень сырым. Поэтому хотелось свой. И по сложности не самая тривиальная библиотека.

До этого я уже успел написать свой SIALogger на swift, не помню есть он в гите или нет. Но с того момента этот логгер сильно улучшился, и современной версии точно нет в гите. Иногда подумываю выложить.

Вначале я формализовал, чего я хочу от библиотеки: Синтаксис похожий на autofaq (C# библиотека) Защиту от крашей в реальном времени как с тайфун Максимально понятное описание проблем Интеграцию со Storyboard, на тот момент, я еще ими пользовался.

Первоначальная идея была основана на исключения - каждое получение объекта могло было кинуть исключение, с понятной ошибкой. Много синтаксиса было скопировано со Swinject. Из-за хауса в голове, названия были то из Typhoon то из Swinject, то из autofaq - в общем никакой структуры

На тот момент я написал статью на хабр, назвал версию 0.9.5, и был готов уже выпускать первую версию. Откуда взялся хабр? Я же не хотел выпускать библиотеку в белый свет...

На решение выложить её в open source повлияло несколько факторов: Она работала! :) Она нравилась тем, кто ей пользовался. Swinject на тот момент все ещё имел кучу багов, и был единственным для swift.

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

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

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

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

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

Что же я такого решил? Я смог придумать как подружить библиотеку с опционалами. Тот кто работал в swift с generic знаю, что у него много проблем. Картинка с решением, для людей знакомых со swift.
notion image

И это послужило отправной точкой, переделки всей библиотеки. На то, что я хочу. Вдобавок мои знания swift уже были хорошими, и я знал как оптимизировать код. P.S. Кстати одну хорошую оптимизацию Swinject потом перенял и себе.

То есть только к третьей версии я успокоился так сказать. Я добился того, что так долго хотел: Сделал удобный, оптимальный синтаксис Сделал проверку графа зависимостей на старте приложения Сделал понятные ошибки Добился "спокойствия" :)

Вот пример с сегодняшнего дня. Я много отвлекаюсь на твиттер, и поэтому менее внимательный. Как итог когда я забыл зарегистрировать новый класс, библиотека мне это написала сразу при запуске программы. Swinject упал бы когда я сделал достаточно большую цепочку действий.
notion image

Третья версия вышла в Сентябре 2017 года. На ней синтаксис библиотеки остановился. Да с момента выхода добавилось много возможностей, Но API библиотеки с 2017 года не менялся, почти:

В середине 2020 года, я выпустил 4 версию, в которой сильно улучшил проверку графа зависимостей. И сделал graph api - то есть теперь любой желающий может получить граф зависимостей в своем коде, и как-нибудь его проанализировать. Поэтому синтаксис проверки графа, чуть изменился

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

Про мотивацию делать библиотеку: Вначале изучения языка swift и его изменений Потом интерес к сложной задаче После желание визуализировать граф зависимостей Звёздочки на github Сейчас мотивация развивать иссякла, только поддержка. Звездочек слишком мало ;)

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

В случае с DI контейнером, мы описываем из чего состоят классы. То есть пишем такую lite версию API класса: Описываем как его создавать, какие протоколы от реализует, какие зависимости имеет. После чего библиотека магическим образом, создает этот класс и его зависимости.

Мне такой подход нравится тем, что он не требует модификации основного кода, под нужды библиотеки. Минус его конечно в том, что приходится писать доп. код. Поэтому я очень сильно старался, сделать наиболее лаконичный синтаксис.

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

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

Последнее особенно интересная возможность. Модификаторы позволяет дополнить информацию о внедряемом объекте. Например many, говорит, что нужно внедрить все объекты соответствующие указанному протоколу.

@punknavsegda @mobileunderhood Этож тупа реклама Clash of Clans. Вот это ты повёлся! Хехе
Вот, хоть один человек понял :D И WoW еще. twitter.com/osmi8_/status/…

Так... Я уже боюсь это писать. Но завтра у нас тема архитектура. А тема сама по себе то уже холивар вызывает. Ох что завтра будет... когда я начну писать... Короче готовимся, будет жарко. twitter.com/mobileunderhoo…

Завтра:

@mobileunderhood Расскажи, зачем в принципе использовать библиотеку для этого (особенно, если граф зависимостей статический)? Что будет, если написать эти «специальные классы, которые будут создавать другие классы руками»?
Как автор библиотеки подобной я должен сейчас рассказать, что весь мир обрушится и т.п. :D На самом деле ничего. Написание своих фабрик, хуже только одним: Гемора больше в не тривиальных кейсах. Ну и скорей всего не будет однообразия со временем. twitter.com/AndreyMishanin…

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

При этом свои фабрики имеют и плюсы: Никакой магии. Код проверяется при компиляции (ну циклы правда нет) Работают быстрее, но это можно заметить с трудом где-то с 5к зависимостей.

Кто-то пользуется, кому-то нравится. Я пользуюсь тоже. Мне нравится простота. А так по своей сути это как SnapKit или использовать anchor для констрейнов. Первый просто чуть красивее.

@mobileunderhood Как вы можете этим хвастаться? Это же жесть. У вас раз в 10 больше разработчиков чем нужно. Какая зона ответственности у одного разработчика? Одна кнопка?
И чего у меня эта запись всплыла в уведомлениях. Мне же Сбер лучше не показывать... это как красная тряпка для меня. 200 !@# разработчиков, над одним мобильным приложением... это же жесть... Ладно уже вечер надо отдыхать. twitter.com/d_KyBa/status/…

Четверг


Доброе утро/день. Сегодня у нас архитектура. Постараюсь писать максимально сухо. Буду описывать с начала карьеры все архитектуры которые я еще не забыл и хоть как-то помню. Один поток одна архитектура. В конце про swiftPM. Но вначале что такое архитектура?

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

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

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

Вот пример - недавняя статья на хабре от додо пицца. Вроде очевидно, что выпиливать БД из приложения человеко-месяц это много. И иметь 3300 вхождений. Но возможно за три года, эта архитектура сэкономила им человеко-год, по сравнению со всеми другими. P.S. но все-же нет :)

Начну с далекого прошлого. Первая архитектура, которую я увидел, была будучи стажером. Там была игра "нанофутбол" - скрестили чапаев и футбол :) Если давать аббревиатуру, то что-то типо: SSM - SceneSingleModel

Каждый экран был сценой. Переход между сценами, был внутри сцен - просто создание. Сами сцены почти целиком в одном файле. Была вынесена физика отдельно, и каждая кнопка. Сцена была активной - обрабатывала нажатия, запускала физику, обновляла UI.

Single - все общие данные хранились в одном месте. Более того был один файл, который подключал больше полу проекта (это С++ делал include половины файлов)

Model - немногочисленные модели, хранились отдельными файлами. Они были пассивными.

Так как было это очень давно, то мало уже помню. Когда я пришел, я много чего менял, не помню уже что. Но одно было точно хорошее архитектурное решение: Я разделил файл со всеми include. Время сборки с 10 минут уменьшилось до 2 с половиной.

Следующие архитектуры были тоже связаны с играми. Но они были моими. На самом деле описывались они просто: SM - SceneModel. Правда моделей было много, и разных.

Как и в прошлом примере, все переходы были из сцены в сцену. Сцены были активные - нажатия кнопок, обновление UI, физика и т.п. было в них. Тут мало отличий.

А вот игровые модели (не меню) отличались сильно - много логики было перенесено в них. Они хранили в себе и физическую модель, и визуальную. У них был метод update. И был общий абстрактный класс. Но это были ООП модели.

Только под конец написания игр, я узнал про КОП, и успел оценить насколько он в играх лучше ООП. КОП - компонентно-ориентированное программирование. Проще всего показать отличие двух подходов на примере:

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

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

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

Следующий проект. Аналог AutoCad. Более 10миллионов строк кода, и еще библиотеки внешние в виде бинарей. Целиком эту архитектуру я не представляю, но приблизительно так: MFCM = MainFeaturesCommonMath и One branch SVN - важный аспект.

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

Каждая фича имела предоставляла информацию о том, как к ней можно попасть из меню. Имела стартовую/ые точки. Если фича была с настройками, то имела свой экран. После этого фича взаимодействовала с MathCore. Фичи тоже могли что-то рисовать на главной сцене.

Common - это не один модуль, а куча модулей, с различными вспомогательными функциями, или макросами. Его использует всем кому не лень.

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

И последнее one branch SVN - я его выделяю, так как тут это было очень плохое архитектурное решение. 50 разработчиков постоянно вливали свои изменения в одну SVN ветку. Даже размер проекта, не помогал избегать конфликтов. Но не это главный минус:

Главный минус был в том, что не было проверки отдельных фич. Даже фичи, которые еще не были написаны, они уже были в ветке. Релизы тоже были из этой же ветке. Это влияло на качество софта. Для показа приложения, был специальный человек который умел тыкать так, чтобы не упало.

Ну и наконец, мобила. В первой компании я не помню всех проектов, и что там было, кроме одного. Это была моя архитектура: MRCVAE - MainRouterControllerServiceModels репозиторий git, с ветками. Команда 4 человека. Срок разработки 3-4 месяца. Как-так :)
notion image

Main - это наш appdelegate, который создавал Router, и запускал некоторые сервисы. Все сервисы создавались с помощью ServiceLocator-а. Сервис локатор создавался в appdelegate и передавался в роутер.

Роутер на основе authService создавал и показывал один из двух экранов. При создании экрана/ViewController-а ему через конструктор передавались нужные сервисы, и также сам роутер, но как протокол. DI :) Роутер реализовал с 10 разных протоколов с методами аля: show{Name}

Экран это был VC состоящий из отдельных View, и обрабатывающий разные события нажатия. Имел свой xib файл. И вызывал в сервисах нужные методы, которые с помощью callback возвращали результат.

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

Дальше шли сервисы. Они отвечали за проверку данных, и получении информации из БД/сети. Но в них не было реализации получения данных по БД/сети. Они вызывали у специальных {Name}Transfer метод, который уже делал запрос в сеть или бд.

Но реализация Transfer была одна, прикрытая разделенными протоколами. Он был не сильно умным и просто вначале делал запрос по сети, если запрос удался, то записывал данные в БД, если не удался, то получал данные из БД.

Сетевые запросы делались с помощью webAPI, который был простенькой оберткой над NSConnection, и лишь добавлял единообразный парсинг. БД это была маленькая, но сложная обертка над Realm (он в тот момент был маленький), которая во всю использовала рефлексию.

Итого: Создание экрана: AppDelegate -> Router -передача себя по протоколу> {Name}ViewController -вызов метода у протокола> I{Name}Router Получение данных: VC -вызов метода с callback> service -> transfer -> webAPI и/или Storage

был DI. но без каких либо библиотек. ServiceLocator + объекты пробрасывались ручками через методы инициализации. были тесты на transfer и webAPI. Тесты спасали, так как REST API начал делаться позже, чем мобила, и постоянно что-то менялось.

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

Архитектуру считаю удавшейся, так как iOS команда смогла завершить проект за 3 месяца, но андройд за 4. При условии, что первых две недели iOS мы потратили только на архитектуру - не строчки кода. web api тесты экономили в неделю часа по 4.

Transfer позволил работать первое время без REST API, при этом когда появилось REST API другие слои не пострадали.

Из минусов помню только один: Router был на самом деле Navigator-ом (см. доклад "То, о чём нельзя говорить - Routing/Navigation слой под"). Мы пару раз на этом огребли - были моменты когда было сложно сделать нужный нам переход.

Остальное прошло как по маслу. Только с рефлексией для оборачивания Realm пришлось немного попотеть. Стоит отметить из плюсов, что REST API у нас был однотипный - это позволяло парсить модели без лишних проблем.

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

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

После я попадаю в Тензор. Тут архитектура не моя, но я влиял на некоторые аспекты её развития. И приложение при этом крупное. Поэтому описание лучше начать со слоев: App UI Declaration Core и отдельно Common

App - слой настройки и инициализации всего. UI/Features - слой содержащий много отдельных модулей по фичам. Declaration - слой хранящий куча протоколов. Протоколы нужны для возможности фич общаться друг с другом. Core - базовая работа с БД и сетью. Common - всякие расширения.

Что же такое фича? Фича тут это полностью независимый модуль, у которого своя БД, свои сетевые запросы, свой UI, своя логика. В общем каждый такой модуль, при желании можно выпускать отдельно. И да такое даже возможно - были мини апки, содержащие только одну фичу + авторизацию.

Команды делились по фичам, и редко пересекались. Каждая команда работает спокойно в своем модуле. Из-за этого же, описать архитектуру внутри модуля фичи невозможно. Было всё: MVC, MVP, VIPER, PIDOR :)

Но так бывает, что функционал пересекается. Например когда пишешь сообщение, хочется добавить файл к нему, или ссылку на задачу. А это три разных модуля: Communication, Disc, Tasks. И для таких ситуация был придумал Declaration слой.

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

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

И отсюда моё желание сделать поддержку опционала внутри моего DITranquillity. Вначале в тензоре использовался Typhoon, после мы перешли на мою библиотеку. Тот кто участвовал в этом переходе, думаю скажут, что после перехода стало намного лучше :)

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

Это позволяло делать отдельные мини апки - во всех местах использования функционала соседа, был опционал, и в зависимости от наличия соседнего функционала, UI адаптировался.

Но все это было только в теории... Ну и первых 1.5 года развития приложения. До момента пока не появились С++ и все ведущие не начали войну и отстаивание фронта. В этот то момент все и полетело.

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

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

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

Где-то посередине была еще одна важная проблема - время запуска приложения. Оно на старых устройствах перешло черту в 20 секунд. И если со стороны iOS мы перешли быстро на статическую линковку, то вот со стороны С++ все было печальней - так у нас появилась одна большая С++ либа.

Скорей всего архитектура бы и по сей день держалась, и давала хорошее соотношение качества/скорости, но она была полностью не готова к: С++ Отсутствию контроля. Второе было проколом iOS тим. лидов. Мы не наладили автоматические проверки, того что стоило.

Где-то в середине всей это истории я увольняюсь. Но общаюсь, и стараюсь быть вкурсе изменений. И где-то я возвращаюсь обратно.

К моему возвращению показатели здоровья: Никто не способен собрать мини апку CI в постоянной красной зоне Официально 30% фактически 50% это багофикс Циклические баги не редкость. Приложение снова подходит к границе в 20 секунд запуска.

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

Назовем это попыткой изменить архитектуру. Я к сожалению не выдержал, и не довел проект до конца. Много других факторов меня доканали. Но что было сделано: Нарисована, и на 70% переделана архитектура. С++ научились дебажить iOS приложения. Отремонтирован CI

Также снова был запущен проект, по оптимизации скорости запуска. Правда в этот раз от iOS почти ничего не требовалось, кроме одного - доказать с матами и криками, что у нас С++ модуль запускается более 20 секунд.

Была предложена концепция что архитектура внутри модуля фичи должна быть однородной на всем проекте. На самом деле это тоже был прокол iOS тим. лидов. Не надо давать такую свободу если у вас нет достаточного количество лидов. Если junior пишет архитектуру, будь готов к проблемам

О забыл важное. За 1.5 года, что я отсутствовал в компании количество фич почти не выросло :) По факту за 1.5 года было много переездов модулей фич на С++, и не меньшее количество багофиксов.

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

И есть картинка как и какие модули взаимодействуют, к моменту моего возвращения.
notion image

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

В период между тензор и тензор, я был в двух компаниях: ЦФТ, и что-то не помню что. Начнем с той, что я не помню. И так архитектура какого-то проекта, в котором я побывал три месяца, и который завернулся за 1.5 года из-за невозможности поддержки

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

Теперь по проекту. Проект был перспективный, на первой стадии должен был быть вход, настройки, чат, который интегрировался с почтой. Команда 5 человек. Распределенная. git, ветки - тут все как принято. CI был и работал (вроде бы...)

Архитектуру, я слегка подзабыл, но было что-то типо: App Navigator-ы ViewController-ы Storage - база данных Network - помойму без оберток и либ. а может и были не помню. Models - протоколы.

ViewController был всему голова. Он вам и бизнес логика, он вам и UI, он вам и парсер. Самый большой был 6.5к строк и раскидан с помощью extension на 5 файлов. Для навигации были обычный навигаторы - протокол с набором методов show{Name} который передавался VC.

Storage - помойму он был на CoreData, не уверен. Но точно помню, что в коде были модели в виде классов хранящие данные, и если у этой модели поменять поле, то оно сразу-же обновлялось в БД.

И самое интересное Models. Они были двух видов: Протоколы. Протокол с описание набора свойств, и информацией можно ли их менять. Объекты в виде структур, которые реализовывали протоколы. И теперь важное - Storage модели, тоже реализовывали эти протоколы.

Почему это важно? да потому-что из-за этих протоколов было две проблемы: xcode в дебаге часто отказывался показывать что хранится в модели. Очень часто view, случайно брала и меняла в БД что-то. Причем из-за протоколов сделать это случайно, было очень легко.

Это тот случай, когда университет вбивший тебе, что передача данных между слоями (DTO модели) должны быть данными, и только данными. И тут ты видишь живой пример, что бывает если это не так.

Но зато какая экономия - не надо модели маппить. Одна модель на все, и хватит.

Но самое чудесное было в VC. Я уже писал, что это царь батюшка. Но один случай запомнил навсегда: меняем мы значит цвет кнопки - обновление дизайна. Поменяли. И тут нам приходит с 10 новых багов на логику. Смотрим код, а там: if button.color == COL1 ... И не в одном месте

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

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

А технические причины, их много: Massive VC Протоколы как DTO модели 60 cocoapods зависимостей Лид который зашугал команду И на это наложим тот факт, что команда была достаточно квалифицированная - у многих было по 5+ лет опыта.

ЦФТ. продукту 7 лет. Продукт работает и развивается. Команда 3-5 человек. git, ветки - все как положено. Гнать на архитектуру с такими показателями, смысла нет. Да в ней было много нарушений всяких принципов. Но она работала.

Мне сложно её описать - я её забыл. В основе был MVP. View была пассивной. Что было в модели не помню - какие-то удобные обертки над сетевым слоем, БД и сервисы. Наверное единственное, чем были не довольны, это DI. Он то был, но только как один God object.

Был волшебный объект, который хранил все сервисы, АПИ по работе с БД/сетью, какие-то вспомогательные классы. В общем объект имел ссылки на всё и передавался во все места.

За время моей работы в компании кроме развития продукта, мы еще: Перевели большую часть на swift, у нас были даже графики сколько строчек/файлов на swift и на obj-c :) Избавились от GodObject, по средством перехода на DITranquillity. Вздохнули с облегчением.

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

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

Короче этот проект показатель того, что не обязательно соблюдать все принципы SOLID, чтобы продукт был хорошим. Достаточно просто в течении 7+ лет, иметь хороших лидов, и разработчиков, и продукт будет постоянно развиваться и улучшаться с приличной скоростью.

И последняя архитектура. Моя. Начитавших всяких дядюшек Бобов, я решил написать Clean Architecture. И хотел уже SwiftPM попробовать. В общем первый раз свою идею, я испытывал на FunCode конкурсе, хоть я и не выиграл, но ребятам которые проверяли вроде бы понравилась.

После того соревнования, я кое-что еще переосмыслил, подправил, устранил неудобства. Много еще раз перечитывал статьи и главы из книжки Clean Architecture. В общем старался повернуть свой мозг и осмыслить зачем же все это нужно.

И так компания Tassta. Когда я пришел был уже написанный код на swift + rxswift, но по многим причинам, то, что было написано нельзя было поддерживать. На момент прихода: ноль iOS разработчиков умерший CI умершие провизионики crashfree 70% 600+ багов

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

Начал решать проблемы по порядку: Бизнесу нужна была срочно фича. Без CI жить точно не вариант. Текущий код нельзя поддерживать - только "работает не трож"

На фичу я потратил месяц. Параллельно запинал CI, с кучей мата - он начал запускаться хотябы. А важный факт - на проекте 12 таргетов. Это все разные бренды. У брендов разные картинки и цветовая гамма. Главное их все надо собрать для заказчика.

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

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

REST API - так как проект старый 8+ лет, формат данных у rest api не всегда совпадает protobuf + tcp socket - еще один канал обмена данными udp socket - для аудио/видео данных SSE - чтобы получать события с сервера

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

Более того функционал между tcp socket и REST API разделен по неведомой никому логике. Ну например: Смена пароля это REST или сокет? Позиция других пользователей на карте это REST или сокет? Если вы подумали, что 1=REST а 2=сокет, то спешу вас огорчить :D

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

Переписав сетевую часть, и переведя весь старый код на новый (что требовало изрядно попотеть), в этот момент только я начинаю заниматься разворачиванием новой архитектуру. Да так, чтобы и старый код остался при этом не сломанным.

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

Tassta. Архитектура до меня. Кодовое название "реактивный синглетон" :D Состоит из: ViewController-View-ViewModel-Manager-Service-API БД полностью отсутствуют как сущность. То что есть сохраняется в UserDefaults. Всё на RxSwift.

View - почти без претензий. Это пассивный view. Но он без инкапсуляции. То есть отвечает за хранение UIKit элементов, констрейны, начальный вид.

ViewController - он настраивает UIKit на view, подписывает на него. Вызывает реактивщину во ViewModel и подписывается на нее.

ViewModel - обрабатывает различные данные от менеджеров и посылает адаптированные события менеджерам. Ну так вроде бы планировалось. На практике ViewController и ViewModel очень смещенные - и сказать, кто что делает очень сложно.

Manager-ы. Все менеджеры синглетоны. С помощью реактивщины, они хранят и обновляют постоянно данные. Иногда берут на себя ответственность, которая вроде бы должна была быть во ViewModel.

Из интересностей. Существуют менеджеры первого и второго звена. Первое звено - менеджеры работающие всегда. Второе звено - менеджеры запускающиеся только при авторизации.

Ой забыл при рассказе о ViewController-ах указать про переходы. Для переходов есть классы {Name}Router, которые создаются внутри VC, и которые содержат методы show{Name1} они делают что-то типо: vc?.navigationController?.pushViewController. Короче так себе абстракция.

Менеджеры друг о друге знают. Так как они синглетоны все, могут позволить безболезненно это делать. В итоге менеджеры: дергают/подписываются на других менеджеров, или дергают сервисы.

Сервисы - ничего не делают. Это крайне простейшая обертка над API, которая немного мапить модель. API - классы дергающие Alamofire который обращается к REST-у.

Если говорить про. UserDefault, то к нему обращаются или из ViewModel или из Manager-ов.

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

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

Tassta. Моя архитектура: View | Router - Presenter - UseCases - Gateways - Network/Storage отдельная костыле приблуда Controllers (это не ViewController!) Самое сложное, было придумать как её натянуть не сломав старый код.

По порядку. Есть RootRouter - его создает AppDelegate. Этот в свою очередь знает обо всех роутерах + умеет создавать старые VC. Тут стоит рассказать про два важный технических решения:

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

GenericViewController - специальный VC, который делает всю магию, и позволяет забыть о VC как таковом. Его обязанность держать presenter, router, view, дабы те существовали пока существует экран.

Забыл про 3: 3. Event - позаимствовал идею у реактивщины и C#. Реализует паттерн Observable. Крайне простейшая обертка над callback, добавляющая 1 доп. вызов в stack trace. Я люблю callback, но иногда нужно иметь более одного подписчика, и появляется гемор.

Возвращаемся к RootRouter - он создает другие Router-ы которые в данные момент нужно показать, и подписывает на события от них. По событию от другого роутера, сам решает, что же нужно сделать - показать другой экран, открыть tab в tab bar-е, мож еще чего.

{FeatureName}Router - роутер отвечает за перемещения между экранами в пределах одной фичи. Если нужно, перейти к другой фичи, то выставляет событие, на которое подписывается RootRouter. Чаще всего имеет не больше 3 экранов, а иногда и вообще один.

Для создания экрана, объявляется два класса: {Name}ScreenView {Name}ScreenPresenter И с помощью GenericViewController + Navigator-а внутри Router-а все это связывается и показывается. Да создать и показать экран, это три строчки :)

ScreenView - пассивная вьюшка. Реализует протокол IScreenView объявленный рядом с presenter-ом. Внутри себя может иметь другие вьюхи, если UI сложный. Задача показывать поступающие данные, и вызывать события по действиям от пользователя. Не должна менять своё состояние сама!

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

Presenter же занимается тем, что связывает двух ребят: View + Interactor. То есть он реагирует на события от обоих, мапит события, и пробрасывает другому. Иногда обработав событие от view, обновляет сразу состояние view.

UseCases это модуль хранящий interactor-ы. Важное правило - interactor-ы ничего не знают друг о друге. Interactor-ы реализуют бизнес логику. Если бизнес логика - получить данные с сервера и показать их, то они все равно есть, просто очень маленькие.

Interactor-ы ни о ком ничего не знают. Они дно в зависимости модулей. Для этого каждый interactor выставляет протоколы DataProvider-ы и использует их. Тем самым он сообщает системы, что ему для работы нужны вот такие вот данные.

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

Network - обертки над всеми сетевыми частями. Обертка над Alamofire для REST. Обертка над Alamofire для SSE. Обертка над системными сокетами для TCP Обертка над системными сокетами для UDP Делают максимально простым работу с ними.

Storage - у меня это сейчас обертка над sqlite. Соответственно информация о том, что это sqlite никак наружу не просачивается. Вообще тут я немного возможно тупанул. Данных не так много, возможно лучше было сохранять все в файлы как json. Меньше мапить модели пришлось бы.

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

Ну и на последок. Вот еще картинка. Это взаимодействие модулей. Замечу, что там TFlex/MCX присутствует кое-где. В архитектуру сразу заложен тот факт, что в скором будущем будет два разных совершенно backend-а.
notion image

И взаимодействие внутри одного модуля.
notion image

А теперь объяснение одной моей фразы: "Сбер не сложнее телеги, хоть и намного больше" Давайте сравню tassta и тензор.

Тензор: Куча разрозненных фич Одна команда может не знать, что делает другая Кода 300к+ строк swift, и еще лям С++ Но тут важное - одна команда почти не зависима от другой. Если и есть пересечения, то это обычно получение функционала другой команды у себя.

Tassta: Намного меньше фич Всем надо работать с базой: каналы, аудио, пользователи, ptt Кода около 70к строк swift. Но тут важный момент - нет ни одной фичи, которая была бы независимой. Все фичи это не маленькие продукты, все фичи это усовершенствование функционала.

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

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

И так. Юридической силы все равно у FunCorp нет на этот код (я ничего не подписывал, код написан мною, идея кода была публичной), да и времени прошло уже много. Встречаем: github.com/ivlevAstef/Fun… Прообраз архитектуры из Tassta.

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

@mobileunderhood Мб уже спрашивали, но это где нарисовано?
Да все картинки с диаграммами я рисую в astah. Очень удобный но платный. Но он того стоит. twitter.com/The_Evernoob/s…

Ох... Ё. Я забыл про SwiftPM же ещё рассказать. Ладно ща отдохну, и напишу про него. Коротко - работу с модулями сильно упрощает, но интеграция в xcode хромает на обе ноги.

Начнем с начала. SwiftPM это пакетный менеджер от apple для swift, а не для iOS, macOS и т.п. В этом его и особенность. Ничего кроме swift (ну и C конечно же) в SwiftPM пакет затащить не получится. Зато универсален и работает даже на линухе.

До недавнего времени, даже ресурсы нельзя было добавлять. Буквально недавно появилась возможность добавлять ресурсы. Честно - пока не успел проверить как оно работает.

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

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

минус SwiftPM - не все поддерживают. В частности Obj-C либы вообще в пролете. плюс SwiftPM - не модифицирует проектный файл. плюс SwiftPM - удобно встроен в xcode (для внешних зависимостей!) минус SwiftPM - скачивает в DeriveredData. Не стоит в общем папку удалять

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

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

А теперь, по поводу использования его в проекте. То есть как его использовать с внутренними модулями. Все также сравниваем с cocoapods:

Плюс SwiftPM - поддержка иерархичности. Когда у вас много своих модулей, смотреть на линейную портянку у cocoapods то еще удовольствие. Со SwiftPM пакеты можно раскидать по папкам. Плюс SwiftPM - все тотже язык swift. Причем полноценная его поддержка.

Минус SwiftPM - не удобно добавлять файлы. Они не поддерживают шаблоны. Файлы создаются пустыми, и хеадер к нему с copyright надо каждый раз писать кучками. Плюс SwiftPM - он является папкой. По этим самым причинам забываем о конфликтах в pbxproj файле.

Минус SwiftPM - Не поддерживает Swift Flags/define из вашего проекта. Я как решение пока нашел ток одно - создать объект, хранящий все define и заполнять его в app delegate. На cocoapods можно прописать копирование define.

Минус SwiftPM - при редактировании описания пакета, часто xcode сходит с ума. Я часто редактирую через сторонний текстовый редактор, с закрытым xcode. Плюс SwiftPM - не создает кучи лишних файлов.

Минус SwiftPM - xcode в import предлагает все существующие пакеты, а не только те которые прописаны в зависимостях. А потом при сборке весело падает, с дурацкими ошибками.

Тут я бы сказал так - использовать для поддержки модульности на текущий момент можно, но из-за косяков xcode крайне геморно. Добавление файла только чего стоит - каждый раз копировать/писать копирайты... Но зато получаем возможность разложить модули по папкам красивенько

Ну и надо понимать. Что из-за таких чтук как Crashlytics, вам в любом случае придется использовать что-то другое. Как минимум carthage.

А теперь супер хак, который сложно провернуть - xcframework. Такая новая/старая фича. Так вот swiftPM теперь поддерживает их подключение. а xcframework может внутри быть даже на Obj-C. Итого на самом деле можно обойти это ограничение.

Например у нас на проекте MapBox - платный SDK для карты. Добавление его в swiftPM было тяжкое. Сейчас для этого есть специальный скрипт, который carthage-ом выкачивает и собирает обычный framework, потом пересобирает его в xcframework, после чего SwiftPM модуль использует его

Вот скриптик. Извиняюсь за синтаксис. я еще тот знаток bash. + почему-то у меня перестали видится команды даже находящиеся в bin директории... Видимо где-то PATH поломал когда-то у себя.
notion image

Завтра у нас собеседования. Благо этот день прошел спокойно. Просто расскажу вначале как изменялось мое мнение, к тому, что нужно спрашивать, какие вопросы я сейчас задаю, и что на самом деле меня интерисует в кандидате. twitter.com/mobileunderhoo…

@mobileunderhood Но ведь ObjC поддерживается жеж. Просто .m/.mm и .h файлы надо дополнительно поместить в папку include. Если есть желание играться с .modulemap файлами можно и более сложную структуру использовать.
Тут правильно меня правят. Возможность есть. Но у меня с ней не заладилось. twitter.com/naithar/status…

@mobileunderhood есть один интересный человек @yegor256 который пропагандирует OpenSource даже в коммерческой разработке. Если ты будешь писать код который увидят все, ты будешь писать лучше. И от этого выиграет и бизнес и ты. И я с ним в этом полностью согласен. Поэтому считаю Ваш пример хорош.
Я тоже с подобными согласен. Но боюсь код который я пишу для компании принадлежит компании. И сомневаюсь, что они будут рады его открытию :) Поэтому и пишу подобные вещи - чтобы было что-то своё. twitter.com/rudinandrey/st…

Most candidates cannot solve this interview problem: 🔸 Input: "aaaabbbcca" 🔸 Output: [("a", 4), ("b", 3), ("c", 2), ("a", 1)] Write a function that converts the input to the output I ask it in the screening interview and give it 25 minutes How would you solve it?
О тут в ленте нашёл такое. В тему алгоритмом и завтрашнего дня. Вот такие задачи я считаю должен решать любой программист. 25 минут это даже перебор. Подобные мини задачи в коммерческом коде встречаются постоянно. twitter.com/al_grigor/stat…

@mobileunderhood Чем больше программистов, не способных решить такую задачу, тем больше у меня работы) А я люблю работать=программировать)
Как в том анекдоте: приходит студент на экзамен. Ничего не знает. Препод ставит 5. Тот спрашивает: "почему?" Препод отвечает - "чем больше таких как ты тем более ценен я на рынке труда" 😄 twitter.com/sagus_helgy/st…

Я смотрю задачка зашла всем 😂 Я уже провел порядка 300+ собеседований (бывали дни по три), и порядка 25% кандидатов не решают подобную задачу. Ещё учитывайте наличие фильтра по резюме. Около 8% это люди с опытом более 3 лет в программировании. twitter.com/mobileunderhoo…

@mobileunderhood @aarexer Тогда извините, вы мне не подходите - HR сказала, что собеседование на лида будет)))
Интересный момент. Но иногда бывают и такие. Приходят говорят я лид, и не буду решать задачи. Благо редкость. Но у меня на этот случай есть тоже вопросы, про управление командой 😅 twitter.com/sagus_helgy/st…

Если такие задачи встречаются постоянно, надо выделять в отдельный SDK. Назначать менеджера, product owner, gatekeeper, пару архитекторов, manual и автомейшен QA, админов и т.д. Кроме шуток, у нас реально есть пара библиотек на несколько строчек кода, где все это есть )) twitter.com/mobileunderhoo…
Где-то в каком-то пакетном менеджере была история. Когда по какой-то коммуникационной причине удалилась библиотека с подобной функцией. Говорят 50% всех приложений перестали собираться. Жалко не помню на чём, но история реальная. twitter.com/ryzzed/status/…


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

Пятница


Доброе утро/днём сегодня у нас собеседования. Будет две части: История как начал собеседовать, и как менялись вопросы со временем. Что я сейчас спрашиваю, почему это, и что жду в ответах. twitter.com/mobileunderhoo…

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

Спрашивали и сложные алгоритмы, и просили свою хэш-таблицу написать, и вопросы вида: "вот код, что в нём ни так". В одну компанию спрашивали скалярное и векторное произведение. Когда я начал собеседоваться в мобильную разработку вопросы показались слишком лёгкими на фоне С++

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

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

Первые вопросы состояли из 4 секций: Информатика - это всякие хранения float, представление числа в памяти компьютера, системы исчисления. Задачки - где-то между medium/hard leetcode. В то время сайта ещё и не было Общая Теория и Язык/платформа. Про них ниже

Общая теория: Шаблоны проектирование (я зря что-ли экзамен сдавал на это?) Особенно я любил "мост" ибо в iOS потрахах используется. MVC/MVP и т.д VIPER не существовало ещё. Принципы ООП. Deadlock/livelock. Самый мало отвечаемый "принципы ООП" - мало кто историю знает :(

Язык: Про особенности синтаксиса Obj-C, про ARC и MRC, жизненный цикл UIViewController. Стандартный набор. Но были вопросы на 5+: Про статические/динамические библиотеки и bundle.

Если смотреть по соотношению, то как-то так: 30% отвечали на алгоритмическую задачку. Один раз чел рассказал как решить способом который мне на ум не приходил. 50% знали информатику 40% знали теорию 60% знали базу языка, 2% могли на 5+ ответить.

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

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

Информатику начинают отвечать меньший процент людей. Скатываемся до 10%. Причины? Всё меньше и меньше людей идут в сферу с ИТ образованием. По этим причинам секция задаётся только если человек с ИТ образованием и недавно закончил - проверяем как учился так сказать.

Секция алгоритмов упрощается до нельзя. Сваливаемся на уровень easy на leetcode (но сайта ещё не существует). Иногда в безнадёге я начинаю спрашивать задачу "найти максимум в массиве любым способом". Язык Swift напомню. Не все даже знаю о наличии функции... Но таких не беру.

Теория - ну тут, вы не поверите, но наоборот процент растёт ну или остаётся приблизительно темже. Правда и я шаблоны начинаю спрашивать реже, а поддаюсь рынку и спрашиваю MVC/MVP/MVVM и позже VIPER, YARCH или что ещё знают.

Язык. Вопросы на 5+ спрашивать бесполезно. Да и теоретически о языке почти не общаемся. Тут я скопировал идею интерактива - я пишу код собеседник отвечает на то что будет напечатано. Вначале это была достаточно сложная секция где ARC, closure, class/struct, generic

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

Уходя из тензора список приблизительно уже такой: Задачка уровня easy leetcode. Интерактив на ARC class/struct, иногда closure MVC/MVP, жизненный цикл VC Многопоточность - потихоньку смещается к интерактиву

Когда я попал в ту компанию где проект был ужасный, то мне пришлось собеседовать на Лида людей. Около 20-30 провёл таких собеседований. Тут я меньше задавал вопросов на знание языка, больше на знание архитектуры и новое было - управление командой.

Что хочу отметить. Люди совсем офишевшие там попадались. Чел хотел как-то 500к+, но не знал ничего технически, и на вопросы про управление ничего адекватного ответить не мог. Ещё и обиделся, со словами "кто я, а кто вы"

Вопросы на управление, это были сценарии по больше части. Например: 1.Что делать есть дедлайн, но команда не успевает 2.Как оценивать трудозатраты 3.Каким образом будет разделять задачи по проекту Что-то ещё спрашивал... Всегда придумывал какой-то сценарий из текущего положения

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

I have a challenge for you. What is wrong with this Swift class? https://t.co/4UIxfTvYGJ
Видимо попросили это ретвитнуть в канал. Чесно я с ходу не вижу проблему: меня напрягает "pointer value" - помойму так нельзя писать, и опциональность у хэшера. Не знаю что будет если в контейнер ничего не добавить. В общем я бы хэш функцию написал бы по другому. twitter.com/evnik0/status/…

Дальше ЦФТ. Из-за моей финансовой проблемы, я ее сильно хотел собеседовать людей, да и был слегка агрессивней чем обычно. Короче ЦФТ это дыра где я собеседовал раз 5 наверное всего. Зато было время подумать.

А тьфу блин. Я понял что мне в функции hash не нравиться. Правильно же писать через combine. А на такую запись не понятно, что должно произойти, даже если она предположим синтаксически корректна

Так ладно. Скину вопросы, в виде трех скриншотов. Первых два скриншота, это что я спрашивал в Тензоре по началу. И еще один вопрос - просто прикольная задачка, которую я тоже спрашивал на собеседованиях в какой-то момент времени
notion image

notion image

И задачка
notion image

После ЦФТ я очень много гулял по собеседования, смотрел, что люди спрашивают (про себя думал как деградировала отрасль 😅), думал над своим опытом обучения других людей. Делал некоторые выводы.

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

Теперь +- выглядит так: Интерактив про ARC, class/struct, closure. И теория, а что же это вообще такое. Интерактив по многопоточности. И теория, что у нас есть в iOS. SOLID, жц VC, MVC/MVP... - ну все спрашивают, а я чем хуже? задачка из easy секции leetcode.

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

@mobileunderhood Интереса ради - что именно пытаетесь проверить задачами 1,2,3 и теория 1? Ни разу не видел практического применения таким знаниям. Кроме разве что праздного интереса. Задачки на математику прикольные,но тоже интересно что именно пытаетесь таким на собеседовании проверять? Спасибо
Разминка. Хотя 10 лет назад приходилось подобное считать в С++. Понимание как хранятся отрицательные числа, и к чему приводит переполнение. На swift сейчас к крашу кстати, на C++ же краша не было. Это мало кто знает наизусть, но это простейший анализ логики человека. twitter.com/StratStuff/sta…

Как я писал уже. Сейчас я от всего этого отказался. Не на С++ все-же пишем. Да и крайне редко, что у нас бывают переполнения (но пару раз видел краши на этом). По теории. Это еще актуально. Люди не понимаю, почему на armv7 может работать, а на arm64 нет. Но больше к Obj-C.

@mobileunderhood А в какой сфере вы видели программистов, пишущих программы без багов и косяков?
Кстати по поводу качества. Есть авио/космическая индустрия. Есть ваши процессоры в компах - там тоже так-то софт. Да они тоже ошибаются, но сравним процент/цену ошибки :) А чтобы понимать, что в этой индустрии твориться открываем и читаем MISRA-C стандарт. twitter.com/_lostineternit…

Кстати еще поздравлю некоторых людей. Уже показали свой характер: "Вначале мы напишем чего-нибудь, а уже потом поймем о чем речь" :) Скорей всего эти люди, не читают документацию. Ну и не исключаю наличие троллей, в данной ситуации. twitter.com/mobileunderhoo…

Так пока тут у всех пуканы не пригорели окончательно, напомню: Эти вопросы я задавал 5 лет назад. Я задавал максимум 8 вопросов из всего списка, в зависимости от кандидата. Сейчас я этого больше не задаю. ИТ очень динамично. 3 года назад, swift никому не нужен был.

@mobileunderhood Вы издеваетесь? Вы хоть представляете сложность предрелизного цикла софта в этих компаниях? Количество сложность и разнообразие тестов? И вы это сравниваете с мобильной разработкой? Нужно четко представлять свою компетенцию и задачи, а не запускать ракеты в приложении заказа еды.
Представляю, был в аналогичной. Да вы конечно правы - там другие процессы, люди другие, сроки другие. Но за место того чтобы спорить, лучше бы задумались, а что же я могу у них взять, чтобы повысить свое качество, не снизив свою скорость? А поверьте, у них есть чему поучиться. twitter.com/_lostineternit…

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

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

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

Что я осознал: Знание шаблонов, архитектур, информатики - все это дело легко обучаемое, если человек мыслит верно. Мне НЕ нужны гении - я ищу людей способных на быстрое обучение в направлении ИТ, в частности iOS. Опыт вообще ничего не показывает. Образование не важно

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

По этим самым причинам, на собеседования меня перестала интересовать теоретические знания актуальные в iOS. Конечно если человек себя позиционирует как сеньор с кучей опыта, то грех не спросить, но с junior/middle спрашивать отличие MVP/MVC или паттерны - смысл?

Но так как люди идут все-же на iOS и даже более того на swift, то это и является точкой с которой я начинаю собеседование. Учить основам языка? не это пожалуйста на курсы, тут все-же работать надо тоже.

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

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

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

Для этого я даю простой пример в 10 где-то строчек. Конечно он на проверку знаний ARC - понять будет nil не nil напечатан. Но когда я его даю, я еще в голове замеряю время, сколько человек потратил на чтение кода. Также тут становится понятно - есть мышление в слух или нет.

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

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

Такими темпами мы потихоньку смотрим на структуры, классы, closure. В общем swiftbook первые главы. Если человек неправильно отвечает, то я рассказываю причину его ошибки. Если после объяснений человек дальше делает подобные ошибки, значит мы точно не сработаемся.

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

Следующим идет многопоточность. Кто бы что не говорил, на iOS постоянно много потоков. А если приложение работает с аудио, видео, сокетами, то и вообще сущий ад. Конечно можно жить в концепции двух потоков - главный/не главный, но будет лагать. А сокеты и вообще терять данные.

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

Спрашиваю я не так много - с чем имел дело (если человек работал с NSThread или posix, то это сразу +), и задаю пару примеров с DispatchQueue и async/sync - с ними работали все. Ну там такие из интернета, их можно даже найти. Если на сеньора, то чуть посложнее, из той же серии.

Для junior наоборот секция иногда упрощается. Если сразу видно, что не ответит, то я вначале объясняю быстро, что да как, а потом смотрю на ответы. Конечно рассказать про очереди и async/sync быстро нельзя, но хоть что-то. Если человек смог это схватить, то круто.

Дальше для сеньор, или если секции предыдущие прошли слишком быстро, то спрашиваю вопросы из тех, что где-то в интернете лежат об iOS. Это MVC/MVP, SOLID, жц VC. Короче, ту теорию которую и так везде спрашивают. Если человек не сморозит ерись, то тут не задерживаемся.

Последняя - задачка. открывает leetcode берем секцию easy, из неё самое простое. Если человек хорошо идет, то могу дать и medium. Выше точно нет. Тут я обычно настаиваю на playground-е, чтобы человек писал в родной среде.

Смысл задачки? Их несколько: Посмотреть как же человек пишет синтаксис языка. Посмотреть умение понимать требования. У нас их тут не на золотом блюдечке приносят. Ну посмотреть всеже решение. Если с решение проблемы, то идею я подсказываю.

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

Я не смогу объяснить процесс выбора. Для junior это интуиция которая мне говорит - научу его или нет. Ни разу не ошиблась, даже когда другие говорили не бери. Для middle/senior интуиция сработаемся или нет.

Как пример: Человек фанат RxSwift. Я нет. Ну не сможем мы работать в одной команде, хоть он трижды гений. Или человек любит все новое, не сидится ему на месте. И смысл такого брать на продукт, который один с одними технологиями?

Ну и в качестве затравочки так сказать. Отвечать имеет смысл только swift разработчикам - java с GB совсем по другим правилам живет :) class C { var str: String = "A" } var c: C? = C() weak var wC: C? = c c = nil print(c?.str ?? "nil") print(wC?.str ?? "nil")

А тем временем я смотрю на тему завтрашнего дня и думаю "кто меня тянул за язык то"... Короче я хз, как я это буду рассказывать. У меня тут есть наброски некоторые. Даже думаю, чего-нибудь помощнее сморозить, и слинять - дальше вы и сами сможете :D twitter.com/mobileunderhoo…

@akaDuality @mobileunderhood @lightdelay так это же функция, где лямбду добавили bool isTrue(int a, int b) v bool (^isTrue)(int a, int b)
Лайф хак от JonFir как запомнить синтаксис блоков. Не знаю кому это нужно, но малоли кто-то ещё пишет на Obj-C :) twitter.com/tygeddar/statu…

Тем временем процент верных ответов поражает - 75%... Почему на собеседованиях около 60% то выходит. Стресс? Другой контингент? twitter.com/mobileunderhoo…

Там кстати по вон тем вопросам, от которых всех разрывает уже который час. Мало того что они были созданы 5 и более лет назад с оглядкой на С++, так они ещё были приблизительным списком. По листочку я спрашивал первых 10 собеседований - когда ещё боялся этого дела.

И я только щас понял, насколько сам того не понимая я делал круто. Этож такой офигенный заход был - люди видят вопросы думаю "что за пздец", а потом их Батц и спрашиваю нормально так - "расскажите о своём опыте?" Жаль я раньше об этом не думал 😂

Не понимаю всеобщего негодования. Своего рода базовая проверка на инженера-программиста. Я был на собесах, где спрашивали подобное для мобильного разраба, например Озон и Ситимобил. Не эталон для собеса? А где эталон, может FAANG? :) twitter.com/mobileunderhoo…
В FAANG кстати вроде не спрашивают подобного. Там априори считают, что человек это знает. А если окажется не так, то он на первом же тех. Собеседовании отвалится - ибо не зная азов, там не пройти на инженера. twitter.com/maxxkazakov/st…

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

Ну а тем кто считаем себя гуру iOS с опытом теперь вопрос со звездочкой. Мысленно переписываем код, на аналогичный но теперь Obj-C и какой будет верный ответ? 😅 twitter.com/mobileunderhoo…

Можно голосовать :)

Завтра за одно расскажу про эти два вопроса. Точнее вопрос один, языка два :) Верные ответы, и почему так (хотя swift вариант вроде и так большинство знают)

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

Суббота


Доброе утро/день. Сегодня у нас: Про Obj-C swift примеры, и что я не до сказал. После чего-нибудь про хороший код. Что-нибудь, что в инете редко пишут, а не одну банальщину.

Ладно у всех кипит от вопросов досихпор. Супер опрос: bigEndian littleEndian, что это?

А пока про задачку с Obj-C, swift. Со swift там все +- норм - большая часть ответили верно. А вот мнения про Obj-C расползлись сильно. И на то есть важные причины. Дальше все в iOS среде - это не важно, но мы же мобильные разработчики :) На скринах в консоле верный ответ.

Начнем с простого. Тут у нас есть один объект, и две ссылки на него: слабая и сильная. Зануляя сильную ссылку, у нас остается только слабая - то есть счетчик ссылок = ноль. Это сразу приводит к удалению объекта, что приводит к занулению weak ссылки.
notion image

Теперь пишем код, в чистом виде на Obj-C. И тут тоже мы получаем тот-же результат. Почему тут nil nil? причина в том, что компилятор не совсем глупый, и в простых кейсах умеет правильно расставлять retain/release без autorelease. Почему же тут отвечают 50/50 ? смотрим ниже.
notion image

А теперь посмотрим на этот вот пример. Внутри цикла написано тоже самое? создаем объект, делаем ссылку, зануляем его. Результат должен быть вроде эквивалентен прошлому? И тут мы видим другой ответ. Почему же так произошло?
notion image

На всякий случай - если написать такой же цикл на swift - результат не изменится. swift всегда остается "логичным"
notion image

И теперь то вспоминаем историю Obj-C. Вначале было MRC. и было не две как многие могут думать команды: retain/release а еще был autorelease. И когда Obj-C перешло на ARC, эти команды не исчезли - компилятор их стал расставлять сам, но они также остались.

и вот тут и прикол - в реальном коде, почти всегда компилятор добавит autorelease к вашему объекту. Да когда код совсем простой, компилятор может быть умнее, и просто поставит retain + release - ему нет смысла усложнять. Но стоит слегка усложнить код, и появляется autorelease

Что это такое? autorelease добавляет объект в специальный autoreleasepool, из-за чего объект будет захвачен, до момента пока этот pool не почиститься. Чиститься pool по достижению его конца. В том случае окончанию одно цикла runloop - который где-то за пределами viewDidLoad
notion image

Почему на Obj-C этот факт важен? Из-за ситуаций когда на одном цикле, мы сами того не зная выделяем куча памяти. И да у меня был случай когда были краши из-за этого. Тут я пожалуй скину статью - там лучше описано :) swiftrocks.com/autoreleasepoo…

Использовать autoreleasepool в Swift нужно тогда, когда мы в цикле вызываем фабричные методы, код которых скомпилирован без ARC. Всё дело в новых autoreleaseReturnValue и retainAutoreleasedReturnValue, которых не было в MRR.
Как правильно тут заметили, в некоторых ситуациях и на Swift тоже приходится знать про autoreleasepool. Наследние Obj-C приследует нас и по сей день :) twitter.com/antonsergeev88…

Сегодня я ещё обещал рассказать про "хороший" код. Буду писать, но медленно. И так поток про "хороший" код:

Изначально поток хотел назвать "правила написания кода" но решил, что звучит не очень, да и правилами это назвать не всегда можно. Но перед этим что такое хороший код?

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

В итоге хорошим кодом я называю код который: Читаемый Выполняет поставленную на него задачу Легко модифицируется (не тоже самое, что читаемый) В коде/проекте легко ориентироваться и дебажить

Последний пункт особенно интересен - как бы мы не хотели, при написании кода стоит учитывать возможности IDE. Если у вас нет дебагера в IDE, то код напичканный print-ами хоть и менее читаемый (хотя зависит как логи писать), зато можно дебажить.

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

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

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

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

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

Тоже самое и с классами - но тут ещё сложнее. Вообще про функции, классы, модули, есть принцип SRP - это всё к нему. К классами у меня правила простое - если начинает превышать 300+ строчек на Swift (на Obj-C лимит выше), то возможно начать делить.

Как делить класс? Ну вот пишем мы presenter. Он уже 1к строк - ну реально большой экран с кучей всего. В подобных случаях я вспоминаю агрегацию и иерархичность. То есть выделяю мелкий функционал и выношу его в отдельный Presenter, который используется внутри главного.

Главное при таком выделении ни в коем случае не выносить только по техническим признакам. Если выносим, то выносимой части нужна давать осмысленное имя. Не стоит: OtherPresenter, PrivatePresenter. Можно: MapZonesPresenter, MapCarTrafficPresenter.

Сложный пункт. Функции должны содержать код, только одного уровня абстракции. Не умею объяснять эту мысль :( Пример такой:

Есть у вас функция со switch - он на каждое действие что-то делает. Но где-то case вызывает другие функции, а где-то сразу исполняет это действие в 2-3 строки. Вот это разные уровни абстракции, и по возможности лучше избегать.

Любому новому типу данных лучше сразу давать имя. Особенно если он будет использоваться в разных местах. Даже если этот тип int. Есть у вас id пользователя. Лучше сразу завести тип: UserID = Int. Тоже самое к ошибкам, callback и т.д.

Зачем? Ну во первых никто не знает когда этот тип поменяется - например на UUID. Во вторых когда у вас в коде одни Int как id, можно случайно передать id чужого объекта и не заметить этого :)

Парные операции. Start/stop begin/end, add/remove subscribe/unsubscribe и т.д. Ну во первых всегда стоит задуматься - а не пригодиться ли пара в будущем. Если есть шанс, лучше завести - чтобы в будущем не париться. Но не это важное:

Всегда располагаете их максимально близко. Особенно при вызове. Мой любимый пример: startActivityIndicator() callLongOperation(callback: { stopActivityIndicator() ... Тут потерять парность почти невозможно. А дальше думаю все вспомнят случаи когда парность терялась в коде

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

Правило влияющее на читаемость: не пишем полотна сплошного кода. Ну 1-2 пустых строки редко навредят. Но и делить через каждые 5 строк не лучшее решение. Лучше выделяйте, логические мини блоки. Возможно суть блока будет понятна только вам, но это лучше полотна :)

Должно было быть вначале. Пошло ещё из С++ и Null. Проверять входные аргументы. Можно и возвращаемые даже :) Ну если вы ожидаете год создания машины, то лучше проверить, что число всеже больше 1800 😂 А пункт просто для перехода на другую/продолжение тему - в новом потоке.

И тут я открываю ещё один поток, связанный с хорошим кодом, и дебагом. Хороший код должно быть легко дебажить - ибо мы точно в наших условиях написания кода допустим баги. И не всегда есть доступ к устройству. Да тред про логи, но начнём с assert 😅

assert - функция которая нужна для программистов и отсекается в дебаге. Может иметь ещё названия: precondition, postcondition. Но суть у них одна. С ней стоит быть аккуратней - нельзя в ней писать код, который что-то может изменить. А то в дебаге работает, в релизе нет :)

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

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

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

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

Логи это не панацея. Если вы не понимаете зачем они вам, и их ценности, то лучше не надо. Это инструмент. Как и дебагер, или профайл - это один из инструментов доступный всем.

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

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

Перед этим важная информация. В проекте я использую крашлитикс и конечно же логи настроена на неё. Более того логи уровня assert и error прилетаю в крашлитикс как nonFatal, и говорят мне - где-то есть проблемы, не приводящие к крашу.

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

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

Проверяем: вводим не верные данные, получаем ошибку, и... ничего. Тут смотрим логи, там запись ещё - логин пароль почистился. А у нас есть опциональная функция - не сохранять данные если ты залогинился. То есть все данные чиститятся

Ага, ок как воспроизвести удалось. Да это всё заняло 5 минут. Но проблема то по факту оказывается не в том, что кнопка не блочиться (это тоже поправил), а в том - а чего данные то чистятся?

Получаем в итоге что это уже не ошибка UI, а ошибка бизнес логики. А это уже критичнее. Вот так за 20 минут было поправлено две разных ошибки - отсутствие обновление UI + косяк в бизнес логике. Последняя возможно в будущем бы стрельнула, а может нет. А UI просто не приятная.

Возвращаемся к этой теме. Из около 10 проектов где я был в 4 мне понадобилось это знание, и в 3 я правил баг связанный с этим. Вначале что это такое вообще, а потом одна самая прикольная история на это. twitter.com/mobileunderhoo…

И так bigEndian и littleEndian относиться - о чудо к записи числа. Как всем известно у нас в памяти идут битики 01001011 :) 8 битиков это один байт (но не везде 8) но число обычно занимает не один байт, а 4 или 8.

Внутри одного байта все биты всегда идут в одном порядке - справа младший разряд слева старший. А вот байты можно переставлять - у кого-то справа старший байт у кого-то слева. Так и появляется два типа записи: bigEndian и littleEndian.

Все устройства в этом мире между собой обмениваются массивами байт/бит. Но вот беда - договориться в каком виде на всех устройства будет запись числа мир ещё не смог. В итоге где-то uint16 со значением 15 = 00000000_00001111 а где-то = 00001111_0000000 Вот такое чудо.

К чему это приводит? Дают тебе блютус устройство, или сокет соединение - или что угодно где массив байт идёт в чистом виде. И говорят: мы вам тут отправляем 4 числа uint32 (тут ещё стоит заметить, могут отправить и uint16, но не сказать 😅)

Вы радостно считываете четыре байта и преобразует в число. Это у нас делается легко. А потом баги - где-то всё ок, а где-то полная ахинея. Смотрите в дебаге - а приходит реально не то число. Идёте ругнуться со второй стороной, та тоже в шоке. Тем временем багу уже месяц 😂

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

И так прихожу на проект. Не буду скрывать - Tassta. Тут есть видео звонки. Понятное дело есть формат обмена данными, и это массив байт. Но суть в другом. В какой-то момент я узнаю: оказывается видео звонки не работают на ios12. Я такой? 😳 Ладно ок посмотрим

Но самое интересное то, как мне это говорят: "прошлые iOS ребята сказали, что ниже ios12 система не поддерживает" Находим код. Там available стоит на ios13 и выше. Убираем. Проверяем - о чёрт реально на ios12 единственном устройстве в компании оно не работает.

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

Тупо во всём коде вначале ставлю одно окончание - не работает. Потом другое - и о чудо работает. И на ios12 и на ios13. Почему на ios12 этом устройстве было не стандартный порядок я хз, но и apple нигде не гарантирует его.

Сам процессор вообще крут - он оба формата поддерживает. Но заранее сказать какой используется нельзя. Вроде везде littleEndian, но никто не гарантирует. Как думаете не зная этого, я бы через скок лет поправил баг? А так заняло пару часов на то, чтобы найти косяк.

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

Мы не пишем на С98 года, нам не нужно располагать объявления переменных в самом начале функции. Поэтому и не надо. Это было в какой-то книжке - куски кода должны быть максимально "сцеплены". Если переменная объявлена, то она должна почти сразу быть использована.

Актуально для Swift/kotlin - константа лучше переменной. Лучше стараться минимизировать количество переменных. Вообще у этого правила корни растут из ФП - эти языки не имеют проблем с потоками в силу отсутствия состояний :) Но избежать совсем переменных сложно.

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

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

Это становиться актуально например когда кнопка может быть заблокирована по куче разных причин - не введен логин, пароль, нет сети, не прошло верификации. И лучше куча флажков на каждую причину с методом update, чем в каждом месте отдельно блочить/разблокировать.

Вот кстати насчет имен переменных, и всего такого - проблема и правда не шуточная. Так что, джуниоры, которые читают взрослых разрабов, имейте ввиду - мы хоть и обшучиваем это, но сами всегда подходим к делу серьезно
Хороший тред. Я нейминг пытаться раскрывать боюсь. Это что-то такое абстрактное, но капец какое важное. Но скажу про язык - я перешёл на swift с Obj-C и С++, потому-что тут не надо думать о многой фигне - времени на что-то важное больше. В частности на нейминг twitter.com/fillpackart/st…

Инфляция инфляция. Случайно зашёл в детский отдел для маленьких. Памперсы как стоили 5 лет назад так и стоят. Вообще цена не изменилась. Вот где стабильность так стабильность 😂😅 Это я так - а то только технические темы :)

Завтра самый сложный день: надо как-то всё, что я понаписал объединить 😅 А так кто что хочет услышать? Предлагайте в комментариях. А пока всё думают, я воспользуюсь положением. Кто ещё не поставил звёздочку моей библиотеке? github.com/ivlevAstef/DIT…

@aarexer @mobileunderhood Джуниор - уверен что не обосрется. Синьор - одевает памперс.
Золотые слова twitter.com/kverlin/status…

Что-то я тут вспомнил одну притчу из фильма "опасная игра слоу" фильм прикольный, и притча подходит под недавние все споры :)
notion image

И напоминаю, что завтра тема свободная. Можете предлагать темы. А то мне тут напомнили один вопрос который я так и не задал (вроде) "История ООП". А то решу завтра её ещё рассказать. Думаю это не то, что вы хотите услышать? 😅

О появился в уведомлениях. Я придерживаюсь того же мнения - колбасить по клавишам и перемещаться по проекту мы должны быстро, и не думая - а то забудем основную мысль. twitter.com/mobileunderhoo…

Кстати напомню я начинал в гипсе писать. И потом избавиться от привычке набором одним пальцем мне пришлось сложно. А слепая печать даже полезнее умения перемещаться по проекту - всеже буквы мы пишем чаще :)

Воскресенье


@mobileunderhood Не, не странное. Это ж частая ошибка, когда схожая логика выполняется из разных точек входа - в одном месте поправил, в другом забыл. А это правило я называю - "через одни ворота"
А кто ещё как называет? Может в книжке какой было кстати это 🤔 twitter.com/ashumidub/stat…

@mobileunderhood С первым всё понятно, а как добиться несовместимости типов? typealias не поможет, городить структуру на каждый тип ID? https://t.co/yIJEYsdgO1
Хороший вопрос. Внизу хорошая ссылка. Но, я пытаюсь придумать как сделать аналог Tagged но без rawValue. Или появление чего-то типо typedef. А так пока только внимательность - типы сверить можно. Иногда в структуру оборачиваю если совсем критично. twitter.com/evnik0/status/…

Доброе утро/день. Ого история ООП отогнала армию даже 😳. Начну сегодня с нескольких вопросов: Как я осваивал 10 пальцевую печать Мой прогноз мобилы на 5-10 лет. Дальше: История ООП и/или армия Прощания :) twitter.com/mobileunderhoo…

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

Первый мини поток - 10 пальцевая печать. Вначале зачем? Я будучи коммерческими разработчиком писал двумя пальцами вначале, и мне не мешало... Но я решил переучиться всеже. Мотивация одна: пока я напишу код, я уже забуду, что я писал 😅

Собственно говоря ради этого и нужен 10 пальцевых набор - чтобы максимально быстро и максимально не задумываясь о клавиатуре его записать. Экономия ресурсов мозга получается значительной. P.S. тоже самое и к перемещению по коду/проекту

А теперь как я учился. Поскольку начинал я в гипсе (на левой руке) то клавиатуру я сразу освоил криво. И писал около 7 лет по итогу такая двумя пальцами. Быстро тыкая - 180 символов в минуту 😅 Но в какой-то момент понял - надо переучиваться, так дело не пойдет

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

Но самый главный шаг, это было купить удобную клавиатуру, и желательно такую, чтобы было сложно писать не правильно. Выбрал я вот такое чудо: microsoft ergonomic keyboard 4000 И по сей день пользуюсь этой серией клавиатур.
notion image

Клавиатура как я считаю помогла сильно - на ней двумя пальцами стало писать не возможно, и начал переучиваться. Руки на ней лежат сразу как надо и пальцы попадают куда надо. Оставалось освоить.

Из ошибок обучения: Я почти не тратил время на каждый палец отдельно, а сразу пошёл в "бой" В общем вначале моя скорость упала до 40-50 символов 😂 Печатал я с визуальной клавиатурой которая показывает какой палец и букву нужно нажать сейчас

Где-то до 120 символов я быстро достаточно нагнал скорость. Но ошибок было 10% почти. Дальше - задротсво. Пару и более часов в день тратил на клавагонки. Где-то ещё за месяц вернуть себе 180 символов в минуту. Но с ошибками.

При этом на работе я печатал как повезёт. Яб назвал это так "два пальца с редко появляющимися соседями" 😂 Где-то к моменту когда я начал 180-200 писать, только тогда я решил и на работе попробовать писать 10 пальцами

По достижению 200+ начал часто играть в режиме "без ошибок" чтобы снизить процент. Скорость в этом режиме составляла около 140 при этом. Но зато в итоге дало скачек - количество ошибок заметно упало (до 3%), и скорость около 250

На этот момент я забросил это дело. 250 решил нормально. После 2 раза возвращался и поднимал скорость среднюю - вначале до 300, потом до 350 с пиковой 400. На 350 остановился - дальше стало уже тяжело поднимать, и меня пока устраивает

Теперь поговорим про "прогнозы" на 5-10 лет. Начнём с главного - я не пытаюсь делать прогнозы даже на 2 года, слишком всё меняется. Поэтому этот поток надо назвать "мои мечты о будущем" чем реальные прогнозы.

Первая моя надежда на ближайшие два года - появление iGlass. И я верю, что apple сделаю то, что нужно рынку. Возможно захватит мир только 2/3 поколение, но apple не должны накосячить тут.

И они изменять наш UI/UX. И думаю намного больше чем появление часов. Скорей всего спрос на AR технологии вырастет после не только у apple. И люди чаще начнут взаимодействовать с миром через AR

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

По софту. Ближайших 5 лет мне кажется мобильная разработка будет дальше "деградировать" - увеличиваться спрос на продукты, программистов а значит большие ЗП и меньшие требования. Циклы моноприложения/много приложений продолжат быть циклами.

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

О языки. Я верю в Swift больше чем в kotlin. Он прогрессивный - они не начали тащить наследие, а сделали новый. У котлина есть интересные хорошие решения, но наследие джавы сильно видно. Ну например вот эти всякие ArrayList LinkedList - ну зачем оно в современном языке?

Apple сделали важный шаг - открыли язык. Это в перспективе времени, должно положительно сказаться на язык.

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

А пока кроссплатформу все делают как один язык, она не станет популярной. С++ с точки зрения кроссплатформы хорош во всём, кроме как того, что это С++. А как бы здорово было - пишешь на высокоуровневом языке и сразу этот код используешь в iOS/kotlin.

Тут Microsoft показатель кстати - их dot. Net (CLR) который объединяет 3+ языка безшовно это круто. С++, С#, F#, и какие-то ещё.

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

Потихоньку переходим к армии. И сразу ответ - идти туда не стоит. Исключение: если вы не способны за собой даже смыть в общественном туалете, то вам стоит 😂 Вот таких личностей там быстро воспитывают.

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

Вначале я учился в учебе пол. Года. Там было почти скучно - снег кидали на дорогу, потом с дороги. Ну пожалуй самое весёлое это люди переболевшие по 3 раза ветрянкой за пол. Года. Но жили мы на болоте/торфе. Весной стало жарко - ну чтож тушить палками горящий лес возможно 😂

А веселье началось после учебки. В боевой части. Вот тут и начались "байки". Начнём с начала. На первой недели я сломал БТР - точнее сломал антену 12 метровую у него. На фотке которая торчит.
notion image

Эта антена поднимается из нутрии - там рычаг который надо крутить. Он застрял, я решил помочь ногой. И тут такой: "бум, бум, бум, бабах" в общем перестарался порвал трос внутри - металлический толщиной в 3 пальца...

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

А да вообще я ездил на вот такой машинке. Обычно командир тот кто вон сверху тусится - его задача поднимать чёртову Антену которая вечно застревает.
notion image

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

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

Тотже! Служащий взорвал БТР. Новый. Полгода назад сделан. Как было: холм, БТР застрял, бежит капитан с криками - глуши мотор {мат} и тут бах. Мотор взорвался пробил корпус. Со слов служащих: Водитель - тут стрелка в красной зоне 11к оборотов. Капитан - прорвёмся, жми

Ну тут уже скрыть не удалось... Служащему влетело по полной. Потом этот БТР до базы везли, и офицерам была головная боль - как начальству доложить подобное?

Чтобы понять надо там было быть: ночь. Надо провести 10км полёвки - это тонкий кабель для связи на котором слон сможет повеситься, выдержит. За руль машины садиться офицер. Вы с двумя мотками этой полёвки взаде с открытой дверью.

И начинаем тянуть. Первый фейл - ров. Офицер решил проскочить. Как переднее колесо пролетело чудом, но заднее нет. Побежали к соседям куда-то вон туда, искать БТР. БТР то и лагерь нашли. Машину искали дольше 😂

Дальше едем - полевка вечно выпадает из машины на кочках. Постоянно останавливаемся и ищем её. На очередной остановке и поисках я чуть себя не "разрезал" - полевка была натянута как струна на уровне шеи. И так метров 200 натяжки такой

Но думаю объяснять, что когда мы доехали ожидать, что будет связь было наивно. 10км провода скрученного из кусков. Садим человека - едем обратно ищем обрывы - раз в 500 метров прозваниваем провод. И держим его в "руках" чтобы не потерять.

Короче не забываемые эмоции. А на улице был ноль. И дождик. Грязь. Я после этого с радостью играл в "гонки героя" - детский лепет по сравнению с тем :)

Ну что было ещё в армии? Да много чего. Мне один раз прилетело автоматом по голове. Благо реакция спасла - закрылся рукой. Шутки про гнутые автоматы - правда. Автоматы все стреляют рандомно. Если вы знаете ИТ - лучше молчать. А то будете документу печатать, и в Excel сидеть...

Ну у нас офицер играл в танки WoT. Поэтому служащие тоже играли в танки начали. С его аккаунт - фармили ему. Как-то кто-то свай принёс. В итоге один человек "траванулся". Офицер вначале отпоил его, а потом "отпорол". Иногда голодали в полях по 2-3 дня.

Вопрос с подвохом на затравочку перед следующей темой. Сколько признаков ООП? P.S. подвох в формулировке вопроса.

А вы бычтро отвечаете на не серьёзные вопросы :) Но я прежде чем попаду домой не начну писать историю - устал уже с телефона писать. twitter.com/mobileunderhoo…

Ладно начнем тему истории ООП. Сразу оговорюсь - я не считаю это чем-то важным для программиста, но и бесполезным тоже не считаю. Так-как твиттер не то мест, где можно много написать, то пройдусь по важным моментам только. Начнем с опроса:

Правильный ответ на опрос "ты серьезно?". И опечатку я совершил случайно, но когда увидел решил оставить. Подвох был в том, что я не уточнил в какое время то нужно считать сколько было принципов. Удивлен, что кто-то ответил 7 - видимо есть еще люди знающие историю

Как говорится вначале было слово, ну точнее до ООП было :) термин ООП ввел Алан Кей, в 1970х годах, для языка smallTalk. Но многие считают, что первым языком был все-же simula67. На всякий случай повторим, что же такое ООП, конечно это можно и в интернете найти:

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

Интересней всего, что думал/говорил Алан Кей в те времена. Да он придумал термин объект. Но его идея ООП была не в этом, а в передаче данных. Вот одни из его слов:

"ООП для меня означает лишь обмен сообщениями, локальное сохранение, и защита, и скрытие состояния, и крайне позднее связывание" И условно говоря, он говорил, что ООП это: обмен сообщениями и инкапсуляция. Тут все это подробней: habr.com/ru/company/ruv…

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

Мне нравится очень такое определение Инкапсуляции - это объединение и сокрытие данных. Просто, лаконично. Кстати не представляю как можно писать на ООП не используя этот принцип :)

Ладно идем дальше. Тут быстренько разобрались. А теперь Java программисты - вы в курсе что язык Java соответствует 7 принципам ООП? Думаю многие даже не в курсе, что был виток развития ООП где было 7 принципов, и java язык который был сделан по ним.

Но интересно, что в Университете нам преподавали именно эти принципы ООП. Хотя на тот момент уже актуально было другое понимание. А сами принципы такие: Абстрагирование, Инкапсуляция, Модульность, Иерархичность + Типизация, Параллелизм, Сохраняемость

Давайте быстро: Абстрагирование - процесс при котором мы выделяем абстракции. Абстракция фокусируется на существенных с точки зрения наблюдателя характеристиках объекта. И это одна из самых сложных задач в ООП - правильно выделить абстракции.
notion image

Инкапсуляцию уже разбирали. Модульность: Это свойство системы, которая была разложена на внутренне связанные, но слабо связанные между собой модули. Модуль сильно связан внутри и слабо связан во вне.

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

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

Сохраняемость – способность объекта существовать во времени, переживая порождающий его процесс, и (или) в пространстве, перемещаясь из своего первоначального адресного пространства.

Вот быстро 7 принципов. Они написаны в книжке Гради Буча Объектно Ориентированный Анализ и Дизайн. Можете почитать - интересное чтиво. Зачем я их тут написал? об этом попозже, давайте посмотрим на современные принципы ООП.

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

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

Полиморфизм это - Свойство системы, позволяющее использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта. Кстати полиморфизмов бывает много, и разных. Вики в помощь. Короче это не только слово override :)

Так это краткий экскурс в теории. А теперь все-же к истории, и выводам. Термин ООП ввел Алан Кей имея ввиду smallTalk 1972 год. JS программисты радуйтесь - ваш язык истинный ООП. И там была основа в посыле сообщений. Кто-то говорит, что язык simula67 тоже был ООП.

Дальше Гради Буч выдвигает своё мнения о ООП, которые записаны в книге ООАД. Это около 90 годов. Скорей всего это мнение он взял из того, что витало тот момент в воздухе. И пишется язык java под этот ООП.

Потом в приблизительно 2010 годах кто-то создает новое понятие ООП и как-то его вписывает в массы. Теперь к выводам из всей этой микро истории, которую обычно я рассказываю больше часа :D

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

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

Кстати посмотрите на swift - там убрали слово protected. Apple как-бы намекает - к черту наследование, используйте модульность. Да и бесполезность public + open без модулей, тоже намекает на это.

В 90 годах параллелизм тоже был чем-то новым. Сейчас эта наша реальность. Задумайтесь над определением "свойство системы, отличающее активные объекты от пассивных" Я это определение очень долго не мог понять, но в нем есть какая-то магия :)

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

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

Это отличное описание к тому, что такое хороший модуль/класс/метод - чем меньше вы удивляетесь при попытке его понять/прочитать, тем лучше этот модуль/класс/метод

Так пора закругляться. Надеюсь кроме кучи холивара/пригорания, я принес кому-нибудь что-нибудь полезное :) Пойду собирать все норм темы в одно место...

Поток, про потоки :) Ну точнее просто тут будет собрано, что я интересного писал за неделю.

Поток про мою финансовую безграмотность, и про то, что не стоит идти против своих принципов: twitter.com/mobileunderhoo…

10 задачек на "алгоритмы" которые мне приходилось решать: twitter.com/mobileunderhoo…

Поток про мою библиотеку DITranquillity: twitter.com/mobileunderhoo…

Потоки про архитектуру до мобилы: twitter.com/mobileunderhoo… twitter.com/mobileunderhoo… twitter.com/mobileunderhoo… twitter.com/mobileunderhoo… Первое мобильное: twitter.com/mobileunderhoo…

Тензор: twitter.com/mobileunderhoo… twitter.com/mobileunderhoo… Что-то что совсем не удалось: twitter.com/mobileunderhoo… ЦФТ: twitter.com/mobileunderhoo…


Моя архитектура чуть древнее Tassta, но которая есть в открытом виде, на небольшом но приближенном к реальности проекте twitter.com/mobileunderhoo…


Как я провожу собеседования сейчас: twitter.com/mobileunderhoo…

Правила для улучшения качества кода/ про хороший код: twitter.com/mobileunderhoo…

Про логирование: twitter.com/mobileunderhoo…


Микро история ООП: twitter.com/mobileunderhoo…

Ну и на последок, небольшой такой милипусенький намек :) Я ищу в команду 1 джуна/мидла и 1 сеньора. Круто есть есть опыт AVFoundation. Интересных задач полно. Есть задачи тянущие на хороший диплом, а то и нобелевку 😅 Кто близок по духу и мыслям @stef63693110

Ну и кто еще не ответил, можно высказать свое мнение о этой недели :) А я закругляюсь. Буду еще отвечать на ваши вопросы, но больше никаких потоков не будет. twitter.com/mobileunderhoo…

Какой интересный тред, чуть не пропустил! У меня есть пара комментариев к твитам, жаль твиттер собака не умеет в бэклинки и референсы как @RoamResearch, но я всё-таки попробую собрать комменты в маааленький тред с референсами) twitter.com/mobileunderhoo…
Дельные комментарии. Я не фанат идей Алана Кея, но согласен с тем, что написал автор. twitter.com/timofeipl/stat…

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

Ссылки