Пиши Дома Нужные Работы

Обратная связь

Три подхода к программированию

 

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

1. Императивный стиль. Самым распространенным классом языков программирования является класс императивных языков (они еще известны под названием операторных). К ним относятся и Паскаль, и Бейсик, и даже Си++, несмотря на всю его объектную ориентированность. Императивный подход наиболее естественен для человека, общающегося с компьютером. Действительно, если вспомнить определение алгоритма: конечная последовательность определенных в каждый момент времени действий, выполнение которых ведет к решению задачи за конечное число шагов, - то именно набор указаний - императив - наиболее приемлем для кодирования. Да и вообще, приятно ведь кем-нибудь покомандовать! Более того, если вспомнить таких классиков теоретического программирования, как Тьюринг и Пост, то становится понятно, что и они, создавая теорию универсальных вычислителей, пользовались именно императивным стилем написания программ. Фортран и более поздние языки программирования также несут в своих операторах приказной тон: ДЛЯ i ОТ 1 ДО 10 ДЕЛАЙ.

2. Функциональный стиль. Среди многих десятков языков программирования есть один "древний старичок". - "ЛИСП". Он чуть моложе Фортрана, и его первый интерпретатор был написан именно на Фортране. Название происходит от английского термина List Processing - обработка списков. Его автором является профессор математики Маккарти. Первая реализация ЛИСП'а была сделана в самом начале шестидесятых годов. Досталось (и достается сейчас) языку довольно много. Началось все с названия. Имя языка совпадает с английским словом "шепелявить". Потом языку досталось из-за безумного количества скобок, используемых для записи программ, из-за бедности типов данных (базовых всего два). Но первый компьютерный психиатр "Элиза" был написан именно на ЛИСП'е и только значительно позже переписан на других языках программирования. Первые экспертные системы и системы автоматического доказательства теорем также были исходно реализованы на ЛИСП'е. И это несмотря на бедность средств работы с периферией, контроль типов во время исполнения программы и т. п. Почему же так случилось? Да потому, что ЛИСП - один из немногих языков программирования, который поддерживает функциональный стиль. Давайте рассмотрим действие некоторой программы P. Она получает на входе некоторый набор (множество) данных М и преобразует его во множество выходных данных M1. То есть программа отображает множество М во множество М1, причем конкретному набору входных данных соответствует конкретный выходной набор. Отображение однозначно! В математике такая зависимость называется функцией, а значит, мы имеем право рассматривать программу как функцию над множеством входных параметров. Кажущаяся сложность определений, полностью окупается тем изяществом, с которым можно писать программы на функциональных языках. Пусть необходимо реверсировать произвольную последовательность. То есть из конструкции вида (A B C D E F Q) получить (Q F E D C B A). Последовательность может быть произвольной длины и произвольной структуры, то есть вместо любого из атомов А, В, и т. д. может стоять произвольная подпоследовательность. (Вообще, в ЛИСП'е такие структуры называются списками). Решение этой задачи занимает всего несколько строк. Вот оно: (DEFUN REVERSE-1 (X) ; Определяем функцию реверсирования с единственным аргументом (COND ((NULL X) NIL) ; Если аргумент пустой, то ничего не делать (вернуть пустой список) (T (APPEND (REVERSE-1 (CDR X)) (LIST(CAR X)))))) ; Иначе объединить реверсированный список, содержащий все элементы исходного за исключением самого первого (головы), со списком, содержащим голову исходного. Согласитесь, что три строчки не так много для сформулированной задачи.



Функциональное программирование, в том числе и ЛИСП, активно применяется в системах символьных вычислений. Мощнейший аналитический решатель задач REDUCE полностью написан на диалекте языка, называемом R-LISP, а все версии AutoCAD, по 12-ю включительно, поддерживают встроенный язык Авто-ЛИСП.

3. Логический стиль.Последний класс языков программирования является "побочным продуктом" разработки компьютеров пятого поколения. Идея была выдвинута в семидесятых годах в Японии, и именно там был реализован логический подход к программированию. Только там мог возникнуть язык, который позволяет компьютеру если не думать, то по крайней мере логично рассуждать. Этот язык получил имя "Пролог" (Programming Logic). Именно логическое программирование на Прологе позволило программисту свести к минимуму усилия по проработке логики программы. Идея, заложенная в логический стиль, проста. Давайте сформулируем аксиомы, касающиеся некоторых объектов, и назовем эти аксиомы фактами. Установим отношения между объектами и назовем их правилами или теоремами. Дальше, построим запрос (опять в виде некоторой теоремы) и попросим компьютер доказать либо опровергнуть его. Реализация сформулированной идеи носит естественные ограничения исчисления предикатов, в рамках которого работает язык (о полуразрешимости исчисления предикатов можно прочесть в любом курсе по математической логике). Удобства, предоставляемые Прологом, становятся особенно заметными после некоторой практики программирования задач символьной обработки и искусственного интеллекта. Однако Пролог нашел интересное применение не только в среде экспертных систем и систем распознавания образов. Для доказательства запросов (целей) правила и факты представляются в Пролог-машине в виде таблицы, то есть любая Пролог-система для каждой задачи строит небольшую реляционную базу данных. Благодаря этому свойству Пролога, стало возможным его использование в качестве языка запросов к обычным базам данных. Использование Пролога в таком новом качестве позволяет многократно повысить скорость обработки запроса, поскольку число промежуточных операций по переводу информации из одного представления в другое резко сокращается.

