пятница, 3 февраля 2017 г.

О “вреде” книг: напутствие любому программисту

Недавно наткнулся на любопытную статью под названием «О вреде книг: напутствие начинающему программисту». Идея в статье простая: книги – это скорее опасно, и лучше практика с пополнением теории по ходу дела, да и образование современное – ни к черту.

Мне сложно судить о современном программистском образовании в России/Украине (эта тема также поднимается в статье). У меня самого нет специализированного образования (я по образованию «специалист» в области систем автоматизированного управления), да и с момента получения оного прошло уже довольно много времени (19 лет с момента поступления в университет). Но мне явно есть что сказать по поводу самообразования и использования книг в этом процессе.

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

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

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

Прочтение книги по F# мне не дало почти ничего, поскольку я не стал применять его на практике. Проблема ли это книги или моего подхода к обучению в тот момент?

Но давайте посмотрим на разные подходы и попробуем определить, какой из них является наиболее эффективным.

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

clip_image001

Сосредоточиться на чем-то одном, практически невозможно. Идея “stay connected” столь сильна и доступность информации столь пленительна, что просидеть даже перед телевизором не проверив твиттер, почту или лицокнигу становится сверх сложно.

И причем здесь обучение? А при том, что отвлечение смертельно вредно для обучения. Для познания чего-то нового мозгу нужен фокус. Нужна одна задача (разные, но и одной темы). Нужен хороший источник информации. Нужны повторения по exponential back off алгоритму: повторить завтра, через день, через неделю, через две. Нужна практика, чтобы теоретические знания осели на реальные проблемы. Нужны глобальные итерации и возврат к одной и той же теме месяцы спустя.

И тут, как мне кажется, книга дает несколько важных преимуществ. Если книга хороша (если она *не* хороша, то нужно ее бросить и найти подходящую), то в ней будет более или менее последовательно изложена информация. Там будут дополнительные ссылки, которые позволят посмотреть на информацию с другой стороны. Там будут практические примеры и, в идеале, задачи. Если задач нет, то их придется придумать самому. Но самое главное, книга дает достойное объяснение и погружение в тему. Дает цель и фокус.

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

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

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

Сегодня я могу выделить 4.5 паттерна обучения:

  1. Ad-hoc обучение
  2. Изучение узкой темы
    1. Изучение узкой темы для написания статьи
  3. Изучение крупной темы
  4. Домашний проект (pet project)

Ad-hoc обучение происходит постоянно. Кто-то из коллег поделился интересной статьей, что-то раскопал сам при решении определенной задачи и т.п. Обычно это что-то весьма конкретное, обычно – практически-направленное. Бывает и теоретическое, но весьма узкое. Ложится такой подход хорошо, когда кусочков в голове много и новой порции есть за что зацепиться.

Изучение узкой темы уже требует подготовительной работы. Например, мне сейчас интересно, как устроены computation expressions в F# или что такое railway-oriented programming, а может быть, что какие-то особенности Dependency Injection или что-то из SOLID-принципов. Или мне нужно изучить гит, или основы работы интерпретаторов.

Я не хочу погружаться слишком на долго и искать книгу, поэтому я нахожу несколько статей или цикл статей: The “Computation Expressions” series на fsharpforfunandprofit.com, Railway Oriented Programming (там же); посты Марка по DI; Think Like a Git, и серию Let’s Build a Simple Interpreter.

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

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

Для изучения крупной темы я предпочитаю найти хорошую книгу в качестве основы. Взявшись за Pro .NET Performance я буду находится в теме в течении нескольких недель. В книге я найду интересные ссылки, которые заставят меня поэкспериментировать и почитать другие источники.

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

Работа над домашним проектом ортогональная предыдущим подходам. Работа над ErrorProne.NET дало много фана и опыта, но я не могу сказать, что я стал экспертом в анализе исходного кода. Да и чтение других анализаторов приводило лишь к недоумению, поскольку большинство решений явно не были production quality.

Я не говорю, что домашние проекты – это плохо, но это явно не замена планомерному изучению.

А как насчет чтения кода? Вот вам небольшая задача: скажите, каким образом обеспечивается параллелизм в ParallelEnumerable.AsParallel. Бытует мнение, что там чистый Fork-Join, где во время fork-а создается поток с локальным хранилищем, в которое складываются промежуточные результаты, а во время join-а они объединяются. Так ли это, или там используются таски и они передают накопленные данные через результат?

Возможно, конечно, что мои навыки чтения кода очень низкие или пример плохой, но мне подобное упражнение показалось весьма сложным. А ведь опыта у меня, вроде бы, не мало, да и инструменты под рукой есть подходящие (в виде портала referencesource.microsoft.com).

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

Так что, нужны книги или нет?

Все сильно зависит от вас, вашего уменя сосредотачиваться и находиться качественные источники в тырнетах. Можно точно сказать, что простое чтение книги от корки до корки дает очень мало пользы. Полноценное изучение подразумевает итеративный подход с переключением с теории на практику на постоянной основе.

