26 июля 2011 г.

Программирование - это искусство

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

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

План

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

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

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

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

Гибкость

Большинство людей так часто говорят слова "software" и "hardware", ссылаясь на программное и аппаратное обеспечение компьютеров, что забывают их изначальный смысл. "Soft" означает "мягкий", а "hard" - "жёсткий", "неизменный". Несложно понять, откуда возникли эти термины. Программный код должен быть "мягким", его должно быть просто изменять. Аппаратная же часть компьютера, единожды разработанная, остаётся неизменной. И речь здесь идёт не про замену дисков или памяти, а про неизменность архитектуры и системы команд. Вспомните, что первые компьютеры программировались аппаратно: не было никаких программ в чистом виде, они были зашиты прямо в аппаратное обеспечение - путём определённого подключения проводов (wire). Т.е. примерно так же, как настенный выключатель "запрограммирован" включать свет, будучи переключён в положение "on".

К чему я это сейчас сказал?

В программировании нужно помнить, что основная, изначальная причина появления программ как таковых, отделения их от железа - это гибкость и "мягкость". Если ваш программный код не гибок и не позволяет легко себя изменять - в чём смысл его существования именно как программного кода? Гибкость - это священный Грааль программного кода. Здесь, правда, нужно правильно понимать термин "гибкость". Многие (начинающие) программисты его не понимают. "Ну, я же могу переименовать переменную и ввести новую. А могу вставить вызов функции. Видишь, я же могу менять код, что тут не так?" Гибкость означает способность к адаптации к изменяющимся требованиям и развивающейся технологии. Под гибкостью понимаются такие вещи как замена одного движка БД на другой, смена GUI на CUI (графического интерфейса на консольный) и т.п. Короче говоря, хороший гибкий код должен работать с абстрактными понятиями, оперировать общим, а не быть привязанным к конкретной реализации, конкретному классу и т.п. Это, кстати, одна из причин возникновения ООП, где гибкость ("абстрактность") возводится аж до уровня синтаксиса языка (по сравнению с предыдущими подходами, где это хоть и возможно, но требует специальных усилий - хотя бы потому, что данные и методы их обработки формально не связаны).

Помните этот пост? Там был такой пункт как "Тестирование". Я знаю, некоторые (начинающие) программисты, могут подумать, что им это не нужно. На самом деле, модульное тестирование кода очень полезно не только собственно тестированием, но и тем, какой эффект оно оказывает на дизайн кода. Ведь когда вы пишете модульный тест, вы должны подсунуть вместо одного слоя другой. Вместо GUI - фиксированный ввод и вывод, вместо соединения с БД - эмулирующую прослойку и т.п. Иными словами, когда вы пишете тест, вы гарантируете определённый уровень гибкости вашего кода. Написание теста раскрывает недостаточную гибкость вашего кода, так что вы можете его исправить. Именно на этом факте основан подход к разработке программного обеспечения TDD (Test Driven Development - разработка через тестирование). Он гарантирует определённый уровень качества вашего кода (в плане гибкости).

Реклама mode on: читайте вводную статью по TDD в пятом выпуске журнала Blaise Pascal Magazine - всё о Delphi, Lazarus и Pascal.

Указанный момент (гибкость) является причиной для появления "гибких" методологий разработки программного обеспечения в попытке обуздать сложность его разработки: Agile, XP, Scrum и т.п. Следует также заметить, что "гибкие" подходы не противопоставляются инженерному подходу в том смысле, что они тоже направлены на борьбу с вышеуказанными проблемами (превышение бюджета и т.п.).

Мастерство

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

(В качестве замечания надо сказать, что успешная программа далеко не всегда имеет качественный код. Качественный код не является каким-либо показателем качественности программы (качественности программы с точки зрения пользователя), он никак не связан с её успешностью и популярностью и не является их гарантией. Качественный код гарантирует лишь простоту развития, изменения, исправления и сопровождения программы. Я не буду продолжать эту тему здесь. Возможно, я потом напишу по ней отдельный пост, но пока она и так прекрасно раскрыта в моём разделе переводов - постами про обеспечение совместимости кривых, но успешных и нужных программ. Т.е. качество исходного кода - это благо разработчика. Качественность/популярность/успешность программы - это благо пользователя. И иногда они конфликтуют друг с другом.)

Мера - всему голова.

К примеру, многие понимают фразы "не надо использовать X", "X - это плохо", "X устарел, используйте Y" буквально. На самом деле, подобные высказывания говорят лишь то, что в большинстве случаев, у X есть какие-то серьёзные проблемы в общем случае. А статьи, которые говорят про то, почему X - это плохо, на самом деле, указывают вам на отрицательные стороны и недостатки X. Вспомните, глобальные переменные, with, goto ("GOTO considered harmful") и другие вещи. Подобного вида статьи нужно понимать так, что они дают вам обзор/знание недостатков X. X тут не плох сам по себе, а лишь во вполне определённых условиях. Что означает, что вы, уже как профессионал в этих вопросах, сможете взвесить все плюсы и минусы и выбрать подходящее решение. Стоит использовать X или нет. Разумеется, поскольку недостатки X столь значительны, что требуют аж специальной статьи, то в большинстве случаев выбор будет склоняться в сторону "не использовать". Именно поэтому все говорят фразы вроде "не используй X". Потому что профессионал и так знает, когда и что надо использовать. А вот начинающий программист такого осознанного и взвешенного выбора сделать не способен. Поэтому пусть лучше ему скажут, как надо делать. А когда "подрастёт" - сам разберётся. Ну и комикс в тему.

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

