Нужны ли программисту математика, английский язык, теория алгоритмов и паттерны проектирования

Нужны ли программисту математика, английский язык, теория алгоритмов и паттерны проектирования

Иногда возникают нюансы. Вам приходится не только писать код, но и формализовать задачу, поставленную заказчиком на манер знаменитого “копать от забора и до обеда”. Или ваш код, написанный “на коленке” за пару минут, работает слишком медленно. Или ваша программа выдает исключение, давно описанное на stackoverflow.com, но вы не умеете читать по-английски. Или возникает необходимость сделать рефакторинг кода, а для вас это звучит как “харакири”. Как правило, начальству наплевать на то, как вы справитесь с этими проблемами, но справиться вы обязаны – “вы же программист”! За что же вам платят эдакие деньжищи?

Математика

Давным-давно, когда компьютеры были большими, а зарплаты программистов – маленькими, каждый программист был математиком. Помните главного героя “Понедельника начинается в субботу” братьев Стругацких, программиста Сашу Привалова?

Нужны ли программисту математика, английский язык, теория алгоритмов и паттерны проектирования

– Кристобаль Хозевич, – сказал я. – Я ее все-таки решил. Вы были совершенно правы. Пространство заклинаний действительно можно свернуть по любым четырем переменным…
…Я отдал ему листки, он сел рядом со мною, и мы вместе разобрали задачу с начала и до конца и с наслаждением просмаковали два изящнейших преобразования, одно из которых подсказал мне он, а другое нашел я сам…

– Это мы опубликуем. Это никому не стыдно опубликовать.

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

В моем дипломе, полученном на факультете прикладной математики, гордо значится специальность – математик. Хотя все понимали, что нас учат на программистов. Нас научили использовать численные методы для решения сложных задач, которые нельзя решить аналитически – например, уравнения теплопроводности. Пригодилось ли это на практике? Пока нет, но еще может пригодиться. Если говорить о нужности для программиста, всю высшую математику можно разделить на три части:

  1. То, что вы будете использовать каждый день: дискретная математика. О ней мы сейчас поговорим подробнее.
  2. То, что вам нужно для решения возникающих математических задач: дифференциальное и интегральное исчисление, линейная алгебра, статистика. Эти разделы математики используются не каждый день, а у многих программистов – даже не каждый год, но знать их все равно очень полезно, а во многих компаниях – даже необходимо. Почему? Если вам хоть изредка приходится ставить математическую постановку задачи – вы просто не сможете этого сделать без соответствующей математической базы. Имея базу, вы сможете найти информацию о своей задаче в Интернете и использовать ее, а без базы вы эту информацию просто не поймете!
  3. Специфические знания. Нужны только для решения задач из определенной прикладной области. Если вы пишете программы именно в этой области – знание необходимых разделов математики будет огромным плюсом, а если не пишете – эти разделы вам не нужны.

Дискретная математика

Этот раздел математики изучает конечные структуры и содержит множество различных подразделов. Самый важный подраздел для программистов – это математическая логика, в которую входит обработка привычных каждому программисту логических операций вроде and, or, и not. Например, следующий оператор срабатывает, если верно a, но не b, или, наоборот, верно b, но не a:

Если вы изучали дискретную математику, то сразу поймете, что то же самое можно написать гораздо проще, используя операцию “исключающее ИЛИ”, причем код будет не только намного короче, но и станет работать быстрее:

Математическая логика также помогает “инвертировать” логические выражения или упрощать их, что может потребоваться программисту буквально каждый день:

Еще один важнейший раздел дискретной математики для программистов – это теория графов. Если слово “граф” для вас ассоциируется с графом Монте-Кристо, а не со структурой данных, состоящей из вершин и соединяющих их ребер, вы рискуете не только провалиться на любом собеседовании, но еще и опозориться:

С чем должно ассоциироваться слово "граф" для программистаС чем должно ассоциироваться слово “граф” для программиста

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

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

