Написать пост

Должен ли «настоящий» программист знать язык Си — отвечают эксперты

Аватар Никита Прияцелюк

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

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

Да, сейчас запросов на разработку современных продуктов на языке С относительно немного. Как показывает наш портфель проектов, выше спрос на С++. Однако, в программисте мы видим, прежде всего, инженера, способного разобраться со сложными вопросами, которые, возможно, до него ещё никто не решал. Поэтому знание основ С — это плюс для общеинженерного развития специалиста.

В современной индустрии преобладает разработка с использованием объектно-ориентированного программирования (ООП), язык Си — процедурный и сейчас стал «нишевым». Он используется в областях, где существуют жесткие требования к производительности, или аппаратные ресурсы платформы сильно ограничены. Примером может стать ядро Linux или программирование микроконтроллеров.

В мобильной разработке язык Си может использоваться при написании игр или для создания native методов Java классов, реализация которых использует вызовы JNI.

Язык Си считается языком низкого уровня. Начав изучение программирования с него, специалист будет лучше понимать базовые вещи в разработке. Кроме того, существует множество языков программирования, синтаксис которых берёт начало у языка Си, например C++, Java, C#. Знание «первоисточника» наверняка облегчит их изучение.

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

Программист высокого уровня должен иметь широкий кругозор и не замыкаться в рамках одной парадигмы программирования или языка. Сегодня в России не так много специалистов, хорошо владеющих «низкими» языками программирования, а знание Си может стать важным конкурентным преимуществом.

«Настоящему» программисту стоит понимать концепции, которые лежат в основе языка Си — как работает управление памятью, указатели, структуры. Здесь можно провести аналогию: нужно ли знать водителю устройство автомобиля? Если человек хочет просто перемещаться из точки в точку, то ему вряд ли пригодятся такие знания в полной мере. А вот если он хочет стать хорошим водителем, то с некоторыми принципами работы автомобиля всё же придётся разобраться.

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

Изучать какой-либо язык программирования, не имея планов по дальнейшему применению этих знаний на практике, к сожалению, бессмысленная затея. Знания, не подкреплённые практикой, как минимум будут неполными, ну а как максимум — «улетучатся» через полгода-год.

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

Несколько реализованных проектов по разработке системного ПО разных классов — и у вас уже будет не только понимание базовых принципов функционирования операционных систем, но и ценный практический опыт. Естественно, реализация будет на языке C/С++!

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

Но сам вопрос — острый, и фокус в нём вовсе не на Cи, а на том, какую технологию выбрать для изучения сейчас, чтобы принимать участие в реальных проектах в будущем. Конечно, верный ответ тут: «любую».

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

Я считаю, что Cи как первый язык — это неудачный выбор. Там нет ни одной интересной парадигмы. Все аргументы вроде «Cи — основа основ», «Cи самый быстрый», «Cи позволяет лучше понимать базовые вещи» не выглядят убедительными. Си важный язык для определённых экосистем, например микроконтроллеров, утилит и ядра ОС, драйверов, встраиваемых систем и т. п. Но это довольно узкие области. Человек, который учит Си конкретно для этих кейсов, обычно не руководствуется понятиями «трушности» технологии.

Для обучения на первоначальном этапе я бы посоветовал рассматривать Java или C++, у них хорошая ООП-парадигма и много интересных новинок в стандартах. Кроме того, они более универсальные и востребованные. В C++ порог входа чуть выше. Также неплохим вариантом будет изучение JavaScript. По тем же причинам.

Да, действительно, в ряде случаев изучение C/С++ улучшает понимание того, как работает компьютер и способствует значительному улучшению качества кода, написанного даже на других языках. Особенно это полезно программисту, для которого единственным известным языком является какой-нибудь достаточно высокоуровневый язык (Python, JavaScript, PHP). С другой стороны, возможно, вы уже знакомы с основами работы компьютера и не собираетесь программировать на C/C++. Тогда терять время на изучение этих языков не стоит. Можно легко проверить себя, ответив на вопросы ниже. Если вы чётко представляете ответы на них, то, скорее всего, C/C++ вам нужно изучать, только если вы собираетесь писать программы именно на этих языках:

  1. Как сложные объекты передаются в функции в известном мне языке программирования? Сколько времени и памяти тратится при такой передаче?
  2. Как рассчитать требуемый объём стека для рекурсивной функции, если известна максимальная глубина рекурсии?
  3. Что такое выделение и освобождение памяти? Где в моей программе память выделяется, а где освобождается? Как спрогнозировать, сколько памяти будет потреблять моя программа?
  4. Что такое полиморфизм в объектно-ориентированном программировании?
  5. Что такое шаблоны (паттерны) проектирования программ? Известны ли вам какие-нибудь из них?

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

