Материал: Руководство по стилю программирования и конструированию по

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

ГЛАВА 19 Общие вопросы управления
451
Одной из единиц измерения «программной сложности» яв- ляется число воображаемых объектов, которые вам прихо- дится одновременно держать в уме, чтобы разобраться в программе. Это умственное жонглирование — один из са- мых сложных аспектов программирования и причина того,
что программирование требует большей сосредоточенности, чем другие виды деятельности. По этой причине программисты не любят, когда их «ненадолго прерывают» — такие перерывы равносильны просьбе жонглеру продолжать под- кидывать три мяча и подержать вашу сумку с продуктами.
Интуитивно понятно, что сложность программы во многом определя- ется количеством усилий, требуемых для ее понимания. Том Маккейб (Tom
McCabe) опубликовал важную статью, утверждающую, что сложность про- граммы определяется ее управляющей логикой (1976). Другие исследователи об- наружили дополнительные факторы, кроме предложенного Маккейбом циклома- тического показателя сложности (например, количество переменных, использу- емых в программе), но они согласны, что управляющая логика — одна из глав- ных составляющих сложности, если не самая главная.
Насколько важна сложность?
Исследователи в области вычислительной техники уже на протяжении двух десятилетий осознают важность пробле- мы сложности. Много лет назад Дейкстра предупреждал об опасности сложности: «Компетентный программист полно- стью осознает строго ограниченные размеры своего чере- па, поэтому подходит к задачам программирования со всей возможной скромно- стью» (Dijkstra, 1972). Из этого не следует, что вам нужно увеличить объем ваше- го черепа, чтобы иметь дело с невероятной сложностью. Это предполагает, что вы можете никогда не связываться с чрезмерной сложностью и всегда должны пред- принимать шаги для ее уменьшения.
Сложность управляющей логики имеет большое значение, потому что она коррелирует с низкой надежностью и частыми ошибками (McCabe, 1976,
Shen et al., 1985). Вильям Т. Уорд (William T. Ward) сообщал о значитель- ном выигрыше в надежности ПО, полученном в Hewlett-Packard в результате при- менения показателя сложности Маккейба (1989b). Этот показатель использовал- ся для идентификации проблемных участков в одной программе длиной 77 000
строк. Коэффициент ошибок после выпуска этой программы составил 0,31 ошибку на 1000 строк кода. Коэффициент ошибок в программе длиной 125 000 строк не превышал 0,02 ошибки на 1000 строк кода. Ворд отметил, что из-за своей мень- шей сложности обе программы имели значительно меньше дефектов, чем другие программы в Hewlett-Packard. Моя компания Construx Software в 2000 г. получила похожие результаты при использовании средств измерения сложности для поис- ка проблемных методов.
Делайте вещи настолько про- стыми, насколько это возмож- но, но не проще.
Альберт Эйнштейн
Перекрестная ссылка О сложно- сти см. подраздел «Главный Тех- нический Императив ПО: управ- ление сложностью» раздела 5.2.

452
ЧАСТЬ IV Операторы
Общие принципы уменьшения сложности
Вы можете бороться со сложностью двумя способами. Во-первых, вы можете улуч- шить свои способности к умственному жонглированию, выполняя специальные упражнения. Но программирование само по себе — уже хорошее упражнение, а люди, похоже, сталкиваются с трудностями при жонглировании б
ó
льшим коли- чеством, чем от пяти до девяти воображаемых сущностей (Miller, 1956). Так что потенциал улучшения невелик. Во-вторых, вы можете уменьшить сложность ва- ших программ и количество усилий, прилагаемых для их понимания.
Как измерить сложность
У вас, возможно, есть интуитивное ощущение того, что де- лает метод более или менее сложным. Исследователи пыта- ются формализовать свои чувства и приводят несколько способов измерения сложности. Возможно, самый важный способ предложил Том Маккейб, Сложность в нем измеря- ется с помощью подсчета количества «точек принятия решения» в методе
(табл. 19-2):
Табл. 19-2. Способы подсчета точек принятия решения в методе
1. Начните считать с 1 на некотором участке кода.
2. Добавляйте 1 для каждого из следующих ключевых слов или их эквивалентов:
if while repeat for and or.
3. Добавляйте 1 для каждого варианта в операторе
case.
Приведем пример:
if ( ( (status = Success) and done ) or
( not done and ( numLines >= maxLines ) ) ) then ...
В этом фрагменте вы начинаете считать с 1, получаете 2 для
if, 3 — для and, 4 —
для
or и 5 — для and. Таким образом, этот фрагмент содержит всего пять точек принятия решения.
Что делать с этим измерением сложности
Посчитав количество точек принятия решения, вы можете использовать это чис- ло для анализа сложности вашего метода:
0–5
Этот метод, возможно, в порядке.
6–10
Начинайте думать о способах упрощения метода.
10+
Вынесите часть кода в отдельный метод и вызывайте его.
Перенос части метода в другой метод не упрощает программу — он просто пере- мещает точки принятия решения. Но он уменьшает сложность, с которой вам при- ходится иметь дело в каждый момент времени. Поскольку одна из главных целей состоит в минимизации количества элементов, которыми приходится мысленно жонглировать, то уменьшение сложности отдельного метода дает свой результат.
Дополнительные сведения Опи- санный здесь подход основан на важной статье Тома Маккейба
«A Complexity Measure» (1976).