Но также можно смело сказать, что чистая «практика» – изучение темы путем брожения по исходникам или решение лишь практических задач, принесет не больше пользы. Полноценное обучение – это не теория vs. практика. Это комбинация этих вещей, при этом процент одного и другого зависит от человека и изучаемой темы.

14 комментариев:

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

    ОтветитьУдалить
    Ответы
    1. Ну так они и остаются кодерами, а не становятся программистами. Не переживайте :)

      Удалить
    2. +1.

      У меня есть знакомые программисты, которые целенаправленно не читают книг (сейчас). Но это люди с +10 лет опыта, которым не проблема получать теоретический опыт в процессе. Но таких людей не очень много.

      Удалить
  2. Интересная статья. Спасибо!
    Как раз по рекомендации прочитал Барбару Оакли "Думай как математик" и очень рад, что это сделал.
    Я думаю, что книги обязательно нужно читать, даже если Вы это делаете "поверхностно". Первое прочтение дает:
    1. Скорее всего узнали что-то новое.
    2. Если не новое, то только убедились, что все делаете верно.
    3. Если новое и очень тесно связано с ежедневно решаемыми задачами, то Вы сразу получили буст.
    4. Если новое и вообще не связано с ежедневно решаемыми задачами, то общая картина останется все равно, детали вылетят из головы. Но через год, встретившись с новым для себя опытом, велика вероятность, что Вы вспомните, что "что-то такое читали" и вернетесь к книге для прочтения нужной главы еще раз, и получится п.3
    Речь же не о том, что прочитали книгу 1 раз и убрали или продали? Очень полезно спустя время освежать мнение о книге и заново открывать для себя изложенные в ней мысли путем перечитывания еще раз. Вот например фильм Матрица в 20 лет и в 30 лет доносит разные эмоции и по-разному воспринимается, более зрело что-ли :)

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

    ОтветитьУдалить
    Ответы
    1. "Угу, угу", сказала Сова.

      Есть люди, которые готовы изоретать на ходу, без внешних источников. Часто они изобретут велосипед заново, но могут сделать и что-то новое. Но обычно, что-то новое изобретается на основе "старых" знаний.

      Удалить
  4. Этот комментарий был удален автором.

    ОтветитьУдалить
  5. Знаю одного "программиста" с достаточно большим опытом работы, которому я в свое время порекомендовал почитать "Чистый код" Р.Мартина и "Рефакторинг" Фаулера, на что он мне ответил, что ему это ни к чему, т.к. все книги (цитирую) "Это всего лишь мнение каких-то людей". После этого прошло больше двух лет и я до сих пор разгребаю то, что он "наваял" когда-то.
    Мое мнение - без учебы никуда в любом деле, а в нашем и подавно. А без книг любая учеба - не учеба. Хотя я бы сюда еще добавил видеокурсы. Но, по-моему, хороший видеокурс - это живой аналог книги.

    ОтветитьУдалить
  6. Статья отличная, мнение разделяю.
    Сергей, можешь порекомендовать open source проекты на .net где, как ты считаешь production quality?

    ОтветитьУдалить
    Ответы
    1. dotnet, roslyn, coreclr. Почти все, что официально от МС-а (кроме Code Contracts) - все продакшн качества.

      Самый хороший вариант, посмотреть github.com/dotnet/ там куча всего хорошего.

      Тестовые фреймворки - тоже вполне ок.

      Удалить
  7. Привет! давно читаю твой блог решил впервые написать, так как тема больная для меня - времени мало, память у меня плохая и информация из книг забывается ужасно быстро. В итоге пришел к такой системе для работы с суперважными книгами и курсами:
    По каждой главе составляю конспект в какой-нибудь программе типа OneNote, где можно смешивать текст и графику.
    По конспекту готовлю карточки в apps.ankiweb.net/
    Карточки регулярно повторяю
    Довольно трудоемко, для ерунды такое делать не будешь. Но в итоге удается помнить очень многое, при этом за счет конспектов очень хорошее общее понимание.
    Лучшая книга, что я читал на тему учебы: www.amazon.com/What-Smart-Students-Know-Learning/dp/0517880857
    Книга очень практичная, есть даже упражнения и сильно повлияла на мое понимание учебного процесса.

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

    ОтветитьУдалить
  9. "Сегодня я могу выделить 4.5 паттерна обучения:"
    "Это я все к тому, что я бы не советовал чтение кода, как *основной* способ получения знаний."

    Чтение кода, действительно не может быть *основным* способом обучения, но оно очень полезно и его вполне можно поставить в список способов обучения. Получится полноценные 5, ну или 5.5 паттернов )).

    Вспомните применяли ли вы кода-либо в новом проекте подходы/практики с которыми когда-то познакомились в процессе изучения кода предыдущих командных проектов. Уверен что каждый скажет "Да". Они хорошо запоминаются.

    Спасибо за статью!

    ОтветитьУдалить