Обязательно ли знать Си современному веб- или мобильному разработчику? Я думаю, что нет. В большинстве случаев в ежедневной разработке знание Си ему не потребуется. С другой стороны, будет ли вредно понимание основ и концепций этого языка? Точно нет. Я уверен, что интересы «настоящего» программиста (в моем субъективном понимании) должны выходить за пределы ежедневной рутины.

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

Не должен.

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

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

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

Си — это язык, который сейчас имеет свою большую нишу: он используется в операционных системах и системах реального времени, область применения которых очень широка — от IoT до управления самолетами. Если такой «хард и металл» — это то, чем вы хотите заниматься, учить Си нужно, но в других сферах деятельности гораздо эффективнее разрабатывать на других языках, и там знание Си, скорее всего, никак не поможет.

Однозначно можно сказать только то, что грести всех под одну гребёнку неверно. И разделение на «настоящих» и «ненастоящих» программистов — одна из попыток людей систематизировать то, что не только не поддаётся систематизации, но и не нуждается в ней. Абсолютно равнозначным в этой ситуации будет такой вопрос: «Должен ли “настоящий” программист С знать другие языки?». Да, С — это старый, завоевавший уважение язык, повлиявший на многие другие, но в 2019-м году нет явной необходимости его учить, чтобы уметь программировать, закрывать задачи бизнеса или понимать внутренние процессы в приложениях. Знание С и умение, например, работать с указателями, помогает в работе, это факт. Очень сильно помогает быстро выучить какой-нибудь С-подобный язык, это тоже правда. Организует и приучает к строгости, возможно. Но так, чтобы «должен, иначе не настоящий программист» — вряд ли.

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

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

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

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

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

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

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

Сейчас кадров с таким бэкграундом в подготовке становится всё меньше, поэтому заявление «если не знаешь С — то ты не программист» теряет актуальность. Прикладные задачи можно спокойно решать и без системного понимания сферы ИТ и места в ней поставленной задачи.

Наверное, стоит начать с того, что такое «настоящий программист». Ещё не так давно программисты практически не разделялись по своей специализации — ну, разве что по языкам. Тем не менее, наиболее сложным видом программирования считалось системное программирование, которое и сегодня почти невозможно без знания С (а также ассемблера и микроархитектуры железа, что, несомненно, тоже должно было входить в арсенал «настоящего программиста»).

С другой стороны, сейчас существуют совершенно несвязанные друг с другом области работы программистов; специалист в области BigData должен иметь другую квалификацию, нежели специалист в области внедрения ERP. Соответствующим образом разделяются и требования к «настоящему программисту», например «настоящий программист» в области искусственного интеллекта не может не знать математику. Поэтому если вы не знаете С — не переживайте, вы всё ещё вполне можете себя найти, скажем, в качестве frontend разработчика.

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

Если же говорить о программистах-разработчиках-исследователях, которые пишут не просто реализацию какого-то известного подхода, то скорее уместно говорить о Python и С++. Первый хорошо подходит для прототипирования, а последний часто используется в продакшн-коде крупных компаний. У нас это основные языки программирования, в целом всё зависит от того, в какой отдел и на какую позицию приходит работать человек. Сейчас язык C встречается мало где, но есть ниши, где требуется знание именно этого языка. Однако лично я не считаю C обязательным языком для каждого программиста.

Есть очень много высокоуровневых языков: для Ruby on Rails, например, достаточно 3–4 месяца, чтобы его освоить хотя бы на базовом уровне. Си — более академический язык, и даёт фундамент для понимания, как работают другие языки. Люди с опытом в Си имеют больше фундаментальных знаний, а также представление о том, как устроены языки программирования, и какие операции и логика будут/могут влиять на память, CPU и другие компоненты приложения и железа. Это связано с тем, что данный язык требует большого внимания к этим деталям и позволяет через код влиять на них. Тратить или не тратить время на изучение — решает каждый сам в зависимости от своих целей. Если говорить о разработке промышленных решений, то знание языка Си пригодится. Если речь идёт о разработке сайтов, панелей админок и небольших стартапов — то знаний других языков будет достаточно.

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