ГЛАВА 19 Общие вопросы управления
453
Максимум в 10 точек принятия решения не является абсолютным ограничением.
Используйте количество этих точек как сигнал, предупреждающий о том, что метод,
возможно, стоит перепроектировать. Не считайте его неколебимым правилом.
Оператор
case со многими вариантами может иметь более 10 элементов, но в зависимости от назначения
case может быть глупо разбивать его на части.
Другие виды сложности
Измерение сложности, предложенное Маккейбом, — не единственный значимый показатель, но он наиболее широко обсуждался в компьютерной литературе и особенно поле- зен при рассмотрении управляющей логики. Другие пока- затели включают количество используемых данных, число уровней вложенности в управляющих конструкциях, число строк кода, число строк между успешными обращениями к переменной («диапа- зон»), число строк, в которых используется переменная («время жизни») и объем ввода и вывода. Некоторые исследователи разработали составные показатели слож- ности, основанные на сочетании перечисленных простых вариантов.
Контрольный список: вопросы
по управляющим структурам
Используют ли выражения идентификаторы true и false,
а не 1 и 0?
Сравниваются ли логические значения с true и false неявно?
Сравниваются ли числовые значения со своими тестовыми значениями явно?
Выполнено ли упрощение выражений с помощью введения новых логиче- ских переменных, использования логических функций и таблиц решений?
Составлены ли логические выражения позитивно?
Сбалансированы ли пары скобок?
Используются ли скобки везде, где они необходимы для большей ясности?
Заключены ли логические выражения в скобки целиком?
Написаны ли условия в соответствии с расположением чисел на числовой прямой?
Используются ли в программах на Java выражения вида a.equals(b), а не
a == b там, где это необходимо?
Очевидно ли применение пустых операторов?
Выполнено ли упрощение глубоко вложенных выражений с помощью повтор- ной проверки части условия, преобразования в операторы if-then-else или
case, перемещения части кода в отдельные методы, преобразования с ис- пользованием более обеъктно-ориентированной модели или они были улуч- шены как-то иначе?
Если метод содержит более 10 точек принятия решения, есть ли хорошая причина, чтобы не перепроектировать его?
Дополнительные сведения Отлич- ное обсуждение показателей сложности см. в «Software En–
gineering Metrics and Models»
(Conte, Dunsmore and Shen, 1986).
http://cc2e.com/1985

454
ЧАСТЬ IV Операторы
Ключевые моменты

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

Глубокая вложенность затрудняет понимание метода. К счастью, вы сравнитель- но легко можете ее избежать.

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

Уменьшение сложности — ключ к написанию высококачественного кода.

1   ...   51   52   53   54   55   56   57   58   ...   104
ГЛАВА 19 Общие вопросы управления
455
Часть V
УСОВЕРШЕНСТВОВАНИЕ
КОДА

Глава 20. Качество ПО

Глава 21. Совместное конструирование

Глава 22. Тестирование, выполняемое разработчиками

Глава 23. Отладка

Глава 24. Рефакторинг

Глава 25. Стратегии оптимизации кода

Глава 26. Методики оптимизации кода

456
ЧАСТЬ V Усовершенствование кода
Г Л А В А 2 0
Качество ПО
Содержание

20.1. Характеристики качества ПО

20.2. Методики повышения качества ПО

20.3. Относительная эффективность методик контроля качества ПО

20.4. Когда выполнять контроль качества ПО?

20.5. Главный Закон Контроля Качества ПО
Связанные темы

Совместное конструирование: глава 21

Тестирование, выполняемое разработчиками: глава 22

Отладка: глава 23

Предварительные условия конструирования: главы 3 и 4

Актуальность предварительных условий для современных программных про- ектов: соответствующий подраздел раздела 3.1
В этой главе мы рассмотрим методики повышения качества ПО в контексте кон- струирования. Конечно, вся эта книга посвящена повышению качества ПО, но в данной главе вопросы качества и контроля качества обсуждаются более целена- правленно. Темой этой главы являются скорее общие вопросы, а не практичес- кие методики контроля качества. Практические советы, касающиеся совместной разработки, а также тестирования и отладки, можно найти в трех следующих главах.
20.1. Характеристики качества ПО
Качество ПО имеет внешние и внутренние характеристики. К внешним характе- ристикам относятся свойства, которые осознает пользователь программы. Они описаны ниже.

Корректность — отсутствие/наличие дефектов в спецификации, проекте и реализации системы.

Практичность — легкость изучения и использования системы.
http://cc2e.com/2036

ГЛАВА 20 Качество ПО
457

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

Надежность — способность системы выполнять необходимые функции в пред- определенных условиях; средний интервал между отказами.

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

Адаптируемость — возможность использования системы без ее изменения в тех областях или средах, на которые она не была ориентирована непосред- ственно.

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

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

Удобство сопровождения — легкость изменения программной системы с це- лью реализации дополнительных возможностей, повышения быстродействия,
исправления дефектов и т. д.

Гибкость — возможный масштаб изменения системы с целью использования ее в тех областях или средах, на которые она не была непосредственно ори- ентирована.

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

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

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

Тестируемость — возможная степень выполнения блочного и системного те- стирования программы и проверки ее соответствия требованиям.
Источник: https://files.student-it.ru/previewfile/206183