Svartsinn1
Как выучить computer science за 3 месяца и не обмануть себя

Самиздат: [Регистрация] [Найти] [Рейтинги] [Обсуждения] [Новинки] [Обзоры] [Помощь|Техвопросы]
Links
Кожевенное мастерство: сумки, ремни своими руками Юристы. Круглосуточно
 Ваша оценка:

На YouTube 2700 роликов с названием "Learn Computer Science in 3 Months". На Coursera больше сотни курсов с тем же обещанием. На Reddit тред r/learnprogramming отвечает на этот вопрос раз в две недели, и ответы там мало меняются за последние десять лет. Все эти планы выглядят похоже: длинный список тем, ссылка на книгу, расписание из 12 предметов в неделю. Половина из них предполагает, что у читателя нет работы, семьи и сна.

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

Computer Science Curricula 2013 и обновлённая версия 2023 года - это официальный документ ACM и IEEE, который перечисляет 18 областей знаний для выпускника CS-программы. К ним относятся: алгоритмы и сложность, архитектура, искусственный интеллект, базы данных, графика, человеко-машинное взаимодействие, сети, операционные системы, разработка ПО, безопасность и ещё восемь. Ни один человек не осваивает 18 областей за три месяца. Это не вопрос воли. Это вопрос когнитивной ёмкости.

Эта статья - другой план. Три месяца, разрезанные не по темам, а по тому, что мозг реально может усвоить. Источники здесь не блогеры, а исследования по когнитивной нагрузке, работе со схемами в обучении программированию и извлечению из памяти. Я честно скажу, что вы не выучите за 90 дней. И покажу, что можно успеть, если работать не 40, а 18 часов в неделю.

Месяц первый - синтаксис это враг, алгоритмы это друг

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

Когнитивная работа Jeroen van Merrienboer и Fred Paas, опубликованная в 1990 году в журнале Computers & Education, исследовала именно эту разницу. Они учили программированию новичков двумя способами: одна группа заучивала синтаксические конструкции, другая сразу решала задачи с разбором на подшаги. Через две недели вторая группа писала программы втрое быстрее и её участники ошибались реже. Синтаксис в отрыве от задач - пустая трата рабочей памяти.

Первую неделю первого месяца вы тратите не на учебник по языку. Вы тратите её на то, чтобы запустить "Hello, World" и написать десять программ по 20-30 строк каждая. Калькулятор, конвертер температур, угадайка чисел, генератор паролей, чтение файла и подсчёт строк. Каждая программа учит одному-двум механизмам: циклы, условия, функции, файловый ввод-вывод. К концу недели синтаксис сам оседает в голове.

Оставшиеся три недели первого месяца - алгоритмическая мысль. Не "учить алгоритмы", а научиться разбивать задачу на шаги. Возьмите три классических шаблона: линейный поиск, бинарный поиск, сортировка вставками. Реализуйте каждый на трёх разных структурах данных: на массиве, на связном списке, на строке. Задача не запомнить, а почувствовать, когда какой алгоритм подходит.

Бинарный поиск - хорошая иллюстрация того, как работает рекурсия и деление пополам. Вот рабочая реализация на Python:

def binary_search(arr, target):
    lo, hi = 0, len(arr) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
    return -1

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

Месяц второй - структуры данных вместо "всех алгоритмов мира"

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

Второй месяц вы учитесь не перечню, а глубине. Шесть базовых структур покрывают 90% реальных задач: массив, связный список, стек, очередь, хеш-таблица, бинарное дерево поиска. Каждую вы реализуете своими руками - три раза: наивная версия, версия с обработкой ошибок, версия с тестами. Это не теория. Это мышечная память.

Хеш-таблица - самый недооценённый объект. Большинство начинающих используют её как чёрный ящик, не понимая, почему при коллизии теряется производительность. Вот минимальная реализация с обработкой коллизий методом цепочек:

class HashTable:
    def __init__(self, size=16):
        self.size = size
        self.buckets = [[] for _ in range(size)]

    def _hash(self, key):
        return hash(key) % self.size

    def set(self, key, value):
        idx = self._hash(key)
        for pair in self.buckets[idx]:
            if pair[0] == key:
                pair[1] = value
                return
        self.buckets[idx].append([key, value])

    def get(self, key):
        idx = self._hash(key)
        for pair in self.buckets[idx]:
            if pair[0] == key:
                return pair[1]
        raise KeyError(key)

Напишите её, и вы увидите, что коллизия - не аномалия, а норма. Поменяйте размер таблицы с 16 на 4 и посмотрите, как деградирует скорость. Поменяйте хеш-функцию на простую len(key) % self.size и понаблюдайте, как строки одинаковой длины скапливаются в одном bucket. Это понимание вы не получите из чтения документации.

