Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Модульный принцип разработки ПО




Основы конструирования (Software Construction Fundamentals)

Фундаментальные основы конструирования программного обеспечения включают в себя:

1) Минимизацию сложности;

2) Ожидание изменений;

3)
Конструирование с возможностью проверки;

4) Стандарты в конструировании.

 

Рис.2. Основные направления конструирования программного обеспечения

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

 

Минимизация сложности (Minimizing Complexity)

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

Один из ведущих программистов фирмы IBM Эдсгер Дэйкстра, отмечал, что информационные технологии – единственная отрасль, заставляющая человеческий разум охватывать диапазон информации от отдельных битов до сотен мегабайт. Этот диапазон характеризуется значениями от 1 до 109. В наше время последняя величина уже имеет порядок 15. Ни один человек не обладает интеллектом, способным охватить все детали современной компьютерной программы. Вместо этого ее нужно разделить на фрагменты, с которыми можно работать по очереди.

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

Простота достигается с помощью следующих средств:

1) модульного принципа разработки программ;

2) прототипирования и макетирования;

3) наиболее простых и понятных алгоритмов решения задач;

4) читабельности программного кода;

5) стандартов программирования.

 

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

 

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

 

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

 

Читабельность – это удобство чтения программного кода. Она достигается с помощью целого ряда средств: структурирования, использования мнемонических имен и пр. Такой подход обеспечивает удобство составления обзоров программ, отладки и внесения изменений.

 

Стандарты программирования делятся на:

a) общие, разрабатываемые специальными организациями, например, ISO, IEEE или Комитетом по стандартизации РФ,

b) стандарты языка (например, java)

c) а также стандарты конкретной организации-разработчика программной системы.

Рассмотрим каждое их перечисленных средств минимизации сложности программных систем подробнее.

 

Модульный принцип разработки ПО

 

Модуль это – фрагмент программы, реализующий один или несколько классов, методов или функций. Обычно он состоит из интерфейсной части и реализации.

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

Пусть С(х) – сложность решения проблемы х. Т(х) – затраты времени на ее решение. Пусть имеется две проблемы: р 1 и р 2, причем их сложность С(р1) > С(р2). Очевидно, что и время их решения будет подчиняться такому же соотношению, т.е.

Т(р1) > Т(р2) (1.1).

Из практики решения проблем человеком следует, что:

С(р1 + р2) > С(р1) + С(р2),

тогда с учетом (1.1) получим:

Т(р1 + р2) > Т(р1) + Т(р2) (1.2).

Соотношение (1.2) обосновывает необходимость использования модульности и методологии «разделяй и властвуй». Сложную проблему легче решить, разделяя ее на управляемые части, как показано на рис. 3.


Рис. 3. Создание модульной архитектуры

Однако, модульность приводит к возникновению межмодульных интерфейсов, которые усложняются с ростом числа модулей. Таким образом, общая сложность и стоимость разработки ПО складывается из двух составляющих (см. рис. 4):

a)
для модулей;

b) для интерфейсов.

 

Рис. 4. Затраты на модульность

 

Из рисунка следует, что существует некоторое оптимальное Opt количество модулей, которое обеспечивает минимальную стоимость разработки. Считается, что оптимальный модуль должен удовлетворять двум критериям:

a) снаружи быть проще, чем внутри;

b) его проще использовать, чем разработать.

Основными свойствами модулей являются:

a) информационная закрытость;

b) связность;

c) сцепление.

Информационная закрытость модулей

Она иллюстрируется рис. 5 и означает следующее:

1) все модули независимы и обмениваются только информацией, необходимой для работы;

2) доступ к операциям и структурам данных модуля ограничен.

Такой подход позволяет обеспечить:

a) разработку модулей независимыми программистами и коллективами;

b) простую модификацию системы.

При объектно-ориентированном программировании рассматриваемое свойство называется инкапсуляцией.

Идеальный модуль это – «черный ящик», содержимое которого не видно, а количество «ручек органов управления» невелико. Его легко корректировать при сопровождении.

 


