После окончания университета через несколько лет работы по специальности у меня появилась мысль прийти на кафедру программирования и предложить организовать лекцию для студентов старших курсов, где я бы рассказал им, как вообще работается программистом, и что я сам хотел бы знать об этом, когда учился. Это по разным причинам не случилось, но идея осталась, и я решил реализовать ее в виде статьи. Текст написан для студентов без опыта работы.
Немного о себе. Я занимаюсь веб-программированием, у меня 12 лет опыта, основной язык PHP. Проекты, где я работаю, это обычно крупные системы, над которыми работает команда программистов, и которые нужны какому-то бизнесу для его деятельности. Такие проекты называют словом "энтерпрайз". Например, это интернет-магазины и связанные с ними внутренние системы.
Языки программирования
Начнем с языков программирования. Мы в университете изучали C++ на первых курсах. Про него нужно знать следующее. Если вы разобрались с классами, указателями, и пишете все лабы на C++, это не значит, что вы знаете C++. Там есть много технических нюансов - undefined behavior, умные указатели, виртуальные деструкторы, и много чего еще. Также надо знать основные библиотеки - std, boost. Если вы этого не знаете, на реальные вакансии вас не возьмут. Если только на стажировку, которая есть далеко не везде. Даже профессиональные программисты на C++ иногда жалуются на техническую сложность C++.
Более современные низкоуровневые языки это Rust и Go. Есть более высокоуровневые языки - например Java, C#, PHP, Python. Все они очень распространены, нет необходимости хорошо знать именно C++. Но в целом понимание, как всё работает на низком уровне, это плюс.
Языки Lisp и Prolog в чистом виде не используются. Функциональные языки, которые используются на практике, это например Haskell, Scala, Erlang, F#. Но их доля относительно императивных языков не очень большая. Нужно знать, что есть такая концепция неизменяемых переменных, у нее есть свои плюсы, и на таких языках тоже можно писать программы.
Могу посоветовать изучить HTML, CSS и JavaScript, даже если это не требуется по программе. Браузер имеет хорошие возможности по отображению графики, в нем удобно делать лабораторные работы, где нужен интерфейс пользователя, но не требуется какой-то определенный язык программирования.
Веб-программирование сейчас очень распространено, обычно в таких проектах есть база данных и серверный язык, который генерирует HTML для браузера, или возвращает в браузер нужные данные, а интерфейс создается с помощью приложения на JavaScript. Серверный язык может быть любым, часто это один из тех, которые я написал выше. JavaScript тоже используется в качестве серверного языка.
Для любых языков важно знать не только сам язык, но и распространенные библиотеки и фреймворки для него. Вас не будут брать на работу, если вы не знаете хотя бы один фреймворк.
Базы данных
Базы данных широко используются. Проектов, где не нужно хранить данные, довольно мало, а если их нужно хранить, то обычно для этого используются базы данных, а не просто файлы. Нужно знать SQL и уметь с ними работать. Реляционную теорию знать не нужно, нормальные формы никто не спрашивает. Нужно знать, как разделять данные на таблицы и как их соединять через внешние ключи. На практике чаще всего используются INNER JOIN и LEFT JOIN, другие формы использовать не рекомендуется, так как их сложно понимать. В джойнах лучше писать только условие равенства ключей, дополнительные условия лучше писать в WHERE.
В контексте теории баз данных есть распространенное утверждение, что искусственные (суррогатные) автоинкрементные первичные ключи использовать не рекомендуется, лучше найти уникальные естественные ключи. Это не так. В реальности любые 2 объекта могут иметь одинаковые характеристики. Характеристики, которые можно использовать в качестве первичного ключа, это такие же искусственные ключи, просто придуманные для некомпьютерного учета. Обычно они тоже имеют инкрементную природу, например, инвентарные номера или номера телефонов. При этом не нужно использовать номер телефона в качестве первичного ключа для таблицы со списком людей, у человека может быть 2 номера или ни одного. Номер телефона может являться первичным ключом только для таблицы телефонов.
Искусственные ключи, которые уже существуют в предметной области, обычно не оптимальны для производительности, поэтому делают числовой автоинкрементный первичный ключ, а на поле, которое можно считать уникальным, добавляют уникальный индекс. Первичный ключ нужен для самой системы, чтобы можно было программным способом идентифицировать и различать соответствующие объекты, поэтому нужно делать так, чтобы это было удобно с технической стороны.
Случай, где отдельный автоинкрементный ключ использовать не нужно - это промежуточные таблицы для связи многие-ко-многим. Связь подразумевает 2 объекта, которые она соединяет, поэтому первичный ключ для нее состоит из ключей этих объектов. Для других связей промежуточную таблицу обычно не делают, поэтому для них используется первичный ключ основной таблицы.
Cистемы контроля версий
Cистемы контроля версий тоже широко используются. Основные это Git, Mercurial, SVN. Самая распространенная система это Git. Они нужны для хранения истории изменений, отслеживания и управления изменениями, особенно при работе в команде.
Если вы с ними не знакомы, и пробовали разрабатывать какую-то большую программу, то у вас скорее всего была необходимость делать копии текущего состояния, которое точно работает, и на которое можно вернуться, если новые изменения не работают. В результате у вас были папки вида "ProjectName v1", "ProjectName v2", "ProjectName v3". Система контроля версий упрощает эти действия, и имеет более развитые возможности, в том числе для работы многих людей над одним проектом. Нужно знать, что такое коммит, ветка, мерж-реквест, и как с ними работать.
Связанные дисциплины
Физику знать не нужно. Желательно иметь представление на школьном уровне об основных терминах, в основном связанных с электричеством, чтобы понимать, о чем идет речь, если она где-то об этом идет.
Математику подробно знать не нужно. Но ее изучение показывает, насколько хорошо вы можете разобраться в незнакомой информации. Также надо иметь представление об основных концепциях, вдруг где-то понадобится - проценты, синус-косинус, логарифмы, матрицы.
Отдельно надо отметить математику, связанную со сложностью алгоритмов. Нужно иметь представление, что такое сложность алгоритмов, как она оценивается. Обычно в работе это не требуется, но иногда все-таки требуется. Несмотря на это, про нее часто спрашивают на собеседованиях, так как это один из способов проверить хотя бы какие-то знания из области ИТ за несколько минут. Сортировки, деревья, графы. Обычный цикл - линейная сложность, вложенный цикл - квадратичная, дерево или рекурсия обычно логарифмическая, но зависит от ситуации. Лучший и худший случай могут иметь разную сложность. Константный множитель не считается.
В работе более важно не знание чего-то, а умение изучать незнакомый материал. Но чтобы изучать, надо хотя бы что-то знать.
Английский язык
Английский язык желательно знать. Он помогает в чтении документации и при поиске работы. Во многих зарубежных компаниях идет общение на английском, и уровень владения им оценивается на собеседовании.
Процесс поиска работы
У тех, кто еще не искал работу, часто есть неправильное представление об этом процессе.
Кажется, что это происходит так. Вы прочитали объявление "Требуется программист", приходите такие, спрашиваете "Еще ищете программиста? - Да - Я согласен - Знаете то-то и то-то? - Да, там вот так-то и так-то - А вот это знаете? - Нет, но я разберусь - Хорошо, вы приняты, начинайте работать". Такого не бывает.
Обычно происходит так. Компания проводит собеседования пару недель, потом из кандидатов выбирает лучшего. Даже если вы ответили на все вопросы, далеко не факт, что возьмут именно вас. Если у другого человека опыт работы на 6 месяцев больше, или есть какие-то дополнительные курсы, проекты, выступления, или он отвечал более подробно и уверенно, возьмут его, а не вас, даже если он проходил собеседование позже. Так, чтобы взяли первого подходящего, происходит крайне редко.
Если вы чего-то не знаете, никто не будет проверять, разберетесь вы или нет. Компания не будет платить вам деньги, чтобы это проверить. Специалисту с хорошим опытом могут поверить, вам без опыта никто не поверит. Поэтому и нужно знать хотя бы один распространенный фреймворк для вашего языка, так выше шансы получить работу, где он используется.
Иногда не берут никого из первых кандидатов и продолжают искать, месяц, два, или дольше. Потому что уволить плохого специалиста не так просто, проще подождать и взять нормального.
Собеседований может быть одно или несколько. Обычно сначала разговор с HR, потом техническое собеседование с программистом, чаще всего с руководителем команды (тимлидом). В небольших компаниях может быть одно сразу техническое, в больших 3-4.
HR-специалисты бывают не всегда компетентны. Технические специалисты, которые проводят собеседование, иногда бывают неприятными в общении людьми, пытаются показать превосходство, задают слишком сложные вопросы, спрашивают не то, что нужно в реальной работе. Надо понимать, что так бывает. C HR-специалистами после приема на работу вы обычно не будете сталкиваться, а вот если вам встретился такой технический специалист, то надо подумать, действительно ли вы хотите работать в такой компании.
Заведите аккаунт на GitHub или Bitbucket, напишите пару небольших проектов с хорошо оформленным кодом и выложите туда, добавьте ссылку в резюме. Тестовые задания тоже обычно просят выложить на GitHub.
Пока у вас нет опыта, берите любые тестовые задания. Это даст вам представление, какие задачи вообще бывают. Нормальное тестовое задание можно сделать за один вечер. Тестовые задания на неделю это странно, такие компании лучше избегать. Можно сделать такое задание из интереса, но не отправлять результат. Иногда дают небольшое задание, и разрешают прислать в течение недели, это нормально.
В тестовом задании важно не только то, что оно должно работать, а еще и стиль кода, структура классов, насколько код понятен и легко читается. Не нужно комментировать каждую строку, это наоборот минус. Нужно выравнивать отступы, понятно называть переменные, классы и методы, разбивать большой код на разные методы, выносить группы связанных методов в разные классы. Нужно использовать общепринятые подходы, даже если для небольшого задания они кажутся избыточными. Тут есть сложность, что если нет опыта, то непонятно, какие подходы общепринятые. Тут ничего не сделаешь, нужен хотя бы косвенный опыт. Уточняйте у проверяющего, что было не так с тестовым заданием, читайте технические книги и статьи, изучайте код open-source проектов, пробуйте сами что-то писать.
Часто на собеседованиях спрашивают, есть ли у вас вопросы. Говорят, что если ничего не спрашивать, то это минус, будто бы показывает, что вы не заинтересованы. Это конечно не так, пока нет опыта, хоть какую-то работу бы найти, но не все HR-специалисты это понимают. Я обычно спрашиваю, сколько человек работает в команде, и еще что-нибудь по ситуации.
Если у вас уже есть какой-то небольшой опыт тут и там, возникает желание добавить всё в резюме. Частая смена места работы у HR вызывает подозрение. Это может говорить о том, что вы плохо взаимодействуете с коллективом и не можете удержаться на одном месте. 2 года и больше на одном месте считается нормально, 1 более-менее, меньше 1 уже странно. Пока у вас мало опыта, объясняйте в описании каждого места, почему ушли - может это был небольшой разовый проект, и вы его завершили, или зарплату платили меньше, чем обещали. Подумайте о том, чтобы объединить несколько мест в одно с названием типа "Разовые проекты" или "Фриланс", без лишних подробностей.
Отзываться плохо о бывших коллегах не рекомендуется, особенно в разговоре с HR. Если на прошлом месте работы были проблемы с поддержкой плохого кода, ищите нейтральные формулировки, или просто не сообщайте подробностей. В разговоре с программистом можно осторожно обсудить технические недостатки решений, он хотя бы поймет. Но без особой причины тоже лучше не нужно. Идеального кода не бывает, везде есть какие-то недостатки, вопрос только в том, насколько приемлемо их количество.
Процесс работы
После приема на работу вы будете работать в команде, поэтому умение взаимодействовать с людьми очень важно. Это называется soft skills. Их проверяют на собеседованиях. Нужно уметь вежливо общаться, защищать свою точку зрения без грубости, даже если кто-то грубит вам, нужно уметь слушать и не перебивать, давать высказать другому человеку его мысль, нужно уметь идти на компромиссы, принимать другую точку зрения, и делать что-то, с чем лично вы не согласны.
Практически на любой работе есть процесс код-ревью. Вы сделали свою задачу, написали код, создаете мерж-реквест с изменениями, и кто-то из других программистов его просматривает. Для этого используются системы контроля версий и связанные с ними инструменты. Код должен не только работать, но и быть понятен для других. Потому что потом задача на изменение этого кода может попасть к другому программисту, и для компании лучше, если он не будет тратить время на то, чтобы разобраться, что вы там написали. Во время код-ревью проверяется соответствие общепринятому стилю, структура и понятность кода, код анализируется на возможные ошибки.
Можно также отметить процесс тестирования. Для кода часто делают юнит-тесты, они находятся вместе с основным кодом проекта, их пишут программисты. В тесте задаются правильные входные и выходные данные для какого-то кода, это гарантирует, что если в дальнейшем при внесении изменений в этот код будет допущена ошибка, из-за которой выходные данные изменятся, то это будет заметно. Такие тесты запускаются перед каждой выкладкой новых изменений на рабочий сервер ("в продакшн"), а также сразу при создании мерж-реквеста.
Кроме этих тестов есть отдел тестирования. Тестировщики тестируют работу проекта с точки зрения пользователя, они проверяют основные сценарии вручную или с помощью специальных автотестов, которые управляют браузером или окном приложения и имитируют взаимодействие пользователя с элементами интерфейса. Иногда такие тесты тоже пишут программисты.
Задачи назначаются в трекере задач, их много разных, самый популярный это Jira. У задачи есть номер, обычно его нужно указывать в сообщении коммита. Так другие программисты в дальнейшем смогут найти, почему было сделано какое-то изменение в коде. Часто есть требование заносить в задачу примерное время, которое на нее было потрачено. Это нужно для отчетов и планирования, в нормальных компаниях никто у вас не будет спрашивать доказательства, почему вы потратили 2 часа вместо 1. Некоторые компании требуют устанавливать средства контроля, которые делают снимки экрана, чтобы проверить, что вы действительно работали, их лучше по возможности избегать. Уточняйте это на собеседованиях.
Часто используется подход, когда рабочий день начинается с общего созвона через интернет или сбора в офисе, где все рассказывают, что они делают, какой прогресс по задачам, и есть ли какие-то проблемы или вопросы.
Удаленная работа практически ничем не отличается от офисной, только в офис ходить не надо. Обычно есть рабочий чат, где можно обсудить любые вопросы.
Книги
Могу посоветовать 3 книги, которые стоит прочитать:
Макконнелл - Совершенный код
Гамма, Хелм, Джонсон, Влиссидес - Приемы объектно-ориентированного проектирования. Паттерны проектирования
Эванс - Предметно-ориентированное проектирование (Domain-Driven Design, DDD): структуризация сложных программных систем