Второй месяц - это месяц перемешивания (interleaving). Чиен-Хо Лин и коллеги в исследовании, опубликованном в Human Brain Mapping в 2012 году, показали, что перемешанная практика, когда учащийся работает то с одной, то с другой структурой в одном занятии, даёт лучшее долгосрочное усвоение, чем блоки по одной теме. Идея: во вторник вы 40 минут со стеком, 40 с деревом, 40 с хеш-таблицей. Не "неделя стека, неделя дерева, неделя хеш-таблицы". Перемешивание форсирует мозг формировать отдельные схемы под каждую структуру, а не один общий шаблон.

Месяц третий - один проект вместо десяти туториалов

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

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

Выберите один проект, на который уйдёт весь третий месяц. Критерии: он использует всё, что вы учили в первом и втором месяце; он не требует новых библиотек, которых вы не знаете; у него есть пользователь, хоть вы сами; его можно показать кому-то, не объясняя тридцать минут контекста. Под эти критерии попадают: REST-сервер с хранением в файле, поисковый движок по вашим заметкам, мини-СУБД для CSV-файлов, простой интерпретатор арифметических выражений.

Вот каркас HTTP-сервера на стандартной библиотеке Python - начало проекта, к которому вы будете дописывать функциональность весь месяц:

from http.server import BaseHTTPRequestHandler, HTTPServer

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-Type', 'text/plain')
        self.end_headers()
        if self.path == '/':
            self.wfile.write(b'Notes API. Try /notes')
        elif self.path.startswith('/notes'):
            self.wfile.write(self._list_notes().encode())

    def _list_notes(self):
        # TODO: читать заметки из файла, фильтровать по параметрам
        return 'no notes yet'

if __name__ == '__main__':
    HTTPServer(('', 8000), Handler).serve_forever()

С этим каркасом вы сделаете за месяц следующее. Неделя 1: хранение заметок в памяти и чтение по GET. Неделя 2: добавление через POST, обновление через PUT, удаление через DELETE. Неделя 3: персистентность в JSON-файл, обработка ошибок, валидация. Неделя 4: тесты, документация, деплой на любой бесплатный хостинг. К концу месяца у вас есть не "учебник", а программный продукт, который вы понимаете от нижнего уровня до HTTP.

Этот проект заменяет вам целый раздел Computer Science Curricula под названием Software Development Practices. CS Curricula 2013 отводит этой области 25-30 часов аудиторной нагрузки. Вы получаете те же часы за счёт практики, а не теории. Теория о SOLID-принципах, паттернах проектирования и CI/CD без живого кода - пустой звук. С живым кодом - инструменты, а не лозунги.

Как учиться, а не что учить - четыре техники с доказательствами

Три месяца - это не так много. Если работать 18 часов в неделю (см. следующий раздел), это 216 часов чистого времени. В эти 216 часов нужно уложиться так, чтобы пройденный материал остался в голове через год. Большинство студентов тратят эти часы впустую: перечитывают конспекты, смотрят лекции повторно, делают заметки, которые потом не открывают. Это всё методы с нулевой или отрицательной эффективностью по данным исследований памяти.

Есть четыре техники с эмпирическим обоснованием. Первая - worked examples, проработанные примеры. В обзорной работе Sweller, van Merrienboer и Paas 2019 года в Educational Psychology Review авторы показывают, что начинающим полезнее разбирать готовые решения, чем пытаться решать задачи с нуля. Это противоречит популярной идее "учиться через борьбу с задачей", но исследование однозначно: пока у вас нет схем в голове, борьба создаёт когнитивную перегрузку и ничего не сохраняется. Только когда вы приобрели базовые схемы, переходите к самостоятельному решению.

Вторая - retrieval practice, извлечение из памяти. Yana Weinstein, Christopher Madan и Megan Sumeracki в работе "Teaching the science of learning" (Cognitive Research, 2018) обобщили десятилетие исследований и пришли к выводу: повторное чтение и просмотр лекций почти не улучшают долгосрочное запоминание. То, что работает - это извлечение: закрыть конспект и попытаться пересказать его, написать код без подсказок, решить задачу в уме. Время, потраченное на извлечение, даёт в 2-3 раза лучшее удержание, чем время, потраченное на повторное восприятие того же материала.

Третья техника - spacing, распределённое повторение. Если учить главу за один присест, к концу недели вы забудете 60% содержания. Если ту же главу растянуть на три сессии по 30 минут с интервалом в два дня, удержание через неделю подскакивает до 80-90%. Это кривая забывания, известная со времён Эббингауза, но в обучении программированию её редко применяют. Расписание трёх месяцев должно быть построено так, чтобы одна тема возвращалась в течение двух недель - это встреча No1, No2 и No3.

