Найти в Дзене
Разумный мир

Программисты такие разные... Или статья по мотивам статей

Оглавление

Заканчивается очередной год, который, как это всегда бывает, выдался трудным. Хочется немного отвлечься от сложных вопросов, пофилософствовать, побурчать (на старости лет можно!). Эта статья будет небольшой статьей-рассуждением, хотя обсуждаемый вопрос далеко не так прост, как кажется с первого взгляда.

Первым "звоночком", который послужил поводом к данной статье, стал пост

Точнее, сказанные там слова "собрался в IT сферу, начинать нужно читать не с книг Джобса, а с книг Дональда Кнута." Поскольку трехтомник "Искусство программирования для ЭВМ" я не просто прочил не один раз, но и большинство задач решил. Правда дело было более 40 лет назад, но что это меняет? Потрясающие книги от которых трудно оторваться. Но вот рекомендовать их для новичков... Я бы точно не стал.

Побурчав про себя я не стал ни комментировать тот пост, ни писать что либо на эту тему. Но сегодня прозвенел второй "звоночек"

И вот тут то я понял, что не высказаться уже не могу... Это будет моим субъективным, но основанным на большом личном опыте, мнением. Разумеется, у каждого читателя может быть свое мнение, радикально отличающееся от моего. Хотите поспорить? В комментариях, при соблюдении стандартных правил взаимного уважения, дискуссия только приветствуется.

Очень коротко о себе

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

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

Легендарный трехтомник. Или четырехтомник?

Полностью закончены и выпущены в виде бумажных книг три тома

Трехтомник издания 1976-1978 годов. Фото мое
Трехтомник издания 1976-1978 годов. Фото мое

Да, это из моей личной библиотеки. Первое издание в СССР. Причем в предисловии редакторов перевода к первому тому говорится, что автором запланирован выпуск 7 томов монографии

Предисловие редакторов перевода в котором говорится о семи запланированных томах. Фото мое
Предисловие редакторов перевода в котором говорится о семи запланированных томах. Фото мое

Приводится в первом томе и письмо самого автора

Письмо самого Д. Кнута опубликованное в первом томе монографии. Фото мое
Письмо самого Д. Кнута опубликованное в первом томе монографии. Фото мое

Однако, после публикации трех томов последовала весьма долгая пауза. И ожидаемый многими четвертый том начал потихоньку, частями, появляться только в 2005 году. Причем полностью он так и не вышел. Опубликована только часть 4А. Частично есть часть 4В. Но ожидать, что когда нибудь действительно выйдут все тома уже не стоит. К огромному сожалению.

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

Пример пары страниц из второго тома. Фото мое
Пример пары страниц из второго тома. Фото мое

И это далеко не самый сложный пример. В книге много иллюстраций, которые наглядно показывают описанное. Но тексты программ приводятся для абстрактной, придуманной самим Д. Кнутом машины, причем они на придуманном им же ассемблере

Примеры программ, реализующие описываемые алгоритмы, приведены на ассемблере для абстрактной машины. Фото мое
Примеры программ, реализующие описываемые алгоритмы, приведены на ассемблере для абстрактной машины. Фото мое

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

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

Почему я для иллюстраций выбрал именно второй том? Просто не так давно я публиковал небольшой цикл статей посвященный машинному представлению чисел. А второй том как и посвящен "Получисленным алгоритмам", имеющим прямое отношение к теме цикла.

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

Что же такое программист?

А теперь давайте задумаемся, существует ли вообще некий "чистый абстрактный программист"? Что такое вообще "программирование"? Увы, четкого и однозначного ответа, который бы признали все, нет.

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

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

Имея алгоритм мы можем реализовать его в виде плана действий выполняемых людьми. Или в виде механической конструкции. Или в виде электронной, и даже просто электрической (например релейной) схемы. И в виде той самой программы. Все это будут лишь варианты реализации алгоритма. А программа, один из вариантов реализации, может быть написана на любом языке программирования! Даже на языке который потом будет преобразован в прошивку для ПЛИС, а не загружен в универсальную ЭВМ. Например, на Verilog.