Рис. 5. Иллюстрация информационной закрытости модуля

 

Связность модулей

 

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

Существует 7 типов связности:

1) Функциональная (СС = 10)

2) Информационная (СС = 9);

3) Коммуникативная (СС = 7);

4) Процедурная (СС = 5);

5) Временная (СС = 3);

6) Логическая (СС = 1);

7) По совпадению (СС = 0).

Типы 5 – 7 являются результатом неправильного, а 4 - небрежного планирования архитектуры программной системы.

Рассмотрим перечисленные типы связности подробнее.

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

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

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

Пример: Прием и проверка записи файла:

Прочитать запись;

Проверить контрольные поля;

Удалить контрольные поля;

Вернуть запись.

Конец.

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

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

Пример: Модуль Отчет и средняя зарплата

Используется Таблица «Зарплаты служащих»;

Сгенерировать отчет по зарплате;

Вычислить значение средней зарплаты;

Вернуть Отчет, Средняя зарплата.

Конец.

В примере все элементы модуля работают с Таблицей «Зарплаты служащих». Для клиента средняя зарплата не нужна (этот обработчик лишний). Для улучшения функциональности модуль лучше разбить на 2.

Информационная и коммуникативная связность отличаются тем, что в первой обработчики действуют в определенном порядке, а во второй – в произвольном.

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

Пример: Модуль Вычисление средних

Используется Таблица А и Таблица В

Вычислить среднее по Таблица А

Вычислить среднее по Таблица В

Вернуть среднее_Таблицы А, среднее_Таблицы.

Конец.

Здесь возникает соблазн объединить вычисление суммы в обеих таблицах в один цикл. Это возможно, если размеры таблиц одинаковые. Но, если при сопровождении программы возникает необходимость в модификации модуля, при которой размеры таблиц станут разными, это приведет к большим проблемам. В данном случае лучше было бы оформить вычисление суммы в виде метода, параметром которого является некая таблица, и обращаться к нему, задавая в качестве исходных данных таблицу А или В.

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

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

Пример: Модуль Пересылка сообщения

Переслать по электронной почте

Переслать по факсу

Переслать в телеконференцию

Конец.

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

Недостатки логической связанности:

a) Сложный код;

b) Запутанная структура с множеством переходов.

Это приводит к тому, что модуль очень сложен для сопровождения.

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

Пример: Модуль Разные функции (параметры)

Проверить исправность аппаратуры

Отправить письмо родителям

Запастись продуктами

Заполнить анкету

Конец.

Модуль похож на логически связанный. Его действия не связаны ни потоком данных, ни по управлению. Здесь даже категории данных разные. Это – самый плохой вид связности. Модуль нужно переписать полностью, разбив его по функциям.

 

Определение связности конкретного модуля

 

Уровень связности конкретного модуля можно определить с помощью следующего алгоритма.

1. Если модуль – единичная проблемно-ориентированная функция, то связность – функциональная (СС = 10),

2. Иначе, если действия внутри модуля связаны, то,

2.1. Если действия внутри модуля связаны данными, то

2.1.1. Если порядок действия внутри модуля важен, то связность – информационная,

2.1.2. Иначе связность – коммуникативная

2.2. Иначе, (если действия связаны не по данным, а по управлению)

2.2.1. Если порядок действия внутри модуля важен, то связность – процедурная,

2.2.2. Иначе связность – временная

3. Иначе (если действия внутри модуля не связаны)

3.1. Если действия внутри модуля принадлежат к одной категории, то связность – логическая,

3.2. Иначе (действия не принадлежат к одной категории), то связность – по совпадению.

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

1) Параллельной цепи (присваивается самый высокий уровень связности);

2) Последовательной цепи (присваивается самый низкий уровень связности).

 

Сцепление модулей

 

Сцепление модулей – это мера взаимодействия модулей по данным. Она является внешней характеристикой модуля, которую желательно уменьшить. Сцепление измеряется степенью сцепления (СЦ). Выделяют 6 типов сцепления модулей.

