Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Стили и методы программирования. Учебное пособие для СПО
.pdf
(но не исчезает) задача выделения самостоятельных компонентов. В
дополнение к полностью самостоятельным переиспользуемым
компонентам здесь можно указать на переиспользование, при котором в
новом применении обеспечивается необходимая часть контекста (т. е.
переиспользуются компонент и эта часть контекста; смотри модули
языков Modula-2 и Object Pascal ). Модули можно рассматривать как
серые ящики для структурного программирования. Возможности
модуляризации достаточно хорошо исследованы и корректно
реализованы в упомянутых выше языках.
Следует отметить, что для рассмотренных случаев задача
переиспользования достаточно часто требует модификации того, что
предоставляется. Рассмотрим простейший пример, который не выходит
за рамки переиспользования черного ящика. Функция вычисления
квадратного корня определена только для неотрицательных аргументов.
Вопрос: нужна ли в переиспользуемой подпрограмме вычисления этой
функции проверка? С одной стороны, она повышает надежность
программирования, но с другой - оказывается избыточной, когда точно
известно (можно доказать), что аргумент больше нуля. В рамках
традиционной техники простых механизмов отключения проверки быть
не может, поскольку все они нарушают принцип черного ящика. В
императивных языках подобные многовариантные подпрограммы
традиционно трактуются как нечто грубейшим образом неструктурное и
даже неавтоматное, как уродство.
Внимание!
Многовариантность как форма серых ящиков соответствует
естественному расширению логики - исчислению предикатов с
частично упорядоченными кванторами - и может быть корректно
добавлена к императивным структурным языкам, а к языкам
автоматного программирования она добавляется естественно, и стоит
лишь пожалеть об отсутствии в них такой возможности.
При использовании сентенциального стиля возможности перестройки
переиспользуемого компонента под ситуацию гораздо выше за счет
высокоуровневых принципов вычислений. Однако точных
практических оценок этого пока что нет. Как правило, повторно
используются крупные и содержательно полные фрагменты программ,
Стили и методы программированияНепейвода Н.Н.
271

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

развиваемость [8].
Проектирование с учетом повторного использования результатов в
будущем возможно осуществлять на четырех уровнях.
1. Уровень приложений. В ходе ведения проекта заботятся о том,
чтобы при декомпозиции и разработке компонентов системы
выявлялись компоненты-кандидаты на переиспользование. Эти
компоненты выделяются в самостоятельные единицы и
оформляются независимо от проекта.
2. Уровень спецификаций и документации. В спецификациях четко
описываются стоящие за программой призраки, в документации
отделяются подпорки от решений и не забывают о призраках.
3. Уровень инструментов. Разработка проекта практически всегда
включает в себя создание инструментальных средств,
поддерживающих унификацию: единые библиотеки
общедоступных для проекта средств, общий контекст и
единообразные средства доступа к нему, средства поддержки
выполнения технологических соглашений и регламентов,
шаблоны проектирования и др. Этот инструментарий (или часть
его) во многих случаях может быть оформлен независимо от
проекта для возможного переиспользования в виде библиотек.
4. Уровень решений. Ценность для переиспользования может
представлять архитектурный уровень проекта. Хорошие
архитектурные решения, как правило, допускают распространение
за рамки конкретного проекта, в котором они появились. Это
могут быть фрагменты, которые пригодны для использования в
качестве образцов для других проектов, и тогда их
переиспользование требует оформления соответствующего
шаблона. Другой вариант независимого решения - каркас проекта,
т. е. набор взаимосвязанных компонентов, требующих
доопределения, в результате чего может быть построено
приложение, подсистема, модуль и др. Использование шаблонов
или каркасов в другом проекте связывает стиль
переиспользования со стилем программирования от образцов.
Приведенный перечень упорядочен по степени значимости уровней для
переиспользования. Наибольшая эффективность достигается, когда
удается при проектировании выйти на уровень решений, но
Стили и методы программированияНепейвода Н.Н.
273

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

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