То есть, нам требуется примерно такая последовательность действий для решения конкретной прикладной задачи. Кстати, это тоже можно считать алгоритмом.

  1. Изучить и понять собственно прикладную задачу. Часто это требует достаточно глубокого погружения в прикладную область. А прикладные области могут быть очень разные. Так бухгалтерия кардинально отличается от медицины или электротехники. Но ведь и бухгалтеры бываю разные. А уж о разных специализациях врачей и говорить не приходится.
  2. Разобравшись с прикладной задачей нам нужно найти пути ее решения. Не обязательно самостоятельно, можно привлекать специалистов в прикладной области.
  3. Описать найденные пути решения в виде наброска алгоритма, пока без детализации методов выполнения отдельных шагов. Например, некий шаг алгоритма может быть таким "если температуры превышает установленные пределы включить систему охлаждения".
  4. Теперь мы можем приступить к детализации каждого шага алгоритма. Причем при этом у нас могут появиться целые алгоритмы (иногда даже для иных прикладных областей), которые используются для выполнения отдельных шагов нашего основного алгоритма. Например, включение системы охлаждения может потребовать выполнения некоторой последовательности действий, причем при этом потребуется и контролировать отдельные параметры в этой последовательности.
  5. Получив детальный алгоритм и все сопутствующие алгоритмы мы можем приступать к выбору путей и способов их конкретной реализации. И эта реализация не обязательно будет программной или чисто программной.

Это очень грубый и максимально обобщенный набросок последовательности шагов по решению конкретной прикладной задачи. Но уже здесь видна масса сложностей. И самая первая, самая большая, множество и разнообразие прикладных областей. Ну не может самый прекрасный специалист в области электропривода (кстати, силового или прецизионного?) быть еще и специалистом в медицине. Самый распрекрасный программист не может быть одновременно и химиком, и бухгалтером.

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

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

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

Да, я описал то, как это было раньше. Сегодня изменилось очень и очень многое. Но по прежнему никуда не делась необходимость досконально разбираться в собственно прикладной задаче. Без этого ничего хорошего не получится. А вот программистами сегодня называются совсем другие люди. Они уже не занимаются алгоритмизацией, но занимаются кодированием на языках программирования, причем языках высокого уровня (ЯВУ).

Когда то программистов готовили как математиков. Потом сделали упор на алгоритмы и методы решения задач на ЭВМ. Сегодня упор часто делается на конкретный язык программирования, зачастую в связке с конкретным средством разработки (framework). Так и появились "программисты на Delphi", которая является одной из реализация компилятора с языка Pascal, изрядно модифицированного, и в связке со средой разработки и кучей готовых библиотек. Посади такого программиста за компилятор чистого Pascal и он окажется бессильным. Впрочем, верно и обратное.

Да, условия меняются непрерывно. Да, это во многом обосновано. Да, сроки разработки требуется сокращать, как можно сильнее. Да, этого требует конкуренция. Да, современный программист должен уметь пользоваться имеющимся в его распоряжении инструментарием, а не изобретать каждый раз велосипед. Все это так... Я даже не пытаюсь это оспорить. Но это возвращает нас к вопросу "что такое программист сегодня"?

Математик? Нет! Хотя без математики невозможно. Аглоритимзатор? Нет! Алгоритмы знать нужно, нужно уметь создавать свои, но это лишь часть работы программиста сегодня. Кодировщик? Нет! Знать только язык программирования сегодня недостаточно. Хотя именно этому и учат начинающих программистов.

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

Программист прикладной узкоспециализированный

К таким можно отнести, например, программистов 1С, которые сегодня достаточно востребованы. К этой же группе я отнесу и программистов, которые занимаются автоматизацией web-сайтов, причем на готовых CMS. Программисты станков с ЧПУ тоже будут в этой группе. И многие многие другие.

