Что надо учить школьнику?

12.10.2019

Меня часто спрашивают, что нужно изучать школьнику, который планирует в будущем стать программистом. Еще чаще я сталкиваюсь с рассуждениями школьников в стиле «я хочу изучать C#, чтобы писать на нем игры». Недавно один школьник спросил меня, мол, мой курс на алгопроге — это больше подготовка к олимпиадам, или «обычный курс обучения программиста», по типу тех, которые более-менее активно рекламируются в интернете? Я тогда ему написал ответ, и ниже я публикую довольно расширенный вариант этого ответа, заодно отвечая и вообще на вопрос, что вообще нужно изучать школьнику, чтобы стать программистом.


На самом деле, это довольно сложный и обширный вопрос. Дело в том, что фраза «просто обычный курс обучения программиста» имеет мало смысла. Программирование — очень широкая область. Ясно, что чтобы программировать, надо знать основы какого-нибудь языка, но что дальше? Дальше можно, например, изучать объектно-ориентированное программирование, шаблоны проектирования и т.д. Или например пойти в низкоуровневые вещи, разбираться, как работает процессор, изучать ассемблер… Или пойти в чисто прикладное направление писать приложения под андроид или там ios или веб или там писать игры под unity или ботов в телеграмме или что там сейчас еще модно. Или можно пойти в сторону машинного обучения, разбираться с разными фреймворками для него, и т.д. Направлений очень много, и все они во многом независимы — например, для изучения ассемблера, да даже для программирования под андроид ООП не особо нужно (ну максимум самые основы).

Мой курс направлен на изучение классических алгоритмов, структур данных, и на умение писать надежные и простые программы и тестировать их. На мой взгляд, это вещь, которая реально нужна и полезна абсолютно любому программисту (в отличие от разных прикладных вещей — например, игры под Unity я никогда не писал и большинство моих знакомых программистов тоже, а вот алгоритмы, как минимум базовые, в том или ином виде знают все). Алгоритмы — это одна из наиболее фундаментальных вещей, которые есть в программировании. Разные фреймворки, концепции программирования и т.д. приходят и уходят, а алгоритмы и тестирование программ нужны всегда и будут нужны и через 20-30 лет. Ну и, как модно говорить, алгоритмы «ум в порядок приводят».


Вообще, не случайно существует понятие фундаментальных и прикладных областей знания. Конечно, это не строгое, четкое, разделение, это непрерывный спектр, есть абсолютно фундаментальные темы, есть абсолютно прикладные, но есть и очень много тем посередине. И учить, особенно в школе, надо в первую очередь более фундаментальные темы. На то есть две причины (безусловно, связанные между собой). Первая — то, что фундаментальные вещи намного медленнее устаревают, вторая — то, что фундаментальных тем, в общем-то, меньше, чем прикладных.

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

Соответственно, имеет ли смысл сейчас изучать какой-нибудь конкретный язык программирования именно ради изучения языка программирования? Или тем более какой-нибудь конкретный фреймворк, тот же Unity (на C# для игр) или, допустим, React (на Javascript для сайтов)? Нынешние школьники в большинстве своем начнут серьезно работать программистом только лет через 10. (При этом разные стажировки, да даже работа младшим разработчиком — это не «серьезная работа».) За 10 лет что фреймворки, что языки программирования изменятся практически неузнаваемо. Те конкретные знания про конкретный язык программирования, которые школьник может получит сейчас, за 10 лет очень сильно устареют.

Действительно, что было популярно 10 лет назад? Никакого React тогда не было, был какой-нибудь Angular (а может и его тогда еще не было). Сейчас, конечно, Angular продолжают использовать, но имхо (я не профессионал в этом деле, конечно) скорее просто по причине необходимости поддерживать старый код. Даже с языками — за последние лет 10 стали популярны, а потом как-то пропали что Ruby, что какой-нибудь R (кажется, сейчас их всех прекрасно вытесняет питон). (Опять-таки, они продолжают где-то использоваться, но по ощущениям хайп прошел.) Даже такой непотопляемый мастадонт как C++ за последние 10 лет (а уж тем более за 20 лет) изменился очень и очень сильно.

Поэтому сейчас учить язык чисто ради изучения языка — это имхо неправильный подход. Изучать языки и фреймворки, конечно, полезно, но не ради знания этого языка, и уж тем более не с целью «хочу учить сейчас C#, чтобы вырасти и писать игры на Unity», или, допустим, «слышал, что программисты на Java неплохо зарабатывают, хочу учить сейчас Java, чтобы после университета работать Java-программистом». К тому времени, как вы будете работать, языки уже сильно изменятся.

(Тут еще, конечно, надо упомянуть и то, что серьезный программист, конечно, не ограничивается одним языком. Серьезный программист довольно хорошо знает минимум 2-3 языка, имеет опыт написания кода на еще 5-10 языках, и вообще не видит очень уж больших сложностей при переходе на новый язык. Поэтому идея «я буду работать Java-программистом» сама по себе очень ограничена.)

Так что же делать?

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


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

Но цель должна быть именно конкретная, до которой вы можете добраться сейчас. Не надо ставить цель «изучить C#, чтобы потом когда-то делать игры». А вот поставить цель «сделать такую-то игру» — вполне осмысленно. И уже дальше думать, что из современных технологий вам будет нужно — пусть это будут те же C# и тот же Unity, но будете их изучать уже не фанатично читая справочник по C# от корки до корки, а вполне конкретно — вот мне сейчас для игры понадобилось то-то и то-то, как это сделать в C#? Или поставьте цель сделайть сайт, и изучайте то, что вам нужно для сайта.

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


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

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

При этом также да, эти же знания нужны и для олимпиад. На то есть много причин (см. отдельный пост). В частности, поэтому, конечно, мой курс также существенно ориентирован и на олимпиады. В частности, многие алгоритмы с высоких уровней моего курса не особо нужны в повседневной работе (но нужны на олимпиадах высокого уровня); и наоборот — ряд алгоритмов, нужных разработчику, засунуты в курсе на высокие уровни потому, что они редко бывают нужны на олимпиадах. Но говорить, что мой курс направлен только на олимпиады — неверно; в частности, у меня занимаются несколько человек, которые уже давно закончили школу и кому олимпиады не нужны вообще — занимаются именно для того, чтобы получить нужные разработчикам навыки.

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


Но, конечно, это мое личное мнение, конечно, каждый человек, ведущий какие-то занятия, будет рассказывать, что это самые нужные занятия :)


Мой курс по алгоритмическому программированию (и подготовке к олимпиадам) для школьников, студентов и всех желающих — algoprog.ru