Разница поколений в ИТ
Давно хотел собрать в один пост ключевые отличия между разными поколениями айтишников. Речь пойдет в основном про разработчиков и чуть-чуть про админов и DevOps.
Вводная
Не буду в очередной раз крыть х#ями тупую молодежь — расскажу лучше о явных и заметных пробелах в компьютерных знаниях, характерных для айтишной молодежи средних современных лет (1995+ года рождения).
Надо понимать что сравнение со старперами вроде меня вообщем-то невозможно, поскольку в мою ИТ-молодость случайных людей в отрасли просто не было, а все неслучайные и хоть чего-то понимающие были самоучками.
В ВУЗах и на курсах такой дисциплине как «программирование» не учили.
Еще в те времена не было разделения на админов и разработчиков — всех кто имел отношение к компьютерам называли «программистами».
«Онлайн-оффлайн»
Больше характерно для пользователей, но захватило еще и существенную часть веб-разработчиков и всяких «рядом стоящих» QA/DevOps, особенно любителей продукции Apple.
Суть явления заключается в том что человек перестает различать состояние «сна», физического выключения устройства и его нормальной работы с подключением к сети.
Для таких товарищей все это техническое разнообразие свелось до двух терминов: «онлайн» — все подключено и могу работать и «оффлайн» — все остальные варианты.
усложнение железа, сокрытие деталей от пользователя, мгновенная загрузка устройства и режим «сна», пришедший из ноутбуков.
На сегодняшний день и с современным железом нужно специально сидеть и разбираться — надо это разумеется не всем.
Получается такой чисто прикладной подход к устройству и его начинке (вплоть до ОС), аккуратно насаждаемый Apple и плавно распространившийся и на Windows а ныне влияющий еще и на популярные Линуксы.
Сетевой стек
Что такое IP-адрес знают даже самые тупые и зеленые из айтишников, но например что такое широковещательный адрес, маска подсети и как ее рассчитать — ныне знают единицы даже из сисадминов.
Даже бл#ть среди цисководов!
Нет это не шутка юмора а печальная реальность.
Хотя эти знания жизненно необходимы любому разработчику занятому в разработке сетевого ПО.
Хозяюшке рекрутеру на заметку:
Вопросом про localhost и 127.0.0.1 можно спокойно валить на собеседованиях даже опытных специалистов
Никто из айтишной молодежи почему-то не в курсе что «loopback» это не один только 127.0.0.1, а целая подсеть:
127.0.0.0/8 - This block is assigned for use as the Internet host
loopback address. A datagram sent by a higher level protocol to an
address anywhere within this block should loop back inside the host.
This is ordinarily implemented using only 127.0.0.1/32 for loopback,
but no addresses within this block should ever appear on any network
anywhere [RFC1700, page 5].
Поэтому в любых ОС возможно использовать в качестве локального адреса например 127.6.6.6 — настроить в вашем любимом Spring Boot прослушивание сокета на одном этом адресе и только он один будет отвечать в браузере.
UDP
Вторым важным пробелом является практически полное отсутствие знаний о протоколе UDP.
Максимум — на уровне теории, что оно вообще существует, в стиле статьи из википедии:
Двумя основными протоколами транспортного уровня являются надежный протокол управления передачей данных TCP (Transmission Control Protocol) и быстрый протокол дэйтаграмм пользователя UDP (User Datagram Protocol). TCP реализует сетевое взаимодействие в режиме с установлением логического (виртуального) соединения, а UDP - без оного.
Причем чаще всего UDP на лекциях описывают как «ненадежный», а TCP — «надежный», без малейшего понимания в чем эта надежность заключается.
Отсюда же происходит смутное представление о DNS и механизме разрешения имен, помимо боязни связываться с «ненадежным» протоколом уже в разработке.
Вспомните вообщем этот текст, когда очередной сервис видеозвонков между пользователями будет дико тормозить и терять кадры.
Например тот же Skype когда-то создавался и работал как раз на UDP. И работал он хорошо.
Все остальное
ICMP, RIP, OSPRF, VLAN — остались только во влажных мечтах рекрутеров и в моем старом резюме.
Даже аббревиатуры эти уже ничего никому не говорят, поэтому если вы знаете хотя-бы что такое ICMP — вы уже чуточку лучше типичного соискателя.
Веб vs натив vs мобайл
Следующим наблюдением является крайне смутное представление современных разработчиков о том что такое софт вообще и какие ключевые отличия есть между веб и нативной разработкой, между настольным ПО и мобильным приложением.
На это тоже есть серьезные причины — такого количества разнообразных вариантов и реализаций во времена моей молодости просто не существовало.
Когда-то все было очень просто:
есть исходный код, из которого собирается готовое бинарное приложение, которое затем запускается у пользователя на компьютере.
В настоящее время, разобраться в той же технологии PWA ( Progressive Web Application) многократно тяжелее чем ее использовать.
И она такая не одна — практически весь современный инструментарий разработки ПО всеми силами старается скрыть внутреннюю сложность, еще и ограничить кругозор разработчика до рамок себя любимого — вводя специфичную терминологию, не используемую вне данного конкретного стека.
Именно отсюда и растут те самые «требования» в вакансиях о владении какой-то определенной технологией Х лет.
Типы данных
Вы наверное догадываетесь что для того чтобы произвести операцию сложения над числами, нужно использовать числовой тип данных, а для работы со строками — строковый?
Так оно когда-то и было, примерно во времена когда тип «строка» еще не существовал и использовались массивы символов.
Ныне во всех модных языках работает автоматический boxing-unboxing, приведение типов и кокантенация.
System.out.println("obj="+ obj);
давно не вызывает никаких проблем ни у компилятора ни у рантайма ни у разработчика.
Так что владение типами данных ныне отсутствует как класс, поэтому не ждите ответа про разницу между double и float, например.
Ну и конечно знания о вещах вроде побитового сдвига остались в далеком прошлом:
int bitmask = 0x000F; int val = 0x2222; // prints "2" System.out.println(val & bitmask);
В новых проектах за последние 10 лет не видел ни разу.
Многопоточность и асинхронность
Наверное самое глупое что можно было сотворить в разработке это взять чисто клиентскую модель многопоточности из браузера и применить ее на серверной стороне, еще и выдав за «ноу-хау».
Бывает что недоделанное и слабое в техническом плане решение внезапно выстреливает и становится мейнстримом.
А проблемы и недочеты потом исправляются годами, если не десятилетиями.
Хороший пример такому подходу — проект Node.js, выкатывающий сборки и релизы чаще чем я обедаю.
Врядли кто-то теперь расскажет сколько на самом деле денег и времени было вбухано в этот проект и сколько ушло на постоянный рефакторинг начиная с 2009 года, но думаю вашему проекту так не повезет.
Еще Node.js сильно популяризовал «асинхронное программирование» и его применение везде и для всего.
асинхронное программирование это мощный инструмент, дающий прекрасный результат в опытных руках.
Например, в моей предыдущей статье про идеальное API — прямо объяснено, что никакое API нельзя делать синхронным. Но делать с помощью асинхронного программирования абсолютно все вообще — как забивать гвозди микроскопом, технически возможно, но точно не нужно.
в Node.js нет синхронного программирования, все вызовы, все функции, все методы — все асинхронное.
Последовательное выполнение вызовов вроде:
callFunction1(); callFunction2(); callFunction3();
в Node.js невозможно без специальных костылей ухищрений.
Поэтому три вызова выше выполнятся не последовательно, один за другим а параллельно.
И с моей скромной точки зрения такие органичения это уже перебор.
Конечно врядли массово встречаются разработчики на Node.js не знающие про такую особенность, но вот про связь между асинхронностью и многопоточностью знают точно единицы.
Дело в том что асинхронное программирование как раз позволяет скрыть детали реализации многопоточности, поэтому вполне можно абсолютно ничего не знать о каких-то там тредах и пулах ( не говоря уже о блокировках и мониторах) при этом каждый день писать асинхронный код.
Что вообщем-то и происходит в большинстве «молодежных» проектов.
Типичный пример, когда все это асинхронное детство заканчивается это разработка многопоточного парсера сайтов — такой штуки, что умеет ходить по страницам и выкачивать из них данные.
Как только появляется подобная задача — очень быстро приходит погружение в удивительный мир дедлоков, таймаутов и outofmemory.
Внезапно оказываются нужны блокировки, пул потоков, контроль выполнения и watchdog.
Если у разработчика не было подобного проекта — целый раздел знаний о внутреннем устройстве ПО является для него закрытым.
Серверы, клиенты и облака
Опять же, раньше все было куда проще и очевидней:
есть клиент — он отправляет запросы и получает данные, есть сервер — получает запросы и отдает данные
Под такое общее описание подходили и вебсерверы с браузерами и вызовы по API и сетевая работа с базами данных.
Исходя из такой простоты, были и простые правила проектирования:
Клиент должен в первую очередь быстро запускаться и прозрачно для пользователя обрабатывать ошибки.
Сервер должен выдерживать нагрузку и отдавать данные за предсказуемое время отклика, скорость холодного старта для сервера не принципиальна.
Теперь вернемся в современные печальные реалии.
Во-первых у нас теперь есть SaaS, PaaS, IaaS и совсем уж запредельная дичь вроде Amazon Lambda и Servless.
Простых правил проектирования для всего этого зоопарка не существует.
Все эти замечательные вещи — экосистемы, еще и со спецификой у каждого конкретного вендора.
А значит, то что будет создавать проблемы в AWS — будет замечательно работать на каком-нибудь GAE.
Теперь представьте себя на месте молодого разработчика, только-только научившегося ваять «облачный код» под Amazon Lambda — много он сможет сделать вне этой штуки и экосистемы Amazon вообще?
Если эта платформа полностью изолирует всю сетевую работу, всю работу с диском и уж конечно с памятью.
Абсолютно все точки взаимодействия с окружающим миром происходят через API платформы:
package example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import com.amazonaws.services.lambda.runtime.RequestHandler; // Handler value: example.HandlerInteger public class HandlerIntegerJava17 implements RequestHandler<IntegerRecord, Integer>{ @Override /* * Takes in an InputRecord, which contains two integers and a String. * Logs the String, then returns the sum of the two Integers. */ public Integer handleRequest(IntegerRecord event, Context context) { LambdaLogger logger = context.getLogger(); logger.log("String found: " + event.message()); return event.x() + event.y(); } } record IntegerRecord(int x, int y, String message) { }
Между прочим это официальный пример «программы» для Amazon Lambda. Сильно похоже на ваш обычный серверный код?
Современные реалии принесли современные же проблемы — путаницу в технических терминах и очевидное отсутствие глубины понимания всего.
Когда-то мне нравилось задавать спорные вопросы на собеседованиях разработчиков, вроде:
«расскажите чем облачный сервер отличается от обычного»
Варианты ответов были самыми разными, некоторые даже добавляли немного веселья в непростой процесс технического интервью.
Но больше я подобные вопросы не задаю — нынешнее поколение разработчиков вообще не знает что такое «обычный сервер», они его просто никогда не видели вживую.
Зато конечно легко рассуждают о «бесконечном масштабировании» и бесперебойной работе.
Итого
Время стремительно летит вперед, появляются новые области знаний, требующие своей отдельной жизни на обучение — например нейросети, AI и компьютерное зрение.
К ним сейчас лишь прикрутили клиентский интерфейс, но не нужно заблуждаться, думая будто вызов API для генерации картинок котиков это и есть вся технология.
Научный базис под этими технологиями — на десятилетия упорного труда.
Так что если вы планировали залететь в эту область с ходу — результат вас сильно разочарует.
Курсы вам конечно продадут, чего-то там вы даже пройдете, но к реальной работе это отношения иметь не будет.
Что касается более ширпотребных технологий вроде обычной веб-разработки — сейчас как никогда стоит тратить определенный процент времени на получение именно базовых знаний: сети, устройство ОС, SICP — вот это все.
Потому как буквально каждый фреймворк, язык или технология в современном мире будут стараться вас затащить к себе всеми способами и не отпускать.
Чтобы вы не выходили за границы решения и вообще не мыслили себе разработку чего-либо без этого конкретного фреймворка.
Думаю не стоит говорить, что такого в годы моей компьютерной юности не было, вернее оно было — но «там», не тут.
Тут, на окраине мира, мы росли сами, все изучали сами, без курсов и этих ваших «коучев»