Четвёртая техника - interleaving, перемешивание. Лин и соавторы в Human Brain Mapping 2012 показали, что студенты, у которых в одной сессии шли три разных типа задач, потом справлялись с переносом лучше, чем те, у кого блоки были разделены по типам. Для программиста это значит: не "понедельник - массивы, вторник - деревья", а "понедельник - 40 минут массивы, 40 минут деревья, 40 минут хеш-таблицы". Перемешивание заставляет мозг различать структуры, а не заучивать контекст.

Эти четыре техники - не украшение плана, это и есть план. Без них любой список тем через три месяца превратится в потерянное время. С ними 216 часов превращаются в навык, который остаётся.

Расписание недели - 18 часов, а не 40

Любой план, обещающий "полное погружение" по 40-50 часов в неделю, написан человеком, который никогда не пробовал это делать. Когнитивная нагрузка - это не метафора, это ограничение архитектуры мозга. Sweller и коллеги в том же обзоре 2019 года указывают: рабочая память может одновременно удерживать 4Ђ1 элемент. Каждый новый материал занимает один из этих слотов. Когда все слоты заняты, обучение останавливается, а вы устаёте, не понимая, почему.

Реальный потолок для самостоятельного изучения CS - 18-22 часа в неделю. Это не маленькая цифра. Это полноценный полставки. Больше - только при условии, что у вас нет другой работы, нет семьи и не нужно вести быт. Большинство взрослых людей, берущих план "3 месяца по 40 часов", держатся неделю-две, потом выпадают на неделю, потом возвращаются и не помнят, что было неделю назад. Получается не прогресс, а возвратно-поступательное движение.

Вот рабочее расписание на неделю. С понедельника по пятницу - два блока по 90 минут каждый, всего 15 часов в неделю "учебной активности". Один блок утром до работы или после, второй вечером. Суббота - четыре часа на проект. Воскресенье - отдых, без кода. Это 19 часов в неделю, и они сделают больше, чем 40 в любую неделю перегруза.

ДеньУтро (90 мин)Вечер (90 мин)
ПонедельникАлгоритмы - теория + примерыПеремешивание: 30/30/30 (стек/дерево/хеш)
ВторникАлгоритмы - самостоятельная задачаЧтение чужого кода (15 минут) + рефакторинг
СредаПроект - фича недели (часть 1)Заметки по ошибкам + retrieval-тест
ЧетвергСтруктуры - реализация с нуляПроект - фича недели (часть 2)
ПятницаПовторение старого материалаСвободное программирование, эксперименты
Суббота4 часа - проект-
ВоскресеньеОтдыхОтдых

В таблице одно важное правило: понедельник начинается не с нового материала. Он начинается с повторения того, что было неделю назад. Это сессия No2 по тому же материалу. Только после неё - новый материал. Без такого правила кривая забывания съест половину того, что выучили.

Если вы вдруг чувствуете, что не понимаете ничего из того, что делаете - это не значит, что вы тупой. Это значит, что вы перешли в режим когнитивной перегрузки. Шаг назад: вернитесь к worked example, который понимали, и двигайтесь от него. Пытаться пробиться сквозь перегрузку усилием воли - самый дорогой по времени путь в долгосрочной перспективе.

Как проверить, что вы что-то выучили

Главный вопрос любого плана - не "сколько тем я прошёл", а "что я могу сделать". Эти два вопроса дают разные ответы. Пройти 40 глав учебника можно за месяц и не научиться ничему. Сделать один проект и уметь объяснить, как он работает, - это и есть результат.

У Sonia Sobral в работе "Bloom's Taxonomy to Improve Teaching-Learning in Introduction to Programming" (IJET 2021) есть рабочая рамка для самопроверки. Она адаптирует таксономию Блума к программированию и предлагает четыре уровня владения материалом: вспоминаю, понимаю, применяю, рассуждаю. Эти уровни - не сорта оценки, это инструмент. Если вы знаете, на каком уровне находитесь, вы знаете, что делать дальше.

Вспоминаю - могу написать функцию сортировки с нуля без подсказки. Понимаю - могу объяснить, почему именно эта сортировка работает за O(n log n), а не O(n^2). Применяю - могу выбрать нужную сортировку под конкретную задачу (поток данных, ограничение по памяти, необходимость устойчивости). Рассуждаю - могу сравнить две реализации и обосновать выбор с учётом контекста.

Этим уровням соответствуют четыре способа самопроверки. Вспоминаю - закрыть конспект, написать код. Понимаю - объяснить вслух, как будто преподавателю. Применяю - взять задачу с LeetCode или Codeforces (только Easy и Medium) и решить её за час. Рассуждаю - написать в заметках сравнение двух решений одной задачи и оценить, какое лучше в каких условиях.

