Введение. Программирование - ремесло, наука, искусство?

    sleep
    «Не умеешь работать, иди руководить.
    Не умеешь руководить, иди учить других.
    Не умеешь учить – пиши книгу
    (или руководи учебным процессом)».

    Слегка измененное автором ходячее изречение

    Да не обидятся читающие это произведение авторы учебников и методисты (для них сей труд не предназначен ). Хотя бы потому, что автор имеет непосредственное к ним отношение. Когда мне в 1987 году как молодому кандидату технических наук было вменено в обязанность чтение лекций по Си, я не представлял себе, что буду заниматься этим всерьез и надолго. Я тогда имел довольно приличный опыт программирования на Aссемблере, знал Паскаль, немного пробовал Си и не интересовался, как этому учились другие. Тем не менее, чем больше я занимался преподаванием, тем больше убеждался в необходимости объяснения вещей, очевидных любому практикующемуся программисту, особенно на первых этапах обучения. Я бы назвал это «программированием здравого смысла». Ибо многие путают изучение языка и практику программирования на нем, а понятие алгоритма у многих ассоциируется с блок-схемой. Конечно, синтаксис языка и правила его записи тоже важны, но никто ведь не начинает изучение иностранного языка с полного перечня слов-исключений или чтения словаря. Между тем много учебников по программированию именно с этого и начинаются – со списка ключевых слов.

    Язык программирования – это, прежде всего, инструмент деятельности, и на него в первую очередь оказывает влияние класс решаемых на нем задач. Нельзя изучать язык ради его самого. Нельзя изучать язык в отрыве от той или иной области программирования. Хотя бы один язык нужно знать досконально, чтобы представлять многообразие имеющихся средств и иметь возможность сравнивать с другими. Опять же нельзя для каждого вида задач, для каждой технологии программирования или для каждого уровня обучения брать новый язык: например, сначала Бейсик, потом Си - «коней на переправе не меняют». Опять же, высокие технологии программирования нельзя объяснять на простых примерах: на них просто не понять сущности проблемы, до нее еще надо «дорасти». («Некоторые вещи нам не понятны, не потому, что наши понятия слабы, а потому что они не входят в круг наших понятий». Козьма Прутков).

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

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

    Другой важный момент – понимание роли и места такой деятельности как программирование среди других наук, ремесел или искусств. Что это такое: наука, искусство, ремесло (на современном языке – технология)? Что оно имеет общего с ними, и в чем отличается от них.

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

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

    • оценка трудоемкости (производительности) программ (алгоритмов). Для решения любой задачи можно написать сколь угодно медленную программу (подтверждается многочисленными курсовыми работами). А вот предел производительности алгоритма, и его зависимость от размерностей обрабатываемых данных (а значит тенденции и перспективы использования при росте их объемов) поддаются математической оценке;

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

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

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

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

    Все перечисленные аспекты деятельности, именуемой программированием, я постарался отразить и взаимно увязать в каждой конкретной теме. Если это удалось в какой-то мере сделать, то только благодаря многим поколениям студентов факультета Автоматики и вычислительной техники НГТУ (Новосибирского государственного технического университета), бывшим в разное время невольными соавторами и подопытными кроликами по отношению к представленному ниже материалу. Насколько в процессе этой совместной работы нам удалось сформулировать идеи «программирования здравого смысла», оценить предлагается читателю по прочтении этой книги.