доводится до реального программного изделия. От макета в
программной системе часто остается лишь система понятий, сам
метод разработки полностью меняется (например, макет был
написан на языке Prolog, а окончательная программа - на Java).
Макет (особенно в системах, поддерживающих его представление
в графической форме, таких как UML [18]
) нередко становится
частью документации готовой программы.
Предоставляется технологический фрейм: нечто, для чего
известны слоты, т. е. позиции (пункты, пустые значения того или
иного типа, в том числе и процедурного), которые требуется
заполнить. В результате должна получиться программа,
архитектурная схема которой задана априори. Это, собственно
говоря, и есть программирование от образцов в самой чистой
форме, которое, в свою очередь, распадается на ряд направлений:
семантические сети искусственного интеллекта;
фирменная методика и технология, которая погружает один
из предшествующих случаев в систему стандартизованных
форм и документов. Пример Rational Unified Process (RUP)
[37]
;
табличное программирование, примеры которого
приведены в данном пособии;
компонентное программирование, например, с
использованием XML или иного языка разметки (которая
задает фрейм ) и языка обработчиков разметки (разделение,
как говорят на программистском жаргоне, на парсер и
обработчик). Это как раз то, что дает объектная модель
документа.
Предоставляется технический фрейм - то, что нужно заполнять.
Он, в отличие от технологического фрейма, совершенно не
требует знания логики будущей программы. Это - облегченный и
упрощенный вариант предыдущего подхода. Вообще говоря,
неясно, программирование ли это, но такой подход очень даже
востребован (см., например, язык Forms из Oracle), а потому
замалчивать его нельзя, тем более что результат - все равно
программа.
Использование технологического и технического фреймов
демонстрирует возможность и особенности сочетания
программирования от образцов с другими стилями. Фрейм, как основа
Стили и методы программированияНепейвода Н.Н.
276

конструируемой программы, может быть разработан в каком угодно
стиле (например, как событийная система), но он предписывает
программисту правила, а иногда и стиль, в котором должны
заполняться слоты. Когда сочетание таких разнородных стилей, которое
без специальной методики и поддержки было бы неосуществимым,
становится продуктивным, тогда можно с полным правом говорить о
программировании от образцов как о самостоятельном стиле и о
реализующей его методике либо методологии.
Стиль программирования от образцов характеризуется тем, что
разработчика программы при создании слотов совершенно не
интересует, как эти компоненты будут использованы, - это заранее
решено в рамках данной системы программирования. Контекст, в
который погружаются компоненты, - это все то, что предоставляется
шаблоном или фреймом, а потому о прямом задании глобальных
действий или использовании глобальных условий здесь нет и речи.
Именно за счет строгой локализации всего, с чем имеет дело
программист, достигаются в данном случае производительность и
качество его работы.
1)
Анализ, проведенный специалистами компании IBM, показывает,
что экономически оправдано говорить о переиспользуемом компоненте,
когда он будет применяться, по крайней мере в трех разработках.
2)
Исключительно сильный и тяжелый контрпример к последнему
утверждению, ограничивающий его область применимости параллельное программирование.
Стили и методы программированияНепейвода Н.Н.
277

Общее понятие о стилях программирования
Следствия теоремы Гёделя о неполноте для программирования.
Логическая несовместимость разных классов задач. Практическая
несовместимость ипостасей внутри стилей. Взаимодействия и
сочетаемость стилей.
Почему нет универсальных методов?
К сожалению, из курсов наших университетов (как это обычно бывало
во времена кризиса России) практически исчезла исключительно
важная для мировоззрения и просто общей культуры наука: логика. Этот
факт особенно прискорбен потому, что за XX век логика заставила
научное мировоззрение перейти на качественно новый уровень
1)
. Она
впервые заставила науку задуматься над границами собственных
возможностей.
Здесь стоит сослаться хотя бы на теорему Гёделя о неполноте (см.,
напр., [20]
), которая утверждает, что нет ни одной полной теории,
описывающей хотя бы натуральные числа. Далее, теорема о неполноте
тесно взаимосвязана с теоремой об универсальном алгоритме, и обойти
ее невозможно (любая попытка обойти ее сама себя опровергает).
Теорема об универсальном алгоритме влечет как следствие
принципиальную непополнимость универсального алгоритма (это
чисто функциональный факт, он никак не зависит от конкретного
построения универсального алгоритма и даже от конкретного понятия
вычислимости, положенного в основу). Вся архитектура и идеология
современных вычислительных систем построена на базе понятия
универсального алгоритма (например, само существование транслятора
с "универсального" языка типа C++ является ее практической
реализацией). Таким образом, понятие ошибки в программе не
устранимо даже в принципе.
Значит, нет универсального метода, который позволяет с гарантией и в
ограниченное время решить любую поддающуюся решению
программистскую задачу.
Вы говорите, что люди же решают задачи. Но посмотрите: каждый
Стили и методы программированияНепейвода Н.Н.
278

