Программная инженерия.Часть II. Учебное пособие
.pdf
Тема 14. СТРУКТУРНОЕ ПРОГРАММИРОВАНИЕ
План
14.1.Основы структурного программирования.
14.2.Методика разработки программ.
14.3.Общие принципы разработки.
14.1. Основы структурного программирования
Структурное программирование использует определенные общие принципы и правила проектирования, разработки и оформления программ, которые облегчают процессы их создания и тестирования, а также способствуют повышению производительности труда программистов и улучшению читабельности результирующей программы. Структура программы и алгоритм решения задачи должны быть легкими для понимания, простыми для доказательства правильности и удобными для модификации. По своей сути структурный подход есть отказ от беспорядочного стиля в алгоритмизации и программировании (в частности, отказ от оператора goto и определение ограниченного числа стандартных приемов построения легко читаемых алгоритмов и программ с ясно выраженной структурой, что особенно важно при разработке больших программных систем).
Опыт применения методов структурного программирования при разработке ряда сложных операционных систем показывает, что правильность логической структуры системы в этом случае легко поддается доказательству, а сама система допускает достаточно полное тестирование. Уменьшение трудностей отладки и тестирования программ приводит к повышению производительности труда программистов, поскольку на тестирование программы тратится от трети до половины времени ее разработки. Производительность труда программиста обычно измеряется числом отлаженных операторов, которые он может написать за день. Приближенные оценки показывают, что применение методов структурного программирования позволяет увеличить это число в 5–6 раз. Также нужно сказать, что структурное программирование предполагает определенную организацию самого процесса программирования и определенную технологию проектирования программ, что также положительно влияет на производительность труда программистов.
Теоретическим фундаментом структурного программирования является теорема о структурировании, из которой следует, что алго-
ритм (программа) решения любой практически вычислимой задачи мо-
жет быть представлен с использованием трех элементарных базисных
II Часть | пособие Учебное
51
управляющих структур: структуры следования, или последовательности, структуры ветвления, структуры цикла, изображенных на рис. 14.1–14.3, где, соответственно, P – условие, S – оператор.
ПРОГРАММНАЯ ИНЖЕНЕРИЯ
Рис. 14.1. Структура |
Рис. 14.2. Структура |
Рис. 14.3. Структура цикла |
следования |
ветвления |
с предусловием |
Структура следования представляет собой естественный ход алгоритма – любую последовательность операторов, выполняющихся друг за другом (рис. 14.1). В языке программирования это соответствует последовательности операторов ввода, вывода или операторов присваивания.
Структура ветвления представляет фактор принятия решения, включает проверку некоторого логического условия P и – в зависимости от результатов этой проверки – выполнение либо оператора S, либо оператора S2. В языках программирования (например, Pascal) реализуется оператором: If P then S1 else S2 (рис. 14.2).
Структура цикла (цикла с предусловием) представляет фактор повторяемости вычислений, обеспечивает многократное повторение выполнения оператора (ов) S, пока выполняется (истинно) логическое условие P. В языках программирования (например, Pascal) реализуется оператором: While P do S (рис. 14.3).
Базисный набор управляющих структур является функционально полным, т. е. с его помощью можно написать любой сколь угодно сложный алгоритм. Однако в целях создания более компактных и наглядных алгоритмов и программ используются дополнительные управляющие структуры: структура сокращенного ветвления, структура варианта или многоальтернативного выбора, структура цикла с параметром, структура цикла с постусловием. В разных языках программирования реализация базовых управляющих структур может быть различной, например, в языке Pascal реализованы все предлагаемые структуры.
Любая программа может быть построена посредством композиции
базисных структур: либо путем их последовательного соединения – об-
52
разования последовательных конструкций, либо путем их вложения друг в друга – образования вложенных конструкций.
Каждая из структур может рассматриваться как один функциональный блок с одним входом и одним выходом. Блоки S, S1, S2, входящие
всостав базисных управляющих структур, сами могут быть одной из них, поэтому возможны вложенные конструкции. Однако, какова бы ни была степень и глубина «вложенности», важно, что любая конструкция
вконечном итоге имеет один вход и один выход. Следовательно, любую сложную структуру можно рассматривать как «черный ящик» с одним входом и одним выходом. Таким образом, можно ввести преобразование любой структуры в функциональный блок. Тогда всякий алгоритм, составленный из стандартных структур, поддается последовательному преобразованию к единственному функциональному блоку, и эта последовательность преобразований может быть использована как средство понимания алгоритма и доказательства его правильности. Обратная последовательность преобразований может быть использована в процессе проектирования алгоритма с постепенным раскрытием единственного функционального блока в сложную структуру основных элементов.
Для структурирования и понимания больших по объему программ используются также дополнительные структурные средства, которые поддерживают модульный принцип разработки ПС: это подпрограммы и модули. Использования аппарата подпрограмм (процедур и функций) – это возможность выделять в самостоятельные программные единицы со своими входными и выходными данными отдельные (часто повторяющиеся) участки кода для последующего многократного вызова их из различных точек программы и других подпрограмм. Модуль представляет собой автономно компилируемую библиотеку описаний типов, данных, процедур и функций, что позволяет группировать описания данных и подпрограмм по их функциям и назначению согласно одному из основных принципов структурного программирования – разбиения больших задач на подзадачи.
14.2. Методика разработки программ
Распространены две методики (стратегии) разработки программ, относящиеся к структурному программированию: программирование «сверху вниз» и программирование «снизу вверх».
Программирование «сверху вниз», или нисходящее проектирование программ – это методика разработки программ, при которой разработка начинается с определения целей решения проблемы, после
чего идет последовательная детализация, заканчивающаяся детальной
программой. Сначала выделяется несколько самых глобальных задач,
II Часть | пособие Учебное
53
ПРОГРАММНАЯ ИНЖЕНЕРИЯ
решение которых может быть представлено в общей структуре функционально независимыми блоками. Разработку логической структуры каждого такого блока и ее модификацию можно осуществлять независимо от остальных блоков. На этом первом этапе проекта раскрываются наиболее важные и существенные связи, определяется функциональное назначение каждого блока, его входные и выходные данные. На последующих этапах проектирования уточняется (детализируется) логическая структура отдельных функциональных блоков общей схемы, что также может осуществляться в несколько этапов детализации, вплоть до простейших инструкций. На каждом этапе проекта выполняются многократные проверки и исправления.
Подобный подход является достаточно рациональным, позволяет намного ускорить процесс разработки сложных программных проектов и в значительной мере избежать ошибочных решений. Кроме того, появляется возможность некоторые подпрограммы (модули) не реализовывать сразу, а временно отложить их разработку, пока не будут закончены другие части. Например, если имеется необходимость вычисления сложной математической функции, то выделяется отдельная подпрограмма такого вычисления, реализуется временно одним оператором, который просто присваивает нужное значение. Когда все приложение будет написано и отлажено, можно приступить к реализации этой сложной функции.
Программирование «снизу вверх», или восходящее проектирование программ – это методика разработки программ, начинающаяся с разработки подпрограмм (процедур, функций), в то время когда проработка общей схемы не закончилась. Такая методика является менее предпочтительной по сравнению с нисходящим проектированием, так как часто приводит к нежелательным результатам: переписыванию кода и увеличению времени разработки. Ее применение может быть целесообразным, если в новом проекте используются известные частные решения.
14.3. Общие принципы разработки
Использование технологии структурного программирования при разработке серьезных программных комплексов основано на следующих принципах:
–программирование должно осуществляться «сверху вниз»;
–весь проект должен быть разбит на подпрограммы с одним входом
иодним выходом;
–любая подпрограмма должна допускать только три основные структуры: последовательное выполнение операторов, ветвление и цикл;
–недопустим оператор goto безусловной передачи управления в любую точку программы;
54
– документация должна создаваться одновременно с программированием, частично в виде комментариев к программе.
Врезультате повышается надежность программ (благодаря хорошему структурированию при проектировании, программа легко поддается тестированию и отладке), повышается эффективность программ (структурирование программы позволяет легко находить и корректировать ошибки, а отдельные подпрограммы можно переделывать (модифицировать) независимо от других), уменьшается время и стоимость программной разработки, улучшается читабельность программ.
Вывод
Вданной лекции рассматриваются методики и принципы структурного программирования для разработки программного обеспечения. Применение структурного программирования при разработке ПО предполагает определенную организацию самого процесса программирования и определенную технологию проектирования программ, что положительно влияет на производительность труда программистов.
Вопросы для самопроверки
1.Каковы основные преимущества структурного программирования?
2.Перечислите основные конструкции структурного программирования. В чем их особенность?
3.Расскажите о методике разработки программ с использованием структурного программирования.
Литература
1.Программная инженерия: учебник / В. А. Антипов и др.; под ред.
Б.Г. Трусова. М.: Академия, 2014. 282 с.
2.Соммервилл И. Инженерия программного обеспечения. 6-е изд. / пер. с англ. М.: Изд. дом «Вильямс», 2002. 624 с.
3.Гецци К., Джазаейри М., Мандриоли Д. Основы инженерии программного обеспечения. 2-е изд./ пер. с англ. СПб.: БХВ-Петербург, 2005. 832 с.
II Часть | пособие Учебное
55
ПРОГРАММНАЯ ИНЖЕНЕРИЯ
Тема 15. ОБЪЕКТНО ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ
План
15.1.Основные понятия.
15.2.Концепции объектно ориентированного программирования.
15.1. Основные понятия
Объектно ориентированное (объектное) программирование (ООП) –
парадигма программирования, в которой основными концепциями являются понятия объектов и классов.
Под парадигмой программирования понимается система идей и понятий, определяющих стиль написания компьютерных программ, а также образ мышления программиста.
В настоящее время количество языков программирования, используемых для создания различных приложений и реализующих объектно ориентированную парадигму, достаточно большое. В области системного программирования общепринятым языком являлся язык C, в котором применяется процедурный стиль программирования. В настоящее время при взаимодействии системного и прикладного уровней операционных систем большое значение имеют языки объектно ориентированного программирования, например, одной из наиболее распространенных библиотек мультиплатформенного программирования является объектно ориентированная библиотека Qt, написанная на языке C++.
Основные понятия
Абстракция данных – подход к обработкеданных по принципу черного ящика. Данные обрабатываются функцией высокого уровня с помощью вызова функций более низкогоуровня. Это позволяет работать с объектами, не вдаваясь в особенности их реализации.
Пример задания абстрактной функции (без ее реализации в данном классе) приведен в листинге 15.1 (синтаксис зависит от языкапрограммирования). Функция уже известна, но ее конкретная реализация будет выполнена на более низком уровне – в классах-потомках.
Листинг 15.1. Пример объявления абстрактного метода
Int Calculate ();
Класс – это тип, описывающий структуру объектов – экземпляров. Под классом подразумевается некая сущность, которая определяет общее поведение объектов этого класса (через методы), а также позволяет
хранить состояние объекта (используя поля класса). Класс можно срав-
нить со схемой, согласно которой создаются объекты этого класса. Обыч-
56
но классы разрабатывают таким образом, чтобы их объекты соответствовали объектам предметной области.
Пример определения класса приведен в листинге 15.2 (синтаксис зависит от языка программирования).
Листинг 15.2. Пример объявления класса class Client
{
}
Члены класса. Класс определяется в виде списка своих членов. К членам класса относятся его поля (свойства) и функции (методы).
Для каждого члена класса можно установить соответствующую область доступа (access control level). Область доступа члена класса определяет участки кода, из которых к этому члену будет возможно обращение.
В большинстве объектно ориентированных языков программирования поддерживаются следующие области доступа:
– private (закрытый, внутренний член класса) – обращения допускаются только из методов того класса, в котором этот член определен; на-
следники класса уже не смогут получить доступ к этому члену;
– protected (защищенный, внутренний член иерархии классов) – обращения допускаются из методов того класса, в котором этот член определен, или из любых его классов-наследников;
– public (открытый член класса) – обращения допускаются из любого класса.
Пример задания членов класса приведен в листинге 15.3 (синтаксис зависит от языка программирования).
Листинг 15.3. Пример задания членов класса classClient
{
private string firstName; private string lastName; privateDateTime birthday;
public Client(string par FirstName, string par LastName, Date Time parBirthday)
{
firstName = parFirstName; lastName = parLastName; birthday = parBirthday;
}
Public int Calculate Age (DateTime parDate)
{
return (par Date – birthday). Year;
}
}
II Часть | пособие Учебное
57
ПРОГРАММНАЯ ИНЖЕНЕРИЯ
Интерфейс класса – это набор публичных полей и методов класса, к которым можно обращаться из других классов, частей программы.
Для примера, в листинге 15.4 в интерфейс класса будут входить конструктор класса: Client (string parFirstName, string parLastName, Date Time parBirthday) и метод вычисления возраста: public int Calculate Age (Date Time parDate).
В некоторых языках программирования появились интерфейсы, объявляемые как типы данных, например, в C# можно объявить интерфейс класса, который будет содержать объявления методов обязательных для реализации в классах, наследующих данный интерфейс.
Прототип – это объект-образец, по образу и подобию которого создаются другие объекты. Если в класс, описанный в предыдущем примере, добавить метод Clone, который будет возвращать экземпляр объекта, инициированный текущими значениями полей, то можно сказать, что класс является прототипом (листинг 15.5).
Листинг 15.5. Пример создания класса-прототипа class Client
{
…
public Client Clone()
{
return new Client(this. FIRSTNAME, this. LASTNAME this. Birthday);
}
}
Абстрактный класс – класс, содержащий хотя бы один абстрактный метод. Абстрактный метод не реализуется для класса, в котором описан, однако должен быть реализован для его неабстрактных потомков.
В некоторых языках объектно ориентированного программирования создавать экземпляры абстрактных классов запрещено, в других это допускается, но обращение к абстрактному методу объекта этого класса в процессе выполнения программы приведет к ошибке. Во многих языках допустимо объявить любой класс абстрактным, даже если в нем нет абстрактных методов, именно для запрещения создания экземпляров.
Абстрактный класс можно рассматривать в качестве интерфейса к семейству классов, порожденному им, но, в отличие от классического интерфейса, абстрактный класс может иметь определенные методы, а также свойства.
Абстрактные методы часто являются и виртуальными (переопределяемыми в потомках), поэтому понятия «абстрактный» и «виртуальный» иногда путают.
58
Пример объявления абстрактного класса представлен в листинге 15.6.
Листинг 15.6. Пример объявления абстрактного класса abstract class Client
{
private string firstName; private string lastName; private DateTime birthday;
public Client(string parFirstName, string par LastName, Date Time ParBirthday);
{
firstName= parFirstName; LastName= parLastName; birthday = parBirthday;
}
public abstract int Calculate Age(DateTime parDate);
}
Объект, наряду с понятием «класс», является основополагающим понятием объектно ориентированного подхода. Под объектом подразумевается некоторая сущность, обладающая состоянием и поведением. Объекты могут принадлежат одному или нескольким классам, которые определяют поведение объекта. Время с момента создания объекта до его уничтожения называется временем жизни объекта.
Инстанцирование – создание экземпляра класса, в отличие от слова «создание», применяется не к объекту, а к классу: говорят «создать экземпляр класса» или «инстанцировать класс».
Экземпляр класса – это конкретный описанный объект (существующий в памяти). Класс описывает свойства и методы, которые будут доступны объекту, относящемуся к этому классу. Экземпляры используют для представления конкретных сущностей реального мира. Создание экземпляра класса может осуществляться операцией new (листинг15.7).
Листинг 15.7. Пример объявления экземпляра класса
Client client = new Client(“Иван”, “Иванов”, DateTime.Parse (“10.04.1983”));
15.2. Концепции объектно ориентированного программирования
В центре ООП находится понятие объекта. Объект – это сущность, которой можно посылать сообщения (вызывать методы) и которая может на них реагировать, используя свои данные. Данные объекта скрыты от остальной программы. Сокрытие данных (объявление для них области
II Часть | пособие Учебное
59
ПРОГРАММНАЯ ИНЖЕНЕРИЯ
видимости «protected» или «private») называется инкапсуляцией. Однако наличие инкапсуляции еще не означает объектной ориентированности языка, для этого требуется наличие наследования. Но в полной мере преимущества ООП проявляются только в том случае, когда в языке программирования реализован полиморфизм – возможность объектов с одинаковой спецификацией иметь различную реализацию.
Кратко суть концепции объектно ориентированного программирования можно выразить следующими тезисами. Система состоит из объектов. Объекты некоторым образом взаимодействуют между собой. Каждый объект характеризуется своим состоянием и поведением. Состояние объекта задается значением полей данных. Поведение объекта задается методами.
Наследование – один из трех важнейших механизмов объектно ориентированного программирования (наряду с инкапсуляцией и полиморфизмом), позволяющий описать новый класс на основе уже существующего (родительского), при этом свойства и функциональность родительского класса наследуются новым классом. Другими словами, класс-наследник реализует спецификацию уже существующего (базового) класса. Это позволяет обращаться с объектами класса-наследника точно так же, как с объектами базового класса.
Класс, от которого произошло наследование, называется базовым, или родительским. Классы, которые произошли от базового, называются
потомками, наследниками, или производными классами (листинг 15.8).
Листинг 15.8. Простейший пример наследования
Class Class1
{
}
Class Class2 : Class1
{
}
Инкапсуляция – свойство языка программирования, позволяющее объединить данные и код в объект и скрыть реализацию объекта от пользователя. При этом пользователю предоставляется только спецификация (интерфейс) объекта. Пользователь может взаимодействовать с объектом только через этот интерфейс. Инкапсуляция может быть достигнута простейшими организационными мерами. Знание того, что «вот так делать нельзя» иногда является самым эффективным средством инкапсуляции (листинги 15.9 и 15.10).
Листинг 15.9. Класс реализации комплексного числа
// Класс комплексного числа
Class Complex
{
60