Английский язык

Нужны ли программисту математика, английский язык, теория алгоритмов и паттерны проектирования

Если вы не умеете быстро и без напряжения читать книги по программированию на английском языке – это значит, что вы просто не сможете постоянно следить за передним краем даже в своей области, не говоря уже о смежных. Конечно, российские издательства выпускают переводы книг по программированию, но к моменту их выхода на Западе уже успевает выйти новое издание. К тому же качество этих переводов настолько плохое, что я предпочитаю читать книги в оригинале, то есть на английском. Зачастую электронные версии самых свежих книг на английском языке появляются задолго до их печати, то есть я могу осваивать новые технологии одновременно со всем миром. К тому же, книг по программированию выходит так много, что далеко не каждая из них вообще будет переведена на русский!

Иногда вам придется и написать абзац-другой – например, задать вопрос на форуме или в отдел технической поддержки. Поскольку писать сочинения вроде “London is the capital of Great Britain” вам едва ли понадобится, это не должно вызвать особых трудностей, если вы уже хорошо умеете читать. Даже если вы сделаете пару ошибок, не страшно – лишь бы вас правильно поняли.

Многие фирмы работают на Запад, и там регулярно проводятся совещания на английском языке. Вот там вам уже понадобятся и разговорные навыки, и аудирование, и даже хорошее произношение. Такие фирмы прямо пишут в своих вакансиях что-то вроде “English – Upper-Intermediate”. Высококлассному специалисту с большим опытом должно быть очень обидно упускать такие вакансии только из-за незнания языка.

Нужны ли программисту математика, английский язык, теория алгоритмов и паттерны проектирования

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

Теория алгоритмов

Нужны ли программисту математика, английский язык, теория алгоритмов и паттерны проектирования

Теория алгоритмов оценивает не точное количество ресурсов (которое на практике редко можно рассчитать), а характер его зависимости от размеров исходных данных, называемой сложностью. Например, цикл по всем элементам массива имеет вычислительную сложность O(N), где N – количество элементов массива. Это значит, что количество вычислительных операций пропорционально N. Общеизвестно, что сложность быстрой сортировки (в среднем) равна O(N * logN), а сложность бинарного поиска – O(log N). Поиск в хеш-таблице происходит еще быстрее: при правильно подобранных ключах и достаточном размере таблицы его сложность O(1), то есть вообще не зависит от размера входных данных! Этим и обусловлена широкая популярность хеш-таблиц, а также базирующихся на них словарей (dictionary) и множеств (set).

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

Теоретически, вы можете писать код, и не зная об алгоритмах, но это будет код школьника-троечника. Причем страшнее всего то, что вы этого даже не почувствуете! Если вам не хватает английского языка – это всегда очевидно: вы не можете понять текст, постоянно лезете в словарь, или, что еще хуже, пользуетесь автоматическим переводчиком. Если вам не хватает математической подготовки – вы, конечно, не сможете обнаружить нехватку самостоятельно, но хотя бы почувствуете, что чего-то не понимаете. А вот люди, ничего не знающие об алгоритмах, не получают никаких “звоночков”. Они успешно пишут код, который прекрасно проходит все тесты (поскольку размер данных в тестах обычно невелик), но у пользователя работать не будет.

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

Паттерны проектирования

Нужны ли программисту математика, английский язык, теория алгоритмов и паттерны проектирования

Пожалуй, впервые важность проектирования была продемонстрирована в книге Ф.Брукса “Мифический человеко-месяц”, вышедшей в далеком 1975-м, но она была ориентирована на менеджеров, а не на программистов. В 1994-м Э. Гамма, Р. Хелм, Р. Джонсон и Д. Влиссидес (называемые “бандой четырех”, “Gang of Four”) опубликовали книгу “Паттерны объектно-ориентированного проектирования”, заложившую основы современного подхода к проектированию ПО. В книге описано множество типовых приемов (которые авторы назвали “паттернами”), помогающих улучшить проекты проекты программ, и это стало основным фактором ее популярности. Стало модно задавать вопросы по паттернам проектирования на собеседованиях, и юные соискатели начали заучивать их наизусть. (Я не рассматриваю SOLID, появившийся позднее, поскольку он слабо помогает проектировать – но заучить его для собеседований вам тоже придется).