специалист имеет свои излюбленные задачи, которые он хорошо
решает. А для Вашего профессионального роста и трезвой самооценки
очень полезно побывать в такой ситуации, когда Ваши излюбленные
методы отказывают. Если Вы сумели проанализировать свою неудачу,
Вы достойны звания специалиста, если же нет, Вы находитесь на пути к
догматизму либо шарлатанству
2)
.
Часто теоретические рассмотрения первого уровня приводят к
наукообразным выводам, которые рассыпаются, при углубленном
исследовании. Но в данном случае повышение глубины лишь усиливает
эффекты неуниверсальности.
Рассмотрим пример типичной ошибки, которую неоднократно делают
при теоретическом обосновании с помощью простейших моделей
вычислимости.
Все, что может быть вычислено, может быть вычислено на машине
Тьюринга. Машину Тьюринга можно промоделировать на языке С++.
Поэтому ничего, кроме языка С++, знать не нужно.
Но тогда не нужно было бы изобретать и сам язык С++, поскольку
машины конструируются таким способом, что любую машину Тьюринга
можно промоделировать и в системе машинных команд.
В истории российской (вернее, еще советской) информатики был
любопытный случай, когда минус на минус дал плюс. Невежество
самонадеянных специалистов-виртуозов наткнулось на невежество
молодого и амбициозного функционера из ЦК.
Когда рассматривался вопрос, стоит ли делать трансляторы, лучшие
московские программисты аргументировали, что делать этого не стоит.
Они разработали исключительно совершенную систему разделения
труда при кодировании на уровне машинных команд, когда программист
писал все в "содержательных обозначениях", а техники (чаще всего
девушки) чисто механически составляли таблицы и переписывали
содержательные обозначения в двоичные коды. Система изложена в
книге [7]
. Поэтому они заявили, что трансляторы не нужны, машинные
программы девочки напишут.
Стили и методы программированияНепейвода Н.Н.
279

Но поднялся молодой и считавший себя весьма знающим функционер из
научного отдела ЦК и заявил примерно следующее:
— Я приоткрою секретную информацию. У нас сейчас создается
машина (это была БЭСМ-6), которая будет выполнять миллион команд в
секунду. Это что же, вам девочки миллион команд напишут?
Поскольку даже в теории сложности есть достаточно независимые
между собой иерархии сложности (например, выигрывая во времени,
мы часто проигрываем в памяти и наоборот), то видно, что для разных
целей нужны разные средства.
Если же подняться еще на один уровень и рассматривать программы не
просто как функции сами по себе, а как средство решения внешних
задач, то мы наталкиваемся на наличие разных вариантов самой
математики (классическая и разные виды конструктивных).
Таким образом, ни абсолютной истины, ни абсолютного совершенства,
ни универсальных методов человеку не дано. Это вывод философский,
но философия также является практический наукой, если уметь ее
применять. Так уж давайте применять не только те научные результаты,
которые нам льстят.
Стили, их ипостаси, методологии, методики,
технологии
Поскольку ничего универсального нет, можно удариться в другую
крайность, скатившись на набор рецептов и потеряв саму суть метода:
гибкость и широкую применимость в самых разных областях. Если мы
ориентируемся на такой ползучий эмпиризм, то дальнейшее развитие
быстро упирается в эффект мусорной кучи: несистематизированные
рецепты знаниями так и не становятся. Для каждого класса задач нужно
искать специализированные методы и подходы.
Чем уже класс задач, тем больше общих особенностей у этих задач. Это
наиболее четко прослеживается в том случае, если класс задач
выделяется не по номенклатурному признаку (например, бухгалтерские
задачи, задачи автоматизации документооборота), а по критериям,
отражающим суть вовлеченных в задачи структур. До некоторой
Стили и методы программированияНепейвода Н.Н.
280
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
