Дорабатываем открытый код — развиваем и показываем всем свои навыки разработки ПО
Многие начинающие разработчики сталкиваются с необходимостью показать существующий опыт разработки ПО. Даже если вакансия называется «программист без опыта работы», то и без Капитана ясно, что предпочтение будет отдано претенденту, показавшему более-менее внятный код, более-менее подтверждающий наличие полезных в работе навыков.
Что же делать? Показать решение типового задания с ранних курсов или дипломный проект? Возможно, этого мало? Может быть, написать какую-нибудь впечатляющую программу и заодно получить опыт разработки? Например… калькулятор или компилятор или что там обычно пишут для получения и показа опыта? А если не хватит сил закончить?
На эти вопросы и сомнения есть один почти универсальный ответ — доработка проектов с открытым кодом. Вы получаете возможность решать реальные проблемы самых разных уровней сложности, результат не только будет работать у сотен-тысяч-миллионов людей во всем мире, но его еще и можно будет показать. Эту возможность иногда упоминают, но обычно на ней не останавливаются. В этот раз — остановимся на ней.
Идея допиливать открытый код у многих наталкивается на самые разные возражения. Вот самые распространенные.
Возражение первое — зачем доделывать «чужое» вместо того чтобы сделать «свое». Очень распространено среди людей без опыта разработки ПО и часто вызвано рассказами людей старшего поколения, которые сами тоже не имеют опыта разработки. Сюжет обычно примерно такой:
1. «сынок/доченька, ты закончишь вон тот прекрасный ВУЗ,
2. станешь ТЫЖПРОГРАММИСТОМ
3. напишешь крутую программу
4. ??????
5. ПРИБЫЛЬ — успех, деньги и вообще все твое»
Здесь все замечательно кроме одного — разработчики обычно не пишут код с нуля, чаще всего они дорабатывают существующий. Где-то нужно разобраться в тонне кода и дописать еще тонну кода. Где-то нужно отладить тонну кода и после переставить две строки местами (даже сами строки менять не нужно). Причина проста: разработка с нуля — очень затратное удовольствие и в новом коде очень много ошибок, поэтому «не каждый день нашему брату достается белить забор» целиком, обычно — закрашивают графити.
Поэтому, если без опыта начать разрабатывать что-то более-менее сложное с нуля, можно столкнуться со следующими проблемами:
1. не удастся довести написание и отладку кода до конца, потому что это сложно, а сил пока маловато, может просто не хватить терпения
2. если пункт 1 пройден, то получилась программа с очень ограниченными возможностями, которую почти никто не будет использовать, потому что… ВНЕЗАПНО у потенциальных пользователей уже есть такая же или похожая привычная и готовая программа, а про вашу новую они не слышали, и чтобы это изменить, вам нужно основательно заниматься продвижением
3. квалифицированных разработчиков, готовых оценить качество вашего кода и дать вам обратную связь, очень мало или нет совсем, а это заметно замедляет ваш рост и может повредить в будущем — вы привыкнете писать код действительно плохо и позже озадачите работодателей и озадачитесь сами.
Если пренебречь этими проблемами, вы рискуете потратить много сил на работу, которая будет обречена на забвение (она же «работа в стол»). Если вы осознаете масштаб этих проблем и вас все устраивает или вы готовы их решать — не читайте дальше, разрабатывайте… что вы там хотели разработать?
Для сравнения, допиливая открытый код, вы
1. можете не разрабатывать с нуля, а дорабатывать уже работающее (да, глючит, но вы же вот-вот исправите), причем доработка может быть как тривиальной (исправление несложной ошибки), так и очень сложной (какая-нибудь впечатляющая новая возможность или ускорение генерации машинного кода компилятором на 15 процентов), вы можете начинать с простого и двигаться все выше
2. если ваши правки приняты, то они попадают в давно существующий канал распространения той программы, которую вы доработали, и вы получаете продвижение результатов своей работы автоматически
3. ваши правки оказываются всеобщим посмешищем на виду у относительно большого числа разработчиков, которые могут, например, указать на неочевидные ошибки и попросить доделать правку
4. вы получаете опыт работы с существующим кодом, его неповреждающей доработки и общения с людьми, которым надо объяснить суть правки и, может быть, ответить на возникшие вопросы, эти навыки очень важны для разработчика — оценка рискованности правок, оценка важности исправления той или иной ошибки, объяснение всем заинтересованным первого и второго помогают всем участникам разработки принимать осмысленные решения.
Итак, дорабатывая «чужой» открытый код, вы избавляетесь от целого ряда существенных препятствий. Проще начать работу, проще получить обратную связь, результат вашей работы вполне может попасть в следующий выпуск программы и постепенно оказаться у сотен-тысяч-миллионов пользователей, плюс он будет лежать в открытом для чтения репозитории и вы сможете его всем показывать. Путь становится намного менее тернистым.
Второе возражение — это же надо иметь уже развитые навыки и многие знания, тысячи их, а знаний еще нет, поэтому недостаточно сил, никак нельзя начать.
Давайте посмотрим на вот этот кусок кода (упрощенный вариант кода одной нужной многопоточной библиотеки)
DWORD waitTime;
DWORD secondsInMilliseconds;
DWORD millisecondss;
/*...............................*/
/* секунды в миллисекунды */
secondsInMilliseconds = (DWORD)interval->seconds * 1000;
/* наносекунды в миллисекунды с округлением вверх */
milliseconds = (interval->nanoseconds + 999999) / 1000000;
/*
* Многие компиляторы выдают предупреждение "условие никогда не выполняется",
* потому что переменная беззнакового типа, но проверка точно зачем-то нужна.
*/
if (0 > (waitTime = secondsInMilliseconds + milliseconds))
{
return EINVAL;
}
Видите, даже есть комментарий, что многие компиляторы выдают на этот код предупреждение, но код «зачем-то нужен». И действительно, VC++, gcc и clang выдают предупреждение на этот код, говорят, что проверка-то бессмысленна.
Спойлер: авторы хотели проверить, что сложение не дает переполнения, в случае знаковых целых этот трюк дает неопределенное поведение, но на большинстве платформ «работает», а здесь числа беззнаковые, поведение Стандартом языка определено, но проверка ничего не проверяет. Правильно так:
if (secondsInMilliseconds > UINT_MAX - milliseconds)
{
return EINVAL;
}
waitTime = secondsInMilliseconds + milliseconds;
Выше в этом же коде присутствуют умножение и сложение с константой, но там переполнение даже не пытались проверить.
Какая нужна квалификация, чтобы понять, что должен был делать этот код и хотя бы примерно как его исправлять? Пять лет опыта работы? Десять? Может быть, джвадцать?
Достаточно заинтересованного студента второго-третьего курса специализированного ВУЗа. Есть, например, один ВУЗ, где в четвертом семестре студенты по подсказкам в учебнике пишут и отлаживают программу, хранящую введенные данные в односвязном списке, звенья которого создаются в динамической памяти, при этом весь код, включая несложный распределитель памяти, нужно написать на ассемблере для x86. Достаточно сил разобраться в работе распределителя памяти, но недостаточно, чтобы разобраться с кодом выше? Да неужели.
Все равно слишком сложно? Тогда попроще — тоже по мотивам реального кода.
void* impl_calloc(size_t numberOfObjects, size_t objectSize)
{
unsigned int totalSize = numberOfObjects * objectSize;
void *p;
p = malloc( totalSize );
/* WHATEVER */
Здесь надо было использовать size_t и проверять, что нет переполнения при умножении. Какая нужна квалификация, чтобы это исправить?
И это слишком сложно? Еще проще — где-то в недрах довольно аккуратного кода очень нужной программы прямо посреди функции стоит ЭТО объявление:
std::stack<const Token*> f;
Да, конечно, все понятно. Очевидно же, что f — это f. Здесь «все работает», но разработчик, который будет отлаживать окружающий код, будет какое-то время недоумевать, что это и зачем, и почему потом добавляют именно эти указатели именно в этот объект std::stack. Здесь совсем не вредно понять, для чего переменная, придумать ей короткое осмысленное имя, согласованное с другими именами в окружающем коде, и исправить. Возможно, нужно назвать переменную fields или functions. Какая нужна квалификация, чтобы это исправить?
В открытом коде полно самых разных дефектов самой разной сложности, многие даже искать не надо, они много лет находятся на видном месте, подпрыгивают и пищат «причешите нас, ну пожалуйста».
Третье возражение — правки могут не принять. Действительно могут. Владельцы проекта могут решить, что предложенная правка по каким-то причинам не подходит (например, новая возможность не нужна). Помогает сначала посмотреть на историю изменений, чтобы понять, есть ли жизнь на Марсе, а затем отправить небольшую правку, чтобы было не так обидно. Как вариант — могут быть обязательные условия в виде отказа от авторских прав (например, в SQLite), которые технически сложно выполнить, такое бывает редко, но лучше заранее об этом узнать. В большинстве случаев все особые условия оговариваются сразу и на видном месте (например, есть раздел contributors). Не все проекты принимают правки одинаково легко, но найти подходящий проект несложно.
Четвертое возражение — там же помойка, не для этого вы столько лет учились. Не такая уж и помойка, тем более все равно разработчики обычно дорабатывают существующий код, в котором присутствуют разные дефекты в большем или меньшем количестве. Посмотрите на это с другой стороны — вы сможете разобраться в сложном непонятном (иногда очень сложном и очень непонятном) коде и улучшить его. Добавление десяти строк кода в широко используемую многопоточную библиотеку может быть намного ценнее целого калькулятора на тысячу строк.
Пятое возражение — надо же сделать что-то сложное для «присоединения» к подходящему проекту. Нет, уже не надо. Такие системы как Github позволяют предложить правки в несколько щелчков мышью. Найти дефекты можно в списке ошибок проекта, просмотром кода, статическим анализатором (например, совершенно бесплатным Cppcheck, код которого также открыт и лежит на Github) или из предупреждений компилятора. Проект вы можете выбрать сами — например, заглянуть ненадолго внутрь библиотеки, которую ранее использовали для работы с XML в вашей курсовой работе.
Можно придумать сколько угодно возражений или начать уже допиливать открытый код.
Дмитрий Мещеряков,
департамент продуктов для разработчиков