1. Сцепление по данным (СЦ = 1), при котором результаты одного модуля являются входными данными для другого (см. рис. 6), причем каждый параметр является элементарным информационным объектом. Такой тип сцепления – наиболее предпочтителен.


Рис. 6. Сцепление по данным

2. Сцепление по образцу (СЦ = 3), при котором результаты одного модуля являются входными данными для другого (см. рис. 7), но параметр является составным информационным объектом (объектом некоторого класса).

 


Рис. 7. Сцепление по образцу

 

3. Сцепление по управлению (СЦ = 4), при котором один модуль посылает другому информационный объект (флаг), предназначенный для управления его внутренней логикой (см. Рис. 8).


Рис. 8. Сцепление по управлению

4.
Сцепление по общей области (СЦ = 7), при котором модули ссылаются на одну область глобальных данных (см. Рис. 9).

Рис. 9. Сцепление по общей области

 

5. Сцепление по содержанию (СЦ = 9), при котором один модуль обращается внутрь другого через некоторую точку входа (см. Рис. 10).

 


Рис. 10. Сцепление по содержанию

 

Сложность программной системы

 

В простейшем случае сложность программной системы определяется как сумма мер сложностей ее модулей. Сложность модулей может измеряться с помощью двух показателей (предложен М. Холстедом):

a) Длины

N ≈ n1 log2 (n1) + n2 log2 (n2)

где n1 - число различных операторов модуля,

n2 - число различных операндов.

b) Объема

V = N * log2 (n1 + n2).

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

V(G) = E*N – 2,

где E – количество дуг, а

N – количество вершин в управляющем графе программной системы.

Для более точной оценки необходимо учитывать и сложность самих вершин (т.е. модулей).

 

Характеристики иерархической сложности
структуры программной системы

 

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

Основными характеристиками структуры являются:

a) Количество вершин (модулей);

b) Количество связей между вершинами;

c) Высота – количество уровней управления;

d) Ширина – максимальное количество модулей, размещенных на отдельных уровнях управления.


Например, у программной системы, структура которой приведена на рис. 11, высота равна 4, а ширина – 6.

 

Рис. 11. Пример иерархической структуры ПС

 

Локальными характеристиками модулей системы являются:

a) Коэффициент объединения по входу, Fan_in(i) – количество модулей, которые прямо управляют i–тым;

b) Коэффициент разветвления по выходу, Fan_out(i) - количество модулей, которыми прямо управляет i–тый модуль.

В примере Fan_in(n) = 4, Fan_out(m) = 3.

 


Наилучшей иерархической структурой программной системы считается дерево (см. Рис.12).

Рис. 12. Оптимальная структура программной системы

 

Количество ребер дерева, имеющего n вершин, равно

et = n -1,

в то же время у полного графа с таким же количеством вершин их

ec = n*(n-1)/2.

Степень отличия реальной структуры программной системы с n вершинами и e ребрами от дерева характеризуется невязкой, которая определяется по формуле:

Nev = (e – et)/ (ec – et) = 2(e – n +1)/ ((n-1)(n-2).

Ее значение лежит в диапазоне от 0 до 1. При Nev = 0 структура ПС является деревом, при Nev = 1 – полным графом.

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


Общая сложность структуры программной системы может быть определена по формуле (см. Рис. 11):

где length(i) – оценка размера i-го модуля (LOC или FP).

 

1.1.2.Прототипирование и макетирование

 

Прототипирование программного обеспечения (от англ. prototyping) — один из этапов разработки программного обеспечения.

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

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

Эффективный прототип должен обладать следующими свойствами:

1) Этап создания прототипа должен быть коротким.

2) Прототипы являются одноразовыми. Они предназначены для того, чтобы донести идею до заказчика. После того как это сделано, прототип может быть отброшен.

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

Процесс создания прототипа состоит из четырех шагов:

1. Определение начальных требований.