К сожалению, навыки кодирования и проектирования очень сильно отличаются друг от друга, так что гениальный проектировщик вряд ли окажется еще и супер-кодировщиком (а когда такое все же случается, в мире появляется очередной Линус Торвальдс). Типичный кодировщик – это юноша, очень быстро набирающий код, то есть обдумывающий его еще быстрее. Типичный проектировщик – это человек с большим опытом, который может не набрать ни одной строки кода на протяжении нескольких дней или даже недель. Его задача – придумать наилучшую архитектуру продукта, вот он и думает. Разумеется, кодировщики, ничего не знающие о проектировании, считают проектировщика просто бездельником! Именно поэтому крупные компании не ставят проектировщика в подчинение руководителю команды кодировщиков, а придумывают для него особую должность “архитектора” (software architect).

Отличный пример широко распространенного, но неправильного понимания паттерна проектирования дает паттерн Bridge (Мост). Начнем с правильного примера использования этого паттерна на C# (код взят из документации Microsoft):

Интерфейс IDBConnection реализует Мост между клиентским приложением и базой данных (БД). Цель паттерна – полная изоляция клиента от деталей реализации каждой конкретной БД. Конкретным объектом, реализующим этот интерфейс, может быть любой экземпляр класса, унаследованного от DBConnection (код создает экземпляры SqlConnection, OdbcConnection и OleDbConnection), но клиент никогда не должен узнать, какого именно. Это позволяет разработчикам клиентского приложения сделать его по-настоящему мультиплатформным, а разработчикам Моста – постепенно добавлять поддержку новых БД, которая не заставит разработчиков клиента ничего менять. Важная парадигма: для клиентского приложения оба “берега”, соединяемых Мостом, всегда представляют одно и то же (в нашем примере – БД), только на “его” берегу находится абстрактное представление о БД, а на “чужом” – ее конкретная реализация.

Теперь взгляните, какой “пример Моста” приведен на сайте Метанит. Там объект программиста обращается к объекту языка программирования через “мост”. Непонятно, зачем изолировать объекты языков программирования от объектов программистов, но проблема даже не в этом. Во-первых, вы не можете заранее предсказать все, что вам потребуется от языков программирования – а это значит, что ваш “мост”, скорее всего, через некоторое время придется изменять, тогда как одна из целей настоящего Моста заключается именно в защите клиента от изменений (как вы думаете, будет ли когда-нибудь изменен IDBConnection?). Во-вторых, вы не можете раз и навсегда определить даже вид соотношения между языками и программистами! Кто сказал, что каждый программист знает только один язык? Такие “мосты” только напрасно усложняют проект и не приносят никакой реальной пользы.

А вот пример того же паттерна с сайта Refactoring Guru. Здесь строится “мост” между пультами и управляемыми с их помощью устройствами. Этот пример уже имеет смысл, поскольку управлять с пульта проще, чем кнопками на устройстве (клиенту всегда проще работать с абстрактным интерфейсом Моста, избавляющим его от ненужных деталей реализации), но все-таки он неудачен. Не все команды управления телевизором и радио будут совпадать. Но самое главное – пульт не скрывает от клиента конкретную реализацию: клиент по-прежнему смотрит телевизор, а не пульт, и слушает радио, а не пульт. А мы уже знаем, что основная цель Моста – именно изоляция клиента от конкретной реализации.

Удачи вам в определении того, чего вам не хватает, и успешного устранения этих пробелов!