Мифы о программировании интересны, в том числе и тем, что их иногда распространяют и сами программисты тоже. Причём иногда они в них сами же ещё и верят. И даже уровень квалификации не является панацеей от этой веры — он лишь понижает вероятность того, что она действительно будет. Поэтому не удивляйтесь, если услышите от какого-то программиста что-то похожее на изложение одного из приведённых здесь мифов.
1. Чтобы быть программистом, надо хорошо знать математику
Конечно, понимание математики — крайне полезная штука. Её активно использует подавляющее большинство наук, а все остальные науки тоже используют, но чуть менее активно. Математика, кроме того, один из лучших способов натренировать абстрактное мышление, понять, что такое «доказательство», и научиться решать задачи.
Однако ирония в том, что программирование — это не столько наука, сколько инженерная деятельность. Причём, хоть результат этой деятельности выглядит очень похоже на всякие сложные учебники, в ней математика используется в гораздо меньшей степени, чем, например, в физике или астрономии.
В самом общем случае программисту из всей математики пригодится только простейшая программа младшей школы — четыре арифметических действия.
Основная же масса ценных научных сведений попадает в программирование из другой науки — формальной логики. Вот её понимание, да, весьма полезно. Но и тут тоже не обязательны какие-то особо запредельные глубины.
Программирование — это своя особая область знания. Довольно сильно изолированная от других наук, хотя и побудившая некоторые из них (те же, например, математику и логику) добавить в себя некоторые занимательные обобщения и заняться их изучением.
Дело в том, что программисты занимаются поиском однозначно трактуемых описаний тех действий, которые должен выполнить компьютер. И не только однозначно трактуемых, а ещё и полных — поскольку компьютер, в отличие от человека, не может сам «додумать» пропущенное. В этих описаниях, да, может встретиться что-то математическое, но в основном оно будет только там, где что-то математическое же и программируется. А это далеко не всегда так.
Однако желание упростить описания и вообще как можно меньше писать там встретится наверняка. Поэтому научная составляющая программирования на 99% посвящена тому, как построить изложение так, чтобы оно было как можно более коротким, понятным и безошибочным. Ну и ещё желательно, чтобы оно как можно быстрее работало.
2. Программисты знают только программирование
Данный миф в некотором смысле является противоположностью предыдущего, поэтому может показаться, что как минимум одно из этих утверждений просто обязано быть верным. Но нет, неверны они оба.
Дело в том, что лишь небольшая часть программ посвящена исключительно самим же программам, а потому не требует никаких дополнительных знаний. Остальные же программы нужны для решения какой-то проблемы из внешнего мира, что с неизбежностью требует понимания контекста этой проблемы.
Можно было бы предположить, что контекстом проблемы займётся специалист, а программист просто возьмёт его инструкции и воплотит их «в коде», но на практике такое бывает очень редко, поскольку специалисты, к сожалению, далеко не всегда понимают, что такое вообще «программирование», и как оно делается, а потому просто не способны дать программистам вот эту вот «абсолютно подробную инструкцию».
Вдобавок в ряде случаев специалисты ещё и не в состоянии придумать «компьютерное» решение проблемы из своей области.
Так, например, художник может отлично понимать, как и что рисуется красками, но при этом не представлять, каким образом это могло бы выглядеть на компьютере. Ни с точки зрения интерфейса программы, ни с точки зрения современных возможностей компьютеров, ни с точки зрения компьютерной имитации процесса.
Да, он может отлично описать, как ведут себя краски в тех или иных условиях, но это будет качественное описание. Приглашённый для консультации физик сможет рассказать, как именно краска растекается по бумаге. Однако они оба не знают, каким образом выразить это в виде последовательности «компьютерных» команд (ну, если, конечно, кто-то из них не является по совместительству ещё и программистами).
Поэтому программисту обычно самому приходится разбираться с предметной областью, прежде чем написать программу. То есть понять и способы изображения окружающего мира при помощи красок, и физику их растекания по бумаге. И только потом уже спроектировать поведение программы и написать её код.
Конечно, программист не обязан уметь рисовать, как художник, и понимать физику, как физик, но освоить основы и даже некоторые более сложные вещи из этих областей ему с неизбежностью придётся — иначе он просто не сумеет всё это запрограммировать.
В результате, как это ни странно, написание программ начинается с изучения программистами тех тем, с которыми связана будущая программа. Подробные же инструкции от специалистов, увы, пока что существуют преимущественно в мечтах о светлом будущем человечества.
3. Существуют «настоящие программисты», которые умеют всё
Этот миф особенно популярен среди начинающих программистов. Им кажется, что вот они сейчас ещё знают мало, а где-то есть «настоящие программисты», которые владеют всеми технологиями и умеют делать всё, связанное с программированием, а то и вообще всё, связанное с компьютерами.
Отголоски этого мифа также зачастую можно увидеть в описаниях вакансий, согласно которым предполагается найти некого мистического супергероя, который одинаково хорошо управляется с лошадью, поездом и космическим кораблём, одновременно с тем умея жонглировать горящими булавами, играть на скрипке и готовить рыбу фугу.
Но даже по разбору предыдущего мифа должно быть понятно, что такое невозможно: программист правда вынужден разбираться с предметной областью, однако такое разбирательство требует времени, поэтому он просто не в состоянии разобраться со всеми областями одновременно.
А области есть не только вовне программирования, но и внутри. Если некто программирует модели физических процессов, происходящих в ядерных реакторах, или посадку космического корабля на Марс, то, скорее всего, он в это время не программирует сайты интернет-магазинов или интеллектуальную обработку больших наборов хитросплетённых данных.
Странно было бы ожидать от учёного, что он будет разбираться в десятке слабосвязанных между собой научных областей на уровне академика каждой из них. И не менее странно думать, что у программистов как-то иначе, и что мастер разработки софта для трёхмерной графики вообще без подготовки начнёт с той же степенью мастерства программировать следующую версию Виндоус или систему автоматического перевода с русского на английский.
Да, наверно он разберётся с тем, как это делается, но на это потребуется время. Меньшее, чем будет нужно тому, кто начинает вообще с нуля, но всё-таки довольно заметное.
И да, следует понимать, что программист, системный администратор и сборщик компьютеров — это три разные профессии. А кроме них существует ещё пара сотен других, тоже тесно связанных с компьютерами. Поэтому, хотя программист, скорее всего, и будет знать что-то про настройку Виндоус, сборку компьютеров и редактирование фотографий в Фотошопе, постоянно обращаться к нему за помощью по этим вопросам и негодовать в случае отказа столь же осмысленно, сколь осмысленно просить у дизайнера обуви починить вам ботинки и натереть их гуталином, а у повара — назвать точный химический состав вашего любимого блюда и помыть вам посуду.
4. Языки программирования — все разные
Ну, «все одинаковые» — тоже было бы неверно. Однако разница чаще всего действительно не очень велика.
Причём имеет смысл рассмотреть даже не одну разницу, а две: разницу в логике устройства и в синтаксисе.
Последнее означает, что в языках используются совершенно одинаковые конструкции, но записываются они разными словами или слова стоят в другом порядке. Примерно, как если бы русский язык перевели бы с кириллицы на латиницу — нам бы пришлось некоторое время привыкать к этим новым буковкам, но все бы понимали, что сам язык-то не изменился.
Так вот, как ни странно, разница в синтаксисе — это сейчас основная «долгоиграющая» разница.
Это может показаться странным: зачем раз за разом изобретать новые языки, которые отличается только способом записи?
Но происходит всё несколько не так. Изобретают в основном не способы записи, а именно что логику устройства. Точнее, не всю целиком, а скорее дополнения к логике устройства предыдущих языков (кои дополнения, впрочем, могут оказаться весьма масштабными).
Однако дополнения, оказавшиеся удачными, через некоторое время расползаются вообще по всем языкам. Возможно, вы слышали такие термины, как «объектно-ориентированное программирование» или «функциональное программирование». Так вот, хотя вам могло показаться, что речь тут про какую-то отдельную область, на практике сейчас и то, и другое есть практически везде. Во всех распространённых языках и даже в ряде не особо распространённых. Причём даже в тех, где всего этого изначально не было.
Да, именно так: Java, C#, C++, Python, Lua, JavaScript и много что ещё сейчас и объектно-ориентированные, и функциональные. Не в самом чистом виде из возможных, но в достаточной степени, чтобы это при программировании на них широко и постоянно использовалось.
Некоторые же другие языки, — например, Wolfram, — хоть и не содержат в своём синтаксисе объектов в явном виде, но позволяют имитацию объектно-ориентированного подхода, почти идентичную натуральной. А в некоторых других языках аналогичное происходит с функциональным подходом.
Какие-то другие успешные дополнения при этом могут не добавляться напрямую к языку, а просто реализовываться на основе уже имеющегося в нём, и в таком виде широко использоваться.
Лишёнными же всех этих радостей оказались лишь те языки, которые давно уже прекратили своё развитие и существуют сейчас как бы «по инерции».
Это, как легко догадаться, приводит к тому, что по логике своего устройства большинство языков программирования весьма близки друг к другу и продолжают сближаться, отличия же остаются преимущественно в том, как эта логика записывается синтаксически.
Но и тут различия не особо велики: у большинства языков синтаксис столь похож, что программист, хорошо знающий один язык, может без особого труда читать программу на другом. И для понимания синтаксиса ему, возможно, даже не придётся даже лезть в какой-то справочник — он просто вычислит синтаксис по примерам кода.
Да, некоторое количество языков с сильно непохожим на другие синтаксисом всё ещё есть (Lisp, Haskell), но основная масса современных языков всё-таки по нему очень похожа.
Поэтому сейчас уже вполне можно сказать, что, поняв один современный и достаточно богатый возможностями язык (например, С#, Java, Scala, Python), вы в некотором смысле одновременно с ним понимаете все языки программирования сразу.
Но тут всё-таки есть нюансы, о которых пойдёт речь в следующем мифе.
5. «Настоящий программист» подбирает язык под каждую задачу
К этому иногда ещё присовокупляется что-то типа: «язык программирования — это инструмент. Как молоток лучше всего подходит для забивания гвоздей, а вольтметр — для измерения напряжения, так и язык программирования тоже должен подбираться под задачу».
Однако суровая практика сильно портит эту стройную теорию. Дело в том, что ровно так же, как почти невозможно одновременно разобраться во всех областях человеческой деятельности, так и невозможно одновременно изучить все языки.
Да, как говорилось ранее, большинство из них сильно похожи друг на друга, однако у каждого есть свои тонкости использования: проблемы, вызванные предысторией и давними ошибками в дизайне, с соответствующими способами их обхода, свои собственные имена тысяч функций, делающих что-то полезное, готовые блоки кода для решения тех или иных задач — библиотеки — со своим собственным устройством. Это всё тоже, как и синтаксис или возможности языков, перекликается между собой, и может быть относительно быстро изучено, однако на привыкание всё-таки требуется время. И то, что программист сделает на привычном для него языке быстро и почти не задумываясь, на другом языке может вызвать изрядные заминки.
Ну как, например, вы вполне можете выучить, скажем, английский и даже говорить на нём, но довольно значительное время вы будете говорить на нём не так быстро и образно, как на русском.
При этом разница в «заточенности инструментов под данную задачу» не столь велика, сколь это зачастую себе представляют. Всё-таки распространённые языки программирования — в основном универсальные, что подразумевает возможность решать на них любые задачи примерно с одинаковым успехом. Количество же узкоспециализированных языков в среднем сокращается, а не растёт. Даже языки, встраиваемые во всевозможные приложения для автоматизации действий в них, сейчас в основном всё те же универсальные, а не свои собственные (в приложениях Adobe это JavaScript, в Майкрософт Офисе — Visual Basic, в Cinema 4d — Python и т. п.).
Поэтому вполне возможно, что затраченное на переучивание и привыкание время попросту не окупится. Вполне возможно, что та небольшая прибавка к скорости, которую даёт другой язык при решении этой задачи, целиком будет съедена вот этими вот заминками.
Вдобавок не очень уверенное понимание всех этих специфических для языка тонкостей добавит программе ошибок, на исправление которых тоже уйдёт время.
Поэтому смена языка программистом или, тем более, коллективом программистов — это довольно сложное решение, которое обычно принимается в расчёте не на одну задачу, а на целое множество будущих задач. И делается это обычно по той причине, что на «новом» языке проще делать вообще всё, а не что-то одно. И после принятия этого решения язык обычно меняется не для одной конкретной задачи, а сразу для всех новых.
6. Программист отлично понимает, как работает его программа
Иногда этот тезис смягчают, уточняя, что речь идёт не просто о «программисте», а о «хорошем» или «настоящем» программисте.
Правда, с такой поправкой следовало бы заключить, что, если это так, то хорошие и настоящие программисты кончились ещё в шестидесятых — когда программы были длиной в сто строк максимум, а машинное время было столь дефицитным, что программы писали на бумажке и отлаживали в уме.
Увы, сейчас большинство программистов более-менее понимают, как работает лишь небольшая часть программы, в разработке которой они поучаствовали. И для основной массы программ не существует ни единого человека на всей планете, кто понимал бы их устройство во всех деталях.
Однако это не следствие падения всех устоев и загнивания отрасли, а, напротив, следствие огромного и стремительного прогресса, обусловившего лавинообразный рост количества знаний в этой области.
Причём и в других областях человеческой деятельности тоже так. Например, нет ни единого человека на всей Земле, который знает точный химический состав всех видов булочек, умеет выпекать все их разновидности на любой плите или печи, знает геномы всех сортов зерна, способен производить удобрения и пестициды, строить комбайны и пекарни, и одновременно с тем развозить готовую продукцию по магазинам. Но это ведь не мешает вам покупать и кушать булочки?
Усложнение процессов и умножение наших знаний о них с неизбежностью приводит к разделению труда, и программирование здесь не исключение. Когда вся программа занимает сто строк и вся сводится к какому-то одному почти линейному процессу, а спектр задач, решаемых при помощи программ, лежит в одной относительно узкой области, действительно можно досконально разобраться со всеми деталями. Но с программами на миллионы строк, выполняющими тысячи разных, но связанных между собой действий, написать которые предполагается всё-таки быстрее, чем за время жизни вселенной, такое уже чисто технически невозможно.
По этой причине каждый программист самостоятельно создаёт лишь небольшую часть кода — даже если работает один. Всё же остальное сделали какие-то другие люди — написавшие операционные системы, драйверы устройств, библиотеки и сам язык программирования, на котором пишет этот программист. Естественно, он знает некоторые детали всего перечисленного, однако, если бы он захотел досконально изучить каждую строчку чужого кода, обеспечивающую работоспособность той части программы, которую он написал сам, то да, счёт времени пошёл бы на тысячелетия.
В результате каждый разработчик вынужден доверяться обещаниям других программистов: что написанная ими часть программы правда работает, и что она делает именно то, что заявлено, и что если там всё-таки обнаружится ошибка, то они сами её исправят. Он вынужден читать краткие инструкции по использованию чужого кода и следовать им, не разбираясь в его внутреннем устройстве. То есть делать ровно то же, что и пользователи его программы, которые работают в ней, как правило, вообще не представляя, каким образом она написана.
Чуть выше речь заходила о том, что программист вынужден разбираться с предметной областью: понимать её, но вовсе не обязательно на уровне академика. Аналогичное же происходит и с тем внешним кодом, который он использует как составную часть своей программы. Надо понимать «основную идею», «подход», «принцип использования», но вовсе не все детали от «а» до «я» — последнее просто невозможно.
Более того, по мере развития методов искусственного интеллекта, полку́ непониманий прибыло. Если раньше для каждого фрагмента кода всё-таки можно было разыскать того, кто понимает, как всё это работает, а про используемую там математику можно было спросить математика, и он бы всё разъяснил, то сейчас стали появляться такие фрагменты программ, работу которых не понимает никто вообще. Точнее, математик понимает математическую логику алгоритма, а программист — способ его программной реализации, но ни тот ни другой, ни оба вместе не смогут вам сказать, каким именно образом этот алгоритм приводит нас к результату.
Да, вот эта запрограммированная нами нейронная сеть правда отличает фотку кота от фотки собаки. Да, мы знаем устройство этой сети, знаем метод её обучения, знаем, как всё это запрограммировано, но при этом мы без понятия, как именно ей удаётся отличать собак от кошек. Однако мы много раз проверили — оно правда работает.
Это кажется парадоксом из парадоксов, но таково современное состояние данной отрасли.
7. «Я же не программист, зачем мне уметь программировать?»
Знаете, повару, например, тоже не обязательно уметь читать. Он же просто еду готовит.
Теоретически он мог бы обойтись без этого навыка. Но представьте, сколь сложна была бы его жизнь в этом случае.
Если ему нужно узнать новый рецепт, то он не может просто прочитать его — придётся просить кого-то пересказать ему этот рецепт.
И записать рецепт он тоже не может. Поэтому ему надо будет каждый день тратить время на повторение ранее заученных рецептов, чтобы они не забылись. Либо же каждый раз искать того, кто прочитает ему эти рецепты.
Ровно так же и с программированием: обойтись без него всё ещё можно, но компьютеры проникли уже практически во все области. Уровень автоматизации всё растёт и растёт.
Вы — редактор? Умей вы программировать, вы бы смогли написать несколько маленьких программок и автоматизировать изрядную часть своей деятельности по подготовке текста.
Вы занимаетесь спецэффектами для телевидения? Многие из них делаются в сто раз быстрее при помощи маленьких программок, а не при помощи расстановки ключевых кадров.
Вы — физик? Умей вы программировать, вы бы могли в сотни раз ускорить обработку результатов ваших экспериментов. И обсчёты моделей тех явлений, которые вы изучаете.
Да, многие вещи уже и так реализованы программистами, но человеческих потребностей слишком много, и программисты просто не успевают автоматизировать каждый возможный случай. Они дают вам некий универсальный инструмент, но он ещё не предел автоматизации: ведь всё ещё можно автоматизировать ваш личный сценарий работы с этим инструментом. А приставить к каждому личного программиста попросту невозможно.
Да и в целом автоматизировать ваши задачи можно было бы гораздо быстрее, если бы не только программисты разбирались в вашей области, а ещё и вы в программировании. Так вы быстрее бы отвечали на вопросы программистов и лучше бы формулировали свои потребности. А в ряде случаев вообще могли бы обходиться без программистов, автоматизируя свою деятельность своими силами.
Программирование действительно не является чем-то необходимым для других профессий, однако оно является крайне полезным для очень многих из них. И в перспективе эта полезность будет только возрастать, усугубляя разрыв в эффективности работы между умеющими и не умеющими программировать.
На практике программирование сейчас уже вплотную подошло к тому, чтобы войти в понятие «базовая грамотность», наряду с умением читать, писать и считать. Оно уже не привязано к одной области, а распространилось практически на все.