При работе с базами данных Пролог во многом удобнее императивного SQL. На нем можно относительно легко реализовать СУБД. Однако фирмы - разработчики программного обеспечения пишут софт на Си++, аргументируя свой выбор возможностью писать в объектах. Текстовый процессор на ЛИСП'е "выжмет" из своего автора гораздо меньше сил, чем такой же процессор, но написанный на другом языке. А отладка если и не доставит удовольствие, то точно уж не будет столь изнурительной. И в объектах писать можно (система CLOS - Common Lisp Object System довольно давно стала негласным стандартом языка), и с периферией работать просто. ЛИСП и Пролог сейчас - это мощные и гибкие системы, хотя пользуются ими единицы-профессионалы.

Говорят, что язык поддерживает некоторый стиль программирования, если в нем есть такие возможности, которые делают программирование в этом стиле удобным (достаточно простым, надежным и эффективным). Язык не поддерживает некоторый стиль программирования, если требуются большие усилия или даже искусство, чтобы написать программу в этом стиле. Однако это не означает, что язык запрещает писать программы в этом стиле. Действительно, можно писать структурные программы на Фортране и объектно-ориентированные программы на С, но это будет пустой тратой сил, поскольку данные языки не поддерживают указанных стилей программирования.

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

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

1. Все конструкции языка должны естественно и элегантно определяться в нем.

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

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

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

5. Пользователю достаточно знать только то множество конструкций, которое непосредственно используется в его программе.

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

 

2. Стиль структу́рного программи́рования

 

Структурное программирование — методология разработки ПО, в основе которой лежит представление программы в виде иерархической структуры блоков. Предложена в 70-х годах XX века Э. Дейкстрой, разработана и дополнена Н. Виртом. В соответствии с данной методологией:

1. Любая программа представляет собой структуру, построенную из трёх типов базовых конструкций:

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

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

3. Разработка программы ведётся пошагово, методом «сверху вниз».

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

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

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

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

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

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

• Сильно упрощается процесс тестирования и отладки структурированных программ.

Общие положения стандарта оформления кода

 

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

На самом деле, нет какого-то единого стиля, овладев которым, можно научиться писать красивые программы. Программист, всю жизнь писавший на С++, довольно быстро может разобраться в программе на Паскале, Java и тем более С#. Довольно быстро - при условии, что она понятно написана. Другое дело - программы, написанные неумело. Если в программе задействована глобальная переменная, изменения которой происходят в несвязанных классах/функциях, можно говорить о неудобной архитектуре. Если в программе жестко прописаны константы и, поменяв числовое значение в одной переменной, мы нарушаем целостность программы, можно говорить о плохой архитектуре. Можно говорить о плохой архитектуре, когда классы связаны между собой крест-накрест, и изменения в одном из них ведут к изменениям в другом, а изменения в другом - к изменению в первом. Когда программа ведет себя непредсказуемым образом - значит, это неудачное программное решение. Проблема состоит в том, что и хорошую, и плохую программу можно написать на разных языках. И раз уж такая глобальная вещь как язык программирования, имеет так мало влияния на качество программы, то что уж говорить об оформлении кода. Конечно, оформление кода не может служить панацеей от кривых рук программиста. Скорее, неаккуратное оформление может развалить красивый код на кучу мало связных кусков.

 

Несколько подходов к стилю

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






ТОП 5 статей:
Экономическая сущность инвестиций - Экономическая сущность инвестиций – долгосрочные вложения экономических ресурсов сроком более 1 года для получения прибыли путем...
Тема: Федеральный закон от 26.07.2006 N 135-ФЗ - На основании изучения ФЗ № 135, дайте максимально короткое определение следующих понятий с указанием статей и пунктов закона...
Сущность, функции и виды управления в телекоммуникациях - Цели достигаются с помощью различных принципов, функций и методов социально-экономического менеджмента...
Схема построения базисных индексов - Индекс (лат. INDEX – указатель, показатель) - относительная величина, показывающая, во сколько раз уровень изучаемого явления...
Тема 11. Международное космическое право - Правовой режим космического пространства и небесных тел. Принципы деятельности государств по исследованию...



©2015- 2024 pdnr.ru Все права принадлежат авторам размещенных материалов.