Кто-то становится журналистом, кто-то писателем, а кто-то учёным. Понятно, что все эти профессии объединяет одно — способность чётко и правильно выражать свои мысли: журналисту — в публицистическом стиле, писателю — в художественном, учёному — в научном. Точно так же и изучение Си способствует вырабатыванию собственного стиля, который может быть применён в дальнейших языках, специализирующихся на своих задачах. Знания Си одинаково полезны будут и системному программисту, и прикладному, и веб-технологу. Стоит только вспомнить, какие языки используют похожий синтаксис: C++, C#, Java, JavaScript, PHP, Perl, AWK. И многие другие.

Ещё один аргумент в пользу того, чтобы начать изучение программирования именно с Си, заключается в том, что этот язык не прощает ошибок. Здесь не получится небрежно обойтись с памятью, уповая на сборщика мусора или на то, что интерпретатор пропустит мимо выход за пределы массива. Здесь нет ни интерпретатора, ни сборщика мусора. Поэтому такие ошибки будут сразу видны, и в сотый раз получив сообщение от операционной системы Segmentation fault, ученик начнёт задумываться, что, в конечном счёте, приведёт к формированию правильного стиля кода и поможет ему в дальнейшем в освоении новых языков.
Конечно, освоивший Си с лёгкостью перейдёт на более высокоуровневые инструменты, но навык хорошего стиля, при достаточном уровне проработки на Си, у такого ученика останется навсегда. А если ученик особо пытливый, он захочет разобраться, как именно исполняется его программа на вычислительной машине и откроет скомпилированный файл в дизассемблере. Благодаря тому, что Си не оброс большим количеством наслоений и абстракций, не составит большого труда сопоставить полученный код с тем, что было изначально. А это первый шаг к изучению языка ассемблера. Сделав такой шаг, ученик встаёт уже на путь системного программиста, программиста микроконтроллеров или исследователя программ. Удивительный мир низкого уровня особенно понравится перфекционистам, которые захотят досконально изучить принципы функционирования вычислительной машины и полностью контролировать её.

Недаром язык Си называет в шутку «кроссплатформенным ассемблером». И хотя словосочетание само по себе является оксюмороном, доля правды в этой шутке всё же есть. Например, интерфейс системных вызовов в UNIX-подобных операционных системах осуществлён именно с использованием библиотек Си. На этом языке также разрабатываются операционные системы, драйверы, программное обеспечение для микроконтроллеров, на этом языке пишутся компиляторы и трансляторы. Компилятор gcc, используемый для компиляции программ на Си — одна из главных программ, входящая в базовую комплектацию любого дистрибутива Linux, поскольку сборка остальных пакетов и модулей происходит путём компиляции исходников именно на этом языке. Стоит также отметить, что большинство технологий и средств разработки более высокого уровня изначально были написаны на Си: интерпретируемые языки вроде Python, Perl и PHP, виртуальная машина Java и многое другое.
Время выполнения того или иного алгоритма и потребление им памяти максимально «честно» можно вычислить именно на языке Си, ведь никаких дополнительных накладных расходов при выполнении программы не происходит. Вот почему это особенно полезно для проверки себя на правильность реализации тех или иных алгоритмов. В учебной программе бакалавриата МАИ уже пять лет успешно изучается курс Си, вытеснив собой язык Pascal. И хотя Pascal даёт возможность понять работу основных алгоритмов, в нём многие ошибки контролируются на уровне синтаксиса. Вот почему важно делать много ошибок на самом начальном этапе, разбирать их, контролировать и не допускать в будущем. Также важно понимать не только ход работы алгоритма, но и представлять, сколько такой алгоритм потребляет системных ресурсов. Классический синтаксис важно изучить, чтобы не возникло проблем с изучением других технологий в будущем. Вот главные причины, почему стоит начать изучение программирования с этого замечательного языка.

Итак, должен ли тру-программист знать Си?

В общем и целом, эксперты сошлись на мнении, что не должен.

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

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

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

Напоминаем, что вы можете задать свой вопрос экспертам, а мы соберём на него ответы, если он окажется интересным. Вопросы, которые уже задавались, можно найти в списке выпусков рубрики. Если вы хотите присоединиться к числу экспертов и прислать ответ от вашей компании или лично от вас, то пишите на experts@tproger.ru, мы расскажем, как это сделать.

Следите за новыми постами
Следите за новыми постами по любимым темам
29К открытий29К показов