2. Разработка первого варианта, который содержит только пользовательский интерфейс системы.

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

4. Переработка прототипа с учетом полученных замечаний и предложений.

Прототипирование имеет множество различных вариантов реализации, основными из которых являются:

a) Быстрое;

b) Эволюционное прототипирование.

При быстром прототипировании (англ. rapid prototyping или throwaway prototyping) предполагается, что создается макет, который на каком-то этапе будет оставлен («выброшен») и не станет частью готовой системы.

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

Быстрое прототипирование не обязательно выполняется в рамках той же платформы и тех же технологий, что и разрабатываемая система. Например, для прототипа графического интерфейса пользователя (GUI) могут использоваться стандартные HTML-страницы, или прототип может подготавливаться с помощью программы, специально предназначенной для создания макетов (например: Axure RP, Microsoft Expression Blend и др.). Важно время, а не точность.

Эволюционное прототипирование (англ. evolutionary prototyping) ставит своей целью последовательное создание макетов системы, которые будут все ближе к реальному продукту.

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

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

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

Преимущества применения прототипирования:

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

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

Недостатки:

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

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

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

Является спорным, применимо ли прототипирование, в той или иной форме, ко всем типам проектов. Системам, основная работа которых состоит в вычислениях, например, системам с интерфейсом командной строки, прототипирование почти не дает преимуществ. Хорошие результаты дает прототипирование при проектировании интерфейсов человек-компьютер.

 

Макетирование

Макетирование – это процесс создания модели программного продукта.

Его часто считают синонимом прототипирования. Модель может быть реализована в виде одной из следующих форм:

1) Бумажный макет или макет на основе компьютера (изображает или рисует человеко-машинный диалог);

2) Работающий макет (выполняет часть требуемых функций ПС);

3) Существующая программа (характеристики которой затем улучшаются).


Макетирование основывается на многократном повторении итераций, в которых участвуют заказчик и разработчик (см. Рис. 13).

Рис. 13 Макетирование

 

Последовательность действий при макетировании приведена на рис. 14. Оно начинается со сбора и уточнения требований к создаваемому ПО. Разработчик и заказчик встречаются и определяют все цели, устанавливают, какие требования известны, а какие нужно доопределить.


Рис. 14. Последовательность этапов макетирования

 

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

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

Достоинства и недостатки макетирования совпадают с теми же показателями у прототипирования.

 

1.1.3. Использование наиболее простых и понятных
алгоритмов решения задач

 

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

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

Большая сложность методов, реализуемых в программе, - один из показателей сложности алгоритма в целом.

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

1. В начале метода положить сложность, равной 1.

2. Для каждого из следующих слов (или их эквивалентов):

if, for, while, do, &&, ||

добавлять по 1.

3. Для каждого варианта оператора switch добавлять по 1.

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

Если оператор if, while или do while содержит сложные условия, то часто бывает трудно понять, что они проверяют. В такой ситуации условие можно разбить на несколько более простых и понятных.

Например, вместо одного оператора со сложным условием:

If ((elementIndex < 0) || max_elements< elementIndex) ||

(elementIndex == lastelementIndex)){

………

}

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

boolean finished = (elementIndex < 0) || max_elements< elementIndex);

boolean repeatedEntry = (elementIndex == lastelementIndex);

if (finished || repeatedEntry) {

……………..

}

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

Сложность метода зависит также от количества параметров, с которыми он работает (исходных данных и результатов). Если метод использует более 7 параметров, то он сложен и требует разбиения.

Если метод универсальный и реализует много функций, то это приводит к следующим проблемам.

1) его очень сложно читать, даже при наличии большого числа подробных комментариев;

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

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

 

1.1.4. Читабельность программного кода

 

Читабельность — свойство текстового материала, характеризующее лёгкость восприятия его человеком.

На читабельность программного кода влияют:

· стили отступов;

· комментарии;

· декомпозиция;

· соглашения об именовании данных.

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