Вот скрипт-помощник для самопроверки: он выбирает из вашего списка изученных тем случайную и спрашивает вас. Если поставить его в cron на утро, вы начинаете день с retrieval-теста.

import random, json

TOPICS_FILE = 'learned_topics.json'

def load_topics():
    with open(TOPICS_FILE, 'r', encoding='utf-8') as f:
        return json.load(f)

def todays_review():
    topics = load_topics()
    pick = random.choice(topics)
    print(f'Сегодня вспоминаем: {pick}')
    print('1. Напиши реализацию с нуля, не глядя в конспект.')
    print('2. Объясни вслух, как будто преподавателю.')
    print('3. Сравни с альтернативой, когда какую брать.')

if __name__ == '__main__':
    todays_review()

В файл learned_topics.json вы складываете пройденные темы в формате ["бинарный поиск", "хеш-таблица с цепочками", "REST-сервёр на Python", ...]. Каждый день скрипт задаёт вам случайную тему, и вы должны с ней что-то сделать. Если не можете - это сигнал, что тема не на уровне "применяю", а на уровне "видел". Возвращайтесь к ней в следующие выходные.

Тест на реальное владение прост. Откройте свой проект третьего месяца. Пройдите по нему с другом, который не программист. Объясняйте каждый блок. Если где-то вы начинаете отвечать "ну, тут работает, не помню как" - это слабое место. Если вы можете объяснить всё от уровня HTTP-запроса до уровня цикла - вы выучили то, что заявлено.

Чего вы НЕ выучите, и почему это хорошо

Самый честный раздел любого трёхмесячного плана - список того, что в него не входит. Computer Science Curricula 2013 перечисляет 18 областей. Три месяца покрывают три-четыре из них: алгоритмы, структуры данных, частично разработку ПО, частично основы архитектуры. Остальные 14 - нет.

Вы не выучите искусственный интеллект. Это не недоразумение, это область, у которой своя предыстория: линейная алгебра, теория вероятностей, оптимизация, статистика. Весь ML базируется на трёх годах математики, которые у вас не было. За три месяца его нельзя выучить, можно только поиграться с библиотеками. Поиграться - полезно, это не вредно, но это не знание CS.

Вы не выучите операционные системы. CS Curricula отводит этой области 40+ часов аудиторной нагрузки, плюс лабораторные. В реальности - это планировщик процессов, управление памятью, файловые системы, безопасность ядра. За три месяца вы успеете прочитать один учебник и написать пятьсот строк ядра, но не научитесь проектировать ОС. Если вы хотите понимать ОС - после трёх месяцев берите отдельный трёхмесячный план только на неё.

Вы не выучите компьютерную графику. Не выучите теорию вычислений на уровне формальных языков и автоматов. Не выучите глубокую безопасность. Не выучите базы данных на уровне проектирования СУБД - научитесь пользоваться, но не строить.

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

Хороший план не обещает невозможного. Он обещает измеримое: выучите четыре области, напишете проект, сможете объяснить его другому человеку. Это и есть computer science для начинающего. Остальное - следующий этап.

Дэвид Лопатто в работе "Undergraduate Research Experiences Support Science Career Decisions and Active Learning" (CBE - Life Sciences Education, 2007) показал, что студенты, участвовавшие в одном серьёзном проекте, имели долгосрочный интерес к науке значительно выше, чем те, кто только слушал лекции. Один проект лучше десяти лекций. Три месяца, потраченные на одну реальную вещь, которую вы понимаете от начала до конца, стоят года прослушанных курсов.

Выводы

Честный план на три месяца не делает из вас computer scientist. Он делает из вас человека, который может написать работающую программу, прочитать чужой код, выбрать подходящую структуру данных, объяснить свой выбор. Это меньше, чем диплом. Это больше, чем ноль.

Главный урок этого плана - в нём самом. Он построен не по принципу "выучи всё", а по принципу "выучи то, что удержится в голове через год". Большинство учебных планов, обещающих 3 месяца, обещают невозможное, потому что игнорируют кривую забывания. План, который уважает эту кривую, выглядит меньше по теме. Он такой и есть. Но то, что он обещает, он выполняет.

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

Computer science - это не навык, который можно "выучить за 90 дней". Это дисциплина. Дисциплина - это привычка работать с информацией так, чтобы она оставалась в голове, а не выветривалась на следующее утро. Если вы научились этому за 90 дней - три месяца сработали. Если нет - никакой список из 47 тем вас не спасёт.

Дальше - следующий этап. Но это уже совсем другой план.


 Ваша оценка:

Связаться с программистом сайта.

Новые книги авторов СИ, вышедшие из печати:
О.Болдырева "Крадуш. Чужие души" М.Николаев "Вторжение на Землю"

Как попасть в этoт список

Кожевенное мастерство | Сайт "Художники" | Доска об'явлений "Книги"