Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Качественное образование — это не просто формальный диплом именитого вуза или парочка сертификатов о пройденных курсах. Это прежде всего новые навыки и уверенное желание применять их на практике. Такое возможно, если человек на самом деле хорошо учился и если его хорошо учили. Ведь даже самую интересную дисциплину можно преподавать так, что студентам будет откровенно скучно.
Меня зовут Антон Полднев, я уже давно пишу в Яндексе на C++ и руковожу сервисом, написанным на этом языке. Параллельно я учу других людей навыкам разработки. С 2016 года я вёл курсы на Coursera, затем мы их прокачали и сделали на их основе курс для Практикума. В этом посте я расскажу, как мы учим людей C++, а также про основные особенности этого языка.
Языковые сложности. C++ VS Python
Да, плюсы́ — не такой популярный язык для студентов, как тот же питон, например. Если мы говорим о человеке, который решил впервые попробовать свои силы в программировании, то он с большей вероятностью пойдёт писать именно на Python, нежели на C++. Здесь дело и в пороге входа, который у плюсов ощутимо выше, и в том, что на Python куда проще получить в результате своих трудов полноценную работающую программу. Ведь там многое доступно сразу из коробки, нет лишних скобочек и связанных с ними сложностей. Работа с файлами там тоже заметно проще — в общем, просто берёшь и работаешь.
Сейчас даже в школах, где уделяют внимание программированию, учат способных учеников именно Python. Конечно, многие из нас с вами на уроках информатики начинали с Pascal или Visual Basic, в ряде школ наверняка они ещё остались. Но проблема Pascal в том, что обучиться-то ему можно, а вот найти применение в реальной жизни уже сложнее. А Python и простой, и дружелюбный, и проектов на нём много.
— Погоди, пост же про плюсы, — скажет внимательный читатель. Да, всё верно, вот и они. Штука в том, что с Python хорошо начинать. А вот дальше всё зависит от задач и желаний программиста. Если вам хочется (и интересно) писать куда более производительный код, над которым у вас будет полный контроль, то для этого понадобится что-то низкоуровневое. Например, Java, C++, C#, в какой-то степени Go.
И в этой низкоуровневости заключается двойственная природа плюсов. С одной стороны, язык изначально сам по себе низкоуровневый, и это круто. С другой стороны, его не очень удобно использовать. Если вы что-то сделаете не так, создавая программу на каком-то другом языке, она будет работать неэффективно или работать с ошибками. Плюсы же не прощают ошибок, и вместо неработающей программы вы вполне можете получить инферно, утягивающее в Страну Вечной Охоты всё, до чего дотянется.
Это так себе история, поэтому за плюсы активно взялись в начале XXI века и начали развивать язык. Как итог, сейчас на C++ не просто можно писать эффективный код. На C++ стало приятно писать эффективный и безопасный код.
Обузданная мощь
В плюсах, как и в других компилируемых низкоуровневых языках, есть статическая типизация кода, которой нет в Python. Благодаря ей вы можете чётко и ясно объявить, что такой-то объект имеет вот такой тип данных, что вот эта штука — число. И всё, после этого оно не станет, скажем, строкой. И это даёт возможность компилятору генерировать более эффективный код.
Программируя на C++, вы на самом деле чувствуете мощь — у вас куча возможностей. Как говорили в таких случаях Питеру Паркеру: «С большой силой приходит большая ответственность», что, кстати, тоже является хорошим стимулом для обучения.
Если вам интересно создавать эффективный код и в процессе перелопачивать огромные объёмы данных, то дополнительным челленджем в C++ станет не просто написать быстрый код, но написать его так, чтобы он был понятен остальным. Люди же будут его использовать, поддерживать и масштабировать — это не вещь в себе, это инструмент. Хороший, работающий и ремонтопригодный.
Ведь как только вы напишете одну хорошую и эффективную программу, вам наверняка захочется начать писать много таких же классных программ. Так, например, в Яндексе мы сейчас пишем множество самых разных сервисов на плюсах. Поэтому вопрос про поддержку отнюдь не праздный.
К счастью, у C++ за всё время накопилось множество хороших практик того, как писать понятный и поддерживаемый код. И это тоже интересный момент в плане обучения: задача усложняется, потому что у вас в руках уже не просто язык посложнее, но при этом и огромный набор инструментов, чтобы на нём хорошо писать. Этому тоже важно учить.
Как не надо учить людей C++
Хотя я выше и писал, что частенько в плюсы приходят из Python в поисках силы и контроля, лично я знаю не так уж и мало людей, для которых C++ стал первым языком.
Идеальный путь мне видится примерно таким.
В школе у вас было программирование, вас учили питону.
Затем вы аккуратно и постепенно переползли на плюсы.
В итоге хорошо разбираетесь в обоих языках, зная достоинства, недостатки и области применения каждого.
Это если сильно всё упрощать.
На самом деле для большинства ситуация выглядит примерно так.
В школе программируете на чём-то, что вроде бы и язык программирования, при этом совершенно бесполезный и в природе уже не встречается. Кроме учебников. Старых учебников.
Затем поступили в университет, а там — сюрприз — внезапно плюсы.
Но и это еще не всё. Вдобавок можно попасть на максимально академический курс. Там вам расскажут, что лет двадцать назад вот эти бородатые мужики придумали С, а вот указатель на память, под которым что-то может быть, напишите 10 строк кода и узнаете, что именно.
В общем, про метапрограммирование вы на таком курсе услышите разве что от других студентов. И то не факт.
Так нельзя делать, и вот почему. Допустим, новичку рассказали про С, попросили сначала (на курсе по C++, да) попрограммировать именно на С. Если элемент страдания на курсе возведён в культ, то студенты будут программировать ещё и на ассемблере, просто для того, чтобы ощутить ту боль и метания, которые испытывали инженеры.
Да, будет что рассказать у костра на конкурсе страшных историй. Но такой подход почти неминуемо вызывает отторжение ко всему семейству языков. И прелесть плюсов до человека, напуганного С и ассемблером, вы просто не донесёте. Разве что его нервная система будет очень крепка. Но тут не Спарта же, мы людей учим.
Менее страшный академический подход будет заключаться в том, что после С вам всё же расскажут про плюсы: смотрите, вместо массива есть вектор, и у него динамически изменяется размер, и всё делается за вас. И вроде как студентам радостно должно быть: круто-то как, само всё работает. Но зачем же тогда студентов перед этим полтора семестра заставляли вот этими руками писать по 50 строк кода, когда такая круть существует?
— А как надо?
А надо просто рассказать людям, что программирование — это не страшно, что можно научиться писать полезные программы, небольшие, на 10–20 строк. Потом плавно переключиться на C++ и показывать, как там всё круто работает и какой хороший код получается.
Этот подход мы применяли на Курсере. Он же у нас и в Практикуме: покажем человеку, какой язык классный. Классный сегодня, без попыток углубиться в историю и рассказов о его предыдущих архивных версиях. Просто покажем, как создать массив чисел. Или массив котиков, например.
Мы сразу говорим студенту, что если хочется набор объектов — используй тип «вектор». Он сам себе выделит память, сколько ему там надо, всё будет ОК, вообще в этой ситуации не думай про управление памятью. Хочется сделать множество элементов, которое можно быстро добавлять и искать в нём — вот тебе контейнер, без проблем.
Для того, чтобы пользоваться стандартными для языка контейнерами, векторами, множествами или словарём, не нужно понимать, как они внутри себя устроены.
А получается, что классическое образование и академический подход в этом плане занимаются археологическими раскопками, причём снизу вверх — с первого уровня, потом просто по хронологии, наслаивая все вехи развития языка. Чтобы через семестр стало понятно, что почти всё из услышанного ранее просто когда-то использовалось, да, но конкретно вам уже не пригодится. И спасибо за внимание.
Мы учим студентов на курсе, начиная с верхнеуровневых вещей, и потом уже раскрываем всё это подробнее, углубляясь в каждую тему. Про устройство контейнеров можно рассказывать уже через пару месяцев обучения, это тоже помогает разработчику прокачиваться. Потому что в отличие от других языков все стандартные средства, например, контейнеры C++ тоже написаны на C++. И мы даём задачки вида «Вы узнали, как на самом деле работает управление памятью. Теперь напишите свой список или вектор».
Всё это мы даём примерно в конце первой половины обучения, чтобы понять, как всё работает изнутри.
Обучение углублённым темам
В плюсах есть множество тем, в которых можно дополнительно попрактиковаться и расширить свои возможности. Например, динамический полиморфизм. Это когда мы пытаемся отчасти приблизиться к Python и заявить: этот объект имеет не совсем фиксированный тип и может быть то числом, то строкой. Но всё это происходит под вашим контролем! И потому всё ещё максимально эффективно для вашей задачи.
С другой стороны, есть полиморфизм статический — механизм, благодаря которому можно писать универсальный код, работающий для разных типов данных. Он выполняется так же эффективно, как код, заточенный под конкретный тип, и всё ещё легко читается. В общем, если вы что-то слышали про метапрограммирование — это оно. А самое приятное, что язык развивается и всё больше упрощает подобные сложные задачи.
И подобных примеров достаточно — они ограничены лишь любознательностью и готовностью изучать новое в, казалось бы, привычном языке.
C++ в Яндексе
А теперь расскажу, как C++ пригождается нам внутри компании. На нём хорошо писать сервисы, которые критичны с точки зрения нагрузки и скорости ответа. Сейчас я руковожу отделом разработки баннерной системы. Это сервис, отдающий рекламу на конкретный запрос конкретному пользователю. Рекламу мы показываем и на поиске Яндекса, и на других сайтах — соответственно, трафика через нас проходит огромное количество. Бо́льшую часть прибыли Яндексу приносит именно реклама. Это важный сервис, и он написан на C++.
К рекламному движку, как мы его называем, предъявляются жёсткие требования по нагрузке: за секунду нужно обрабатывать сотни тысяч запросов, и делать это нужно за десятки–сотни миллисекунд. Спроектировать и поддерживать такой сервис довольно тяжело. И современный C++ нам в этом помогает.
Известный всем поиск Яндекса сталкивается с похожими проблемами. Он тоже написан на плюсах, и наши команды активно обмениваются опытом разработки и проектирования высоконагруженных сервисов. Или взять, например, браузер: он должен быть эффективным и не замедлять систему пользователю, который установит его на свой компьютер и откроет пару сотен вкладок. Тоже C++, и тоже челленджи.
Чеклист «Как надо»
Закончить пост я хочу чеклистом, который поможет правильно преподавать плюсы. Возможно, не только их.
Убедитесь, что вы начали рассказывать про язык, а не про историю развития этого языка.
Убедитесь, что уже после первых уроков ваши студенты осилят написать рабочий код, простой и в то же время близкий к боевому. Давайте им все основные инструменты сразу.
Вообще не страшно рассказать про вектор и при этом не рассказать про шаблоны классов. Детали реализации обсудить всегда успеете.
А ещё не страшно рассказать про словарь и не рассказать, что такое бинарное дерево.
Не усложняйте. Любая популярная идея в своём ядре понятна и проста. Если это не что-то хитрое типа метапрограммирования, то про это не надо рассказывать сложно. Пусть, например, вы рассказываете про активное использование ссылок. Ссылки в массе своей пришли на замену указателям. Поэтому расскажите про ссылки и не рассказывайте про указатели. До поры до времени.
Расскажите про важность алгоритмов, хотя бы базово. Потому что плюсы — про эффективность. Нужно уметь оценить, что алгоритм А работает за линейное время, а алгоритм Б — за квадратичное. Поэтому первый будет быстрее, ведь линейная сложность лучше квадратичной. Это полезная теория.
Убедитесь, что студент понимает, зачем вы ему это рассказываете. Если вы решили рассказать про словарь просто потому, что словарь — это круто, студент может не понять. Покажите, зачем ему словарь.
Рассказывайте про новое в языке. Быть современным важно.
Не рассказывайте вообще всё. Это ловушка для преподавателя: когда вы давно в C++ и хорошо знаете язык, хочется рассказать про него всё. Рискуете перенасытить студентов и усложнить подачу.
А усложнять не надо.
Вот так мы и учим наших студентов. Если у вас есть вопросы, с радостью отвечу.