Стиль отступов — правила форматирования исходного кода, в соответствии с которыми программные блоки проставляются в удобочитаемой манере.

Используемый стиль отступов обычно особо оговаривается в стандарте оформления кода. Он применяется всеми программистами группы.

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

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

int min=Integer.Max_Value;

int nummin= -1;

for(i=0;i<mas1.length;i++){

If (mas1[i] %4==0){

If (mas1[ i] <min){

min= mas1[i];

nummin=i;

} } }

В них важную роль играют также операторные скобки и их положение, а также пустые строки в тексте. Существует несколько подходов к расстановке отступов и скобок. Например, в литературе приводятся следующие стили расстановки скобок.

Стиль 1 («K&R»)

Назван в честь Кернигана и Ритчи потому, что все примеры из их книги «Язык программирования Си» отформатированы именно так. Основной отступ, показанный ниже, состоит из 8 пробелов (или одной табуляции) на уровень. Чаще всего используется 4 пробела.

if (Условие) {

Тело блока

}

Стиль 2

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

Первое выражение внутри программных скобок располагается на новой строке с отступом по выбору программиста на 1 символ табуляции; 2, 4, 8 или любое другое количество пробелов (конкретный выбор количества пробелов должен оставаться неизменным на протяжении всего текста программы)

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

Закрывающая программная скобка располагается с отступом, равным отступу соответствующей ей открывающей программной скобке (то есть точно под нею).

Например

if (Условие)

{

Тело блока

}

Стиль 3

Его называют стиль Уайтсмитс — популярен из-за примеров, шедших с Whitesmiths C — одним из первых компиляторов языка С. Основной отступ на уровень для скобок и блока — 8 пробелов.

Например

if (Условие)

{

Тело блока

}

Стиль 4

Его называют стиль GNU — используется во всех исходных текстах проекта GNU. Отступ составляет 2 символа на уровень, скобки расположены на собственном отступе.

Например

if (Условие)

{

Тело блока

}

 

Комментарии — пояснения к исходному тексту программы, находящиеся непосредственно внутри программного кода. Их синтаксис определяется языком программирования. С точки зрения компилятора или интерпретатора, комментарии — часть текста программы, не влияющая на её семантику. Они не оказывают никакого влияния на результат компиляции. Кроме исходных текстов программ, комментарии также применяются в языках разметки и описания.

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

a) говорящие названия переменных, функций, классов, методов и пр. (что будет рассмотрено позднее),

b) разбиение программы на простые для понимания части,

c) максимально понятные и прозрачные структуры классов и баз данных и т. д.

Некоторые программисты считают, что если для понимания программы требуются комментарии, то она плохо написана.

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

С точки зрения синтаксиса, существуют два вида комментариев

a) Однострочные и

b) Многострочные.

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

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

Специальным образом оформленные комментарии (т. н. документирующие) используются для автоматического создания документации, в первую очередь, к библиотекам функций или классов. Для этого используются генераторы документации, например, такие как javadoc для языка Java.

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

Пример документирующего комментария

/*** Имя или краткое описание объекта* * Развернутое описание* * @имя_дескриптора значение* @return тип_данных*/

В некоторых средах программирования (например, Eclipse, NetBeans, Visual Studio) документирующие комментарии используются в качестве интерактивной подсказки по интерфейсу классов и функций.

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

При декомпозиции руководствуются следующими правилами.

1. Каждое разбиение образует свой уровень иерархии, как показано на рис. 15.

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

Упрощенное графическое представление декомпозированной системы называется ее иерархической структурой. Эта структура может быть изображена в виде ветвящейся схемы, пример которой представлен на рис.15. Здесь на нулевом уровне располагается исходная система С1, на следующих уровнях — её подсистемы. С целью получения более полного представления о системе и ее
связях в структуру включают надсистему и составляющие ее части (другие системы нулевого уровня, например, вторая система С2 на рисунке).

Рис.15. Пример иерархической структуры программной системы

 

Для анализа иерархической структуры можно применять теорию графов. Это позволяет перей

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...