Всех этих людей объединяет глубокое погружение в конкретную прикладную область и использование, в большинстве случаев, конкретного инструмента (пакета программ, фреймворка, языка). Эти программисты находятся на грани, на стыке, между прикладными специалистами и "чистыми" (условными) программистами. Привязка к конкретному средству и области требует серьезного переучивания при изменении "точки приложения сил", что вообще не всегда возможно. Вряд ли любой "программист 1С" сможет стать специалистом, например, в области 3-мерной машинной графики одного из "движков" используемых при разработке современных игр. Равно как и наоборот.

Программист прикладной универсальный

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

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

Именно таких вот прикладных универсальных программистов часто и считают "программистами классическими".

Программист системный

А вот тут уже немного сложнее... Раньше считалось, что системный программист работает "на уровне операционной системы", которой уже пользуются прикладные программисты. При этом его задачей была не разработка операционных систем, за редким исключением, а скорее ее доработка, настройка, увязывание в единое целое разрозненных модулей. Ведь не всегда ОС была монолитом, воздействовать на который можно только редактированием файлов конфигурации. Раньше ОС была просто большим наборов исходных текстов из которых система и собиралась. И это иногда было посложнее, чем сегодня установка Gentoo.

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

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

Системный программист работает не на прикладном уровне, а ниже, он обеспечивает базу для прикладных программистов. Для него прикладным уровнем являются собственно прикладные программисты с их потребностями. Системному программисту часто не до высокоуровневых объектов и абстракций, хотя и это бывает нужно. Но ему требуется работать с оборудованием на уровне регистров и протоколов этого оборудования. Хоть и не всегда.

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

Нет, это не "политкорректное" обозначение глупости. Низкоуровневые программисты работают на самом нижнем уровне иерархии средств разработки, которые используются для решения задач. И это очень сложный уровень! Далеко не каждый программист может на нем работать. Здесь требуется глубочайшее знание и понимание (это чрезвычайно важно!) все тонкостей конкретной вычислительной машины. И это не столько "ассемблер", сколько понимание всех тонкостей архитектуры и ее аппаратной реализации.

Как работает конкретный функциональный узел системы? Как с ним общаться на уровне программы? Сколько регистров, каковы их адреса, назначение отдельных бит регистров, особенности их установки и сброса... И только после изучения всего этого можно написать хоть что-то. Язык? Это не обязательно ассемблер, часто бывает и С. Но вот от низкоуровневых операций, от прямой работы с битами, от соблюдения временнЫх параметров, никуда не деться.

Программист встраиваемых систем