Вот почему программирование в первую очередь это искусство. Не имеет значения, сколько вы прочитаете книг и статей по обучению программированию, сколько вы ни узнаете советов "делай так"/"не делай так" - в конечном итоге процесс разработки программ сводится к опыту и умению. Можно вложить в себя кучу знаний, но от этого у вас не появится, как бы это сказать, "чувство правильности". Это примерно как два человека, затратив одинаковое количество усилий и используя одинаковый набор ингредиентов, могут превратить их или во вкусный торт или в несъедобную дребедень. В процессе разработки всегда есть какие-то A и B и куча промежуточных вариантов между ними. Достойный разработчик делает правильный выбор между этими вариантами на основе своего опыта и ощущений, выбрав нужный баланс. Если человек чувствует процесс разработки, ухватывает его суть, то знание конкретных технических деталей отходит на второй план. Вот почему хороший разработчик всегда что-то изучает (новую технологию, методологию и т.п.), расширяет свой опыт и кругозор.

Собственно, причиной для этого поста и стали вопросы вида "стоит ли использовать глобальные переменные в этом случае", заданные в комментариях к моему посту о глобальных переменных. Там я кратко просуммировал мысль: "Мне кажется, что какой-бы подход мы не предложили - всегда найдутся люди, которые его используют неправильно". А этот пост - развёрнутый вариант ответа (в некотором роде).

Мораль истории? Программированию нельзя научится в ВУЗе. Это - искусство, которому нужно учиться самому.

В этом смысле это был пост-добавка к предыдущему посту.

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

3 комментария :

  1. Согласен, что это искусство. Если взглянуть на художников - то они тоже учат какими кистями, красками, на каком полотне рисовать. Для того чтобы нарисовать человека - они изучают анатомию, и это полноправно считают искусством. Но самое главное - в картине, точно так же как и в программе не видно мастерства автора. Я смотрю на картину и могу сказать только нравится она мне или нет, и даже профессионал с трудом сразу может сказать что-либо о мастерстве автора. Картина это сродни интерфейсу в приложении, то что видно пользователю. Кстати на этом основано распознание оригинала от подделки. Один из способов распознания - это изучение мазков. Раньше в красках (а может и сейчас) содержался свинец, и под рентгеном его хорошо видно. Посмотрев на рентген можно безошибочно определить (с этим даже и непрофессионал справится) где подделка. Это все равно что заглянуть в исходный код. Внешне приложение можно создать похожим, но в оригинале (написанном мастером) там будет красивая архитектура, а в подделке (написанной любителем) костыль на костыле ;)

    ОтветитьУдалить
  2. >"не надо использовать X", "X - это плохо"

    Если создатели языка предусмотрели в нем какую-то конструкцию, то очевидно, что предусмотрено ее использование, иначе ей не место в языке.

    Марксизм не догма, а руководство к действию.

    ОтветитьУдалить
  3. Простите но дочитать не смог.
    Отрицание -
    программирование низводят до уровня "механического вырезания болтов на станке".

    Для меня это след:
    1. Амбиции при написании програм вредны. Оставьте это профессионалам, учившимся на это. Настоящим художникам и дизайнерам.
    2. Когда человек делает, то что необходимо по чертежам используя вверенные и созданные для этого инструменты - это не стыдно. Стыдно не делать, то что указано в спеках и тз. Потому как на тебя расчитывают другие люди в комманде. В эти моменты Мы все слесаря. даже если делаем это по своим же чертежам.
    3. Исскуство формализовано. Сначала осваиваются базовые навыки и учатся их применять. В программировании все наоброт. Все делают холокосты из своих прог, затем переходят в манагеры, читают пару книг и затем начинают вершить свои технологии производства ПО.

    И держат свои головы как павлины. Хотя молодых прогеров надо таскать и драть за уши. Везде это есть, а в программировании это редкость.

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

    Когда все это переварите. осознайте. Что исскуство не в бунтарстве, а в прогрессе. Создатель паровоза - создатель нового. Нужного. Работающего на благо. А не засоряющее и усложняющее без того бездарные тексты програм.

    P/S - STL - это плохой пример до чего может довести желание исскусничать. К сожалению это стало еще и стандартом(но ненадолго). Есть простые и изящные средства разроботки. Инструменты. И их создают спечиально, для нас Программистов. Чтобы мы делали что-то простое, надежное и удобное. И делали это вместе, а не по одиночке лепили одноруких статуи

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

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и (опционально) ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку.

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.

Примечание. Отправлять комментарии могут только участники этого блога.