Это весьма обширная и разнообразная группа программистов. Их объединяет то, что они пишут программы не для универсальных ЭВМ, а для специализированных. У таких ЭВМ часто ограниченные ресурсы (мал объем памяти, области кода и данных разделены, нет "человекоориентированных" средств ввода и вывода (даже текстовой консоли и клавиатуры), нет операционной системы. А разработка программ ведется на универсальных ЭВМ с помощью кросс-компиляторов.

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

Так чему же учить программистов?

Раз программисты бывают настолько разными, то и учить их нужно по разному. Или я не прав? И знания, которые требуются узкоспециализированному прикладному программисту во многом отличаются от знаний, которые требуются низкоуровневому программисту. Да, есть общие знания, которыми должны обладать все программисты. Например, любой программист должен знать об алгоритмах. Но даже эти общие знания имеют свои особенности!

Вот именно поэтому я не согласен со многим в статье "Не верьте опытным программистам... А хотя верьте... Или о том, что всё сложно", о которой говорил в начале. Она написана преподавателем, задачей которого является, как я понял, именно подготовка универсальных прикладных программистов:

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

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

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

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

Сегодня очень часто услышишь не призывы экономить байты, а слова о том, что даже ООП устарело и сковывает по рукам и ногам реализация этой парадигмы в некоем языке программирования. Мол хочется "широты полета мысли воплощенной в короткой строчке кода". И мне, как действительно представителю старой школы это кажется не всегда верным. Но только "НЕ всегда"!

Не согласен я и с утверждением автора "Поэтому программист, привыкший писать «эффективно», а не понятно, заимеет себе проблемы с трудоустройством. Его будут отправлять переучиваться писать так, чтобы другим с его кодом работать было удобно". Вы меня простите, но вот действительно текст, например, на С++ с использованием громоздкой иерархии классов, включая шаблонные и виртуальные, да еще со столь любимыми некоторыми функторами (функциональными объектами) будет легок и понятен всем исключения, кроме автора этого текста? Это не "ворчание старика", это опыт человека, которому пришлось разбираться с написанными другими людьми программами. Да, оно может выглядеть очень красивым и эффектным. Но вот сколько за всем этим реально потянется машинного кода очень мало программистов представляют. И если где то в иерархии что то изменилось и она "рассыпалась"... Это суровая реальность, а не страницы учебника или курсы обучения программированию.

Безусловно, программистов нужно учить общим вопросам, таким, как алгоритмы и математика. Учить стройно и логично мыслить тоже важно. А вот дальше... Без изучения хоть одного языка программирования не обойтись. Выбор не столь важен, хотя первый язык накладывает заметный отпечаток на всю жизнь. Когда то таким языком был FORTRAN, почти для всех. Хотя в некоторых ВУЗах учили PL/I. Экономистам преподавали COBOL. В ГДР был распространен Algol-60. Потом пришли C и Pascal. Язык нужно знать, что бы на практике знакомится с тем, что изучают на занятиях теорией. Что бы самостоятельно научиться превращать алгоритмы в работающие программы.

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

Но я все таки реалист, поэтому понимаю, что узкоспециализированному прикладному программисту достаточно иметь некоторое представление о том, что такое существует. Прикладнику-универсалу часто будет достаточным знать о некоторых особенностях и свойствах этих агрегатах данных. В конце концов, в STL в C++ для контейнеров и алгоритмов (это все классы, если кто не знает) можно указывать, какие типы использует контейнер. Это не повлияет на работоспособность, но повлияет на быстродействие.

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

Системному программисту, тем более, низкоуровневому, уже важны особенности конкретной машины. И здесь уже будет недостаточно обучения в ВУЗе!

Даже отладка программ будет разной для прикладного программиста, низкоуровневого, и программиста встраиваемых систем.

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

Как и два физика, два программиста не всегда смогут понять друг друга. Таковые реалии дня сегодняшнего. И становление профессионала это не быстрый процесс. И он отнюдь не заканчивается окончанием ВУЗа. И далеко не все профессионалы призывают "экономить байты", сегодня таких как раз меньшинство.

Учить программиста нужно сначала общим вопросам. А дальше он должен сам определить, в какой области хочет работать. И дальнейшее обучение должно вестись с учетом этого выбора. И никак иначе. Кого то нужно учить использованию средства быстрой разработки, а кого и по монографии Д. Кнута.

И с чем же тогда ты автор согласен?

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

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

Согласен я и с главным выводом той статьи "Верить на слово профессиональным программистам не стоит. Они могут узко мыслить только в рамках того, что знают и могут представить сами, они могут быть фанатично одержимы какими-то идеями и т.д. Поэтому к профессиональным разработчикам стоит прислушиваться, изучать то, что они говорят, изучать мнения за и против — вот это будет полезно и умно". Да, любой профессионал, и это неизбежно, является профессионалом в своей области, его знания, стиль мышления, несут большой отпечаток жизненного опыта. В силу этого любой профессионал является субъективным. Но все это касается не только программистов, но и преподавателей!

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

Даже тому, что 2х2=4 не всегда можно верить! Не верите? И правильно делаете. Просто попробуйте записать это "тождество" в троичной системе счисления...

Заключение

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

До новых встреч!