Справочник от Автор24
Поделись лекцией за скидку на Автор24

Технологии программирования

  • ⌛ 2016 год
  • 👀 526 просмотров
  • 📌 457 загрузок
  • 🏢️ Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования «Сибирский государственный индустриальный университет»
Выбери формат для чтения
Загружаем конспект в формате pdf
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Конспект лекции по дисциплине «Технологии программирования» pdf
Министерство образования и науки РФ Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования «Сибирский государственный индустриальный университет» Кафедра автоматизации и информационных систем КОНСПЕКТ ЛЕКЦИЙ ПО УЧЕБНОЙ ДИСЦИПЛИНЕ Технологии программирования Направление подготовки 09.03.02 Информационные системы и технологии Квалификация (степень) выпускника Бакалавр Форма обучения очная Новокузнецк 2016 Основы объектно-ориентированного программирования Введение Целью настоящих методических указаний является ознакомление студентов с основами объектно-ориентированного программирования (ООП) посредствам поэтапного создания программы с использованием принципов объектно-ориентированного программирования. В рамках выполнения задания необходимо, проанализировав проблемную область, создать классы, реализующие характеристики и действия объектов. В реализации классов создать поля и методы, необходимые для выполнения задачи. Для лучшего усвоения теоретического материала по основам ООП, покажем принципы использования ООП на примере программы, реализующей хаотичное движение окружностей, заданного радиуса и цвета, по полю прямоугольного размера, реализовав возможность добавления и удаления окружностей. 1 Анализ проблемной области Первым шагом при выполнении задания является анализ проблемной области, задачей которого является выделение объектов и их классов, а также определение их иерархии принадлежности1 и иерархии наследования2. Также необходимо выделить характеристики и действия классов, что, в итоге, будет выражено в виде полей и методов классов. При анализе проблемной области можно использовать как дедуктивный, так и индуктивный подход. При использовании дедуктивного подхода выделяется самый «большой» в плане иерархии принадлежности класс, описываются его характеристики, включая более «мелкие» пользовательские классы, на описание которых в дальнейшем переходит программист. При индуктивном подходе программист сначала описывает самый «маленький» класс, в структуру которого не входят другие классы, разрабатываемые программистом в рамках проблемной области, а в дальнейшем переходят к описанию более «крупных» классов, в структуру которых в качестве полей входят уже описанные более «маленькие» классы. При программировании чаще всего используется индуктивный подход в силу того, что в самой программе для её правильной компиляции необходимо описать те классы, экземпляры которых далее используются в качестве полей других классов. Мы выберем индуктивный подход. В рассматриваемой задаче можно выделить два класса: класс окружности и класс поля. Причём экземпляры класса окружности будут Под иерархией принадлежности будем понимать то, как классы взаимодействуют между собой в программе, то есть экземпляры каких классов будут принадлежать (выступать в качестве полей) другим классам. 1 Под иерархией наследования будем понимать то, как классы создаются на основе других классов, то есть напрямую используется один из основополагающих принципов объектно-ориентированного программирования – наследование. 2 входить в качестве полей в класс поля. Таким образом, иерархия принадлежности наших классов представлена на рисунке 1, а иерархия наследования – на рисунке 2. Класс поля Класс окружности Рисунок 1 – Иерархия принадлежности примера Родительский класс Дочерний класс поля Дочерний класс окружности Рисунок 2 – Иерархия наследования примера Конечно, не любую задачу можно решить с помощью объектноориентированного подхода, однако большинство задач, особенно крупные, легче решаются и реализуются именно с помощью ООП, но при этом необходимо помнить несколько моментов:  если программа изначально не проектировалась как объектная, то лучше не пытаться переделать проект с помощью объектной модели – проще и быстрее переписать с нуля;  реализация объектной модели всегда необходимо начинать с проектирования (то есть пока предполагаемая структура классов и взаимосвязи между ними не будут реализована на бумаге, то лучше даже не приступать к написанию кода – это будет бесполезно потерянное время);  для упрощения процедуры проектирования и улучшения степени наглядности структуры классов и взаимосвязей между ними желательно применять широко известные методы и языки моделирования, например, UML;  не надо проектировать и реализовывать сущностей сверх необходимого: если можно обойтись одним классом, не создавайте два (однако необходимо помнить, что крайности пагубны – не надо пытаться реализовать в одном классе разнообразную функциональность, лучше действовать по принципу: один класс – одно действие);    необходимо всегда давать классам, методам и свойствам осмысленные имена (сколь бы длинными они не были) и желательно не сокращать эти имена; нельзя допускать повторения одного и того же кода в двух местах (если один и тот же или очень похожий программный код повторяется – это повод вынести его в отдельный класс или отдельный метод); реализовывать каждый класс необходимо в расчёте на то, что им будет пользоваться абсолютно незнакомый программист, даже если этого не будет. 2 Описание классов Учитывая, что в программе сначала необходимо описать те классы, которые в иерархии принадлежности находятся на самом нижнем уровне, а в иерархии наследования на самом верхнем, первично будем описывать и реализовывать класс окружности. Перед тем, как начнём реализацию классов в интегрированной среде разработки программного обеспечения Borland Delphi, необходимо создать новое оконное приложение, которое будет выступать в качестве интерфейса между пользователем программы и самой программой. А реализацию всех классов необходимо поместить в отдельный модуль этого же проекта (для этого надо создать новый модуль командой меню File|New|Unit). Старайтесь разделять реализацию интерфейса программы от реализации классов, причём в одном модуле желательно реализовывать только родственные по назначению классы. Основные понятия Классом называется особая структура, ктр может иметь в своём составе поля, методы и св-ва. Такой тип также называется объектным типом: type TMyObject = class(TObject) MyField: Integer; end; function MyMethod: Integer; Поля объекта аналогичны полям записи. Это данные, уникальные для каждого созданного в программе экземпляра класса. (В примере поле MyField). Методы - это процедуры и ф-ии, описанные внутри класса и пердназначенные для операций над его полями. В состав класса входит указатели на специальную табл., где содержится вся инфо, необходимая для вызова методов. От обычных процедур и ф-ий методы отличаются тем, что им при вызове передаётся указатель на тот объект, ктр их вызывал. Поэтому обрабатываться будут поля именно того объекта, ктр вызвал метод. Понятие свойства можно определить как поле, дооступное для чтения и записи не напрямую, а через соответствующие методы. Классы могут быть описаны только в секции интерфейса модуля. Чтобы использовать новый тип в программе, необходимо объявить переменную этого типа. Переменная объектного типа назыв. экземпляром класса или объектом. var AMyObject: TMyObject; Создание и уничтожение объектов Объект создаются в результате вызова специального метода, ктр инициализирует объект - конструктора. Созданный экземпляр уничтожается другим методом - деструктором. Обычно они назыв. соответственно Create и Destroy. type TMyObject = class(TObject) MyField: Integer; Constructor Create; Destructor Destroy; end; function MyMrthod: Integer; var AMyObject: TMyObject; ... AMyObject := TMyObject.Create; {действия с созданным объектом} ... AMyObject.Destroy; Для уничтожения экземпляра класса рекомендуется использовать метод Free, ктр сначало проверяет указатель (не равен ли он nil) и только затем вызывает Destroy: AMyObject.Free; До передачи управления телу конструктора происходит собственно создание объекта - под него отводится память, обнуляются нгачение всех полей. Далее выполняется код конструктора, написанный программистом. Т.О., конструктор это ф-ия, вовращающая соданный и проинициалиированный объект. Все объекты, во время выполнения приложения, необходимо сначала создать, а потом уничтожить. При этом у некоторых объектов в явном виде не указаны методы Create и Destroy (Free), наприме, те объекты, ктр были взяты из Палитры компонентов Delphi. Инкапсуляция. Свойства Понятие инкапсуляции и свойства Классическое правило ООП утверждает, что для обеспечения надёжности нежелателен прямой доступ к полям объекта: чтение и обновление их содержимого должно производиться посредством вызова соответствующих методов. Это правило и называется инкапсуляцией. Пользователь объекта может быть полностью отгорожен от полей при помощи свойств. Инкапсуляция делает объекты похожими на маленькие программные модули, в которых скрыты внутренние данные и у которых имеется интерфейс использования в виде подпрограмм. Использования инкапсуляции значительно повышает ясность и надежность программ. Обычно свойство определяется тремя элементами: полем и двумя методами, которые осуществляют его чтение/запись: type TAnObject = class(TObject) AField: TSomeType; function GetAProperty: TSomeType; procedure SetAProperty(ANewValue: TSomeType); property AProperty: TSomeType read GetAProperty write SetAProperty; end; Ключевые слова read и write называются спецификаторами доступа. После слова read указывается поле или метод, к которому происходит обращение при чтении (получении) значения свойства, а после слова write – поле или метод, к которому происходит обращение при записи (установке) значения свойства. Если один из спецификаторов доступа опущен, то значение свойства можно либо только читать (задан спецификатор read), либо только записывать (задан спецификатор write). В данном примере доступ к значению поля AField осуществляется через вызовы методов GetAProperty (при чтении данных, хранящихся в поле) и SetAProperty (при обновлении данных, хранящихся в поле). Причем вызывать данные методы явно нет никакой необходимости, потому что они вызываются автоматически при обращении к свойству. Например, для записи нового значения в поле надо обратиться к свойству: AnObject.AProperty := AValue; Причем автоматически будет вызван метод SetAProperty, новое значение AValue будет передано через параметр ANewValue метода. Таким образом, задача программиста состоит в определении внутри метода SetAProperty возможности записи нового значения в поле AField. Аналогично, для чтения значения, хранящегося в поле AField, необходимо обратиться к свойству: AVariable := AnObject.AProperty; Причем автоматически будет вызван метод GetAProperty, результатом выполнения будет возвращаемое функцией значение. Таким образом, задача программиста заключается в определении внутри метода GetAProperty возможности чтения значения из поля AField. Из приведенных примеров видно, что для пользователя свойства выглядят в точности как обычное поле, но за всяким обращением к нему стоят нужные для программиста действия, например, по изменению свойства цвет нарисованного квадрата на другой, может происходить перерисовка квадрата с последним цветом: type TRectObject = class(TObject) Canvas: TCanvas; procedure Show; function GetColor: TColor; procedure SetColor(NewColor: TColor); property Color: TColor read GetColor write SetColor; end; ... procedure TRectObject.SetColor(NewColor: TColor); begin if Canvas.Pen.Color <> NewColor then begin Canvas.Brush.Color := NewColor; Show; end; end; ... function TRectObject.GetColor: TColor; begin Result := Canvas.Brush.Color; end; ... procedure TRectObject.Show; begin Canvas.Rectangle(Left, Top, Left + Width, Top + Height); end; Кроме обычных свойств в классах могут использоваться свойства-массивы (векторные свойства). Свойство-массив — это индексированное множество значений. В описании свойства-массива разрешено использовать только методы, но не поля. В этом состоит отличие свойства-массива от обычного свойства. Векторное свойство выглядит как массив: type TStrings = class(TObject) ... function GetString(Index: Integer): String; procedure SetString(Index: Integer; NewValue: String); property AStrings[Index: Integer]: String read GetString write SetString; end; ... var MyString: TStrings; begin MyString.AStrings[1]:='первый'; ... end; Также векторные свойства имеют два важных отличия от обычных массивов: их индексы не ограничиваются диапазоном и могут иметь любой тип данных, а не только Integer (например, можно создать свойство-массив, в котором индексами будут строки: AProp.Items['FirstName'] := 'Александр';); операции над свойством-массивом в целом запрещены (разрешены операции только с его элементами). Использование свойств дает программисту два преимущества: во-первых, свойства позволяют представить конечному пользователю некий интерфейс, полностью скрывающий реализацию объекта и обеспечивающий контроль за доступом к объекту; а, во-вторых, дает программисту возможность замещать методы в классах-потомках с целью обеспечения полиморфного поведения объектов. Однако использование свойств не всегда необходимо. Так, чаще всего, механизм свойств используется в случаях, когда необходимо сделать автоматически какие-либо действия при обращении к полю; когда необходимо оградить внутреннее содержание класса от пользователя, предоставив ему унифицированный интерфейс. Область видимости атрибутов класса Для обеспечения ограничения доступа к полям объекта недостаточно использовать свойства. Все атрибуты класса (не только поля, но и методы, и свойства) по умолчанию видимы и доступны практически из любой точки кода программы. Например, реализовав свойства, как это было указано выше, программист в любом модуле своей программы будет иметь доступ как к свойству, так и к полю, которое свойство «защищает». Программист может разграничить доступ к атрибутам своих объектов для других программистов (и себя самого) с помощью специальных ключевых слов: private, protected, public, published, automated. private Все, что объявлено в данной секции недоступно за пределами модуля. Секция private позволяет скрыть те поля и методы, которые относятся к так называемым особенностям реализации класса. Необходимо отметить, что те поля и методы, находящиеся в секции private, будут недоступны даже прямым потомкам класса, если они описаны в другом модуле. protected Поля, методы и свойства, объявленные в данной секции, видны за пределами модуля только потомкам данного класса; остальным частям программы они не видны. Так же как и private, директива protected позволяет скрыть особенности реализации класса, но в отличие от нее разрешает другим программистам порождать новые классы и обращаться к полям, методам и свойствам, которые составляют так называемый интерфейс разработчика. В эту секцию обычно помещаются виртуальные методы. public Поля, методы и свойства, объявленные в данной секции, не имеют никаких ограничений на использование, то есть всегда видны, даже за пределами модуля. Все, что помещается в секцию public, служит для манипуляций с объектами и составляет программный интерфейс класса. Отметим, что конструктор и деструктор класса должны быть описаны в секции public. published Устанавливает правила видимости те же, что и директива public. Особенность состоит в том, что для элементов, помещенных в секцию published, компилятор генерирует информацию о типах этих элементов. Эта информация доступна не только во время выполнения программы, но и во время разработки приложения, что позволяет превращать объекты в компоненты визуальной среды разработки. Секцию published разрешено использовать только тогда, когда для самого класса или его предка включена директива компилятора $TYPEINFO. automated Эта секция сохранена только для обеспечения обратной совместимости с Delphi 2.0. Данная секция используется только для объявления свойств и методов, которые будут добавлены к так называемого интерфейсу OLEобъектов автоматизации. Область видимости членов этой секции не ограничена. Перечисленные секции могут чередоваться в объявлении класса в произвольном порядке, однако в пределах секции сначала следует описание полей, а потом методов и свойств. Любая секция может быть пустой. Если в определении класса нет ключевых слов private, protected, public и published, то для обычных классов всем полям, методам и свойствам приписывается атрибут видимости public, а для тех классов, которые порождены от классов библиотеки VCL, — атрибут видимости published. Внутри модуля никакие ограничения на доступ к атрибутам классов, реализованных в этом же модуле, не действуют. Наследование Понятие наследования Еще одним основополагающим принципом объектно-ориентированного программирования наравне с инкапсуляцией является принцип наследования. Под принципом наследования понимают возможность создания новых объектов, которые обладают свойствами и поведением родительских объектов. Такой принцип позволяет создавать иерархии объектов, включающие наборы объектов, порожденных от одного общего предка и обладающих все большей специализацией и функциональностью по сравнению со своими предшественниками. Достоинством наследования является, в первую очередь, разделение общего кода многими объектами, потому что порожденный класс автоматически наследует поля, методы и свойства своего родителя и может добавлять новые. Любой класс может быть порожден от другого класса. Для этого при объявлении создаваемого класса указывается имя класса, на основе которого он создаётся: TChildClass = class(TParentClass) ... end; Теперь в экземпляре класса будут доступны все атрибуты класса TParentClass. Далее можно добавлять новые члены класса к вновь создаваемому классу. Создаваемый класс называется потомком или дочерним классом. Класс, на основе которого создается новый класс, называется предком или родительским классом. Принцип наследования может обеспечивать поэтапное создание сложных классов и разработку собственных библиотек классов. Характерным примером наследования является объектная модель, реализованная в Delphi. Так, все классы Delphi порождены от единственного родителя – класса TObject. Этот класс не имеет полей и свойств, но включает в себя методы самого общего назначения/ обеспечивающие весь жизненный цикл любых объектов – от создания до уничтожения. Все создаваемые программистом классы создаются на основе класса TObject, даже если это не указано явно. То есть записи TMyClass = class(TObject) и TMyClass = class абсолютно одинаковы по смыслу. Поскольку класс TObject является предком для всех классов, то кратко рассмотрим его методы, которые по принципу наследования есть во всех вновь создаваемых классах, как в стандартных, уже существующих, так и в пользовательских: type TObject = class constructor Create; procedure Free; class function InitInstance(Instance: Pointer): TObject; procedure CleanupInstance; function ClassType: TClass; class function ClassName: ShortString; class function ClassNameIs(const Name: string): Boolean; class function ClassParent: TClass; class function ClassInfo: Pointer; class function InstanceSize: Longint; class function InheritsFrom(AClass: TClass): Boolean; class function MethodAddress(const Name: ShortString): Pointer; class function MethodName(Address: Pointer): ShortString; function FieldAddress(const Name: ShortString): Pointer;               function GetInterface(const IID: TGUID; out Obj): Boolean; class function GetInterfaceEntry(const IID: TGUID): PInterfaceEntry; class function GetInterfaceTable: PInterfaceTable; function SafeCallException(ExceptObject: TObject; ExceptAddr: Pointer): HResult; virtual; procedure AfterConstruction; virtual; procedure BeforeDestruction; virtual; procedure Dispatch(var Message); virtual; procedure DefaultHandler(var Message); virtual; class function NewInstance: TObject; virtual; procedure FreeInstance; virtual; destructor Destroy; virtual; end; Краткое описание методов в классе TObject: Create – стандартный конструктор. Free – уничтожает объект: вызывает стандартный деструктор Destroy, если значение псевдопеременной Self не равно nil. InitInstance – при создании объекта инициализирует нулями выделенную память. На практике нет необходимости вызывать этот метод явно. CleanupInstance – освобождает память, занимаемую полями с типом string, Variant, динамический массив и интерфейс. На практике нет необходимости вызывать этот метод явно. ClassType – возвращает описатель класса (метакласс3). ClassName – возвращает имя класса. ClassNameIs – проверяет, является ли заданная строка именем класса. ClassParent – возвращает описатель базового класса. ClassInfo – возвращает указатель на соответствующую классу таблицу RTTI (Runtime Type Information – информация о типе времени исполнения). Таблица RTTI используется для проверки типов данных на этапе выполнения программы. InstanceSize – возвращает количество байт, необходимых для хранения в памяти одного объекта соответствующего класса. Заметим, что значение, возвращаемое этим методом и значение, возвращаемое функцией SizeOf при передаче ей в качестве аргумента объектной переменной – это разные значения. Функция SizeOf всегда возвращает значение 4, поскольку объектная переменная – это ни что иное, как ссылка на данные объекта в памяти. InheritsFrom – проверяет, является ли переданный в качестве параметра класс AClass базовым классом. MethodAddress – возвращает адрес метода, имя которого задается параметром Name. Данный метод должен быть описан в секции published. MethodName – возвращает имя метода по заданному адресу. Данный метод должен быть описан в секции published. FieldAddress – возвращает адрес поля, имя которого задается параметром Name. Данное поле должно быть описано в секции published. 3 Термин метакласс обозначает понятие класс класса, позволяющий рассматривать классы объектов как своего рода объекты, которыми можно манипулировать в программе. Понятие метаклассов и способы их использования рассмотрим в следующих работах.  GetInterface – возвращает ссылку на интерфейс через параметр Obj; идентификатор интерфейса задается параметром IID4.  GetInterfaceEntry – возвращает информацию об перданном в качестве параметра интерфейсе, который реализуется классом.  GetInterfaceTable – возвращает указатель на таблицу с информацией обо всех интерфейсах, реализуемых классом.  AfterConstruction – автоматически вызывается после создания объекта. На практике не используется, потому что для решения практически любой задачи достаточно конструктора.  BeforeDestruction – автоматически вызывается перед уничтожением объекта. На практике не используется, потому что для решения практически любой задачи достаточно деструктора.  Dispatch – служит для вызова методов-сообщений, объявленных с ключевым словом message5.  DefaultHandler – вызывается методом Dispatch в том случае, если метод, соответствующий переданному в качестве параметра сообщению Message, не был найден.  NewInstance – вызывается при создании объекта для выделения динамической памяти, чтобы разместить в ней данные объекта. Метод вызывается автоматически, поэтому нет необходимости вызывать его явно.  FreeInstance – вызывается при уничтожении объекта для освобождения занятой объектом динамической памяти. Метод вызывается автоматически, поэтому нет необходимости вызывать его явно.  Destroy – стандартный деструктор. В описании структуры класса TObject присутствует ранее не встречавшееся описание методов, когда перед словом procedure или function записывается зарезервированное слово class. Объявленные таким образом методы называются методами класса и тесно связано с понятием метакласса. Метод класса оперирует не экземпляром объекта, а непосредственно классом. Такого рода методы могут быть вызваны как обычные процедуры и функции без создания экземпляра класса, членом которого является данный метод, но они не должны использовать никакой информации экземпляра класса. Принцип наследования приводит к созданию ветвящегося дерева классов, постоянно разрастающегося при перемещении от класса TObject к его потомкам. Причем каждый потомок дополняет возможности своего родителя новыми и передает их своим потомкам6. В качестве примера на рисунке 1 показан фрагмент объектной модели Delphi. Понятие интерфейса класса, его реализацию и применение рассмотрим в следующих работах. Создание и использование пользовательских методов обработки сообщений рассмотрим в следующих работах. 6 Необходимо отметить, что дочерний класс не может удалить какой-либо атрибут родительского класса. 4 5 TObject TInterfaceObject TPersistent TStreamAdapter Exception EInOutError TCollection TComponent EOutOfMemory EAbort TString TControl TWinControl Рисунок 1 – Фрагмент дерева классов Delphi. В языке Object Pascal у каждого класса может быть сколь угодно много потомков, но только один предок. В других языках программирования (например, С++) имеются функции множественного наследования. Множественное наследование означает, что некоторый класс может быть наследником двух или более различных классов. Однако, если есть необходимость во множественном наследовании , то его можно реализовать средствами Object Pascal. Есть несколько способов: во-первых, можно включить экземпляр одного класса в качестве поля другого класса; во-вторых, можно породить классы-предки один от другого; в-третьих, можно использовать так называемые интерфейсы. Как отмечалось ранее, унаследованные от класса-предка поля и методы доступны в дочернем классе. Однако, если имеет место совпадение имен методов, реализованных в классе-предке и классе-потомке, то говорят, что такие методы перекрываются. При наследовании поля классов перекрываются полностью, то есть из классапотомка не доступны поля класса-предка, если они имеют одинаковые имена. Однако, в отличие от полей, внутри других методов перекрытый метод доступен при указании служебного слова inherited. Рассмотрим подробнее поведение методов при наследовании. Классификация методов. Перекрытие методов при наследовании В Object Pascal существует несколько видов методов: статические, виртуальные, динамические, перегружаемые и абстрактные. Рассмотрим каждый из них в отдельности, обратив особое внимание на поведение каждого вида методов при наследовании. Статические методы Статические методы работают подобно обычным процедурам и функциям. Этот тип методов принимается по умолчанию, то есть, если при объявлении метода не указано иное, то этот метод считается статическим. Адрес такого метода уже известен на стадии компиляции, и компилятор в тексте программы оформляет все вызовы данного метода как статические, то есть вместо названий методов указаны адреса расположения методов в памяти программы. Статические методы в своей работе основываются на механизме раннего связывания7. Статические методы работают быстрее за счет более быстрого вызова самого метода. При наследовании статические методы без ограничений перекрываются в классепотомке. Причем для перекрытия достаточно новый метод назвать таким же именем, что и старый (тип данных может быть другой). Виртуальные методы Виртуальные методы коренным образом отличаются от статических. В отличие от статических методов, во время компиляции адрес конкретного вызываемого виртуального метода неизвестен. Соответствие адреса и имени виртуального метода производится с помощью специализированной информационной структуры – таблицы виртуальных методов. Данную таблицу создает для каждого класса компилятор, и она обеспечивает определение адреса вызываемого метода в процессе выполнения программы. Данный механизм называется поздним связыванием8. По сравнению со статическими вызов виртуальных методов производится медленнее из-за механизма позднего связывания. Однако только с помощью механизма позднего связывания можно в полной мере реализовать полиморфизм классов. Таблица виртуальных методов содержит все виртуальные методы предка и виртуальные методы самого объекта, и потому виртуальные методы используют несколько бóльшую память, чем далее рассматриваемые динамические методы, но при этом их вызов происходит быстрее, чем вызов динамических методов. Вызов виртуального метода осуществляется следующим образом: 1. через объектную переменную выполняется обращение к занятому объектом блоку памяти; 2. из этого блока извлекается адрес таблицы виртуальных методов; 3. на основании порядкового номера виртуального метода извлекается адрес соответствующей подпрограммы; 4. вызывается код, находящийся по этому адресу. Весь этот механизм реализован на уровне языка Object Pascal, что избавляет программиста от лишней работы. Чтобы компилятор создал виртуальный метод, ему необходимо сообщить это с помощью директивы virtual, поместив её сразу после объявления метода при объявлении класса. TMyObject = class(TObject) ... procedure MyVirtualMethod; virtual; ... end; При наследовании виртуальные методы могут быть перекрыты в классе-потомке только одноименными методами, имеющими тот же тип (то есть список параметров, а для функций еще и тип возвращаемого значения). Причем в дочернем классе при объявлении метода вместо директивы virtual надо указать директиву override: T1stObject = class(TObject) ... procedure MyVirtualMethod(AValue: Real); virtual; ... Ранним связыванием называется процесс статического связывания методов с объектами во время компиляции. 7 Поздним связыванием называется процесс динамического связывания методов с объектами во время выполнения. 8 end; T2ndObject = class(T1stObject) ... procedure MyVirtualMethod(AValue: Real); override; ... end; Динамические методы Динамические методы в целом подобны виртуальным методам, но обслуживаются другой диспетчерской системой. Каждому динамическому методу компилятор назначает уникальный индекс и использует его вместе с адресом метода для построения таблицы динамических методов. Таблица динамических методов содержит только методы данного объекта. При вызове динамического метода происходит поиск в данной таблице; в случае неудачи просматриваются таблицы динамических методов всех классов-предков в порядке иерархии и, в конечном итоге, класс TObject, у которого имеется стандартный обработчик вызова динамических методов. В отличие от виртуальных методов, благодаря тому, что таблица динамических методов класса содержит только методы данного объекта, обеспечивается экономия используемой памяти, но вместе с тем замедляется вызов динамического метода, поскольку для поиска его адреса, скорее всего, будет просмотрена не одна таблица динамических методов в иерархии объектов. Динамические методы также как и виртуальные используются, чаще всего, для обеспечения полиморфизма. Чтобы компилятор создал динамический метод, ему необходимо сообщить это с помощью директивы dynamic, поместив её сразу после объявления метода при объявлении класса. TMyObject = class(TObject) ... procedure MyDynamicMethod; dynamic; ... end; При наследовании динамические методы могут быть перекрыты в классе-потомке только одноименными методами, имеющими тот же тип. Причем в дочернем классе при объявлении метода вместо директивы dynamic надо указать директиву override: T1stObject = class(TObject) ... function MyDynamicMethod(AValue: Real): Integer; virtual; ... end; T2ndObject = class(T1stObject) ... function MyDynamicMethod(AValue: Real): Integer; override; ... end; Как было указано выше, динамические и виртуальные методы практически не отличаются друг от друга. Однако, введение этих методов позволяет обеспечить программисту два способа оптимизации объектов: по скорости работы (использование виртуальных методов) или по объему памяти (использование динамических методов). Абстрактные методы Абстрактными методами называются методы, которые определены в классе, но не содержат никаких действий, никогда не вызываются и обязательно должны быть переопределены в потомках класса. Абстрактными могут быть только виртуальные и динамические методы. Чтобы компилятор создал абстрактный метод, ему необходимо сообщить это с помощью директивы abstract, поместив её сразу после директивы virtual или dynamic в объявлении метода при объявлении класса. type TMyObject = class(TObject) ... procedure NeverCallMe; virtual; abstract; ... end; При этом никакого кода для этого метода писать не нужно, а вызов этого метода приведет к исключительной ситуации EAbstractError. Абстрактные методы применяются при построении иерархии наследования классов, когда работа виртуального/динамического метода в базовом классе еще не известна и наполняется содержанием только в наследниках. Таким образом, абстрактные методы позволяют абстрагироваться от частностей, которые реализуются в классахпотомках. Абстрактный метод подразумевает логическое действие, а не конкретный способ его реализации. Если в каком-либо классе объявлен абстрактный метод, то этот класс считается абстрактным, и в процессе выполнения приложения не может быть создано объектов этого абстрактного класса. При наследовании абстрактные методы должны быть переопределены в классепотомке. Так как они являются виртуальными или динамическими, то при перекрытии ведут себя соответственно. Причем в дочернем классе при объявлении метода других директив, кроме override, указывать не надо: T1stObject = class(TObject) ... function DoSomeThing(AValue: Real): Boolean; virtual; abstract; ... end; T2ndObject = class(T1stObject) ... function DoSomeThing(AValue: Real): Boolean; override; ... end; Однако необходимо помнить, что в методах классов-потомков ссылаться на абстрактный метод класса-предка с помощью inherited запрещено, поскольку он не имеет реализации. Проиллюстрируем применение абстрактного метода на следующем примере. Пусть двум программистам необходимо написать программу, которая решает систему линейных алгебраических уравнений (СЛАУ) каким-либо способом. Чтобы сократить время на создание программы, один программист будет писать часть программы, связанную с вводом/выводом коэффициентов (А, В) и неизвестных (Х) СЛАУ, а второй – программирует метод расчета СЛАУ. Первый программист, не зная, каким именно способом будет рассчитываться СЛАУ, создает класс СЛАУ, который только содержит поля с коэффициентами (А, В) и неизвестными (Х) СЛАУ, а также методы ввода/вывода этих данных, причем перед выводом Х, их рассчитывает (напомню – метод расчета неизвестен). Таким образом, описание класса принимает вид: type TSLAU = class(TObject) Count: Byte; A: array [1..10, 1..10] of Real; B, X: array [1..10] of Real; procedure Input(StringGrid: TStringGrid); procedure Output(StringGrid: TStringGrid); procedure Calculate; end; Здесь методы Input и Output производят операции ввода начальных данных СЛАУ и вывод результатов расчета в указанные StringGrid‘ы, соответственно. Реализация метода Input для примера неважна, а метод Output реализован следующим образом: procedure TSLAU.Output(StringGrid: TStringGrid); var i: Byte; begin Calculate; for i := 1 to Count do begin StringGrid.Cells[0, i] := FloatToStr(X[i]); end; end; в котором сначала рассчитываются неизвестные, а затем выводятся на форму. Однако, чтобы запустить программу, необходимо написать реализацию метода Calculate, которую создает другой программист. Поэтому надо объявить метод Calculate как абстрактный. Таким образом, объявление класса TSLAU станет: type TSLAU = class(TObject) Count: Byte; A: array [1..10, 1..10] of Real; B, X: array [1..10] of Real; procedure Input(StringGrid: TStringGrid); procedure Output(StringGrid: TStringGrid); procedure Calculate; virtual; abstract; end; Второй программист, в свою очередь, создает свой класс – потомок класса TSLAU, в котором реализует только метод расчета СЛАУ, переопределяя метод Calculate, который по принципу наследования вместе с остальными полями и методами доступно в классе-предке: type TGauss = class(TSLAU) procedure Calculate; override; end; ... procedure TGauss.Calculate; begin {реализация конкретного метода расчета СЛАУ} end; В дальнейшем можно использовать только класс TGauss, а экземпляры класса TSLAU в программе создавать нельзя. Поэтому для использования метода расчета СЛАУ надо в программе создать, например, обработчик события OnClick объекта Button1: procedure TForm1.Button1Click(Sender: TObject); var SLAU: TGauss; begin SLAU := TGauss.Create; SLAU.Input(StringGrid1); SLAU.Output(StringGrid2); SLAU.Free; end; в котором объявляется экземпляр класса TGauss, затем производится ввод исходных данных и вывод результатов (в методе вывода результатов производится расчет неизвестных параметров СЛАУ). В дальнейшем можно создавать другие дочерние классы класса TSLAU, в которых будут реализовываться другие методы расчета СЛАУ. Перегружаемые методы В Object Pascal имеется возможность в рамках одного класса объявлять несколько одноименных методов, которые называются перегружаемыми методами. Чтобы одноименные методы можно было отличить друг от друга, каждый из них должен иметь уникальный набор параметров. В ходе выполнения программы при обращении к одному из одноименных методов программа проверяет тип и количество фактических параметров обращения и выбирает нужный метод. Если метода для указанного типа аргументов нет, или метод находится вне области видимости, то возникает ошибка компиляции. Характерным примером перегружаемых методов может служить метод Rectangle класса TCanvas, который позволяет рисовать прямоугольник на холсте в заданных координатах. Так, программист может задать координаты прямоугольника двумя способами: или координаты верхней левой и нижней правой точки отдельно, или сразу координаты прямоугольника с помощью типа TRect: или Canvas.Rectangle(Left, Top, Left + Width, Top + Height); или var ARect: TRect; begin ARect := Rect(Left, Top, Left + Width, Top + Height); Canvas.Rectangle(ARect); end; В обоих случаях будет нарисован прямоугольник. Перегружаемые методы должны быть объявлены с указанием директивы overload (использовать эту директиву при описании первого перегружаемого метода необязательно): type TMyObject = class(TObject) i: Real; str: String; procedure SetData(AValue: Real); overload; procedure SetData(AValue: String); overload; end; ... procedure TMyObject.SetData(AValue: Real); begin i := AValue; end; procedure TMyObject.SetData(AValue: String); begin str := AValue; end; procedure TForm1.Button2Click(Sender: TObject); var MyObject: TMyObject; begin MyObject := TMyObject.Create; MyObject.SetData(1.23); MyObject.SetData('Hi!'); ... end; Таким образом, в программе можно одновременно использовать оба метода. Также можно создать класс-потомок, в котором добавить еще один метод с другими параметрами (в этом случае методы не перекрываются, а добавляются к наследованным от классапредка). Для примера создадим на основе ранее созданного класса новый класс: T2ndObj = class(TMyObject) j: Integer; procedure SetData(AValue: Integer); overload; end; ... procedure T2ndObj.SetData(AValue: Integer); begin j := AValue; end; Тогда в программе можно использовать все три метода: procedure TForm1.Button2Click(Sender: TObject); var MyObject: T2ndObj; begin MyObject := T2ndObj.Create; MyObject.SetData(1.23); MyObject.SetData('Hi!'); MyObject.SetData(1); ... end; В предыдущем примере используются статические методы, однако в качестве перегружаемых методов можно использовать и виртуальные или динамические методы. Для перегрузки виртуального или динамического метода в классе-потомке нужно использовать директиву reintroduce: type TMyObject = class(TObject) i: Real; str: String; procedure SetData(AValue: Real); overload; virtual; procedure SetData(AValue: String); overload; virtual; end; T2ndObj = class(TMyObject) j: Integer; procedure SetData(AValue: Integer); reintroduce; overload; end; ... procedure TMyObject.SetData(AValue: Real); begin i := AValue; end; procedure TMyObject.SetData(AValue: String); begin str := AValue; end; procedure T2ndObj.SetData(AValue: Integer); begin j := AValue; end; procedure TForm1.Button2Click(Sender: TObject); var MyObject: T2ndObj; begin MyObject := T2ndObj.Create; MyObject.SetData(1.23); MyObject.SetData('Hi!'); MyObject.SetData(1); ... end; Кстати, обратите внимание на следование директив в объявлении методов – другой порядок следования директив не допускается. Также необходимо указать, что на перегрузку методов накладывается ограничение – нельзя перегружать методы, находящиеся в области видимости published. Проиллюстрируем использование перегружаемых методов на примере рассмотренного ранее примера решения СЛАУ. Так, в классе TSLAU был объявлен метод Output, в котором помимо расчетов производится вывод найденных значений параметров СЛАУ в передаваемый в качестве параметра метода StringGrid. Однако одномерный массив можно выводить и в компонент типа TMemo или в файл, поэтому можно предусмотреть данную возможность и дополнить объявление класса и реализацию методов следующим образом: type TSLAU = class(TObject) Count: Byte; A: array [1..10, 1..10] of Real; B, X: array [1..10] of Real; procedure Input(StringGrid: TStringGrid); procedure Output(StringGrid: TStringGrid); overload; procedure Output(Memo: TMemo); overload; procedure Output(FileName: String); overload; procedure Calculate; virtual; abstract; end; ... procedure TSLAU.Output(Memo: TMemo); var i: Byte; begin Calculate; for i := 1 to Count do begin Memo.Lines.Add(FloatToStr(X[i])); end; end; procedure TSLAU.Output(FileName: String); var F: Text; i: Byte; begin Calculate; AssignFile(F, FileName); Rewrite(F); for i := 1 to Count do begin WriteLn(F, X[i]); end; CloseFile(F); end; Далее можно использовать любой из трех методов вывода результатов, например: procedure TForm1.Button1Click(Sender: TObject); var SLAU: TGauss; begin SLAU := TGauss.Create; SLAU.Input(StringGrid1); SLAU.Output('Answer.txt'); SLAU.Free; end; Методы-сообщения В классе могут быть определены также и методы обработки сообщений, которые создаются для реакции на те или иные сообщения Windows. Эти методы никогда не вызываются из программы. Более подробно обработка сообщений будет рассматриваться в следующий практических работах. Полиморфизм Понятие полиморфизма Слово «полиморфизм» означает много форм. Понятие полиморфизма довольно расплывчато и не однозначно. В разных источниках можно найти разные определения принципа полиморфизма. Так, можно выделить два наиболее общих определения принципа полиморфизма, акцентирующих внимание на двух свойствах одного и того же явления – полиморфизма. Полиморфизм и перегрузка методов Полиморфизм – это свойство классов решать схожие по смыслу проблемы разными способами. В рамках Delphi поведенческие свойства класса определяются набором входящих в него методов. Изменяя алгоритм того или иного метода в потомках класса, программист может придавать этим потомках отсутствующие у родителя специфические свойства. Для изменения метода необходимо перекрыть его в потомке, объявив в потомке одноименный метод и реализовав в нем нужные действия. В результате в объектеродителе и объекте-потомке будут действовать два одноименных метода, имеющих разную алгоритмическую основу и, следовательно, придающие объектам разные поведенческие свойства. Основой использования принципа полиморфизма в данном понимании являются перегружаемые методы, которые позволяют наращивать функциональность объекта с помощью одноименных методов, но имеющих различную алгоритмическую основу. Причем использование перегружаемых методов возможно не только в потомках, но и в самом родительском классе. Использование перегружаемых методов подробно обсуждалось в предыдущей практической работе. Таким образом, здесь приведем лишь конкретный пример использования такого рода методов на задаче, используемой в качестве общего примера во всех практических работах. Добавим функциональности разрабатываемому приложению, реализовав возможность удаления фигуры не только по ее порядковому номеру, но и по щелчку «мыши» по выбранной фигуре. Для этого добавим в объявление класса TField метод, который будет реализовывать указанную функциональность, но иметь тоже имя, что и существующий метод удаления фигуры: TField = class(TObject) ... procedure RemoveCircle(Tag: Integer); overload; virtual; procedure RemoveCircle(X, Y: Integer); overload; virtual; procedure RemoveRect(Tag: Integer); overload; virtual; procedure RemoveRect(X, Y: Integer); overload; virtual; ... end; Приведем реализацию метода RemoveCircle(X, Y: Integer): procedure TField.RemoveCircle(X, Y: Integer); var i: Byte; begin for i := 1 to 5 do begin if Circle[i] <> nil then begin if sqrt(sqr(X - Left - Circle[i].Placement.X) + sqr(Y - Top - Circle[i].Placement.Y)) <= Circle[i].Radius then begin Circle[i].Free; Circle[i] := nil; Show; break; end; end; end; end; В данной реализации производится перебор всех окружностей, проверка их существования, а далее производится проверка указанных координат на принадлежность кругу. Если проверка успешна, то данная окружность удаляется, производится прорисовка поля и прерывается работа цикла. Проверка существования окружностей (if Circle[i] <> nil) необходима, так как на текущий момент неизвестно сколько окружностей из пяти возможных создано. Если такой проверки не делать, то может произойти ошибка во время выполнения программы. Реализацию метода RemoveRect(X, Y: Integer) оставим на самостоятельную работу. Вызов созданных методов можно производить с помощью обработчика события щелчка «мыши» по форме: procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin Field.RemoveCircle(X, Y); Field.RemoveRect(X, Y); end; Здесь сначала производится удаление окружностей, если это необходимо, а потом удаление прямоугольника, если необходимо. Если щелчок произошел на пустом поле, то ни одна фигура не будет удалена. Полиморфизм и соответствие типов Полиморфизм означает, что в производных классах можно изменять работу уже существующих в базовом классе методов. При этом весь программный код, управляющий объектами родительского класса, пригоден для управления объектами дочернего класса без всякой модификации. Например, можно породить новый класс кнопок с рельефной надписью, переопределив метод рисования кнопки. Новую кнопку можно "подсунуть" вместо стандартной в какую-нибудь подпрограмму, вызывающую рисование кнопки. При этом подпрограмма "думает", что работает со стандартной кнопкой, но на самом деле кнопка принадлежит производному классу кнопок и отображается в новом стиле. Таким образом, с помощью полиморфизма можно присваивать действию одно имя, которое затем совместно используется вниз и вверх по иерархии объектов, причем каждый объект иерархии выполняет это действие способом, именно ему подходящим. В данном случае полиморфизм использует правила контроля соответствия типов языка Object Pascal, смысл которых заключается в том, что объекту как указателю на экземпляр объектного типа может быть присвоен адрес любого экземпляра любого из дочерних типов. Понятие полиморфизма лучше рассмотреть на примере. Пусть есть модуль Unit2, в котором описан родительский класс, используемый для хранения и отображения данных в строковом формате. Причем на текущий момент неизвестно данные в каком формате (строковые, целые или вещественные) будет хранить этот класс (это можно реализовать в классах-потомках). Также в модуле описана процедура, не принадлежащая какому-либо классу, задача которой выводить на экран значение, хранящееся в классе: unit Unit2; interface uses Dialogs; type TField = class function GetData: string; virtual; abstract; end; procedure ShowData(AField: TField); ... implementation ... procedure ShowData(AField: TField); begin ShowMessage('Значение: ' + AField.GetData); end; В данном примере класс TField объявлен как абстрактный, поэтому нельзя создавать экземпляры этого класса. Его метод GetData объявлен также как абстрактный, потому что неизвестно какие данные будут хранить потомки класса. Обратите внимание на параметр AField процедуры ShowData, он объявлен как экземпляр класса TField (но не создан, а только объявлен, поэтому ошибки здесь нет). В другом модуле, например Unit1, программист описывает дочерние классы для хранения строк, целых и вещественных данных. В этом же модуле описана форма, на которой расположены три кнопки, по нажатию на которые создаются экземпляры соответствующих дочерних классов, и выводится значение, хранящееся в них. Листинг данного модуля следующий: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Unit2; type TStringField = class(TField) str: String; constructor Create; function GetData: string; override; end; TIntegerField = class(TField) Int: Integer; constructor Create; function GetData: string; override; end; TRealFeald = class(TField) Flt: Real; constructor Create; function GetData: string; override; end; TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); end; var Form1: TForm1; implementation constructor TStringField.Create; var i: Integer; begin {Создаем строку из 15 случайных заглавных букв русского алфавита} for i := 1 to 15 do begin str := str + chr(Random(32) + 192); end; end; function TStringField.GetData: string; begin Result := str; end; procedure TForm1.Button1Click(Sender: TObject); var StrField: TStringField; begin StrField := TStringField.Create; ShowData(StrField); StrField.Free; end; constructor TIntegerField.Create; begin Int := Random(100); end; function TIntegerField.GetData: string; begin Result := IntToStr(Int); end; procedure TForm1.Button2Click(Sender: TObject); var IntField: TIntegerField; begin IntField := TIntegerField.Create; ShowData(IntField); IntField.Free; end; constructor TRealFeald.Create; begin Flt := Random; end; function TRealFeald.GetData: string; begin Result := FloatToStr(Flt); end; procedure TForm1.Button3Click(Sender: TObject); var FltField: TRealFeald; begin FltField := TRealFeald.Create; ShowData(FltField); FltField.Free; end; begin Randomize; end. Результат работы данной программы представлен на рисунке 1. Рисунок 1 – Результат работы приложения, использующего полиморфизм. В представленном примере (листинг модуля Unit1) классы содержат разнотипные поля данных Str, Int и Flt и только могут сообщить о значении этих полей текстовой строкой (метод GetData). Внешняя по отношению к ним процедура ShowData (описанная в модуле Unit2) получает объект в виде параметра и показывает эту строку. В процедуре ShowData параметр описан как ТField, а согласно правилам контроля соответствия типов это значит, что в неё можно передавать объекты классов и StringField, и TIntegerField, и TRealField, и любого другого потомка класса TField. При этом вызывается тот метод GetData, который соответствует классу фактически переданного типа. Этот принцип и называется полиморфизмом. Используя полиморфизм можно облегчить разработку программного обеспечения на основе объектно-ориентированного программирования. Так, чтобы смоделировать средствами ООП некоторую совокупность явлений или процессов, необходимо выделить их самые общие черты и те из них, которые не изменяют своего содержания, должны быть реализованы в виде статических методов, а те, которые изменяются при переходе от общего к частному, лучше реализовать с помощью виртуальных или динамических методов. Основные методы (реализующие общие, характерные для всех объединяемых наследованием методов) нужно описать в родительском классе и затем перекрывать эти методы в потомках. Возвращаясь к рассмотренному примеру, программисту, создающему процедуру вроде рассмотренной ShowData, важно лишь то, что объект, переданный в эту процедуру, является потомком класса ТField, и он имеет метод GetData, с помощью которого можно получить значение поля, хранящегося в классе-потомке. Такой подход при программировании можно использовать и при формировании динамических библиотек эту библиотеку можно будет раз и навсегда использовать без изменений, хотя будут появляться и новые, неизвестные в момент её создания классы - потомки TField. Обработка сообщений Сообщения Windows Все действия, происходящие в операционной системе Windows, производятся только по какому-нибудь событию. Каждое событие, происходящее в системе, операционной системой отображаются в виде сообщений, которые либо обрабатываются самой операционной системой, либо перенаправляется для обработки той или иной пользовательской прикладной программой. Таким образом, сообщение представляет собой извещение о некотором имевшем место событии, посылаемое операционной системой Windows в адрес приложения. Любые действия пользователя вынуждают Windows отправить приложению сообщение, извещающее о том, что произошло в системе. Потребности программиста на Delphi практически полностью удовлетворяются возможностями работы с событиями, предоставляемыми библиотекой визуальных компонентов (VCL). События и сообщения Windows находятся в пропорции 80:20 (то есть доступные в компонентах Delphi события соответствуют 20% наиболее важных сообщений, которые покрывают 80% типовых потребностей программиста). Однако при создании серьезных нестандартных приложений потребуется непосредственно обрабатывать сообщения Windows, после чего генерировать события, соответствующие этим сообщениям. Также при разработке приложений может возникнуть ситуация, когда приложению потребуется послать сообщение либо самому себе, либо другому приложению из числа созданных программистом. Это может потребоваться, например, для поддержки реального полиморфизма, поскольку не требует наличия каких-либо знаний о типе объекта – получателя сообщения; для широковещательного обращения к нескольким получателям. Структура сообщения Сообщение представляет собой определенную запись, передаваемую приложению системой Windows. Эта запись содержит сведения о том, что именно произошло, а также дополнительную информацию, зависящую от типа события. Тип данных, используемый Delphi для представления сообщений Windows, называется TMsg., и представляет собой запись, объявленную в модуле Windows следующим образом: type TMsg = packed record hwnd: HWND; message: UINT; WParam; WPARAM; LParam: LPARAM; time: DWORD; pt: TPoint; end; Назначение полей представленного типа записи сообщения следующее: hwnd Дескриптор окна, которому предназначено сообщение. Окно может быть практически любым экранным объектом, так как Win32 поддерживает дескрипторы окон для большинства визуальных объектов, например, кнопок. message Константа (целое число), представляющая тип сообщения. Она может быть определена системой Windows и описана в модуле Windows, либо определена программистом как определяемое пользователем сообщение. Wparam Поле может содержать некоторой целое число и использоваться для передачи любой дополнительной информации через сообщение. Lparam Поле аналогичное Wparam. time Время создания приложения. pt Положение указателя мыши в момент создания сообщения. Типы сообщений Сообщения Windows В Win32 API каждому сообщению Windows ставится в соответствие определенное значение, которое заносится в поле message записи TMsg. В Delphi все эти константы определяются в модуле Messages, а большая их часть дополнительно описана в интерактивной справочной системе. Имя каждой константы, представляющей тип сообщения Windows, начинается с символов WM (т.е. Windows Message). В таблице 1 представлены некоторые наиболее распространенные сообщения Windows и их числовые коды. Таблица 1 – Некоторые типы сообщений Windows Идентификатор Значение Описание сообщения WM_CREATE $0001 Создание окна WM_DESTROY $0002 Уничтожение окна WM_SIZE $0005 Изменение размера окна WM_ACTIVATE $0006 Активация или деактивация окна WM_SETFOCUS $0007 Окном получен фокус WM_PAINT $000F Перерисовка клиентской области окна WM_CLOSE $0010 Данное окно должно быть закрыто WM_QUIT $0012 Программа должна быть завершена WM_KEYDOWN $0100 На клавиатуре была нажата клавиша WM_KEYUP $0101 На клавиатуре была отпущена клавиша WM_CHAR $0102 Для некоторой клавиши были посланы сообщения WM_KEYDOWN или WM_KEYUP WM_TIMER WM_HSCROLL WM_VSCROLL WM_MENUSELECT WM_MOUSEMOVE WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK $0113 $0114 $0115 $011F $0200 $0201 $0202 $0203 Произошло событие таймера Горизонтальный скроллинг Вертикальный скроллинг Выбор пункта меню Указатель мыши переместился Пользователь нажал левую кнопку мыши Пользователь отпустил левую кнопку мыши Пользователь сделал двойной щелчок левой кнопкой мыши Система событий Delphi представляет собой интерфейс для взаимодействия с сообщениями Windows, по крайней мере – с некоторой их частью. Многие события компонентов библиотеки VCL непосредственно связаны с сообщениями Windows типа WM_ХХХХ. В таблице 2 приведены основные события компонентов библиотеки VCL и связанные с ними сообщения Windows. Таблица 2 – Соответствие событий компонентов библиотеки VCL сообщениям Windows Событие VCL Сообщение Windows OnActivate WM_ACTIVATE OnClick WM_XBUTTONDOWN OnDblClick WM_XBUTTONDBLCLICK OnCreate WM_CREATE OnKeyDown WM_KEYDOWN OnKeyUp WM_KEYUP OnKeyPress OnPaint OnResize WM_CHAR WM_PAINT WM_SIZE OnTimer WM_TIMER Не стоит писать обработчик сообщения Windows, если для него уже имеется предопределенное событие того же назначения. Поскольку обработка событий не является обязательной, это существенно упрощает их использование по сравнению с прямой обработкой сообщений Windows. Нестандартные сообщения. Извещающие сообщения Извещающие сообщения (notification messages) представляют собой сообщения, посылаемые родительскому окну в том случае, когда в одном из его дочерних элементов управления происходит нечто, заслуживающее внимания родителя. Эти сообщения генерируются только стандартными элементами управления Windows (кнопки, списки, раскрывающиеся списки, поля редактирования) и общими элементами управления Windows (дерево объектов, список объектов и т.п.). К событиям, вызывающим генерацию извещающих сообщений, можно отнести, например, щелчок на управляющем элементе, выбор текста в поле редактирования или перемещение ползунка полосы прокрутки. Обработка извещающих сообщений осуществляется с помощью соответствующих процедур обработки, принадлежащих той форме, в которой содержится некоторый управляющий элемент. В таблице 3 приведен список извещающих сообщений для стандартных управляющих элементов Win32. Таблица 3 - Извещающие сообщения стандартных элементов управления Windows Извещение Описание Извещения от кнопок BN_CLICKED Щелчок на кнопке BN_PAINT Кнопка должна быть перерисована BN_HILITE Выделение кнопки BN_UNHILITE Выделение кнопки должно быть отменено BN_DISABLE Кнопка переведена в неактивное состояние BN_DOUBLECLICKED Двойной щелчок на кнопке BN_SETFOCUS Установка фокуса кнопке BN_KILLFOCUS Кнопка потеряла фокус Извещения раскрывающихся списков CBN_ERRSPACE Элементу управления списка не хватает памяти CBN_SELCHANGE Выбран новый элемент списка CBN_DBLCLK Двойной щелчок на строке CBN_SETFOCUS Список получил фокус ввода CBN_KILLFOCUS Список потерял фокус ввода CBN_EDITCHANGE Текст в поле ввода изменен CBN_EDITUPDATE Требуется вывести измененный текст CBN_DROPDOWN Раскрытие списка CBN_CLOSEUP Раскрытый список был закрыт CBN_SELENDOK Выбор пользователя подтвержден CBN_SELENDCANCEL Пользователь отказался от сделанного им выбора Извещения полей ввода EN_SETFOCUS Поле ввода получило фокус ввода EN_KILLFOCUS EN_CHANGE EN_UPDATE EN_ERRSPACE EN_MAXTEXT EN_HSCROLL EN_VSCROLL LBN ERRSPACE LBN_SELCHANGE LBN_DBLCLK LBN_SELCANCEL LBN_SETFOCUS LBN_KILLFOCUS Поле ввода потеряло фокус ввода Требуется обновление после внесения изменений Требуется отображение введенного текста Элементу управления не хватает памяти Введенный текст был обрезан Горизонтальная прокрутка Вертикальная прокрутка Извещения списков Элементу управления не хватает памяти Изменение выделения Двойной щелчок по списку Отмена выделения Список получил фокус ввода Список потерял фокус ввода Нестандартные сообщения. Внутренние сообщения компонентов VCL Компоненты библиотеки VCL используют обширный набор собственных внутренних и извещающих сообщений. Имена этих сообщений всегда начинаются с префикса СМ_ (сообщения компонентов – component messages) или CN_ (извещения компонентов – component notification). Они используются компонентами библиотеки VCL для управления состоянием их внутренних свойств – например, для передачи фокуса, установки цвета, изменения состояния видимости, выдачи требования перерисовки окна, поддержки операций перетаскивания и т.д. Полный список этих сообщений можно найти в разделе интерактивной справочной системы Delphi, посвященном созданию пользовательских компонентов. Пользовательские сообщения Пользовательские сообщения определяются самим программистом, они ничем не отличаются от рассмотренных ранее сообщений. Основное их отличие заключается в том, что сообщение должно иметь идентификатор в диапазоне от WM_USER+100 до $7FFFF (этот диапазон Windows резервирует для сообщений пользователя). Имя же у сообщения может быть любым, лишь бы удовлетворяло общим требованиям языка программирования к именам идентификаторов. Конечно, программист должен не только предусматривать посылку своего сообщения либо своей программе, либо другому приложению, но и еще необходимо предусмотреть и обработку принимаемых пользовательских сообщений. То есть не достаточно послать пользовательское сообщение, необходимо его правильно обработать. Чаще всего пользовательские сообщения применяются для решения нескольких задач. Во-первых, использование сообщений представляет собой механизм поддержки реального полиморфизма, поскольку не требует наличия каких-либо знаний о типе объекта – получателя сообщения. Таким образом, технология работы с сообщениями имеет ту же мощь, что и механизм виртуальных методов, но обладает существенно большей гибкостью. Во-вторых, сообщения допускают необязательную обработку – если объект-получатель не обработает поступившее сообщение, то ничего страшного не произойдет. И, в-третьих, сообщения позволяют широковещательное обращение к нескольким получателям и организацию параллельного прослушивания, что весьма трудно реализовать с помощью механизма вызова процедур. Перед использованием пользовательских сообщений их необходимо объявить в разделе объявления констант. Например, в следующем примере объявлено пользовательское сообщение SX_MYMESSAGE: const SX_MYMESSAGE = WM_USER + 102; // Идентификатор пользовательского // сообщения Принципы работы системы сообщений Необходимо различать работу системы сообщений Windows и систему обработки сообщений в Delphi. Принципы работы системы сообщений Windows    1. 2. 3. 4. 5. 1). Система сообщений Windows состоит из трех компонентов. Очередь сообщений (Message queue). Windows содержит отдельную очередь сообщений для каждого приложения. Приложение Windows должно получать сообщения из этой очереди и передавать их соответствующему окну. Цикл сообщений (Message loop). Группа циклически выполняемых операторов приложения, осуществляющая выборку каждого сообщения из очереди и передачу его соответствующему окну для обработки, и так – до окончания работы приложения. Процедура окна (Window procedure). Каждое окно приложения имеет собственную процедуру, которая получает все передаваемые этому окну сообщения. В ответ на полученное сообщение процедура должна выполнить определенные действия. Эта процедура является процедурой обратного вызова9 и обычно возвращает Windows некоторое значение по завершении обработки сообщения. В общем, работа системы сообщений Windows состоит из пяти этапов: В системе происходит некоторое событие. Windows превращает это событие в соответствующее сообщение и помещает его в очередь сообщений пользовательского приложения. Приложение получает сообщение из очереди и помещает его в запись типа TMsg. Приложение передает сообщение процедуре соответствующего окна приложения. Процедура окна выполняет некоторые действия в ответ на сообщение. Перечисленные этапы можно представить схематично в виде блок-схемы (рисунок Функция обратного вызова (callback function) представляет собой функцию в пользовательской программе, вызываемую Windows или некоторым другим внешним модулем. 9 Действие Возникновение события Создание сообщения ОС Windows создает сообщение Очередь сообщений ОС Windows помещает сообщение в очередь сообщений Цикл сообщений Цикл сообщений выбирает сообщение из очереди сообщений Процедура окна Сообщение передается в процедуру окна соответствующего окна приложения Рисунок 1 – Схема обработки сообщений Windows Этапы 3 и 4 выполняются циклом сообщений, который фактически представляет собой "сердце" программы Windows. Именно этот цикл обеспечивает взаимодействие программы с внешним миром, получая сообщения из очереди и передавая их соответствующему окну приложения. Если очередь сообщения данного приложения будет исчерпана, система Windows обратится к другим приложениям и позволит им выполнить обработку сообщений в их очередях. Система обработки сообщений в Delphi Подпрограммы библиотеки VCL выполняют существенную часть обработки сообщений Windows в приложении, например, цикл сообщений встроен в модуль Forms библиотеки VCL, поэтому прикладному программисту не придется беспокоиться о выборке сообщений из очереди и передаче их соответствующим процедурам окон. Кроме того, Delphi помещает информацию из записи типа TMsg в собственную запись типа TMessage (описана в модуле Message.pas), описание которой следующее: type TMessage = packed record Msg: Cardinal; case Integer of 0: ( WParam: Longint; LParam: Longint; Result: Longint); 1: ( WParamLo: Word; WParamHi: Word; LParamLo: Word; LParamHi: Word; ResultLo: Word; ResultHi: Word); end; В запись TMessage помещается только та часть информации, которая необходимая для дальнейшей обработки, поэтому она содержит меньше информации, чем исходная запись TMsg. Также обратите внимание, что в записи TMessage содержится поле Result. Таким образом, с помощью данного поля можно организовать возврат результатов обработки сообщений. В дополнение к общей записи типа TMessage в модуле Messages определен набор специализированных записей практически для всех типов сообщений Windows. Назначение этих записей состоит в предоставлении программисту всей содержащейся в исходном сообщении Windows информации, но без необходимости дешифровки значений полей wParam и lParam. Ниже приведены описания трех специализированных записей, используемых для большинства типов сообщений Windows о событиях мыши, прорисовки окон и изменении размеров. type TWMMouse = packed record // события мыши Msg: Cardinal; // тип сообщения Keys: Longint; // код клавиши мыши case Integer of 0: ( XPos: Smallint; // координата щелчка по Х YPos: Smallint); // координата щелчка по Y 1: ( Pos: TSmallPoint; // координата щелчка Result: Longint); // результат end; TWMPaint = packed record Msg: Cardinal; DC: HDC; Unused: Longint; Result: Longint; end; TWMSize = packed record Msg: Cardinal; SizeType: Longint; Width: Word; Height: Word; Result: Longint; end; // // // // // события прорисовки окон тип сообщения дескриптор канвы не используется результат // // // // // // // // события изменения размеров окна тип сообщения тип изменения: SIZE_MAXIMIZED, SIZE_MINIMIZED, SIZE_RESTORED, SIZE_MAXHIDE, SIZE_MAXSHOW новая ширина окна новая высота окна результат Названия записей типов сообщений подчиняется соглашению о присвоении имен, которое требует, чтобы имя записи было равно имени сообщения с префиксом Т и без символа подчеркивания. Например, запись для сообщения WM_SETFONT должна иметь имя TWMSetFont. Следует отметить, что запись типа TMessage создается для всех типов сообщений Windows и в любых ситуациях. Однако работать с этими записями менее удобно, чем со специализированными записями сообщений. Обработка сообщений Обработка сообщений означает, что приложение тем или иным образом реагирует на получаемые от операционной системы сообщения. В стандартном приложении Windows обработка сообщений сосредоточивается в процедурах окна. Однако Delphi, частично обрабатывая сообщения, упрощает работу программиста, позволяя реализовывать обработку сообщений различными способами. Обработка сообщений с помощью методов-сообщений Delphi, частично обрабатывая сообщения, упрощает работу программиста, позволяя вместо одной процедуры для обработки всех типов сообщений создавать независимые процедуры для обработки сообщений различных типов. Любая процедура обработки сообщений в этом случае должна отвечать трем требованиям:  Процедура должна быть методом объекта.  Процедуре должен передаваться один передаваемый по ссылке (с помощью описания var) параметр с типом TMessage или с типом любого другого специализированного сообщения.  Описание процедуры должно включать ключевое слово message, за которым должна следовать константа, задающая тип обрабатываемого сообщения. В качестве примера напишем простую процедуру обработки сообщения WM_MOVE (данное сообщение происходит в случае перемещение окна), которая при перемещении окна будет выводить новые координаты формы в заголовке. Сначала производится объявление процедуры10, обрабатывающей сообщение WM_MOVE, в объявлении класса: type TForm1 = class(TForm) ... procedure WMMove(var Msg: TWMMove); message WM_MOVE; ... end; Далее в раздел implementation модуля добавим определение процедуры. procedure TForm1.WMMove(var Msg: TWMMove); begin Form1.Caption := 'Положение формы: X: ' + IntToStr(Msg.XPos) + '; Y: ' + IntToStr(Msg.YPos); inherited; end; Обратите внимание на использование в процедуре ключевого слова inherited, которое позволяет передать сообщение обработчику этого сообщения, принадлежащему классу-предку. Причем в отличие от вызова обычных унаследованных методов, в данном случае имя метода предка не указывается. Дело в том, что при обработке сообщений имя метода не имеет значения, так как Delphi отыскивает процедуру обработки сообщения по значению, задаваемому в интерфейсе класса ключевым словом message. Если в пользовательском обработчике сообщения не вызвать метод предка, то компоненты VCL, выполняющие большую часть обработки своими встроенными средствами, не смогут произвести обработку данного сообщения. Событие OnMessage класса TApplication Другой метод обработки сообщений заключается в использовании события OnMessage класса TApplication. При назначении процедуры этому событию она будет вызываться всякий раз при получении сообщения из очереди и подготовке его к обработке. Обработчик события OnMessage всегда вызывается до того, как система Windows получит Соглашение по присвоению имен требует присваивать обработчику сообщений то же имя, что и имя обрабатываемого им сообщения, но без символа подчеркивания и с указанием первых знаков имени прописными буквами. 10 возможность обработать сообщение. Подпрограмма обработки сообщений, ассоциированная с обработчиком события TApplication.OnMessage, должна иметь тип TMessageEvent и объявляться со следующим списком параметров: procedure SomeObject.AppMessageHandler(var Msg: TMsg; var Handled: Boolean); Все параметры сообщения передаются обработчику события OnMessage в параметре Msg. Параметр Handled используется для указания того, обработано сообщение или нет: если Handled приравнять True, то сообщение будет считаться обработанным и далее обрабатываться не будет11. Для примера рассмотрим создание обработчика сообщения WM_LBUTTONUP (щелчок левой кнопки мыши), в котором производится подсчет количества щелчков и по достижению 10 выход из программы. Для чего создадим класс, в котором и будет производится данная проверка: type TObj = class(TObject) private CountClick: Integer; public constructor Create; procedure ProcessMessages(var Msg: TMsg; var Handled: Boolean); end; Здесь описан метод ProcessMessages, который имеет процедурный тип TMessageEvent, и будет являться обработчиком события OnMessage. Далее реализуем методы: constructor TObj.Create; begin inherited Create; CountClick := 0; Application.OnMessage := ProcessMessages; end; procedure TObj.ProcessMessages(var Msg: TMsg; var Handled: Boolean); begin if Msg.message = WM_LBUTTONUP then begin inc(CountClick); if CountClick = 10 then begin ShowMessage('Осуществлено 10 кликов.'); Application.Terminate; end; Handled := False; end; end; В конструкторе производится создание объекта, обнуление поля и производится назначение метода ProcessMessages в качестве обработчика события Application.OnMessage. В методе ProcessMessages производится анализ типа сообщения и, если произошло событие щелчок левой кнопки мыши, то увеличить количество щелчков, а если их 10, то выйти из приложения. Обратите внимание, что параметру Handled присвоено Система обработки сообщений Delphi достаточно сложна и включает многоуровневую последовательную обработку сообщения, на каждом из этих уровней программист может предусмотреть некие действия. 11 значение False, если присвоить True, то приложение и все компоненты на форме не будет реагировать на щелчок левой кнопки мыши. Далее производится создание описанного объекта типа TObj: var Form1: TForm1; Obj: TObj; ... procedure TForm1.FormActivate(Sender: TObject); begin Obj := TObj.Create; end; Запустив программу, щелкните 10 раз по форме – форма закроется. Основное ограничение события OnMessage состоит в том, что оно перехватывает только сообщения, выбранные из очереди, и не работает с сообщениями, переданными непосредственно процедурам окна различных окон приложения. С другой стороны, событие OnMessage перехватывает все сообщения, направляемые в адрес всех идентификаторов окон, относящихся к данному приложению. И только с помощью обработчика события OnMessage можно реализовать обработку сообщений, направленных объекту, не имеющему собственного дескриптора. Обработчик события OnMessage самая загруженная подпрограмма приложения – она обрабатывает практически все сообщения – до тысячу в секунду. Поэтому необходимо избегать выполнения в этой процедуре любых продолжительных действий, иначе работа всего приложения может существенно замедлиться. Система сообщений библиотеки VCL После того как Windows отправит сообщение, оно проходит несколько последовательных этапов обработки, прежде чем достигнет процедуры обработки сообщений пользовательского приложения. Подпрограммы библиотеки VCL обеспечивают доступ к сообщению на протяжении всего пути. Любое сообщение Windows, посланное без требования получения результатов обработки, первоначально обрабатывается методом Application.ProcessMessage, в котором реализован главный цикл обработки сообщений средствами библиотеки VCL. Следующий этап состоит в передаче сообщения обработчику события Application.OnMessage. Событие OnMessage генерируется при выборке сообщения из очереди приложения в методе ProcessMessage. Если обработчик события OnMessage не обработал сообщение, то неявно вызывается функция Win32 API DispatchMessage, которая, в свою очередь, передает каждое сообщение функции StdWndProc. Для отправляемых сообщений эта функция вызывается непосредственно системой Win32. Функция StdWndProc представляет собой написанную на ассемблере функцию низкого уровня, которая принимает сообщение от Windows и переправляет его назначенному объекту. Метод объекта, который получает сообщение, называется MainWndProc. Начиная с этого момента в программе можно выполнять любую специальную обработку сообщения, какая только может потребоваться. Адрес функции окна (MainWndProc) системе сообщается через функцию SetWindowLong. При желании можно сообщить и другой адрес, однако это требует определенной квалификации. Однако метод MainWndProc не виртуальный, поэтому программисту тяжело "вклиниться". По завершении работы метода MainWndProc сообщение передается методу, адрес которого содержится в свойстве WindowProc. По умолчанию здесь содержится адрес виртуального метода WndProc. Для обработки сообщений программисту можно либо переопределить значение свойства WindowProc, присвоив ему адрес собственной процедуры обработки, либо перекрыть виртуальный метод WndProc. Для разных компонентов внутри WndProc может быть предусмотрена обработка тех или иных сообщений. В противном случае сообщение поступает в распоряжение механизма диспетчеризации сообщений, функционирующий в рамках виртуального метода TObject.Dispatch; именно этот метод реализует поиск необходимого динамического метода-обработчика по индексу сообщения (иными словами переправляет сообщение дальше, некоторой конкретной процедуре обработки сообщений, определенной либо программистом, либо уже имеющейся в составе средств библиотеки VCL). Здесь для программиста открываются две возможности: перекрыть Dispatch или написать свой метод-обработчик сообщения (реализация данной возможности приведена в 1.3.1.4.1). Если метод Dispatch не нашел обработчика для данного индекса сообщения, вызывается виртуальный метод DefaultHandler (здесь программист также может перекрыть данный метод в своем классе для обработки сообщения). Этот метод осуществляет любые завершающие действия по обработке сообщения и, если обработка все еще не завершена, то передает сообщение функции, адрес которой находится в свойстве DefWndProc. По умолчанию здесь содержится адрес функции Win32 API DefWindowProc (но может и содержаться другая стандартная процедура обработки, например DefMDIProc). В этих функциях производится стандартная обработка средствами ОС Windows. Программисту для обработки сообщения, в принципе, можно сообщить и другой адрес в свойство DefWndProc, который будет указывать на обработчик сообщения, реализованный программистом. В зависимости от обстоятельств нужные программисту действия можно предусмотреть на любом из уровней. В 90% случаев достаточно написать динамический метод-обработчик. Общая схема механизма обработки сообщений средствами библиотеки VCL представлена на рисунке 2. Сообщение Метод Application.ProcessMessage Событие Application.OnMessage Win32 API-функция DispatchMessage Win32 API-функция StdWndProc Win32 API-функция SetWindowLong Механизм обработки сообщений средствами библиотеки VCL Метод SomeClass.MainWndProc Свойство W indowProc Метод SomeClass.WndProc Метод SomeClass.Dispatch Обработчик сообщения класса SomeClass Обработчик сообщения класса-предка Обработчик сообщения класса-предка N Метод SomeClass.DefaultHandler Свойство DefWndProc Стандартная процедура обработки ОС Windows, например, Win32 API-функция StdWndProc Рисунок 2 – Схема механизма обработки сообщений Delphi Также необходимо отметить, что, если на каком-нибудь из приведенных этапов обработка сообщения производится, то дальнейшие этапы не производится. При обработке сообщений всегда следует вызывать метод inherited, за исключением тех случаев, когда имеется абсолютная уверенность в том, что стандартная обработка сообщения не требуется. Поскольку все необработанные сообщения доставляются обработчику DefaultHandler, этот метод представляет собой самое подходящее место для выполнения обработки сообщений из других приложений. В качестве примера обработки сообщений средствами библиотеки VCL разберем способы обработки сообщений с помощью перекрытия методов WndProc и DefaultHandler. Сначала производим описание идентификатора пользовательского сообщения, если программа должна обрабатывать пользовательское сообщение, а не стандартное сообщение Windows. const SX_MYMESSAGE = WM_USER + 102; // Идентификатор пользовательского // сообщения Еще раз напомню, описывать идентификатор пользовательского сообщения надо только в том случае, если не используется стандартное сообщение Windows. Далее производится объявление методов в описании класса. В нашем случае используется класс формы, однако, так как рассматриваемые в примере способами можно обрабатывать сообщения только средствами VCL, то нужно использовать классы, у которых есть дескриптор (свойство Handle), иначе нельзя отправить объекту сообщения, и он не сможет обработать. Таким образом, объявление методов в описании класса будет следующим: type TMainForm = class(TForm) ... private {Обработка сообщений на уровне процедуры WndProc} procedure WndProc(var Msg: TMessage); override; {Обработка сообщений по умолчанию} procedure DefaultHandler(var Msg); override; end; Далее производится реализация самих методов: procedure TMainForm.WndProc(var Msg: TMessage); {Процедура WndProc объекта формы} begin // Проверка получения собственного сообщения формы if Msg.Msg = SX_MYMESSAGE then begin // Произведение каких-либо действий, например, сообщение ShowMessage('Пришло пользовательское сообщение в WndProc'); // Если пользовательское сообщение больше обрабатывать никаким // обработчиком не надо, то следующий оператор нужен, иначе – надо // следующий оператор убрать exit; end; // Проверка получения стандартного сообщения Windows if Msg.Msg = WM_MOUSEMOVE then begin Form1.Caption := 'Положение мыши: X: ' + IntToStr(Msg.LParamLo) + '; Y: ' + IntToStr(Msg.LParamHi); end; // Вызов обработчика события у класса предка inherited WndProc(Msg); end; procedure TMainForm.DefaultHandler(var Msg); {Обработка сообщения по умолчанию} begin // Проверка поступления собственного сообщения приложения if TMessage(Msg).Msg = SX_MYMESSAGE then begin // Произведение каких-либо действий, например, сообщение ShowMessage('Пришло пользовательское сообщение в DefaultHandler); // Если пользовательское сообщение больше обрабатывать никаким // обработчиком не надо, то следующий оператор нужен, иначе – надо // следующий оператор убрать exit; end; // Проверка получения стандартного сообщения Windows if TMessage(Msg).Msg = WM_MOUSEMOVE then begin Form1.Caption := 'Положение мыши: X: ' + IntToStr(TMessage(Msg).LParamLo) + '; Y: ' + IntToStr(TMessage(Msg).LParamHi); end; // Вызов обработчика события у класса предка inherited DefaultHandler(Msg); end; Обратите внимание: процедура DefaultHandler несколько отличается от рассмотренных ранее – требуется передавать один нетипизированный var-параметр. Суть в том, что в процедуре DefaultHandler предполагается, что первое слово в значении параметра будет идентификатором сообщения, тогда как остальная часть сообщения процедурой игнорируется, в результате можно легко извлечь из сообщения его идентификатор с помощью явного приведения параметра к типу TMessage. Способы отправки сообщений пользователем Аналогично тому, как система Windows посылает свои сообщения различным окнам приложения, в самом приложении также может появиться необходимость обмена сообщениями между его окнами и управляющими элементами. Delphi предоставляет разработчику несколько способов осуществления обмена сообщениями в пределах приложения: метод Perform (работающий независимо от Windows API), функции Win32 API SendMessage и PostMessage и широковещательные сообщения методом Broadcast. Также с помощью функций Win32 API SendMessage и PostMessage можно передавать сообщения и между приложениями. Метод Perform Этим методом обладают все потомки класса TControl, входящие в состав библиотеки VCL. Метод Perform позволяет послать сообщение любой форме или управляющему элементу, заданному именем экземпляра требуемого объекта. Методу Perform передается три параметра – само сообщение и соответствующие ему параметры WParam и LParam. Определение этого метода имеет следующий вид: function TControl.Perform(Msg: Cardinal; Wparam, Lparam: Longint): Longint; Для посылки сообщения форме или управляющему элементу используется следующий синтаксис: RetVal := ControlName.Perform(MessageID, Wparam, Lparam); Например, чтобы отменить последнюю операцию в компоненте TMemo нет никаких стандартных методов, однако это можно сделать, послав следующее сообщение: Memo1.Perform(WM_UNDO, 0, 0); При вызове метода Perform управление вызывающей программе не будет возвращено до тех пор, пока сообщение не будет обработано. В методе переданные ему параметры собираются в запись типа TMessage, после чего с помощью свойства WindowProc вызывается метод WndProc указанного объекта, минуя систему обработки сообщений Windows API. Функции Win32 API SendMessage и PostMessage В некоторых случаях может потребоваться послать сообщение окну, для которого нет соответствующего экземпляра объекта Delphi. Например, иногда необходимо послать сообщение окну, созданному не Delphi, и вся информация, которая доступна программе, – это его дескриптор. Для подобных целей используются две функции Windows API – SendMessage и PostMessage, – которые практически идентичны, но имеют одно существенное различие. Функция SendMessage посылает сообщение непосредственно процедуре окна и ожидает окончания его обработки, причем функция возвращает значение, полученное в результате обработки сообщения. В отличие от нее, функция PostMessage просто помещает сообщение в очередь сообщений Windows и немедленно возвращает управление вызвавшей ее программе, не дожидаясь результатов обработки сообщения. Функция PostMessage возвращает значение, указывающее, удалось ли поместить сообщение в очередь сообщений соответствующего окна или нет. Функции определены следующим образом: function SendMessage(hWnd: HWND; Msg: LongWord; WParam: Longint; LParam: Longint): Longint; function PostMessage(hWnd: HWND; Msg: LongWord; WParam: Longint; LParam: Longint): LongBool; где hWnd – дескриптор окна-получателя сообщения; Msg – идентификатор сообщения; WParam – 32 бита дополнительной уточняющей информации; LParam – 32 бита дополнительной уточняющей информации. В качестве примера приведем отправку сообщения об отмене последнего действия компоненту TMemo с помощью функций SendMessage и PostMessage: SendMessage(Memo1.Handle, WM_UNDO, 0, 0); или PostMessage(Memo1.Handle, WM_UNDO, 0, 0); В данном случае обработка сообщения не требует возврата результата, поэтому результат выполнения функций ни к чему не присваивается. Широковещательные сообщения Класс, производный от класса TWinControl, может с помощью метода Broadcast послать широковещательное сообщение каждому управляющему элементу, владельцем которого он является. Эта технология используется в тех случаях, когда требуется послать одно и то же сообщение группе компонентов. Например, чтобы изменить шрифт у всех управляющих компонентов, принадлежащих, например, компоненту GroupBox1, можно послать широковещательное стандартное сообщение Windows WM_SETFONT с указанием дескриптора нового шрифта: procedure TForm1.Button1Click(Sender: TObject); var M: TMessage; F: TFont; begin F := TFont.Create; F.Size := 20; F.Name := 'Arial'; M.Msg := WM_SETFONT; M.WParam := F.Handle; GroupBox1.Broadcast(M); end; В примерах отправки сообщений данного параграфа использовались стандартные сообщения Windows, однако программист может отправить и пользовательское сообщение как в рамках одного приложения, так и в между приложениями. Обмен сообщениями между приложениями При необходимости организовать обмен сообщениями между двумя или более приложениями следует использовать в них функцию Win32 API RegisterWindowMessage: function RegisterWindowMessage(lpString: PChar): LongWord; Этот метод гарантирует, что для заданного типа сообщений каждое приложение будет использовать один и тот же номер. Функция RegisterWindowMessage принимает в качестве параметра строку с завершающим нулем и возвращает идентификатор для нового сообщения в диапазоне $С000 - $7FFF. Это означает, что вызова этой функции с одной и той же строкой в качестве параметра в каждом приложении будет достаточно, чтобы гарантировать одинаковые номера сообщений во всех приложениях, принимающих участие в обмене. Еще одно преимущество этой функции состоит в том, что система гарантирует уникальность идентификатора, назначенного любой заданной строке. Это позволяет посылать широковещательные сообщения всем существующим в системе окнам, не опасаясь нежелательных побочных эффектов. Недостатком данного метода является некоторое усложнение обработки подобных сообщений. Суть в том, что идентификатор сообщения становится известным только при работе приложения, поэтому использование стандартных процедур обработки сообщений оказывается невозможным. Для работы с подобными сообщениями потребуется переопределить стандартный метод WndProc или DefaultHandler соответствующих компонентов либо создать подкласс существующей процедуры окна. В остальном передача сообщений между приложениями ничем не отличается от передачи сообщений внутри приложений с помощью рассмотренных ранее функций SendMessage и PostMessage, только в качестве дескриптора окна (первый параметр) надо использовать дескриптор интересующего приложения. Возврат результата обработки сообщения При обработке определенных сообщений Windows ожидает возврата некоторого результирующего значения. Для возврата результата обработки сообщения в записи TMessage (или записи сообщения другого типа, но не TMsg) есть поле Result, которому и надо присвоить результат после вызова метода inherited. Например, по стандартному сообщению WM_GETFONT окну необходимо вернуть дескриптор шрифта, который в настоящее время является текущим. Но программист может подменить возвращаемый шрифт, например, с помощью перекрытого метода DefaultHandler: procedure TForm1.DefaultHandler(var Msg); var F: TFont; begin if TMessage(Msg).Msg = WM_GETFONT then begin F := TFont.Create; F.Size := 30; F.Name := ‘Arial’; TMessage(Msg).Result := F.Handle; exit; end; inherited DefaultHandler(Msg); end; Результатом обработки сообщения, посланного форме, будет шрифт Arial с размером символов 30 пт. Чтобы отправить сообщение WM_GETFONT форме и дождаться возврата результата обработки данного сообщения можно воспользоваться функцией SendMessage: procedure TForm1.Button1Click(Sender: TObject); var F: TFont; begin F := TFont.Create; F.Handle := SendMessage(Form1.Handle, WM_GETFONT, 0, 0); FontDialog1.Font := F; FontDialog1.Execute; end; В данном примере производится отправка сообщения WM_GETFONT форме Form1 и ожидается возвращение результата, который присваивается дескриптору созданного шрифта F.Handle и полученный шрифт отображается с помощью стандартного диалога FontDialog1. Интерфейсы Интерфейс - это связь двух отдельных сущностей. Виды интерфейсов: языковые, программные, аппаратные, пользовательские, цифровые и т. п. Программный (API) и/или аппаратный интерфейс (port) - это способы преобразования входных/выходных данных во время объединения компьютера с периферийным оборудованием. В ЯП - это программа или часть программы, в которой определяются константы, переменные, параметры и структуры данных для передачи другим. В программировании термин интерфейс олицетворяет собой набор операций, обеспечивающих определение видов услуг и способов их получения от программного объекта, предоставляющего эти услуги. На начальном этапе программирования в роли интерфейса выступают операторы обращения к ее процедурам и функциям программ через формальные параметры. Программы, процедуры и функции записывались в одном ЯП. Операторы обращения включали имена вызываемых объектов (процедур и функций) и список фактических параметров, задающих значения формальным параметрам и получаемым результатам. Последовательность и число формальных параметров соответствовало фактическим параметрам. Выполнение функции в среде программы на одном ЯП не вызывало проблем, так как типы данных параметров совпадали. В случае, когда один из элементов (программа, процедура или функция) записаны на разных ЯП и, кроме того, если они располагаются на разных компьютерах, то возникают проблемы неоднородности типов данных в этих ЯП, структур памяти платформ компьютеров и операционных сред, где они выполняются. Понятие интерфейса, как самостоятельного объекта, сформировалось в связи со сборкой или объединением разноязыковых программ и модулей в монолитную систему на больших ЭВМ (mainframes). Рис. 1. Схема вызова модулей А и В из С через интерфейсы А'и B' Интерфейс играл роль посредника между вызываемым и вызывающим модулями. В нем давалось описание формальных и фактических параметров, производилась проверка соответствия передаваемых параметров (количества и порядка расположения), а также их типов данных. Если типы данных параметров оказывались не релевантными (например, передается целое, а результат функции вещественное или наоборот), то производилось прямое и обратное их преобразование с учетом структуры памяти компьютеров. На рис. 1 приведена схема программы , в которой содержатся два вызова и с параметрами, которые через интерфейсные модули-посредники и производят преобразование данных и их передачу модулям и . После выполнения и результаты преобразуются обратно к виду программы . Интерфейс в ООП и в современных средах Интерфейс в ООП. В ООП главным элементом является класс, включающий множество объектов с одинаковыми свойствами, операциями и отношениями. Класс имеет внутреннее (реализацию) и внешнее представление - интерфейс (табл. 1). Таблица 1. Структура представления класса и интерфейса Класс Внешнее представление Внутреннее представление Интерфейсные операции: Реализация операций класса,  публичные, доступные всем определение поведения. клиентам:  защищенные, доступные классу п подклассу:  приватные, доступные классу. Интерфейс содержит множество операций, описывающих его поведение. Класс может поддерживать несколько интерфейсов, каждый из которых содержит операции и сигналы, используются для задания услуг класса или программного компонента. Интерфейс именует множество операций или определяет их сигнатуру и результирующие действия. Если интерфейс реализуется с помощью класса, то он наследует все его операции. Одни и те же операции могут появляться в различных интерфейсах. Если их сигнатуры совпадают, то они задают одну и ту же операцию, соответствующую поведению системы. Класс может реализовывать другой класс через интерфейс. Операции и сигналы могут быть связаны отношениями обобщения. Интерфейспотомок включает в себя все операции и сигналы своих предков и может добавлять собственные путем наследования всех операций прямого предка, т.е. его реализацию можно рассматривать как наследование поведения. Новое толкование интерфейса объектов дано в работе П.Вегнера, который сформулировал парадигму перехода от алгоритмов вычислений к взаимодействию объектов. Суть этой парадигмы заключалась в том, что вычисление и взаимодействие объектов рассматривались как две ортогональные концепции. Взаимодействие - это некоторое действие ( ), но не вычисление, а сообщение - не алгоритм, а действие, ответ на которое зависит от последовательности операций ( ), влияющих на состоянии разделенной ( , ) памяти локальной программы (рис. 2). Операции интерфейса ( и ) относятся к классу неалгоритмических и обеспечивают взаимодействие объектов через сообщения. Рис. 2. Интерфейс взаимодействия через операции интерфейса (по Вегнеру) Вегнер рассматривает модель взаимодействия, как обобщение машины Тьюринга - распределенной интерактивной модели взаимодействия объектов с входными (input) и выходными (output) действиями и возможностью продвижения в ней потенциально бесконечного входного потока (запросов, пакетов) в заданном интервале времени. Дальнейшим развитием идеи взаимодействия, основанного на действиях, является язык AL (Action language), обеспечивающий вызовов процедур (локальных или распределенных) с разверткой каждого вызова в программу, состоящую из операторов действий. Программа из вызовов процедур рассматривается в AL как ограниченное множество конечных программ, взаимодействующих со средой, в которую они погружаются. Интерфейс в современных средах и сетях. Появление разных компьютеров и их объединение в локальные и глобальные сети привело к уточнению понятия интерфейса как удаленного вызова (сообщения) программ, расположенных в разных узлах сети или среды и получающих входные данные из сообщений. Сети строятся на основе стандартной семиуровневой модели открытых систем OSI (Open Systems Interconnection). Объекты уровней в этой модели связываются между собой по горизонтали и вертикали. Запросы от приложений поступают на уровень представления данных для их кодирования (перекодирования) к виду используемой в приложении платформы. Открытые системы предоставляют любым приложениям разного рода услуги: управление удаленными объектами, обслуживание очередей и запросов, обработка интерфейсов и т. п. Доступ к услугам осуществляется с помощью разных механизмов:  вызова удаленных процедур RPC (Remote Procedure Call) в системах ОNС SUN, OSF DSE;  связывания распределенных объектов и документов в системе DCOM;  языка описания интерфейса IDL (Interface Definition Language) и брокера объектных запросов - ORB (Object Request Broker) в системе CОRBA; вызова RMI (Remote Methods Invocation) в системе JAVA и др. RPC- вызов задает интерфейс удаленным программам в языках высокого или низкого уровней. Язык высокого уровня служит для задания в RPC-вызове параметров удаленной процедуры, которые передаются ей через сетевое сообщение. Язык низкого уровня позволяет указывать более подробную информацию удаленной процедуре: тип протокола, размер буфера данных и т. п. Взаимосвязь процесса с удаленно расположенным от него другим процессом (например, сервером) на другом компьютере выполняет протокол UDP или TCP/IP, который передает параметры в stub- интерфейсе клиента stub-серверу для выполнения удаленной процедуры. Механизм посылки запроса в системе CORBA базируется на описании запроса в языке IDL для доступа к удаленному методу/функции через протокол IIOP или GIOP. Брокер ORB передает запрос генератору, затем посылает stub/skeleton серверу, выполняющему интерфейс средствами объектного сервиса (Common Object Services) или общими средствами (Common Facilities). Так как брокер реализован в разных распределенных системах: CORBA, COM, SOM, Nextstep и др., то он обеспечивает взаимодействие объектов в разных сетевых средах. Вызов метода RMI в системе JAVA выполняет виртуальная машина (virtual machine), которая интерпретирует byte-коды вызванной программы, созданные разными системами программирования ЯП (JAVA, Pascal, С++) на разных компьютерах и средах. Функции RMI аналогичны брокеру ORB. Интерфейс в среде клиента и сервера В распределенной среде реализуется два способа связывания: на уровне ЯП через интерфейсы прикладного программирования и компиляторов IDL, генерирующих клиентские и серверные Stab. Интерфейсы определяются в языках IDL или APL, динамический интерфейс от объекта клиента к объекту сервера и обратно выполняет брокер ORB. Интерфейсы имеют отдельную реализацию на ЯП и доступны разноязыковым программам. Компиляторы с IDL как часть промежуточного слоя сами реализуют связывание с ЯП через интерфейс клиента и сервера, заданного в том же ЯП. Интерфейс в IDL или в API включает описание формальных и фактических параметров программ, их типов и порядка задания операций передачи параметров и результатов при их взаимодействии. Это описание есть не что иное, как спецификация интерфейсного посредника двух разноязыковых программ (аналогично, как на рис. 1), которые взаимодействуют друг с другом через механизм вызова интерфейсных функций или посредников двух типов программ (клиент и сервер), выполняемых на разных процессах. В функции интерфейсного посредника клиента входят:  подготовка внешних параметров клиента для обращения к сервису сервера,  посылка параметров серверу и его запуск в целях получения результата или сведений об ошибке. Общие функции интерфейсного посредника сервера состоят в следующем:  получение сообщения от клиента, запуск удаленной процедуры, вычисление результата и подготовка (кодирование или перекодирование) данных в формате клиента;- возврат результата клиенту через параметры сообщения и уничтожение удаленной процедуры и др. Описание интерфейсного посредника не зависит от ЯП взаимодействующих объектов и в целом одинаково для всех вызывающих и вызываемых объектов. Посредник описывается в языке спецификации интерфейса IDL. Интерфейсные посредники задают связь между клиентом и сервером (stub для клиента и skeleton для сервера). Их описания отображаются в те ЯП, в которых представлены соответствующие им объекты или компоненты. Эти интерфейсы используются в системах CORBA, DCOM, LAVA и др. Они предоставляют всевозможные сервисы разработки и выполнения приложений в распределенной среде. Системные сервисы подключаются к приложению с помощью брокера. Брокер обеспечивает интероперабельность компонентов и объектов при переходе из одной среды другую. Под интероперабельностью понимается способность совместного, согласованного взаимодействия разнородных компонентов системы для решения определенной задачи. К средствам обеспечения интероперабельности и передачи данных между разными средами и платформами относится, например, стандартный механизм связи между JAVA и C/C++ компонентами, основанный на применении концепции Java Native Interface (JNI), реализованной как средство обращения к функциям из JAVAклассов и библиотек, разработанных на других языках. Эти средства включает в себя анализ JAVA-классов в целях поиска прототипов обращений к функциям, реализованных на языках C/C++, и генерацию заголовочных файлов для использования их при компиляции C/C++ программ. В средстве JAVA классу известно, что в нем содержится обращение не к JAVA-методу (он называется и для загрузки необходимых C/C++ библиотек добавляется вызов функции), ориентируется именно на такую связь. Данная схема действует в одном направлении от JAVA к C/C++ и только для такой комбинации ЯП. Еще вариант реализации аналогичной задачи предлагает технология Bridge2Java,которая обеспечивает обращение из JAVA- классов к COM-компонентам. В этих целях генерируется оболочка для COM-компонента, который включает проксикласс, обеспечивает необходимое преобразование данных средствами стандартной библиотеки преобразований типов. Данная схема не требует изменений в исходном Java-классе и COM-компоненты могут быть написаны в разных языках. Механизм интероперабельности реализован также на платформе . Net с помощью языка CLR (Common Language Runtime). В этот язык транслируются коды,  написанные в разных ЯП (C#, Visual Basic, C++, Jscript). CLR разрешает не только интегрировать компоненты, разработанные в разных ЯП, а и использовать библиотеку стандартных классов независимо от языка реализации. Такой подход позволяет реализовать доступ к компонентам, которые были разработаны раньше без ориентации на платформу . Net, например к COMкомпонентам. Для этого используются стандартные средства генерации оболочки для COM-компонента, с помощью которой он представляется как . Net-компонент. При такой схеме реализуются все виды связей и для любых ЯП данной среды. Интерфейс языков программирования (ЯП) Интерфейс и взаимосвязь с ЯП Основные ЯП, используемые для описания компонентов в современных средах, это С++, Паскаль, JAVA и др. Разноязыковые программы, записанные в этих языках, обращаются друг к другу через удаленный вызов, который предполагает взаимно однозначное соответствие между фактическими параметрами вызывающей программы и формальными параметрами вызываемой программы. При неоднородности одного из параметров из множества формальных или фактических параметров разноязыковых программ необходимо провести отображение (mapping) неэквивалентного типа данных параметра в одном ЯП в соответствующий тип данных в другом ЯП. Аналогично решается задача преобразования неэквивалентных типов данных в ЯП. Представим это преобразование такими этапами. Этап 1. Построение операций преобразования типов данных для множества языков программирования . Этап 2.Построение отображения простых типов данных для каждой пары взаимодействующих компонентов в и , а также применение операций селектора и конструктора для отображения сложных структур данных в этих языках. Один из способов формализованного преобразования типов данных - создание алгебраических систем для каждого типа данных где - тип данных, : - множество значений, которые могут принимать переменные этого типа данных, - множество операций над этими типами данных. В качестве простых типов данных современных ЯП могут быть . Сложные типы данных - комбинация простых типов данных. Этим типам данных соответствуют следующие классы алгебраических систем: (1) Каждый элемент класса простых и сложных типов данных определяется на множестве значений этих типов данных и операций над ними: , где . Операциям преобразования каждого типа данных соответствует изоморфное отображение двух алгебраических систем с совместимыми типами данных двух разных языков. В классе систем (1) преобразование типов данных для пары языков и обладает такими свойствами отображений: 1. системы и для языков и - изоморфны, если их типы данных определены на одном том же множестве простых или сложных типов данных; 2. между значениями если множества операций и и типов данных и существует изоморфизм, , применяемых для этих типов данных, различны. Если это множество пусто, то имеем изоморфизм двух систем . Если тип данных множествами 3. и , есть строка, а тип и - вещественное, то между не существует изоморфного соответствия; алгебраические системы по мощности должны быть равны, так как они представлены на множестве типов данных языков и Отображения 1, 2 сохраняют линейный порядок элементов, поскольку алгебраические системы являются линейно упорядоченными. Общая схема связи ЯП в распределенной среде. Характерная особенность ЯП, используемых в распределенных средах, - их неоднородность как в смысле представления типов данных в них, так и платформ компьютеров, где реализованы соответствующие системы программирования. Причина неоднородности - это различные способы передачи параметров между объектами в разных средах, наличие разных типов объектных моделей и форматов данных для задания параметров, разные виды операторов удаленного вызова и получения результатов выполнения запросов и др. Системы программирования с ЯП имеют следующие особенности компилирования программ:  разные двоичные представления результатов компиляторов для одного и того же ЯП, реализованных на разных компьютерах;  двунаправленность связей между ЯП и их зависимость от среды и платформы;  параметры вызовов объектов отображаются в операции методов;  связь с разными ЯП реализуется ссылками на указатели в компиляторах;  связь ЯП осуществляется через интерфейсы каждой пары из множества языков промежуточной среды. Связь между различными языками осуществляется через интерфейс пары языков , , взаимодействующих между собой в среде, генерирующей соответствующие конструкции в операции описания интерфейса и наоборот. Взаимодействие ЯП в среде CORBA.Принцип взаимодействия объектов в среде CORBA состоит в том, что любой объект выполняет метод (функцию, сервис, операцию) при условии, если другой объект, выступающий в роли клиента для него, посылает ему запрос для выполнения этого метода. Объект выполняет метод через интерфейс. Взаимодействие ЯП в системе CORBA состоит в отображении типов объектов в типы клиентских и серверных стабов путем  отображения описания запроса клиента в ЯП в операции IDL;  преобразования операций IDL в конструкции ЯП и передачу их серверу средствами брокера ORB, реализующего в типы данных клиента. Так как ЯП системы CORBA могут быть реализованы на разных платформах и в разных средах, то их двоичное представление зависит от конкретной аппаратной платформы. Для всех ЯП системы CORBA (С++, JAVA, Smalltalk, Visual C++, COBOL, Ada-95) предусмотрен общий механизм связи и расположения параметров методов объектов в промежуточном слое. Связь между объектными моделями каждого ЯП системы СОМ и JAVA выполняет брокер ORB (рис. 4). Рис. 4. Интегрированная среда системы CORBA Если в общую объектную модель CORBA входит объектная модель СОМ, то в ней типы данных определяются статически, а конструирование сложных типов данных осуществляется только для массивов и записей. Методы объектов используются в двоичном коде и допускается двоичная совместимость машинного кода объекта, созданного в одной среде разработки, коду другой среды, а также совместимость разных ЯП за счет свойства отделения интерфейсов объектов от реализаций. В случае вхождения в состав модели CORBA объектной модели JAVA/RMI, вызов удаленного метода объекта осуществляется ссылками на объекты, задаваемые указателями на адреса памяти. Интерфейс как объектный тип реализуется классами и предоставляет удаленный доступ к нему сервера. Компилятор JAVA создает байткод, который интерпретируется виртуальной машиной, обеспечивающей переносимость байткодов и однородность представления данных на всех платформах среды СORBA. Взаимодействие разноязыковых программ В отличие от рассмотренной общей схемы взаимодействия программ с двумя модулями (рис.1), здесь рассмотрены высокотехничные средства обеспечения процесса преобразования: панели, сценарии, иконки и образцы интерфейсных программ для каждого конкретного случая взаимодействия программ. Далее дается краткое описание шести схем средств описания разноязыковых программ, взаимодействующих с языками, приведенными во второй колонке данной таблицы. Интерфейс между Visual Basic и другими ЯП осуществляется с помощью оператора обращения, параметрами которого могут быть строки, значения, массивы и другие типы данных. Их обработка проводится функциями Windows API, API DLL и операциями преобразования типов данных. В качестве примера приведена схема обработки Интернет-приложений, задаваемых HTML-страницами Basic Visual, размещаемых в Web-браузере и базах данных. Сформированный файл вызывается из программы в С++ и преобразовывается к виду архитектуры компьютера, куда отсылается результат. Базовые средства Smalltalk обеспечивают создание приложений в среде VisualWorks и включают модель приложений, методы объектов, сообщения для передачи значений внешним объектам и пользовательский интерфейс (рис. 5). Модель приложения содержит функции DLL из класса внешнего интерфейса, взаимодействующие с функциями библиотеки С++. Рис. 5. Схема взаимодействия модели приложения с библиотекой Система LabView предназначена для автоматизации производственных процессов, сбора данных, проведения измерений и управление созданием программ, взаимодействующих с аппаратурой. В ее состав входят прикладные средства, тестирования программ и драйверы взаимодействия с аппаратурой, запускаемых с пульта. Система взаимодействует с ANS C, Visual Basic, Visual C++ Lab Windows/CV. Эти средства расширяют возможности создания систем реального времени, которые позволяют производить с помощью функций связи измерение аппаратуры типа: регуляторы, термометры, переключатели и др. Результаты измерений могут передаваться в сеть. Среда Java содержит инструменты взаимодействия со всеми языками, приведенными во второй колонке таблицы. Общая схема связи языков JAVA, C и C++ программ приведена на рис. 6. Язык Perl появился в 80-х годах прошлого столетия как язык задания сценариев для взаимодействия с Интернет, управления задачами и создания CGI-сценариев на сервере в системе Unix. Данный язык имеет интрфейс с С, С++, Visual Basic и Java. Интерпретатор с языка Perl написан в языке С и каждый интерфейс с другим языком рассматривается как расширение, представляемое процедурами динамической библиотеки. Рис. 6. Схема взаимодействия приложения и программ Java, C, C++ Оператор вызова программы в С или С++ обеспечивает преобразование ее в специальный код, который размещается в библиотеке интерпретатора Perl. Сам интерпретатор может быть включен в Win32 или в программу на C/C++. Таким образом, в работе тщательно исследованы самые современные средства и инструменты представления разноязыковых программ и принципы их взаимодействия с широко используемыми ЯП. Даны рекомендации по конкретному применению каждого средства с учетом условий среды и правил прямой и обратной передачи параметров программе в ЯП из класса рассмотренных ЯП. Приведены многочисленные примеры, которые проверены экспериментально, ими можно пользоваться на практике либо использовать в качестве образца. Интерфейс платформ и преобразование данных Преобразование форматов данных Программы, расположенные на разных типах компьютеров, передают друг другу данные через протоколы, их форматы преобразуется к формату данных принимающей серверной платформы (так называемый маршалинг данных) с учетом порядка и стратегии выравнивания, принятой на этой платформе. Демаршалинг данных - это обратное преобразование данных (т. е. полученного результата) к виду передавшей клиентской программы. Если среди передаваемых параметров оператора вызова содержатся нерелевантные типы или структуры данных, которые не соответствуют параметрам вызванного объекта, то производится прямое и обратное их преобразование средствами ЯП или стандарта. К средствам преобразования данных и их форматов относятся:  стандарты кодировки данных (XDR - eXternal Data Representation, CDR Common Representation Data), NDR - Net Data Representation) и методы их преобразования;  ЯП и механизмы обращения компонентов друг к другу;  языки описания интерфейсов компонентов - RPC, IDL и RMI для передачи данных между разными компонентами. На каждой платформе компьютера используются соглашения о кодировке символов (например, ASCII), о форматах целых чисел и чисел с плавающей точкой (например, IEEE, VAX и др. ). Для представления целых типов, как правило, используется дополнительный код, а для типов float и double-стандарт ANSI/IEEE и др. Порядок расположения байтов зависит от структуры платформы (Big Endian или Little Endian) и от старшего к младшему байту и от младшего байта к старшему. Процессоры UltraSPARC и PowerPC поддерживают обе возможности. При передаче данных с одной платформы на другую учитывается возможное несовпадение порядка байтов. Маршаллинг данных поддерживается несколькими стандартами, некоторые из них рассмотрим ниже. XDR-стандарт содержит язык описания структур данных произвольной сложности и средства преобразования данных, передаваемых на платформы (Sun, VAX, IBM и др. ). Программы, написанные в ЯП, могут использовать данные в XDRформате, несмотря на то, что компиляторы выравнивают их в памяти машины поразному. В XDR-стандарте целые числа с порядком "от младшего" приводятся к порядку байтов "от старшего" и обратно. Преобразование данных - это кодирование (code) или декодирование (decode) XDR-процедурами форматирования простых и сложных типов данных. Кодирование - это преобразование из локального представления в XDRпредставление и запись в XDR-блок. Декодирование - это чтение данных из XDRблока и преобразование в локальное представление заданной платформы. Выравнивание данных - это размещение значений базовых типов с адреса, кратного действительному размеру в байтах (2, 4, 8, 16). Границы данных выравниваются по наибольшей длине (например, 16). Системные процедуры оптимизируют расположение полей памяти под сложные структуры данных и преобразуют их к формату принимающей платформы. Обработанные данные декодируются обратно к виду формата платформы, отправившей эти данные. CDR-cтандарт среды CORBA обеспечивает преобразование данных в форматы передающей и принимающей платформ. Маршаллинг данных выполняет интерпретатор TypeCode и брокер ORB. Процедуры преобразования сложных типов включают в себя:  дополнительные коды для представления целых чисел и чисел с плавающей точкой (стандарт ANSI/IEEE);  схему выравнивания значений базовых типов в среде компилятора;  базовые типы ( signed и unsigned ) в IDL, а также плавающий тип двойной точности и др. Преобразование данных выполняются процедурами encoder() и decoder() интерпретатора TypeCode, который используют базовые примитивы при выравнивании информации и помещения ее в буфер. Для сложного типа вычисляется размер и границы выравнивания, а также их размещение в таблице с индексами значений TCKind, используемых при инициализации брокера ORB. ХМL-стандарт обеспечивает устранение неоднородности во взаимосвязях компонентов в разных ЯП с помощью XML-формата данных, который учитываются разные платформ и среды. Промежуточные среды (CORBA, DCOM, JAVA и др. ) имеют в своем составе специальные функции, аналогичные XML - альтернатива сервисам CORBA в плане обеспечения взаимосвязей разноязыковых программ. XML имеет различные системные поддержки: браузер - Internet Explorer для визуализации XML-документов, объектная модель DOM (Document Object Model) для отображения XML-документов и интерфейс IDL в системе CORBA. Тексты в XML-стандарте описываются в формате ASCII, что дает возможность более эффективно применять их при обмене данными. XML используется для кодирования типов данных с помощью файловых форматов. При необходимости перехода программной системы к XML-стандарту проводится переформатирование данных системы в формат XML и наоборот. Таким образом, XML-язык позволяет представлять объекты для разных объектных моделей на единой концептуальной, синтаксической и семантической основе. Он не зависит от платформы и среды модели взаимодействия компонентов прикладного уровня. XML упрощает обработку документов, работу с БД с помощью стандартных методов и средств (XML-парсеры, DOM-интерфейсы, XSL-отображение XML в HTML и др. ). Преобразование данных БД Преобразование данных БД связано с различием логических структур данных, а также со следующими проблемами: 1. Многомодельность представления данных (иерархические, сетевые, реляционные) в различных БД и СУБД; 2. Различия в логических структурах данных, в справочниках, классификаторах и в системах кодирования информации; 3. Использование различных языков для представления текстовой информации; 4. Разные типы СУБД и постоянное развитие данных БД в процессе эксплуатации. Проблема 1 решается путем перехода к реляционной модели данных и СУБД, которая является мощным математическим аппаратом, основанным на теории множеств и математической логике. Эта модель состоит из структурной, манипуляционной и целостной частей. В этих частях соответственно фиксируется структура данных, описание программ в SQL-языке и требования к целостности. Иерархические или сетевые модели данных в общем не поддерживают целостность, поэтому при переходе от них к реляционным БД возникает нарушение целостности данных. Проблема 2 вызвана тем, что логическая структура данных или концептуальная схема БД предполагают проектирование новой структуры БД при изменении предметной области или при переходе на новый тип СУБД. При этом сопоставляются данные старой и новой БД и изменяется справочная информация и классификаторы. Проблема 3 определяется разноязычными текстовыми представлениями информации в БД. В старых БД использовался, как правило, один язык, а в новых может быть их несколько, поэтому для хранения данных с простым доступом к текстовым данным устанавливается соответствие текстовых данных, записанных в разных языках. Проблему 4 можно сформулировать как метод хранения и обработки разных данных, вызванных спецификой СУБД иерархического, сетевого и реляционного типов. Наличие явной несовместимости типов и структур этих моделей данных, различные языки манипулирования данными приводят к тому, что нельзя сгенерировать на языке старой СУБД скрипты для переноса данных и последующего запуска БД в среде другой СУБД. Каждая СУБД обеспечивает внесение изменений в БД, которые в некоторой степени меняют и концептуальную модель данных, если в нее вносятся новые объекты. Внесенные изменения должны отображаться в справочниках и классификаторах, что обеспечивает перенос данных из старой БД в новую с учетом текущих изменений. Преобразование данных в БД. Учитывая приведенные проблемы, рассмотрим пути их решения. При длительной промышленной эксплуатация систем, работающих с БД, могут изменяться прикладные программы и данные, если в систему введена новая БД, а часть ранее определенных данных перенесена в новую БД. Это влечет за собой доработку прикладных программ доступа, чтобы приспособить их к измененной структуре новой БД или к старой БД. Для переноса данных из старой БД в новую создаются скрипты или DBF-файлы, которые размещаются в транзитной БД для переноса в новую БД. Если окажется, что процесс приведения структуры транзитной БД к новой окажется нецелесообразным, то разработка новой БД проводится "нуля". При этом справочники и классификаторы дополняются появившимися новыми данными. Проблемы преобразования данных при использовании разных СУБД возникают также из-за того, что данные имеют различные способы хранения данных, среди которых могут оказаться несовместимые типы данных или доступ к данным осуществляется разными языками манипулирования. Преобразование данных может проводиться несколько раз путем создания специальных скриптов и файлов с учетом ранее введенных данных, без их дублирования и корректного приведения несовместимых типов данных. Могут возникнуть ошибки, связанные с изменением форматов данных, дополнением старых справочников новыми данными и т. п. Этапы преобразования данных основаны на использовании:  метода 1, выполняющего перенос данных из старой БД в транзитные файлы, а затем занесение этих файлов в транзитную БД;  метода 2 для обработки данных в транзитной базе при изменении кодировки данных, приведении соответствия между структурами старой и новой БД, а также кодов справочников и классификаторов;  метода 3, предназначенного для системного переноса данных из транзитной базы в основную БД с проверкой преобразованных данных. Первый метод - наиболее безболезненный для пользователей и разработчиков. Второй метод представляет собой создание нового проекта системы с заданной моделью данных. При третьем методе - система создается заново, в новую БД могут заноситься унаследованные данные из старой БД. Поскольку структуры БД могут оказаться различными, то, как правило, создаются временные приложения, в которых осуществляются необходимые преобразования данных при переносе в новую БД. При применении первого и второго методов структура старой БД сохраняется и никакого преобразования данных, соответствия справочников и классификаторов не требуется, так как они используют единый формат хранения данных. Файлы передачи данных между разными БД. Проблема преобразования и переноса данных между различными СУБД решается на основе использования: 1. специального драйвера (две СУБД соединяются друг с другом и напрямую передают данные, используя интерфейс); 2. транзитных файлов, в которые копируются данные из старой БД для переноса в новую БД. Процесс преобразования и переноса данных из разных БД в новую БД приведен на рис. 9. Рис. 9. Процесс преобразования и формирования новой БД из старых БД В случае использования драйвера две СУБД соединены напрямую и передают данные, используя определенный интерфейс и специальные программы взаимодействия двух СУБД, при которых вторая СУБД понимает результаты выполнения запросов на языке манипулирования данными первой СУБД, и наоборот. Данные на выходе первой СУБД являются данными на входе второй СУБД в языке манипулирования данными второй СУБД, такие данные могут быть внесены в транзитную БД. Данный метод сложный в реализации и требует поставки программ переноса данных из других СУБД, которые привязаны к старой и новой СУБД. Поэтому второй метод переноса данных между различными СУБД - более предпочтительный. Во втором случае данные из старой БД переносятся в транзитные файлы, SGLскрипты, DBF-файлы с заранее заданными форматами данных, которые пересылаются в новую транзитную БД через сеть с помощью специальных утилит или средств новой СУБД. Если вторая СУБД реляционного типа, то данные в транзитных файлах преобразуются к табличному виду. Если первая СУБД не реляционная, то данные должны быть приведены к табличному виду и первой нормальной форме. Дальнейшая нормализация данных и приведение их к структуре новой БД осуществляется в транзитной БД с использованием 3-я или 4-я нормальной формы для задания структур данных. Каждая более высокая форма нормализации содержит в качестве подмножества более низкую форму, например, первую нормальную форму в виде скалярных значений. Иными словами, отношения находятся в первой нормальной форме, если они хранятся в табличном виде (все ячейки в строке таблицы расположены в строго определенной последовательности) и каждая ячейка таблицы содержит только атомарные значения (элемент не является множеством). Отношение находится в третьей нормальной форме тогда и только тогда, когда каждый кортеж состоит из значения первичного ключа, идентифицирующего некоторую сущность, и набора пустых значений или значений независимых атрибутов этой сущности. Т. е. отношение находится в третьей нормальной форме, когда неключевые атрибуты - взаимно независимы, но зависят от первичного ключа. Два или несколько атрибутов - взаимно независимы, если ни один из них не зависит функционально от какой-либо комбинации остальных атрибутов. Подобная независимость подразумевает, что каждый атрибут может быть обновлен независимо от остальных. Процесс нормализации отношений позволяет избавиться от проблем, которые могут возникнуть при обновлении, внесении или удалении данных, а также при обеспечении целостности данных. Структуры старых БД не всегда можно привести к третьей нормальной форме, поэтому требуется, чтобы данные, находящиеся в транзитных файлах, существовали хотя бы в первой нормальной форме и относились к реляционной модели. В качестве унифицированного формата транзитных файлов используется формат DBF-файлов, поскольку многие СУБД, такие как DB2, FохРго и некоторые другие хранят данные в таких файлах, тем самым не требуется начальный перенос данных из старой СУБД в транзитные файлы. Большинство СУБД, формат хранения данных которых отличается от формата DBF-файлов, снабжены утилитами или драйверами, которые позволяют перенести данные в такой формат. Методы изменения (эволюции) компонентов и ПС Активное использование готовых ПС проводится при создании и сопровождении системы. При этом возникают разного рода ошибки, которые требуют внесения изменений в систему после того, как ошибка обнаружена или возникла необходимость в изменении или улучшении некоторых характеристик системы. В отличие от технического обеспечения, которое с течением времени требует ремонта, программное обеспечение не "снашивается", и поэтому процесс сопровождения нацелен более всего на эволюцию системы, то есть не только на исправление ошибок, а и на замену ее отдельных функций и возможностей. Типичные причины внесения изменений это:  выявление дефектов в системе во время эксплуатации, которые не были обнаружены на этапе тестирования;  выяснение несоответствия или невыполнения некоторых требований заказчика, благодаря чему система не выполняет отдельные функции;  изменение условий заказчиком, которые связаны с корректировкой ранее поставленных им требований. Как утверждают эксперты, процесс внесения изменений в эксплуатируемую систему достаточно дорогой, оценки его стоимости достигают от 60 до 80 % от общей стоимости разработки системы. К видам сопровождения относятся:  корректировка - внесение изменений в ПС для устранения ошибок, которые были найдены после передачи системы в эксплуатацию;  адаптация продукта к измененным условиям (аппаратуре, ОС) использования системы после ее передачи в эксплуатацию;  предупредительное сопровождение - деятельность, ориентированная на обеспечение адаптации системы к новым техническим возможностям. Одна из проблем, влияющая на процесс внесения изменений, - это степень подготовки персонала, способного вносить необходимые изменения при возникновении определенных нерегулярных условий. В связи с тем, что почти каждые 8-10 лет происходит смена архитектур компьютеров, ЯП и операционных сред, возникают проблемы сопровождения готовых ПС и их компонентов в новой среде или архитектуре, решение которых приводит к изменению либо обновлению отдельных элементов системы, или системы полностью. В общем, процесс изменения (эволюции) ПС проводятся путем:  анализа исходного кода для внесения в него изменений;  настройки компонентов и системы на новые платформы;  кодирования и декодирование данных при переходе с одной платформы на другую;  изменения функций системы или добавления новых;  расширения возможностей (сервиса, мобильности и др. ) компонентов;  преобразования структуры системы или отдельных ее компонентов. Цель внесения изменений в один компонент или в их совокупности - придание старой ПС нового назначения в новых условий применения. Методы изменения ПС служат способом продления жизни наследуемых и стареющих программ. С теоретической точки зрения эти методы изучены недостаточно, а с практической точки зрения многие программисты решают задачи внесения изменений в ПС постоянно. Например, широкий круг специалистов затронула проблема изменения формата даты в 2000 году. Для систематической переделки функционирующих программ к новым возможностям ОС, языков и платформ современных компьютеров и т. п. используются современный аутсорсинг (Индия, Россия, Украина и др. ). Внесение изменений в ПО можно рассматривать как эволюционный путь его развития. Эволюция ПО осуществляетсявнешними методами обработки компонентов в распределенной среде и внутренними методами, как изменение компонентов (СОМ), интерфейсов (Int) и/или систем. К внутренним методам эволюции отнесены методы реинженерии, рефакторинга и реверсной инженерии (рис. 10). Эти методы обеспечивают разноплановое изменение программ или систем. К ним относятся корректировка спецификаций, документации и программного кода в соответствии с требованиями на изменения. Рис. 10. Схема методов эволюции компонентов ПС Суть этих методов состоит в следующем:  реинженерия обеспечивает перепрограммирование отдельных компонентов в новые ЯП, платформы и среды, а также расширение возможностей ПС;  рефакторинг обеспечивает внесение изменений в компоненты или интерфейсы (добавление, расширение и т. д. ), добавление экземпляров компонентов, новых функций или системных сервисов; - реверсная инженерия означает полную переделку компонентов, а иногда и перепрограммирование всей системы. Реинженерия программных систем Реинженерия (reengineering) - это эволюция программы (системы) путем ее изменения в целях повышения удобства ее эксплуатации, сопровождения или изменения ее функций. Она включает в себя процессы реорганизации и реструктуризации системы, перевода отдельных компонентов системы в другой, более современный ЯП, а также процессы модификации или модернизации структуры и системы данных. При этом архитектура системы может оставаться неизменной. Метод реинженерии - целевое средство получения нового компонента путем выполнения последовательности операций внесения изменений, модернизации или модификации, а также перепрограммирования отдельных компонентов ПС. Реализуется совокупностью моделей, методов и процессов, изменяющих структуру и возможности компонентов с целью получения компонента с новыми возможностями. Новые компоненты идентифицируются именами, которые используются при создании компонентных конфигураций и каркасов системы. С технической точки зрения реинженерия - это решение проблемы эволюции системы путем изменения ее архитектуры в измененной среде, в которой компоненты размещаются на разных компьютерах. Причиной эволюции может быть изменение ЯП системы, например, Fortran, Сobol и др. с переходом на современные объектноориентированные языки, такие, как Java или C++. Однако с коммерческой точки зрения реинженерию принимают часто за единственный способ сохранения наследуемых систем в эксплуатации. Полная эволюция системы - дорогостоящая либо рискованная процедура продления времени существования системы. По сравнению с более радикальными подходами к совершенствованию систем реинженерия имеет следующие преимущества. 1. Снижение риска при повторной разработке ПС. В то же время существует риск получения неудовлетворительного результата при внесении ошибок в спецификации или при изменении функциональности некоторых программ. Снизить возникающие риски можно за счет удаления ошибок и улучшения качества работы измененных программ. 2. Снижение затрат за счет использования компонентов повторного использования при разработке новой ПС. Согласно данным различных коммерческих структур повторное использование в четыре раза дешевле, чем новая разработка системы. Реинженерия применяется для изменения деловых процессов, снижения количества излишних видов деятельности в них и повышения эффективности отдельных деловых процессов за счет внедрения новых программ или модификации существующих программ. Если бизнес-процесс зависит от наследуемой системы, то изменения в нее должны планироваться. Основное различие между реинженерией и новой разработкой системы состоит в том, что написание системной спецификации начинается не с "нуля", а с рассмотрения возможностей старой наследуемой системы. К основным этапам процесса реинженерии относятся:  перевод исходного кода в старом ЯП на современную версию этого языка либо в другой ЯП;  анализ программ по документированной структуре и функциональных возможностей системы; модификация структуры программ для наращивания новых свойств и возможностей;  разбиение системы на модули для их группирования и устранения избыточности;  изменение данных, с которыми работает программа, с учетом проведенных изменений в программе. Причинами, требующими преобразование исходного кода программ в другой язык, могут быть:  обновление платформы аппаратных средств, на которой может не выполняться компилятор ЯП;  недостаток квалифицированного персонала для программ, написанных в ЯП, вышедших из употребления;  изменение структуры программы в связи с переходом на новый стандартный язык программирования. К операциям реинженерии относятся:  именование компонентов и их идентификация;  расширение функций существующей реализации компонентов;  перевод языка компонента в новый современный ЯП;  реструктуризация структуры компонента;  модификация описания компонента и его данных. Рефакторинг компонентов Рефакторинг получил развитие в объектно-ориентированном программировании в связи с широким применением интерфейсов, шаблонов проектирования и методов улучшения кода. Разработаны библиотеки типовых трансформаций искомых объектов (классов), которые улучшают те или иные характеристики ПС. Метод рефакторинга компонента - это целевой способ получения нового компонента на базе существующего, который включает операции модификации (изменение, замещение, расширение) компонентов и интерфейсов. Цель метода преобразование состава компонентов ПС или изменение отдельного компонента системы для придания ему новых функциональных и структурных характеристик, удовлетворяющих требованиям конфигурации. Метод включает совокупность моделей, методов и процессов, применяемых к определенным классам объектов и компонентам для получения новых или измененных объектов компонентов с целью повышения качественных характеристик ПС или добавление новых возможностей. Процесс рефакторинга может быть ориентирован на получение новых компонентов, которые включают следующие операции по организации проведения изменений:  добавление новой реализации для существующего и нового интерфейса;  замена существующей реализации новой с эквивалентной функциональностью;  добавление нового интерфейса (при наличии соответствующей реализации);  расширение существующего интерфейса для новых системных сервисов в компонентной среде. Каждая операция рефакторинга - базовая, атомарная функция преобразования, сохраняющая целостность компонента, т. е. правила, ограничения и зависимости между составными элементами компонента, позволяющие рассматривать компонент как единую и цельную структуру со своими свойствами и характеристиками. После выполнения операций рефакторинга компоненты должны быть идентичны функциям исходного компонента. В случае коренного изменения группы компонентов системы путем внесения новых функций система приобретает новую функциональность. Операции над компонентами удовлетворяют условиям:  объект, полученный в результате рефакторинга, - это компонент с соответствующими свойствами, характеристиками и типичной структурой;  операция не изменяет функциональность компонента и новый компонент может применяться в ранее построенных компонентных системах;  перестройка компонентов, а иногда и перепрограммирования проводится в процессе реверсной инженерии. Реверсная инженерия Методы реверсной инженерии, которые разработаны в среде объектноориентированного программирования, базируются на выполнении базовых операций визуализации (visual) и измерения метрик (metric) ПС в рамках модели, которая предлагает следующие цели:  обеспечение высокого качества системы и переосвидетельствование ее размера, сложности и структуры;  поиск иерархии классов и атрибутов программных объектов с целью наследования их в ядре системы;  идентификация классов объектов с определением размера и/или сложности всех классов системы;  поиск паттернов, их идентификация, а также фиксация их места и роли в структуре системы. Этот подход ориентирован на индустриальные системы в миллион строк кода с использованием метрических оценок характеристик системы. Он разрешает генерацию тестов для проверки кодов, а также проведение метрического анализа системы для получения фактических значений внутренних и внешних характеристик системы. В результате анализа системы строится модель, которая содержит список классов и паттернов системы, которые могут модифицироваться и перепроектироваться и тем самым составлять процесс эволюции системы. Если некоторый класс плохо спроектирован (например, много методов, пустые коды) или  система не выполняет требуемую работу, то проводится сбор информации для изменения модели системы. В данном подходе действия по визуализации системы отражаются на экране в виде иерархического дерева, узлы которого отображают объекты и их свойства, а отношения задаются контурами команд фрагментов программ. При этом применяется таблица метрик, в которой находятся сведения о метриках классов объектов (число классов, атрибутов, подклассов и строк кода), метрик методов объектов (количество параметров, вызовов, сообщений и т. п. ), метрик атрибутов объектов (время доступа, количество доступов в классе и т. п. ). В процессе визуализации ведется сбор метрических данных о системе. Если реально определены все данные в разных фактических метриках ПС, выполняются оценка качества и разрабатывается план перестройки устаревшей системы на новую систему с получением тех же возможностей или еще и дополнительных. Таким образком, рассмотрены базовые понятия интерфейса, подходы к обеспечению интерфейса языков программирования и взаимодействия разноязыковых программ и данных. Определены общие проблемы неоднородности ЯП, платформ компьютеров и сред, влияющие на выполнение связей между разноязыковыми программами, сформулированы пути их решения. Изложены стандартные решения ISO/IEC 11404-1996 по обеспечению независимых от ЯП типов данных, стандарты преобразования форматов данных и эволюция программных систем. Контрольные вопросы: 1. Дайте определение интерфейса и перечислите основные виды интерфейсов. 2. Приведите схему вызова модулей A и B из С через интерфейсы A’ и B’. 3. Каким образом можно обратиться к услугам, предоставляемыми системами модели OSI? 4. Какие функции есть у интерфейсного посредника клиента в клиентсерверной архитектуре? 5. Что такое «маршалинг» и «демаршалинг» данных? 6. Приведите схему методов эволюции компонентов ПС. 7. Дайте определение реинженерии. 8. Какие преимущества у реинженерии? 9. Перечислите основные этапы процессы реинженерии. 10.Дайте определение методу рефакторинга компонентов. 11.Для чего используется реверсная инженерия. Раздел 2 Управление требованиями и качеством Методы определения требований 4 ч лекций Краткое содержание: Методы определения требований в программной инженерии: сбор, накопление, спецификации и классификация требований. Каждая программная система представляет собой определенный преобразователь данных и вывод результатов этого преобразования. Для построения ПС к ней формируются требования, которые определяют функции и разные виды обработки данных при выполнении функций. Эти требования являются предметом практического соглашения между заказчиком и разработчиком системы [3.1]. Рис. 3.1. Основные разделы разработки требований В общем случае под требованиями к ПС понимают свойства, которыми должна обладать система для адекватного выполнения предписанных ей функций. Примерами таких функций могут быть бизнес-функции, документооборот, управление данными и структурой информации, необходимой для принятия системных решений и др. В ядре знаний SWEBOK изложены основные концепции и особенности инженерии требований и приведены на рис. 3.1. Основные инструменты инженерии требований - UML и RUP, согласно которым требования определяются и уточняются с помощью вариантов использования use case, которые преобразуются к проектным решениям и к архитектуре системы. Далее рассмотрим общие, практические и объектно-ориентированные подходы к разработке требований к системе, учитывая приведенные разделы на рис. 3.1. 3.1. Общие подходы к определению требований Определение требований - это нетривиальная задача и проводится, как правило, путем обсуждения взглядов заказчика на систему с будущими ее разработчиками. Заказчик предъявляет свои потребности к автоматизации функций и задач системы и формулирует их в виде разных видов требований, классификация которых приводится ниже. 3.1.1. Классификация требований До настоящего времени отсутствуют общепринятые определения терминов, которыми пользуются для описания: требований пользователя, требований к ПО, функциональных требований, системных требований, технологических требований и требований к продукту. В разных источниках понятие требований определяются исходя из разных взглядов на то, что по ним создается. Согласно ряду публикаций формирование требований к ПО рассматривается как некоторая деловая игра, во время которой выявляются интересы заинтересованных в разработке ПО лиц, правила реализации этих интересов в конкретном ПО. При этом высказываются разного рода претензии и ограничения на свойства и способы обеспечения требований для получения конечного результата - программного продукта. Кроме того, нет формализованных методов сбора и описания требований, а также отсутствует общепринятое определение самого понятия - требование. Приведем некоторые из них [3.1-3.3]. Требования - это утверждения о функциях и ограничениях системы. Требования - это свойства, которыми должен обладать продукт, чтобы представлять какую-то ценность для пользователей. Требования - это спецификация того, что и как должно быть реализовано. Согласно международному глоссарию по терминологии требования включают описание: 1. условий или возможностей, необходимых пользователю для решения поставленных проблем или достижения целей; 2. функций и ограничений, которыми должна обладать система или системные компоненты, чтобы выполнить договор заказчика на разработку системы; 3. положений и регламента используемых стандартов, отображаемых в спецификациях или других формальных документах на систему; 4. документированное представление условий, возможностей ограничений среды на проектирование системы. Требования к продукту охватывают условия пользователей на внешнее поведение системы и разработчиков на некоторые параметры системы. Термин пользователи относится ко всем лицам, заинтересованным в создании системы. Требования к ПО состоят из требований пользователей, функциональных, системных и нефункциональных требований. Требования пользователей (user requirements) основываются на целях и задачах, которые пользователям позволит решать будущая система. К способам представления этого вида требований относятся варианты использования, сценарии, прецеденты, таблицы "событие-отклик" и т.п. Системные требования (system requirements) определяют внешние условия для выполнения системных функций и ограничений на создаваемый продукт, а также требования к описанию подсистем (функциональных, программно-аппаратных). Системные требования накладывает ограничения на архитектуру системы, средства ее представления и функционирования. Для описания системных требований используются специальные шаблоны и формы, помогающие описывать входные и выходные данные и автоматизировать трассировку требований. Требования к атрибутам качества (quality attributes) представляют собой некоторые ограничения к свойствам функций или к системе, важных для пользователей или разработчиков. Например, переносимость, целостность и устойчивость к сбоям системы. Функциональные требования - это перечень функций или сервисов, которые должна выполнять система, а также ограничений на данные и поведение системы. Спецификация функциональных требований (software requirements specification) включает в себя описание функций, которые не должны быть противоречивыми и взаимоисключающими. Нефункциональные требования определяют условия и среду выполнения функций (например, защита и доступ к БД, секретность и др.), они непосредственно не связаны с функциями, а отражают пользовательские потребности к выполнению функций. Они характеризуют принципы взаимодействия со средами или другими системами, а также учитывают время работы, защиту данных, а также стандарты качества для достижения отдельных показателей или атрибутов качества. Эти требования отражают потребности заказчиков системы, т.е. тех, кто финансирует проект, покупает систему или проводит ее маркетинг. Нефункциональные требования могут иметь числовое представление (время ожидания ответа, количество обслуживаемых клиентов, объем БД и др.), а также содержать значения показателей надежности системы, период смены версий системы и др. Для большинства современных многопользовательских ПС требования включают условия и ограничения типа:  конфиденциальность, безопасность и защиту данных;  отказоустойчивость;  одновременность доступа к системе пользователей;  время ожидания ответа при обращении к системе (производительность);  состав выполняемых функций системы (запуск, скорость реакции и др.);  стандартные положения к формулировке требований. Для каждой системы формулируются нефункциональные требования, относящиеся к защите данных, несанкционированному доступу, к регистрации событий системы (резервное копирование, восстановление БД, аудит отказов и др.). Эти требования на этапе анализа и проектирования структуры системы определяются и формализуются аналитиками. В случае обеспечения безопасности системы определяются категории пользователей системы, которые имеют право доступа к тем или иным данным и компонентам. При этом используется система мер по регистрации пользователей, их идентификация, аутентификация и др. Защита данных реализуется в соответствии с регламентированным доступом к данным (например, к таблицам, файлам, БД). Если же требуется ограничить доступа к данным (например, к отдельным записям, полям в таблице), то в системе предусматриваются специальные средства (например, мандатная защита). Для восстановления и хранения резервных копий БД, архивов баз данных анализируются возможности СУБД и способы обеспечения требуемого уровня бесперебойной работы системы, а также правил доступа неавторизованных пользователей и мер борьбы с разными угрозами, которые поступают извне от пользователей, не имеющих прав доступа к некоторым данным или ко всем данным системы. К выходному продукту предъявляются нефункциональные требования:  к применению (качество пользовательского интерфейса, учебные курсы и др.);  к производительности (пропускная способность, время реакции и др.);  к надежности выполнения (ошибки, интенсивность отказов и др.);  к интерфейсным внешним атрибутам, с которыми взаимодействует система. Процесс описания функциональных и нефункциональных требований, а также требований к характеристикам качества с учетом стандарта ISO/IEC 9126-94 уточняется при разработке архитектуры системы. При спецификации требований важной является проблема стандартизации терминологии для нескольких классов ПрО (например, информационные технологии, системы реального времени и др.). Имея стандартизированный понятийный базис для большинства ПрО, можно достигнуть единого с заказчиком понимания терминов, которые используются при описании концептуальной модели и спецификации требований к системе. В спецификациях требований используются терминологические дескрипторы и общепринятые термины, принятые для структуры ПО и функций, названий показателей качества, документации, алгоритмов и структур данных. С помощью спецификаций системных и нефункциональных требований задаются принципы взаимодействия проектируемой системы с другими средами, платформами и общесистемным обеспечением (БД, СУБД, сеть и др.). Документ со спецификациями требований завершается на этапе проектирования архитектуры и согласуется с заказчиком и разработчиком. В дальнейшем этот документ используется в качестве руководства к действиям при выполнении задач на этапах ЖЦ разработки программного продукта. При выявлении на этих этапах несогласованных требований, проводится их уточнение и соответственно изменение процесса разработки системы. Методы анализа требований 4 ч лекций, 4 ч лабораторных работ Краткое содержание: Методы анализа требований. Структурный анализ: диаграммы потоков данных; описание потоков данных и процессов. Методы анализа, ориентированные на структуры данных. Метод анализа Джексона. 3.1.2. Анализ и сбор требований В современных информационных технологиях процесс ЖЦ, на котором фиксируются требования на разработку системы, является определяющим для задания функций, сроков и стоимости работ, а также показателей качества, которых необходимо достигнуть в процессе разработки. Выдвижение требований проводится путем обсуждения проекта, анализа предметной области и определения подходов к проектированию промежуточных продуктов на этапах ЖЦ. Требования отражают потребности людей (заказчиков, пользователей, разработчиков), заинтересованных в создании ПС. Заказчик и разработчик совместно проводят обсуждение проблем проекта, сбор требований, их анализ, пересмотр, определение необходимых ограничений и документирование. Обсуждение проекта системы проводится в целях выработки первых впечатлений и выводов относительно целесообразности выполнения проекта и прогнозирования реальности его выполнения в заданные сроки и бюджет, которые определяет заказчик. Современные ПС предоставляют набор услуг для выполнения функций ПрО, которые ориентированны на определенную профессиональную деятельность пользователей (например, веб-сервисы). Лицо, которое заказало проект системы, желает получить от разработчика набор необходимых услуг. К участникам системы относятся операторы, менеджеры разных уровней, бухгалтеры и т.п. Именно они будут обращаться к системе за услугами, получать от нее сообщения, реагировать на них в соответствии со своими профессиональными обязанностями. Оценить возможность реализации услуг в проекте заказываемой системы в заданный срок и бюджет, могут разработчики системы. Среди них назначается главный аналитик, ответственный за требования к системе и главный программист, ответственный за их реализацию. Они проводят согласование требований и определение области действия проекта на совместных переговорах с заказчиком для уточнения следующих вопросов: спектра проблем ПрО, при решении которых будут реализованы услуги системы;  функциональное содержание услуг;  операционную среду работы системы. В обсуждении требований на систему принимают участие:  представители заказчика из нескольких профессиональных групп;  операторы, обслуживающие систему;  аналитики и разработчики будущей системы. Согласованная область действий по проекту дает возможность оценить требуемые инвестиции в проект, заранее определить возможные риски и способности разработчиков выполнить проект. Итогом обсуждения проекта может быть решение о развертывании реализационных работ на проекте или отказ от него. Анализ требований начинается после обсуждения проблематики проекта. При рассмотрении требований среди них могут оказаться  неочевидные, не одинаково важные, которые брались из устаревших источников и документов заказчика;  разные типы, которые соответствуют разным уровням детализации проекта и требующие применения методов управления ими;  постоянно изменяемые, развиваемые и уточняемые;  с уникальными свойствами или значениями;  сложные по форме и содержанию, трудные для согласования их с заказчиком. Разработчики требований должны обладать определенными знаниями в данной предметной области и уметь провести:  анализ проблем предметной области, потребностей заказчика и пользователей системы,  выявление функций системы, которые должны быть реализованы в проекте,  внесение изменений в отдельные элементы требований. В требованиях к ПС, кроме проблем системы, фиксируются реальные потребности заказчика, касающиеся функциональных, операционных и сервисных возможностей разрабатываемой системы. Результаты обследования и анализа предметной области фиксируются в документе описания требований и в договоре между заказчиком и исполнителем проекта.  Ошибки по причине нечетких или неоднозначных формулировок требований, которые могут привести к тому, что будет изготовлена система, не удовлетворяющая заказчика. Поэтому на этапах разработки требования должны постоянно уточняться и переутверждаться заказчиком. В отдельных случаях внесенные изменения в требования могут привести к необходимости перепроектировать отдельные части или всю систему в целом. Согласно статистике, доля ошибок в постановке требований и в определении задач системы превышает долю ошибок, допускаемых во время кодирования системы. Это объясняется субъективным характером процесса формулирования требований и отсутствием способов их формализации. В США, например, ежегодно расходуется до $ 82 млрд. на проекты, признанные после реализации не соответствующими требованиям заказчиков. Существующие стандарты (ГОСТ 34.601-90 и ГОСТ 34.201-89) на разработку требований к системе и документам фиксируют результаты создания программного, технического, организационного и др. видов обеспечения автоматизированных систем на этапах ЖЦ. Сбор требований. Источниками сведений для формирования требований могут быть:  цели и задачи проекта, которые формулирует заказчик разработчиком будущей системы, должны осмысливаться ими;  коллектив, выполняющий реализацию функций системы, не должен использовать старую систему, переставшую удовлетворять заказчика или персонал. Изучение и фиксация реализованных функциональных возможностей в действующей системе дает основу для учета имеющегося опыта и формулирования новых требований к ней. При этом необходимо отделить новые требования от требований к старой системе, чтобы не повторить неудачные решения старой системы в новом ее варианте. Требования к системе формулируются заказчиком в терминах понятий проблемной области с учетом терминологического словаря, ведомственных стандартов, условий среды функционирования будущей системы, а также трудовых и финансовых ресурсов, выделенных на разработку системы. Методы сбора требований следующие:  интервью с представителями интересов заказчика системы;  наблюдение за работой действующей системы для отделения проблемных свойств, которые обусловлены кадровыми ресурсами; примеры возможных вариантов выполнения функций, ролей ответственных лиц, запускающих эти варианты или взаимодействующих с системой при ее развертывании и функционировании. Внешние и внутренние аспекты требований соответствуют характеристикам качества и касаются свойств создаваемого продукта, а именно функциональности системы, ее назначения и выполнения в заданной среде. Конечный пользователь ожидает достижения максимального эффекта от применения выходного продукта и ориентируется на его конечное эксплуатационное качество. При определении требований, относящихся к внешним и внутренним характеристикам качества, выбираются методы их достижения на процессах ЖЦ. Внутренние характеристики предназначены для достижения необходимых внешних показателей качества и применяются при оценке промежуточных (рабочих) продуктов ПС на процессах ЖЦ. Разработанные требования представляются в специальном документе неформально, который является основой заключения контракта на разработку системы между заказчиком и разработчиком. 3.1.3. Инженерия требований Инженерная дисциплина анализа и документирования требований заключается в преобразовании предложенных заказчиком требований к системе в описание требований к ПО, их спецификацию и валидацию. Она базируется на моделях процессов разработки требований, действиях актеров и управлении постепенным преобразованием требований к проектным решениям и спецификациям компонентов с обеспечением их качества. Модель процесса определения требований - это схема процессов ЖЦ, которые выполняются от начала проекта и до тех пор, пока не будут определены и согласованы требования. Управление требованиями к ПО заключается в планировании и контроле формирования требований, задании на их основе проектных решений, в преобразовании их в спецификации компонентов системы на других процессах. Качество и процесс улучшения требований - это процесс проверки характеристик и атрибутов качества (надежность, реактивность и др.), которыми должна обладать система и ПО, методы их достижения на процессах ЖЦ. Управление требованиями к системе - это руководство процессами формирования требований на всех этапах ЖЦ, которое включает управление изменениями требований, отражающих свойства программного продукта, а  также восстановление источника требований. Неотъемлемой составляющей процесса управления является трассирование требований, состоящее в отслеживании правильности задания и реализации требований к системе и ПО на этапах ЖЦ и обратный процесс сверки ПС с заданными требованиями. Основные задачи управления требованиями это:  разработка атрибутов требований,  управление вариантами требований,  управление рисками, возникающими при неточном определении требований,  контроль статуса требований, измерение усилий при формировании требований;  реализация требований на этапах ЖЦ. Разработка и управление требованиями связана с другими областями знаний (рис. 3.2.): проектирование, интеграция, управление качеством, версиями, рисками и др. Кроме того, приведены основные задачи разработки требований: спецификация и утверждение, формирование проектных решений. Рис. 3.2. Разработка, управление требованиями и связь с задачами SWEBOK Планирование работ на проекте касается вопросов организации интеграции компонентов, управления рисками, версиями системы, на которые влияют заданные требования и их изменения. Управление рисками состоит в контроле появления и обнаружения неадекватных ситуаций при реализации требований, оценке их влияния на другие процессы и в предупреждении рисковых ситуаций. Управления версиями системы включает формирование конфигурации системы в принятых для системы терминах и обозначениях. 3.1.4. Фиксация требований Сбор требований является начальным этапом процесса разработки ПС, завершается формированием списка требований к системе, именуемого в отечественной практике техническим заданием. Фиксация требований (Requirement Capturing) в техническом задании определяется желаниями заказчика получить при реализации заданные им свойства системы. При этом предусмативается спецификация, верификация и валидация требований на правильность, соответствие и полноту. Спецификация требований к ПО - это формализованное описание функциональных, нефункциональных и системных требований, требований к характеристикам качества, а также к структуре ПО, принципам взаимодействия с другими компонентами, алгоритмам и структуре данных системы. Валидация требований - это проверка требований, для того чтобы убедиться, что они определяют именно данную систему. Заказчик и разработчик ПО проводят экспертизу сформированного варианта требований с тем, чтобы разработчик мог далее проводить его проектирование. Одним из методов валидации является прототипирование, т.е. быстрая отработка отдельных требований на конкретном инструменте, анализ масштаба изменения требований, измерение функциональности и стоимости системы, а также определение зрелости процессов определения требований. Верификация требований - это процесс проверки правильности спецификации требований на их соответствие, непротиворечивость, полноту и выполнимость, а также на соответствие стандартам. В результате проверки требований создается согласованный выходной документ, устанавливающий полноту и корректность требований к ПО, а также возможность продолжить проектирование ПО. 3.1.5. Трассировка требований Одной из главных проблем сбора требований является проблема их изменения. Требования создаются итерационно путем постоянного общения представителей заказчиков с аналитиками и разработчиками будущей системы в целях выявления потребностей. Требования изменяются в зависимости от задач и условий их определения, а также постоянного уточнения на этапе заключения договора на создание системы. На момент заключения договора состав требований, их виды и свойства становятся более полными, т.е. соответствуют взглядам заказчика на создаваемую систему [3.4]. Одним из инструментов установления зависимости между сформулированными требованиями и их изменениями является трассировка, т.е. поддерживается развитие и обработка требований с прослеживанием идентифицированных связей, которые должны быть зафиксированы по двум направлениям - от источника требований к реализации и, наоборот (рис. 3.3.). Выявляются причины появления разнообразных неточностей, добавлений и определяется необходимость внесения изменений в требования в одном из приведенных направлений. Рис. 3.3. Типы трассируемости требований Если после разработки некоторого рабочего продукта возникает потребность в изменении отдельных требований или необходимость проследить за происхождением внесенных требований в одном из направлений данной схемы трассирования, то уточняются связи между отдельными требованиями и элементами рабочих продуктов В случае трассирования требований от продукта, движение в обратном направлении, т.е. - к требованиям, можно выяснить, как написана каждая строка этого продукта и соответствует ли она отдельным атрибутам требований. Связи трассируемости требований помогают найти незапланированные и реализованные некоторые функции или фрагменты программ, не соответствующие заданным требованиям. И, наоборот, выявить нереализованные требования к функциональности. Взаимосвязи и зависимости между отдельными требованиями сохраняются, например, в таблице трассируемости, удаляются или модифицируются при различных изменениях. Методы трассировки базируются на формальных спецификациях связей между элементами требований либо ограничиваются описаниями функций, ситуаций, контекста и возможных решений. Основу трассировки составляют:  требования, которые изменяются при их формировании;  некоторые детали выполнения функций в рабочем продукте системы, которые не предусматривались, но появились в связи с возникшей практической ситуацией;  связи между различными моделями процесса проектирования системы на ЖЦ программного продукта и принятые решения о необходимости изменения требований в связи с появившимися недостатками в промежуточном продукте;  информация о согласованных атрибутах требований на разных уровнях рассмотренной схемы трассирования и сохранение ее матрице трассирования;  специальные системные требования, касающиеся повторного использования готовых компонентов или частей системы;  результаты тестирования, по которым можно определить наиболее вероятные части кода, требующие проверки на наличие в них дефектов. В матрице требований в строках указываются пользовательские требования, а столбцах - функциональные требования, элемент проектирования, вариант версии и др. В этих столбцах заполняются данные о степени выполнимости системных требований на каждом элементе создаваемого продукта. Механизм ссылок в таблице позволяет проверять связанные с каждым элементом продукта диаграммы вариантов использования, потоки данных, классы и др. Процедура трассирования состоит в следующем:  выбирается элемент (функция, фрагмент или некоторая часть) из матрицы трассирования требований, за которым проводится прослеживание на этапах ЖЦ;  составляется список вопросов, по которым на каждом этапе проверяются связи при реализации требований в продукте, и если изменяется какое-то звено в цепочке требований (рис. 3.3.), то может модифицироваться процедура разработки этого элемента на последующем этапе ЖЦ;  проводится мониторинг статуса каждого требования на соответствие выполнения согласно принятому плану;  уточнение ресурсов выполнения проекта при необходимости проведения изменений в требования и в элементы проекта. Условием принятия решения о возможных модификациях требований и результатов промежуточного проектирования, является обновленная информация о связях между различными частями системы и первоначально заданными требованиями к ним. Трассировка обеспечивает:  ввод более сложных отношений вместо простых связей или специфических отношений;  использование разных путей трассировки (между моделями или иерархическими связями);  ведение базы данных объектов трассировки и отношений между ними. Трассировка может быть выборочной для отдельных объектов или связанной с другими объектами, а также с возможными переходами от одной модели проектирования к другой путем проверки трансформации одних объектов в другие. 3.2. Объектно-ориентированная инженерия требований В объектно-ориентированных подходах и методах разработки программных систем главным является объект. Объектно-ориентированный подход, в частности UML моделирование позволяет с помощью вариантов использования задавать требований. Основные средства UML к формированию и представлению требований к системе и к ПО - это use case сценарии или прецеденты. Представленные сценариями или прецедентами требования к системе в UML, последовательно трансформируются к другим сценариям, приближающим к логической структуре системы. Главные элементы сценариев - это объекты, классы объектов и акторы, задающие действия по выполнению системы. 3.2.1. Сценарный подход Одним из методов построения проектной модели системы, логической и физической моделей являются сценарии use case, используемые для визуального представления требований в проектной модели системы. Эта модель уточняется и дополняется новыми сценариями для получения логической и физической моделей. Термин сценарий обозначает некоторый вариант представления модели выполнения системы [3.1, 3.5]. При применении сценарного подхода общая цель системы декомпозируется на отдельные подцели, для которых определяются функциональные или нефункциональные требования и проектные решения. Цели, как источники требований к системе, позволяют выявить противоречия и ограничения на выполнение функций и установить зависимости между ними, устранить конфликты между целевыми функциями, а также объединить некоторые из них между собою в определенные отношения. После выявления целей определяются носители интересов, которым отвечает каждая цель, и возможные варианты удовлетворения составных целей в виде сценариев работы системы, которые помогают пользователю получить представление о назначении и функциях системы. Это соответствуют первой итерации определения требований к разработке системы. Далее производится последовательная декомпозиция сложной проблемы к виду совокупности целей, каждая из которых трансформируется в совокупность возможных сценариев использования системы, а затем в совокупность взаимодействующих объектов. Т.е. имеем цепочку трансформаций: проблема цель сценарий объект. Она отражает степень концептуализации анализируемой проблемы, и ее декомпозицию с помощью вариантов использования для снижения сложности системы. Трансформация данной цепочки выражается в терминах базовых понятий проблемной области и активно используется для представления и развития моделей системы. Каждый сценарий инициирует актор, выступающий в роли пользователя определенной работы в системе, представленной этим сценарием. Фиксацию ролей акторов можно рассматривать как определенный шаг при выявлении целей системы и постановщиков задач, для решения которых создается система. Актор - это внешний фактор и его действия, носящие недетерминированный характер. В роли актора может выступать и программная система, если она инициирует выполнение некоторых работ, удовлетворяющих поставленной цели системы. Актор, как абстракция внешнего объекта, может быть человеком или внешней системой. В модели системы актор может быть представлен классом, а пользователь экземпляром класса. Если актором является другая ПС, то он будет представлять ее интересы. При этом одно лицо может быть экземпляром нескольких акторов. Если актор находится вне системы, то он взаимодействует с ней через сценарий, который инициализирует последовательность операций для выполнения системы. Когда пользователь, как экземпляр актора, вводит определенный символ для старта экземпляра соответствующего сценария, то это приводит к выполнению ряда действий в системе, которые заканчиваются тогда, когда экземпляр сценария находится или в состоянии ожидания очередного входного символа или завершения сценария Экземпляр сценария существует, пока он выполняется и его можно считать экземпляром класса, он имеет состояние и поведение. Взаимодействие между актором и системой порождает новый сценарий или объект, которые изменяют внутреннее состояние системы. Если несколько сценариев системы имеют одинаковое поведение, то их можно рассматривать как класс сценариев. При внесении изменений осуществляется повторное моделирование акторов и запускаемых ими сценариев. Сценарий - это цепочка событий, инициированных актором, и реакции на них. Каждого актора обслуживает соответствующая совокупность сценариев. Можно выделить базовую цель событий, существенную для сценария, и альтернативную в случае ошибок пользователя и др. Для задания модели сценариев используется специальная графическая нотация со следующими правилами:  актор обозначается иконой человека, под которой указывается название;  сценарий изображается овалом, в середине которого указывается название иконы;  актор связывается стрелкой с каждым овалом запускаемого им сценария. Пример диаграммы сценариев для читателя библиотеки в роли актора, который запускает заданный сценарий при обращении к автоматизированной системе обслуживания библиотеки, представлен на рис. 3.4. Все сценарии, которые включены в систему, обведены рамкой, определяющей границы системы, а актор находится вне рамки, являясь внешним фактором по отношению к системе. Рис. 3.4. Пример диаграммы сценариев Отношения между сценариями.Между сценариями задаются отношения пунктирными стрелками с указанием названия типа отношений. Для сценариев можно задавать два типа отношений: 1. отношение "расширяет" означает, что функция одного сценария является дополнением к функции другого и используется при наличии нескольких вариантов одного и того же сценария (рис. 3.5). Рис. 3.5. Пример отношения "расширяет" Инвариантная часть сценария изображается в виде основного сценария, а отдельные варианты как расширения. При этом основной сценарий является устойчивым, не меняется при расширении вариантов функций и не зависит от них. 2. отношение "использует" означает, что некоторый сценарий может быть использован как расширение нескольких других сценариев (рис. 3.6). Рис. 3.6. Пример отношения "использует" На данном рисунке показан сценарий "ведение репозитария", который связан отношением "использует" с несколькими сценариями - разработка интерфейса, описание компонента, создание схемы развертки. Инженерия требований завершается построением модели требований, которая включает в себя: 1. описание требований и основных понятий ПрО; 2. модель сценариев; 3. интерфейсы сценариев. Модель сценариев - это неформальное описание каждого из входящих в нее диаграмм сценариев. Описание сценария задается последовательностью следующих элементов:  название сценария (некоторой цели системы), задаваемое на диаграммах модели требований, и которое является ссылкой на другой сценарий;  краткое содержание сценария в неформальном представлении;  список акторов, которые будут запускать сценарии модели;  параметры взаимодействия системы с акторами, запрещенные действия актора и возможные последствия;  предусловия, определяющие начальное состояние сценария на момент его запуска, и условия успешного выполнения;  функции, которые реализуются при выполнении сценария;  нестандартные ситуации, которые могут появиться при выполнении сценария (например, ошибка в действиях актора или системы). На дальнейших этапах ЖЦ сценарий актора трансформируется в сценарий поведения системы, т.е. к элементам модели добавляются нефункциональные требования, обеспечивающие запуск сценария, ввод данных и отработку нестандартных ситуаций. На процессе проектирования ЖЦ выполняется преобразование трансформированного сценария в описание функциональных компонентов системы и проверка их правильности методом верификации. В описании интерфейсов компонентов отражаются требования пользователей к системе, собранные на этапах анализа, сбора и определения требований. Компоненты и их интерфейсы размещаются в репозитарии. На основе построенных сценариев можно построить прототип системы для моделирования действий акторов при выполнении сценариев и отработке разных их деталей. 3.2.2. Описание требований прецедентами Альтернативным термином для сценария являются прецеденты. Как и в случае сценариев, задача описания требований прецедентами сводится к анализу дерева целей системы и к описанию реакции системы в случае недостижимости той или иной поставленной цели к проектируемой системе. Основным условием описания требований с помощью прецедентов является полнота системных требований, касающихся интерфейса пользователя, протоколов и форматов ввода-вывода [3.2,3.5]. Содержательной стороной системной части требований является описание функций, данных и принципов функционирования. Методология формирования требований с помощью прецедентов реализована в среде Rational Rose (www.rational.com.uml) и включает построение ряда моделей на основе прецедентов. Функциональные возможности проектируемой системы могут задаваться набором прецедентов, каждый из которых представляет некоторый поток событий в системе, когда прецедент будет выполнен. Каждый прецедент выполняет свою задачу. Набор прецедентов устанавливает все возможные пути применения системы. Прецеденты играют определенную роль в каждом из основных процессов проектирования: разработка требований, анализ и проектирование, выполнение и испытание системы. Экземпляр прецедента - это последовательность действий, выполняемых системой и наблюдений за получением результата. В управляемом прецедентами проекте разрабатываются два представления системы - внешнее и внутреннее. Прецедент отражает внешнее представление ПрО, которое определяет, что должно исполниться в системе, чтобы обеспечить заказчику требуемые результаты. Это представление разрабатывается, когда проводится обсуждение целей и задач системы и задание их прецедентами. Во внешнем представлении прецендента определяются принципы взаимодействия системы и ее субъектов. Реализация прецедента является внутренним его представлением в системе и принципом организации работы системы для достижения планируемых результатов. Она охватывает сущности, которые участвуют в выполнении прецедента, и связи между ними. Иными словами, разрабатывается такое представление прецедентов, чтобы каждый из прецедентов выполнял определенное действие для достижения требуемых результатов. В процессе анализа проблемы и формирования требований создается модель прецедентов моделируемой цели системы, которая состоит из:  используемых терминов (глоссария) предметной области;  основных действующих лиц и их целей;  используемых технологий и принципов взаимодействия с другими системами;  требований к форматам и протоколам взаимодействия;  требований к тестированию и к процедуре развертывания системы у заказчика; организационных вопросов управления процессом разработки системы. На этапе анализа и проектирования модель прецедентов реализуются в модели проекта в терминах взаимодействующих объектов, т.е. дается описание того, как прецедент будет выполняться в системе. С синтаксической точки зрения эта модель имеет следующий вид. <Модель прецедента> ::= <имя прецедента/действующего лица>, <имя роли / краткое описание роли действующего лица>, <описание границ системы>, <список всех заинтересованных лиц в анализе ключевых целей системы>, <исходные условия>, <результат успешного завершения определения целей системы>, <шаги сценария для формирования шаблона достижения целей проекта>, <описание информации, необходимой разработчику для реализации системы>. Данный подход к представлению системы с помощью прецедентов задается в форме Vision-шаблонов [3.5]. Он применяется в офисной сфере, где деловой прецедент отражает представление этой сферы с внешней стороны, чтобы обеспечить субъекта требуемыми результатами. При выполнении делового прецедента определяется взаимодействие деловой сферы и субъекта. Совокупность деловых прецедентов устанавливает границы системы. Внутреннее представление делового прецедента - это реализация, которая охватывает функции деловых работников и соответственно участвующих в их выполнении, а также связи между ними. Такое задание системы разрабатываются для того, чтобы решить, как должна быть организована работа в каждом деловом прецеденте для достижения результатов.  Характеристики качества ПО 4 ч лекций, 4 ч лабораторных работ Краткое содержание: Внутренние и внешние характеристики качества ПО. Методики повышения качества ПО и оценка их эффективности. Стандарты IEEE, связанные с качеством ПО. Закон контроля качества ПО. СММ (модель зрелости процесса разработки ПО). Разработка ПС достигла такого уровня развития, что стало необходимо использовать инженерные методы, в том числе для оценивания результатов проектирования на этапах ЖЦ, контроля достижения показателей качества и метрического их анализа, оценки риска и степени использования готовых компонентов для снижения стоимости разработки нового проекта. Основу инженерных методов в программировании составляет повышение качества, для достижения которого сформировались методы определения требований к качеству, подходы к выбору и усовершенствованию моделей метрического анализа показателей качества, методы количественного измерения показателей качества на этапах ЖЦ. Главная составляющая качества - надежность, которой уделяется большое внимание в области надежности технических средств и тех критических систем (реального времени, радарные системы, системы безопасности и др.), для которых надежность - главная целевая функция оценки их реализации. Как следствие, в проблематике надежности разработано более сотни математических моделей надежности, являющихся функциями от ошибок, оставшихся в ПС, от интенсивности отказов или частоты появления дефектов в ПС. На их основе производится оценка надежности программной системы. Качество ПО - предмет стандартизации. Стандарт ГОСТ 2844-94 дает определение качества ПО как совокупность свойств (показателей качества) ПО, которые обеспечивают его способность удовлетворять потребности заказчика в соответствии с назначением. Этот стандарт регламентирует базовую модель качества и показатели, главным среди них - надежность. Стандарт ISO/IEC 12207 определил не только основные процессы ЖЦ разработки ПС, но и организационные и дополнительные процессы, которые регламентируют инженерию, планирования и управления качеством ПС. Согласно стандарту на этапах ЖЦ должен проводиться контроль качества ПО:  проверка соответствия требований проектируемому продукту и критериев их достижения;  верификация и аттестация (валидация) промежуточных результатов ПО на этапах ЖЦ и измерение степени удовлетворения достигаемых отдельных показателей;тестирование готовой ПС, сбор данных об отказах, дефектах и других ошибках, обнаруженных в системе;  подбор моделей надежности для оценивания надежности по полученным результатам тестирования (дефекты, отказы и др.); оценка показателей качества, заданных в требованиях на разработку ПС. Далее излагаются модели качества и надежности, а также способы их применения. 10.1. Модель качества ПО Качество ПО - это относительное понятие, которое имеет смысл только при учете реальных условий его применения, поэтому требования, предъявляемые к качеству, ставятся в соответствии с условиями и конкретной областью их применения. Оно характеризуется тремя аспектами: качество программного продукта, качество процессов ЖЦ и качество сопровождения или внедрения (рис. 10.1).  Рис. 10.1. Основные аспекты качества ПО Аспект, связанный с процессами ЖЦ, определяет степень формализации, достоверности самих процессов ЖЦ разработки ПО, а также верификацию и валидацию промежуточных результатов на этих процессах. Поиск и устранение ошибок в готовом ПО проводится методами тестирования, которые снижают количество ошибок и повышают качество этого продукта. Качество продукта достигается процедурами контроля промежуточных продуктов на процессах ЖЦ, проверкой их на достижение необходимого качества, а также методами сопровождения продукта. Эффект от внедрения ПС в значительной степени зависит от знаний обслуживающего персонала функций продукта и правил их выполнения. Модель качества ПО имеет следующие четыре уровня представления. Первый уровень соответствует определению характеристик (показателей) качества ПО, каждая из которых отражает отдельную точку зрения пользователя на качество. Согласно стандарту [10.1-10.4] в модель качества входит шесть характеристик или шесть показателей качества: 1. функциональность (functionality); 2. надежность (realibility); 3. удобство (usability); 4. эффективность (efficiency); 5. сопровождаемость (maitainnability); 6. переносимость (portability). Что такое функциональность ПО? Ответ: набор возможностей (функций), которые предоставляет данное программное обеспечение. Что такое надежность ПО? Ответ: способность программного продукта безотказно выполнять определенные функции при заданных условиях в течение заданного периода времени с достаточно большой вероятностью. Что такое удобство ПО? Ответ: характеристика степени удобности программного обеспечения для применения пользователями при достижении определённых целей. Что такое эффективность ПО? Ответ: характеристика достижения каких-либо определённых результатов от ПО с минимально возможными издержками. Что такое сопровождаемость ПО? Ответ: характеристика процесса улучшения, оптимизации и устранения дефектов программного обеспечения после передачи его в эксплуатацию. Что такое переносимость ПО? Ответ: характеристика, отражающая адаптацию ПО или его части, с тем чтобы оно работало в другой среде, отличающейся от той среды, под которую оно было изначально написано с максимальным сохранением его пользовательских свойств. Второму уровню соответствуют атрибуты для каждой характеристики качества, которые детализируют разные аспекты конкретной характеристики. Набор атрибутов характеристик качества используется при оценке качества. Третий уровень предназначен для измерения качества с помощью метрик, каждая из них согласно стандарту [10.1] определяется как комбинация метода измерения атрибута и шкалы измерения значений атрибутов. Для оценки атрибутов качества на этапах ЖЦ (при просмотре документации, программ и результатов тестирования программ) используются метрики с заданным оценочным весом для нивелирования результатов метрического анализа совокупных атрибутов конкретного показателя и качества в целом. Атрибут качества определяется с помощью одной или нескольких методик оценки на этапах ЖЦ и на завершающем этапе разработки ПО. Четвертый уровень - это оценочный элемент метрики (вес), который используется для оценки количественного или качественного значения отдельного атрибута показателя ПО. В зависимости от назначения, особенностей и условий сопровождения ПО выбираются наиболее важные характеристики качества и их атрибуты (рис. 10.2). Выбранные атрибуты и их приоритеты отражаются в требованиях на разработку систем либо используется соответствующие приоритеты эталона класса ПО, к которому это ПО относится. увеличить изображение Рис. 10.2. Модель характеристик качества 10.1.1. Характеристика показателей качества Краткое описание семантики характеристик модели качества приведены в табл. 10.1, а их содержательное описание - ниже. Таблица 10.1. Краткая характеристика показателей качества Показатель Описание свойств показателя Функциональность Группа свойств ПО, обуславливающая его способность выполнять определенный перечень функций, которые удовлетворяют потребностям в соответствии с назначением Надежность Группа свойств, обусловливающая способность ПО сохранять работоспособность и преобразовывать исходные данные в результат за установленный период времени, характер отказов которого является следствием внутренних дефектов и условий его применения Удобство применения Совокупность свойств ПО для предполагаемого круга пользователей и отражающих легкость его освоения и адаптации к изменяющимся условиям эксплуатации, стабильность работы и подготовки данных, понимаемость результатов, удобства внесения изменений в программную документацию и в программы Сопровождаемость Группа свойств, определяющая усилия, необходимые для выполнения, приспособленность к диагностике отказов и последствий внесения изменений, модификации и аттестации модифицируемого ПО Рациональность Группа свойств, характеризующаяся степенью соответствия используемых ресурсов среды функционирования уровню качества (надежности) функционирования ПО при заданных условиях применения Переносимость Группа свойств ПО, обеспечивающая его приспособленность для переноса из одной среды функционирования в другие, усилия для переноса и адаптацию ПО к новой среде функционирования Функциональность - совокупность свойств, определяющих способность ПО выполнять перечень функций в заданной среде и в соответствии с требованиями к обработке и общесистемным средствам. Под функцией понимается некоторая упорядоченная последовательность действий для удовлетворения потребительских свойств. Функции бывают целевые (основные) и вспомогательные. К атрибутам функциональности относятся: функциональная полнота - свойство компонента, которое показывает степень достаточности основных функций для решения задач в соответствии с назначением ПО;  правильность (точность) - атрибут, который показывает степень достижения правильных результатов;  интероперабельность - атрибут, который показывает возможность взаимодействовать на ПО специальными системами и средами (ОС, сеть);  защищенность - атрибут, который показывает на способность ПО предотвращать несанкционированный доступ (случайный или умышленный) к программам и данным. Надежность - совокупность атрибутов, которые определяют способность ПО преобразовывать исходные данные в результаты при условиях, зависящих от периода времени жизни (износ и его старение не учитываются). Снижение надежности ПО происходит из-за ошибок в требованиях, проектировании и выполнении. Отказы и ошибки в программах появляются на заданном промежутке времени [10.5-10.10]. К подхарактеристикам надежности ПО относятся:  безотказность - атрибут, который определяет способность ПО функционировать без отказов (как программы, так и оборудования);  устойчивость к ошибкам - атрибут, который показывает на способность ПО выполнять функции при аномальных условиях (сбой аппаратуры, ошибки в данных и интерфейсах, нарушение в действиях оператора и др.);  восстанавливаемость - атрибут, который показывает на способность программы к перезапуску для повторного выполнения и восстановления данных после отказов. К некоторым типам систем (реального времени, радарных, систем безопасности, коммуникация и др.) предъявляются требования для обеспечения высокой надежности (недопустимость ошибок, точность, достоверность, удобство применения и др.). Таким образом, надежность ПО в значительной степени зависит от числа оставшихся и не устраненных ошибок в процессе разработки на этапах ЖЦ. В ходе эксплуатации ошибки обнаруживаются и устраняются. Если при исправлении ошибок не вносятся новые или, по крайней мере, новых ошибок вносится меньше, чем устраняется, то в ходе эксплуатации надежность ПО непрерывно возрастает. Чем интенсивнее проводится эксплуатация, тем интенсивнее выявляются ошибки и быстрее растет надежность ПО.  К факторам, влияющим на надежность ПО, относятся:  совокупность угроз, приводящих к неблагоприятным последствиям и к ущербу системы или среды ее функционирования;  угроза как проявление нарушения безопасности системы;  целостность как способность системы сохранять устойчивость работы и не иметь риска. Обнаруженные ошибки могут быть результатом угрозы извне или отказов, они повышают риск и уменьшают некоторые свойства надежности системы. Надежность - одна из ключевых проблем современных программных систем, и ее роль будет постоянно возрастать, поскольку постоянно повышаются требования к качеству компьютерных систем. Новое направление инженерия программной надежности (Software reliability engineering) ориентировано на количественное изучение операционного поведения компонентов системы по отношению к пользователю, ожидающему надежную работу системы [10.7], и включает:  измерение надежности, т.е. проведение ее количественной оценки с помощью предсказаний, сбора данных о поведении системы в процессе эксплуатации и современных моделей надежности;  стратегии и метрики конструирования и выбора готовых компонентов, процесс разработки компонентной системы, а также среда функционирования, влияющая на надежность работы системы;  применение современных методов инспектирования, верификации, валидации и тестирования при разработке систем, а также при эксплуатации. Верификация применяется для определения соответствия готового ПО установленным спецификациям, а валидация - для установления соответствия системы требованиям пользователя, которые были предъявлены заказчиком. В инженерии надежности термин dependability (пригодноспособность) обозначает способность системы иметь свойства, желательные для пользователя, который уверен в качественном выполнении функций ПС, заданных в требованиях. Данный термин определяется дополнительным количеством атрибутов, которыми должна обладать система, а именно:  готовность к использованию (availability);  готовностью к непрерывному функционированию (reliability);  безопасность для окружающей среды, т.е. способность системы не вызывать катастрофических последствий в случае отказа (safety);  секретность и сохранность информации (сonfidential); способность к сохранению системы и устойчивости к самопроизвольному ее изменению (integrity);  способность к эксплуатации ПО, простота выполнения операций обслуживания, а также устранения ошибок, восстановление системы после их устранения и т.п. (maintainability);  готовность и сохранность информации (security) и др. Достижение надежности системы обеспечивается предотвращением отказа (fault prevention), его устранением (removal fault), а также оценкой возможности появления новых отказов и мер борьбы с ними с применением методов теории вероятности. Каждый программный компонент, его операции и данные обрабатываются в дискретные моменты времени, например, . Пусть за время после первого неудачно обработанного компонента системы появился отказ,  вероятность этой неудачи, тогда ожидания Положим, что . момент времени фиксированным, тогда имеем данном случае - непрерывная и среднее время убывает, величина а время остается , время до отказа в , распределенная экспоненциально с параметром . Таким образом, оценка надежности ПО - это трудоемкий процесс, требующий создания устойчивой работы системы по отношению к отказам ПО, т.е. вероятности того, что система восстановится самопроизвольно в некоторой точке после возникновения в ней отказа (fault). Удобство применения характеризуется множеством атрибутов, которые показывают на необходимые и пригодные условия использования (диалоговое или не диалоговое) ПО заданным кругом пользователей для получения соответствующих результатов. В стандарте [10.3] удобство применения определено как специфическое множество атрибутов программного продукта, характеризующих его эргономичность. К подхарактеристиками удобства применения относятся:  понимаемость - атрибут, который определяет усилия, затрачиваемые на распознавание логических концепций и условий применения ПО;  изучаемость (легкость изучения) - атрибут, который определяет усилия пользователей на определение применимости ПО путем использования операционного контроля, диагностики, а также процедур, правил и документации;  оперативность - атрибут, который показывает на реакцию системы при выполнении операций и операционного контроля; согласованность - атрибут, который показывает соответствие разработки требованиям стандартов, соглашений, правил, законов и предписаний. Эффективность - множество атрибутов, которые определяют взаимосвязь уровней выполнения ПО, использования ресурсов (средства, аппаратура, материалы - бумага для печатающего устройства и др.) и услуг, выполняемых штатным обслуживающим персоналом и др. К подхарактеристикам эффективности ПО относятся:  реактивность - атрибут, который показывает время отклика, обработки и выполнения функций;  эффективность ресурсов - атрибут, показывающий количество и продолжительность используемых ресурсов при выполнении функций ПО;  согласованность - атрибут, который показывает соответствие данного атрибута с заданными стандартами, правилами и предписаниями. Сопровождаемость - множество свойств, которые показывают на усилия, которые надо затратить на проведение модификаций, включающих корректировку, усовершенствование и адаптацию ПО при изменении среды, требований или функциональных спецификаций. Cопровождаемость включает подхарактеристики:  анализируемость - атрибут, определяющий необходимые усилия для диагностики отказов или идентификации частей, которые будут модифицироваться;  изменяемость - атрибут, который определяет удаление ошибок в ПО или внесение изменений для их устранения, а также введение новых возможностей в ПО или в среду функционирования;  стабильность - атрибут, указывающий на постоянство структуры и риск ее модификации;  тестируемость - атрибут, показывающий на усилия при проведении валидации и верификации с целью обнаружения несоответствий требованиям, а также на необходимость проведения модификации ПО и сертификации;  согласованность - атрибут, который показывает соответствие данного атрибута соглашениям, правилам и предписаниям стандарта. Переносимость - множество показателей, указывающих на способность ПО адаптироваться к работе в новых условиях среды выполнения. Среда может быть организационной, аппаратной и программной. Поэтому перенос ПО в новую среду выполнения может быть связан с совокупностью действий, направленных на обеспечение его функционирования в среде,  отличной от той среды, в которой оно создавалось с учетом новых программных, организационных и технических возможностей. Переносимость включает подхарактеристики:  адаптивность - атрибут, определяющий усилия, затрачиваемые на адаптацию к различным средам;  настраиваемость (простота инсталляции) - атрибут, который определяет необходимые усилия для запуска данного ПО в специальной среде;  сосуществование - атрибут, который определяет возможность использования специального ПО в среде действующей системы;  заменяемость - атрибут, который обеспечивают возможность интероперабельности при совместной работе с другими программами с необходимой инсталляцией или адаптацией ПО;  согласованность - атрибут, который показывает на соответствие стандартам или соглашениями по обеспечению переноса ПО. Метрики качества 4 ч лекций, 4 ч лабораторных работ Краткое содержание: Метрики качества. Метрики объектноориентированных программных систем (специфика). Набор метрик Чидамбера-Кемерера. Метрики Лоренца и Кидда. Метрики Абреу. 10.1.2. Метрики качества программного обеспечения В настоящее время в программной инженерии еще не сформировалась окончательно система метрик. Действуют разные подходы к определению их набора и методов измерения [10.11-10.13]. Система измерения включает метрики и модели измерений, которые используются для количественной оценки качества ПО. При определении требований к ПО задаются соответствующие им внешние характеристики и их атрибуты (подхарактеристики), определяющие разные стороны управления продуктом в заданной среде. Для набора характеристик качества ПО, приведенных в требованиях, определяются соответствующие метрики, модели их оценки и диапазон значений мер для измерения отдельных атрибутов качества. Согласно стандарту [1.16] метрики определяются по модели измерения атрибутов ПО на всех этапах ЖЦ (промежуточная, внутренняя метрика) и особенно на этапе тестирования или функционирования (внешние метрики) продукта. Остановимся на классификации метрик ПО, правилах для проведения метрического анализа и процесса их измерения. Типы метрик. Существует три типа метрик:  метрики программного продукта, которые используются при измерении его характеристик - свойств;  метрики процесса, которые используются при измерении свойства процесса ЖЦ создания продукта.  метрики использования. Метрики программного продукта включают:  внешние метрики, обозначающие свойства продукта, видимые пользователю;  внутренние метрики, обозначающие свойства, видимые только команде разработчиков. Внешние метрики продукта - это метрики:  надежности продукта, которые служат для определения числа дефектов;  функциональности, с помощью которых устанавливаются наличие и правильность реализации функций в продукте;  сопровождения, с помощью которых измеряются ресурсы продукта (скорость, память, среда);применимости продукта, которые способствуют определению степени доступности для изучения и использования;  стоимости, которыми определяется стоимость созданного продукта. Внутренние метрики продукта включают:  метрики размера, необходимые для измерения продукта с помощью его внутренних характеристик;  метрики сложности, необходимые для определения сложности продукта;  метрики стиля, которые служат для определения подходов и технологий создания отдельных компонентов продукта и его документов. Внутренние метрики позволяют определить производительность продукта и являются релевантными по отношению к внешним метрикам. Внешние и внутренние метрики задаются на этапе формирования требований к ПО и являются предметом планирования и управления достижением качества конечного программного продукта. Метрики продукта часто описываются комплексом моделей для установки различных свойств, значений модели качества или прогнозирования. Измерения проводятся, как правило, после калибровки метрик на ранних этапах проекта. Общая мера - степень трассируемости, которая определяется числом трасс, прослеживаемых с помощью моделей сценариев типа UML и оценкой количества:  требований;  сценариев и действующих лиц;  объектов, включенных в сценарий, и локализация требований к каждому сценарию;  параметров и операций объекта и др. Стандарт ISO/IEC 9126-2 определяет следующие типы мер:  мера размера ПО в разных единицах измерения (число функций, строк в программе, размер дисковой памяти и др.);  мера времени (функционирования системы, выполнения компонента и др.);  мера усилий (производительность труда, трудоемкость и др.);  мера учета (количество ошибок, число отказов, ответов системы и др.). Специальной мерой может служить уровень использования повторных компонентов и измеряется как отношение размера продукта, изготовленного из готовых компонентов, к размеру системы в целом. Данная мера используется также при определении стоимости и качества ПО. Примеры метрик:  общее число объектов и число повторно используемых;  общее число операций, повторно используемых и новых операций;  число классов, наследующих специфические операции;  число классов, от которых зависит данный класс;  число пользователей класса или операций и др. При оценке общего количества некоторых величин часто используются среднестатистические метрики (среднее число операций в классе, наследников класса или операций класса и др.). Как правило, меры в значительной степени являются субъективными и зависят от знаний экспертов, производящих количественные оценки атрибутов компонентов программного продукта. Примером широко используемых внешних метрик программ являются метрики Холстеда - это характеристики программ, выявляемые на основе статической структуры программы на конкретном языке программирования: число вхождений наиболее часто встречающихся операндов и операторов; длина описания программы как сумма числа вхождений всех операндов и операторов и др. На основе этих атрибутов можно вычислить время программирования, уровень программы (структурированность и качество) и языка программирования (абстракции средств языка и ориентация на проблему) и др. В качестве метрик процесса могут быть время разработки, число ошибок, найденных на этапе тестирования и др. Практически используются следующие метрики процесса:  общее время разработки и отдельно время для каждой стадии;  время модификации моделей;  время выполнения работ на процессе;  число найденных ошибок при инспектировании;  стоимость проверки качества;  стоимость процесса разработки. Метрики использования служат для измерения степени удовлетворения потребностей пользователя при решении его задач. Они помогают оценить не свойства самой программы, а результаты ее эксплуатации - эксплуатационное качество. Примером может служить точность и полнота реализации задач пользователя, а также затраченные ресурсы (трудозатраты, производительность и др.) на эффективное решение задач пользователя. Оценка требований пользователя проводится с помощью внешних метрик. 10.1.3. Стандартная оценка значений показателей качества Оценка качества ПО согласно четырехуровневой модели качества начинается с нижнего уровня иерархии, т.е. с самого элементарного свойства оцениваемого атрибута показателя качества согласно установленных мер. На этапе проектирования устанавливают значения оценочных элементов для каждого атрибута показателя анализируемого ПО, включенного в требования. По определению стандарта ISO/IES 9126-2 метрика качества ПО представляет собой "модель измерения атрибута, связываемого с показателем его качества". При измерении показателей качества данный стандарт позволяет определять следующие типы мер:  меры размера в разных единицах измерения (количество функций, размер программы, объем ресурсов и др.); меры времени - периоды реального, процессорного или календарного времени (время функционирования системы, время выполнения компонента, время использования и др.);  меры усилий - продуктивное время, затраченное на реализацию проекта (производительность труда отдельных участников проекта, коллективная трудоемкость и др.);  меры интервалов между событиями, например, время между последовательными отказами;  счетные меры - счетчики для определения количества обнаруженных ошибок, структурной сложности программы, числа несовместимых элементов, числа изменений (например, число обнаруженных отказов и др.). Метрики качества используются при оценке степени тестируемости с помощью данных (безотказная работа, выполнимость функций, удобство применения интерфейсов пользователей, БД и т.п.) после проведения испытаний ПО на множестве тестов. Наработка на отказ как атрибут надежности определяет среднее время между появлением угроз, нарушающих безопасность, и обеспечивает трудноизмеримую оценку ущерба, которая наносится соответствующими угрозами. Очень часто оценка программы проводится по числу строк. При сопоставлении двух программ, реализующих одну прикладную задачу, предпочтение отдается короткой программе, так как её создает более квалифицированный персонал и в ней меньше скрытых ошибок и легче модифицировать. По стоимости она дороже, хотя времени на отладку и модификацию уходит больше. Т.е. длину программы можно использовать в качестве вспомогательного свойства для сравнения программ с учетом одинаковой квалификации разработчиков, единого стиля разработки и общей среды. Если в требованиях к ПО было указано получить несколько показателей, то просчитанный после сбора данных показатель умножается на соответствующий весовой коэффициент, а затем суммируются все показатели для получения комплексной оценки уровня качества ПО. На основе измерения количественных характеристик и проведения экспертизы качественных показателей с применением весовых коэффициентов, нивелирующих разные показатели, вычисляется итоговая оценка качества продукта путем суммирования результатов по отдельным показателям и сравнения их с эталонными показателями ПО (стоимость, время, ресурсы и др.).  1. Т.е. при проведении оценки отдельного показателя с помощью оценочных элементов просчитывается весомый коэффициент -метрика, -показатель, -атрибут. Например, в качестве показателя возьмем переносимость. Этот показатель будет вычисляться по пяти атрибутам ( ), причем каждый из них будет умножаться на соответствующий коэффициент . Все метрики -атрибута суммируются и образуют -показатель качества. Когда все атрибуты оценены по каждому из показателей качества, производится суммарная оценка отдельного показателя, а потом и интегральная оценка качества с учетом весовых коэффициентов всех показателей ПО. В конечном итоге результат оценки качества является критерием эффективности и целесообразности применения методов проектирования, инструментальных средств и методик оценивания результатов создания программного продукта на стадиях ЖЦ. Для изложения оценки значений показателей качества используется стандарт [10.4], в котором представлены следующие методы: измерительный, регистрационный, расчетный и экспертный (а также комбинации этих методов). Измерительный метод базируется на использовании измерительных и специальных программных средств для получения информации о характеристиках ПО, например, определение объема, числа строк кода, операторов, количества ветвей в программе, число точек входа (выхода), реактивность и др. Регистрационный метод используется при подсчете времени, числа сбоев или отказов, начала и конца работы ПО в процессе его выполнения. Расчетный метод базируется на статистических данных, собранных при проведении испытаний, эксплуатации и сопровождении ПО. Расчетными методами оцениваются показатели надежности, точности, устойчивости, реактивности и др. Экспертный метод осуществляется группой экспертов - специалистов, компетентных в решении данной задачи или типа ПО. Их оценка базируется на опыте и интуиции, а не на непосредственных результатах расчетов или экспериментов. Этот метод проводится путем просмотра программ, кодов, сопроводительных документов и способствует качественной оценки созданного продукта. Для этого устанавливаются контролируемые признаки, которые коррелированны с одним или несколькими показателями качества и включены в опросные карты экспертов. Метод применяется при оценке таких показателей, как анализируемость, документируемость, структурированность ПО и др. Для оценки значений показателей качества в зависимости от особенностей используемых ими свойств, назначения, способов их определения используются:  шкала метрическая (1.1 - абсолютная, 1.2 - относительная, 1.3 - интегральная);  шкала порядковая (ранговая), позволяющая ранжировать характеристики путем сравнения с опорными;  классификационная шкала, характеризующая наличие или отсутствие рассматриваемого свойства у оцениваемого программного обеспечения. Показатели, которые вычисляются с помощью метрических шкал, называются количественные, а определяемые с помощью порядковых и классификационных шкал - качественные. Атрибуты программной системы, характеризующие ее качество, измеряются с использованием метрик качества. Метрика определяет меру атрибута, т.е. переменную, которой присваивается значение в результате измерения.Для правильного использования результатов измерений каждая мера идентифицируется шкалой измерений. Стандарт ISO/IES 9126-2 рекомендует применять 5 видов шкал измерения значений, которые упорядочены от менее строгой к более строгой:  номинальная шкала отражает категории свойств оцениваемого объекта без их упорядочения;  порядковая шкала служит для упорядочивания характеристики по возрастанию или убыванию путем сравнения их с базовыми значениями;  интервальная шкала задает существенные свойства объекта (например, календарная дата);  относительная шкала задает некоторое значение относительно выбранной единицы;  абсолютная шкала указывает на фактическое значение величины (например, число ошибок в программе равно 10). 10.1.4. Управление качеством ПС Под управлением качества понимается совокупность организационной структуры и ответственных лиц, а также процедур, процессов и ресурсов для планирования и управления достижением качества ПС. Управление качеством - SQM (Software Quality Management) базируется на применении стандартных положений по гарантии качества - SQA (Software Quality Assurance) [10.4, 10.15]. Цель процесса SQA состоит в гарантировании того, что продукты и процессы согласуются с требованиями, соответствуют планам и включают следующие виды деятельности:  внедрение стандартов и соответствующих процедур разработки ПС на этапах ЖЦ;  оценка соблюдения положений этих стандартов и процедур. Гарантия качества состоит в следующем:  проверка непротиворечивости и выполнимости планов;  согласование промежуточных рабочих продуктов с плановыми показателями;  проверка изготовленных продуктов заданным требованиям;  анализ применяемых процессов на соответствие договору и планам;согласование с заказчиком среды и методов разработки продукта;  проверка принятых метрик продуктов, процессов и приемов их измерения в соответствии с утвержденным стандартом и процедурами измерения. Цель процесса управления SQM - мониторинг (систематический контроль) качества для гарантии того, что продукт будет удовлетворять потребителю и предполагает выполнение следующего:  определение количественных свойств качества, основанных на выявленных и предусмотренных потребностях пользователей;  управление реализацией поставленных целей для достижения качества. Процесс SQM основывается на гарантии того, что:  цели достижения требуемого качества установлены для всех рабочих продуктов в контрольных точках продукта;  определена стратегия достижения качества, метрики, критерии, приемы, требования к процессу измерения и др.;  определены и выполняются действия, связанные с предоставлением продуктам свойств качества;  проводится контроль качества (SQA, верификация и валидация) и целей;  выполняются процессы измерения и оценивания конечного продукта на достижение требуемого качества. Основные стандартные положения [10.1[10.2-10.4, 10.15] по созданию качественного продукта и оценки достигнутого его уровня позволяют выделить два процесса обеспечения качества на этапах ЖЦ: гарантия (подтверждение) качества ПС как результат определенной деятельности на каждом этапе ЖЦ с проверкой соответствия системы стандартам и процедурам, ориентированным на достижении качества;  инженерия качества как процесс предоставления продуктам ПО свойств функциональности, надежности, сопровождения и других характеристик качества. Процессы достижения качества предназначены для:  управления, разработки и обеспечения гарантий в соответствии с указанными стандартами и процедурами;  управления конфигурацией (идентификация, учет состояния и действий по аутентификации), риском и проектом в соответствии со стандартами и процедурами;  контроль базовой версии ПС и реализованных в ней характеристик качества. Выполнение указанных процессов включает такие действия:  оценка стандартов и процедур, которые выполняются при разработке программ;  ревизия управления, разработки и обеспечение гарантии качества ПО, а также проектной документации (отчеты, графики разработки, сообщения и др.);  контроль проведения формальных инспекций и просмотров;  анализ и контроль проведения приемочного тестирования (испытания) ПС. Для организации, которая занимается разработкой ПС, в том числе из компонентов, инженерия качества ПС должна поддерживаться системой управлением качеством (планирование, учет и контроль). Инженерия качества включает набор методов и мероприятий, с помощью которых программные продукты проверяются на выполнение требований к качеству и снабжаются характеристиками, предусмотренными в требованиях на ПО. Система качества (Quality systems - QS) [10.15] - это набор организационных структур, методик, мероприятий, процессов и ресурсов для осуществления управления качеством. Для обеспечения требуемого уровня качества ПО применяются два подхода. Один из них ориентирован на конечный программный продукт, а второй - на процесс создания продукта. При подходе, ориентированном на продукт, оценка качества проводится после испытания ПС. Этот подход базируется на предположении,  что чем больше обнаружено и устранено ошибок в продукте при испытаниях, тем выше его качество. При втором подходе предусматриваются и принимаются меры по предотвращению, оперативному выявлению и устранению ошибок, начиная с начальных этапов ЖЦ в соответствии с планом и процедурами обеспечения качества разрабатываемой ПС. Этот подход представлен в серии стандартов ISO 9000 и 9000-1,2,3, который дает рекомендации организациямразработчикам создавать систему качества согласно схемы, приведенной на рис. 10.3. Важное место в инженерии качества отводится процессу измерения характеристик процессов ЖЦ, его ресурсов и создаваемых на них рабочих продуктов. Этот процесс реализуется группой качества,верификации и тестирования. В ее функции входит планирование, оперативное управление и обеспечение качества. Рис. 10.3. Требования стандарта к организации системы качества Планирование качества представляет собою деятельность, направленную на определение целей и требований к качеству. Оно охватывает идентификацию, установление целей, требований к качеству, классификацию и оценку качества. Составляется календарный планграфик для проведения анализа состояния разработки и последовательного измерения спланированных показателей и критериев на этапах ЖЦ. Оперативное управление включает методы и виды деятельности оперативного характера для текущего управления процессом проектирования и устранения причин плохого или неудовлетворительного функционирования ПС. Обеспечение качества заключается в выполнении и проверки того, что объект разработки выполняет указанные требования к качеству. Цели обеспечения качества могут быть внутренние и внешние. Внутренние цели создание уверенности у руководителя проекта, что качество обеспечивается. Внешние цели - это создание уверенности у пользователя, что требуемое качество достигнуто и получено качественное программное обеспечение. Как показывает опыт, ряд фирм, выпускающих программную продукцию, имеют системы качества, что обеспечивает им производство конкурентоспособной продукции. Система качества включает мониторинг спроса на выпускаемый новый вид продукции, контроль всех звеньев его производства, включая подбор и поставку готовых компонентов для системы. При отсутствии соответствующих служб качества разработчики ПО должны применять собственные нормативные и методические документы, регламентирующие процесс управления качеством ПО для всех категорий разработчиков и пользователей программной продукции. Сложность ПС 2 ч лекций, 2 ч лабораторных работ Краткое содержание: Основные виды сложности проектирования и функционирования ПС. Показатели вычислительной сложности: временная, программная, информационная сложность и основные факторы, влияющие на их значение. Измерение и оценка сложности программных средств. Сложность программы для систем реального времени преимущественно определяется допустимым временем отклика, а для информационно-поисковых систем – количеством типов обрабатываемых переменных. Вычислительная сложность непосредственно связана с ресурсами вычислительной системы, необходимыми для получения совокупности законченных результатов. Временной сложностью алгоритма называется время счета, затрачиваемое программой для получения результатов на некоторой эталонной ЭВМ, в зависимости от объема исходных данных. Программная сложность характеризуется длинной программы или объемом памяти ЭВМ, необходимой для размещения программного комплекса. Информационную сложность можно представить как объем базы данных, обрабатываемых комплексом программ, или как емкость оперативной и внешней памяти, используемой для накопления и хранения информации при исполнении программ. Сложность текста – это длина самого короткого двоичного слова, содержащего всю информацию, необходимую для восстановления рассматриваемого текста при помощи некоторого способа декодирования. Структурная сложность программ определяется числом взаимодействующих компонент, числом связей между компонентами и сложностью их взаимодействия. Сложность некоторой межмодульной связи в процессе проектирования можно характеризовать вероятностью ошибки при ее формализации и степенью влияния этой ошибки на последующее функционирование модулей. Корректность ПС 2 ч лекций, 4 ч лабораторных работ Краткое содержание: Основные понятия и виды корректности программ. Функциональная, детерминированная, стохастическая, динамическая корректность. Типы эталонов, методы измерений и проверки корректности программ. Ошибки в ПС. Количественное описание ошибок ПС. Классификационная схема программных ошибок. Источники ошибок. Применение метрики ПС для обнаружения и устранения ошибок. Корректность программного средства – соответствие проверяемого объекта некоторому эталонному объекту или совокупности более или менее формализованных эталонных характеристик и правил. Корректность текстов программ – степень соответствия исходных программ формализованным правилам языков спецификаций и программирования. Конструктивная корректность модулей – соответствие их структуры общим правилам структурного программирования и конкретным правилам оформления и внутреннего построения программных модулей в данном заказе. Функциональная корректность модулей – корректность обработки исходных данных и получения результатов. Конструктивная корректность данных определяется правилами их структурирования и упорядочения. Функциональная корректность данных связана, в основном, с конкретизацией их содержания в процессе исполнения программ, а также при подготовке данных внешними абонентами. Конструктивная корректность программных модулей определяется правилами структурного, модульного построения программных комплексов и общими правилами организации межмодульных связей. Эта составляющая может быть проверена формализованными автоматизированными методами. Конструктивная корректность данных определяется правилами их структурирования и упорядочения. Функциональная корректность данных связана, в основном, с конкретизацией их содержания в процессе исполнения программ, а также при подготовке данных внешними абонентами. Конструктивная корректность программных модулей определяется правилами структурного, модульного построения программных комплексов и общими правилами организации межмодульных связей. Эта составляющая может быть проверена формализованными автоматизированными методами. Функциональная корректность комплексов программ наиболее трудно формируется вследствие большого количества возможных эталонных значений и распределений. В наиболее сложном случае для программ реального времени ее можно разделить на: • детерминированную корректность – должно быть обеспечено однозначное соответствие исходных и результирующих данных исполняемых программ определенным эталонным значениям; • стохастическую корректность – статистическое соответствие распределений результирующий случайных величин заданиям эталонным распределениям при соответствующих распределениях исходных данных; • динамическую корректность – соответствие изменяющихся во времени результатов исполнения программ эталонным данным. Синтаксический контроль корректности текстов программ – проверка входного текста программ на соответствие синтаксису языка программирования. Семантический контроль текстов программ – проверка корректности применения и взаимодействия базовых конструкций языка программирования в тексте проверяемых программ. Формализованный структурный контроль программ основывается на статической проверке соответствия структуры программ и последовательности основных операций использования памяти системе эталонных правил. Верификация (подтверждение правильности) состоит в проверке и доказательстве корректности разработанной программы по отношению к совокупности формальных утверждений, представленных в программной спецификации и полностью определяющих связи между входными и выходными данными этой программы. Надежность ПС 2 ч лекций, 2 ч лабораторных работ Краткое содержание: Определение надежности ПС. Показатели надежности ПС. Факторы, определяющие надежность ПС. Определение показателей надежности на различных этапах жизненного цикла ПС. Аналитические, имитационные, экспериментальные методы оценки надежности ПС. Моделирование и обеспечение надежности в процессе создания ПС. Статические, динамические, эмпирические модели. 10.2. Модели оценки надежности Из всех областей программной инженерии надежность ПС является самой исследованной областью. Ей предшествовала разработка теории надежности технических средств, оказавшая влияние на развитие надежности ПС. Вопросами надежности ПС занимались разработчики ПС, пытаясь разными системными средствами обеспечить надежность, удовлетворяющую заказчика, а также теоретики, которые, изучая природу функционирования ПС, создали математические модели надежности, учитывающие разные аспекты работы ПС (возникновение ошибок, сбоев, отказов и др.) и позволяющие оценить реальную надежность. В результате надежность ПС сформировалась как самостоятельная теоретическая и прикладная наука [10.5-10.10, 10.16-10.24]. Надежность сложных ПС существенным образом отличается от надежности аппаратуры. Носители данных (файлы, сервер и т.п.) обладают высокой надежностью, записи на них могут храниться длительное время без разрушения, поскольку физическому разрушению они не подвергаются. С точки зрения прикладной науки надежность - это способность ПС сохранять свои свойства (безотказность, устойчивость и др.), преобразовывать исходные данные в результаты в течение определенного промежутка времени при определенных условиях эксплуатации. Снижение надежности ПС происходит из-за ошибок в требованиях, проектировании и выполнении. Отказы и ошибки зависят от способа производства продукта и появляются в программах при их исполнении на некотором промежутке времени. Для многих систем (программ и данных) надежность - главная целевая функция реализации. К некоторым типам систем (реального времени, радарные системы, системы безопасности, медицинское оборудование со встроенными программами и др.) предъявляются высокие требования к надежности, такие, как отсутствие ошибок, достоверность, безопасность и др. Таким образом, оценка надежности ПС зависит от числа оставшихся и не устраненных ошибок в программах. В ходе эксплуатации ПС ошибки обнаруживаются и устраняются. Если при исправлении ошибок не вносятся новые или, по крайней мере, новых ошибок вносится меньше, чем устраняется, то в ходе эксплуатации надежность ПС непрерывно возрастает. Чем интенсивнее проводится эксплуатация, тем интенсивнее выявляются ошибки и быстрее растет надежность системы и соответственно ее качество. Надежность является функцией от ошибок, оставшихся в ПС после ввода его в эксплуатацию. ПС без ошибок является абсолютно надежным. Но для больших программ абсолютная надежность практически недостижима. Оставшиеся необнаруженные ошибки проявляют себя время от времени при определенных условиях (например, при некоторой совокупности исходных данных) сопровождения и эксплуатации системы. Для оценки надежности ПС используются такие статистические показатели, как вероятность и время безотказной работы, возможность отказа и частота (интенсивность) отказов. Поскольку в качестве причин отказов рассматриваются только ошибки в программе, которые не могут самоустраниться, то ПС следует относить к классу невосстанавливаемых систем. При каждом проявлении новой ошибки, как правило, проводится ее локализация и исправление. Строго говоря, набранная до этого статистика об отказах теряет свое значение, так как после внесения изменений программа, по существу, является новой программой в отличие от той, которая до этого испытывалась. В связи с исправлением ошибок в ПС надежность, т.е. ее отдельные атрибуты, будут все время изменяться, как правило, в сторону улучшения. Следовательно, их оценка будет носить временный и приближенный характер. Поэтому возникает необходимость в использовании новых свойств, адекватных реальному процессу измерения надежности, таких, как зависимость интенсивности обнаруженных ошибок от числа прогонов программы и зависимость отказов от времени функционирования ПС и т.п. К факторам гарантии надежности относятся:  риск как совокупность угроз, приводящих к неблагоприятным последствиям и ущербу системы или среды;  угроза как проявление неустойчивости, нарушающей безопасность системы;  анализ риска - изучение угрозы или риска, их частота и последствия;  целостность - способность системы сохранять устойчивость работы и не иметь риска; Риск преобразует и уменьшает свойства надежности, так как обнаруженные ошибки могут привести к угрозе, если отказы носят частотный характер. 10.2.1. Основные понятия в проблематике надежности ПС Формально модели оценки надежности ПС базируются на теории надежности и математическом аппарате с допущением некоторых ограничений, влияющих на эту оценку. Главным источником информации, используемой в моделях надежности, является процесс тестирования, эксплуатации ПС и разного вида ситуации, возникающие в них. Ситуации порождаются возникновением ошибок в ПС, требуют их устранения для продолжения тестирования. Базовыми понятиями, которые используются в моделях надежности ПС, являются [10.5-10.10]. Отказ ПC (failure) - это переход ПС из работающего состояния в нерабочее или когда получаются результаты, которые не соответствуют заданным допустимым значениям. Отказ может быть вызван внешними факторами (изменениями элементов среды эксплуатации) и внутренними дефектами в самой ПС. Дефект (fault) в ПС - это последствие использования элемента программы, который может привести к некоторому событию, например, в результате неверной интерпретации этого элемента компьютером (как ошибка (fault) в программе) или человеком (ошибка (error) исполнителя). Дефект является следствием ошибок разработчика на любом из процессов разработки - в описании спецификаций требований, начальных или проектных спецификациях, эксплуатационной документации и т.п. Дефекты в программе, не выявленные в результате проверок, являются источником потенциальных ошибок и отказов ПС. Проявление дефекта в виде отказа зависит от того, какой путь будет выполнять специалист, чтобы найти ошибку в коде или во входных данных. Однако не каждый дефект ПС может вызвать отказ или может быть связан с дефектом в ПС или среды. Любой отказ может вызвать аномалию от проявления внешних ошибок и дефектов. Ошибка (error) может быть следствием недостатка в одном из процессов разработки ПС, который приводит к неправильной интерпретации промежуточной информации, заданной разработчиком или при принятии им неверных решений. Интенсивность отказов - это частота появления отказов или дефектов в ПС при ее тестировании или эксплуатации. При выявлении отклонения результатов выполнения от ожидаемых во время тестирования или сопровождения осуществляется поиск, выяснение причин отклонений и исправление связанных с этим ошибок. Модели оценки надежности ПС в качестве входных параметров используют сведения об ошибках, отказах, их интенсивности, собранных в процессе тестирования и эксплуатации. 10.2.2. Классификация моделей надежности Как известно, на данный момент времени разработано большое количество моделей надежности ПС и их модификаций. Каждая из этих моделей определяет функцию надежности, которую можно вычислить при задании ей соответствующих данных, собранных во время функционирования ПС. Основными данными являются отказы и время. Другие дополнительные параметры связаны с типом ПС, условиями среды и данных. Ввиду большого разнообразия моделей надежности разработано несколько подходов к классификации этих моделей. Такие подходы в целом основываются на истории ошибок в проверяемой и тестируемой ПС на этапах ЖЦ. Одной из классификаций моделей надежности ПО является классификация Хетча [10.10]. В ней предлагается разделение моделей на прогнозирующие, измерительные и оценочные (рис. 10.4). Прогнозирующие модели надежности основаны на измерении технических характеристик создаваемой программы: длина, сложность, число циклов и степень их вложенности, количество ошибок на страницу операторов программы и др. Например, модель Мотли-Брукса основывается на длине и сложности структуры программы (количество ветвей, циклов, вложенность циклов), количестве и типах переменных, а также интерфейсов. В этих моделях длина программы служит для прогнозирования количества ошибок, например, для 100 операторов программы можно смоделировать интенсивность отказов. Рис. 10.4. Классификация моделей надежности Модель Холстеда прогнозирует количество ошибок в программе в зависимости от ее объема и таких данных, как число операций ( ) и операндов ( ), а также их общее число ( ). Время программирования программы предлагается вычислять по следующей формуле: где - число Страуда (Холстед принял равным 18 - число умственных операций в единицу времени). Объем вычисляется по формуле: где - максимальное число различных операций. Измерительные модели предназначены для измерения надежности программного обеспечения, работающего с заданной внешней средой. Они имеют следующие ограничения:  программное обеспечение не модифицируется во время периода измерений свойств надежности;  обнаруженные ошибки не исправляются;  измерение надежности проводится для зафиксированной конфигурации программного обеспечения. Типичным примером таких моделей являются модели Нельсона и РамамуртиБастани и др.Модель оценки надежности Нельсона основывается на выполнении k-прогонов программы при тестировании и позволяет определить надежность где - время выполнения -прогона, она интерпретируется как интенсивность отказов. В процессе испытаний программы на тестовых надежности вычисляется по формуле и при прогонах оценка где - число прогонов программы. Таким образом, данная модель рассматривает полученные количественные данные о проведенных прогонах. Оценочные модели основываются на серии тестовых прогонов и проводятся на этапах тестирования ПC. В тестовой среде определяется вероятность отказа программы при ее выполнении или тестировании. Эти типы моделей могут применяться на этапах ЖЦ. Кроме того, результаты прогнозирующих моделей могут использоваться как входные данные для оценочной модели. Имеются модели (например, модель Муссы), которые можно рассматривать как оценочную и в то же время как измерительную модель [10.16, 10.17]. Другой вид классификации моделей предложил Гоэл [10.18, 10.19], согласно которой модели надежности базируются на отказах и разбиваются на четыре класса моделей:  без подсчета ошибок;  с подсчетом отказов;  с подсевом ошибок;  модели с выбором областей входных значений. Модели без подсчета ошибок основаны на измерении интервала времени между отказами и позволяют спрогнозировать количество ошибок, оставшихся в программе. После каждого отказа оценивается надежность и определяется среднее время до следующего отказа. К таким моделям относятся модели Джелински и Моранды, Шика Вулвертона и ЛитвудаВералла [10.20, 10.21]. Модели с подсчетом отказов базируются на количестве ошибок, обнаруженных на заданных интервалах времени. Возникновение отказов в зависимости от времени является стохастическим процессом с непрерывной интенсивностью, а количество отказов является случайной величиной. Обнаруженные ошибки, как правило, устраняются и поэтому количество ошибок в единицу времени уменьшается. К этому классу моделей относятся модели Шумана, Шика- Вулвертона, Пуассоновская модель и др. [10.2110.24]. Модели с подсевом ошибок основаны на количестве устраненных ошибок и подсеве, внесенном в программу искусственных ошибок, тип и количество которых заранее известны. Затем определяется соотношение числа оставшихся прогнозируемых ошибок к числу искусственных ошибок, которое сравнивается с соотношением числа обнаруженных действительных ошибок к числу обнаруженных искусственных ошибок. Результат сравнения используется для оценки надежности и качества программы. При внесении изменений в программу проводится повторное тестирование и оценка надежности. Этот подход к организации тестирования отличается громоздкостью и редко используется из-за дополнительного объема работ, связанных с подбором, выполнением и устранением искусственных ошибок. Модели с выбором области входных значений основываются на генерации множества тестовых выборок из входного распределения, и оценка надежности проводится по полученным отказам на основе тестовых выборок из входной области. К этому типу моделей относится модель Нельсона и др. Таким образом, классификация моделей роста надежности относительно процесса выявления отказов, фактически разделена на две группы:  модели, которые рассматривают количество отказов как марковский процесс;  модели, которые рассматривают интенсивность отказов как пуассоновский процесс. Фактор распределения интенсивности отказов разделяет модели на экспоненциальные, логарифмические, геометрические, байесовские и др. 10.2.3. Марковские и пуассоновские модели надежности Марковский процесс характеризуется дискретным временем и конечным множеством состояний. Временной параметр пробегает неотрицательные числовые значения, а процесс (цепочка) определяется набором вероятностей перехода , т.е. вероятностью перейти на -шаге из состояния в состояние . Процесс называется однородным, если он не зависит от . В моделях, базирующихся на процессе Маркова, предполагается, что количество дефектов, обнаруженных в ПС, в любой момент времени зависит от поведения системы и представляется в виде стационарной цепи Маркова [10.5, 10.7, 10.10]. При этом количество дефектов конечное, но является неизвестной величиной, которая задается для модели в виде константы. Интенсивность отказов в ПС или скорость прохода по цепи зависит лишь от количества дефектов, которые остались в ПС. К этой группе моделей относятся: Джелински- Моранды [10.20], ШикаВулвертона, Шантикумера [10.21] и др. Ниже рассматриваются некоторые модели надежности, которые обеспечивают рост надежности ПО (модели роста надежности [10.7, 10.10]), находят широкое применение на этапе тестирования и описывают процесс обнаружения отказов при следующих предположениях:  все ошибки в ПС не зависят друг от друга с точки зрения локализации отказов;  интенсивность отказов пропорциональна текущему числу ошибок в ПС (убывает при тестировании программного обеспечения);  вероятность локализации отказов остается постоянной;  локализованные ошибки устраняются до того, как тестирование будет продолжено;  при устранении ошибок новые ошибки не вносятся. Приведем основные обозначения величин при описании моделей роста надежности:  - число обнаруженных отказов ПО за время тестирования;  - интервалы времени между отказами и , при ;  - моменты времени отказов (длительность тестирования до отказа), при ;  - продолжительность тестирования ПО (время, для которого определяется надежность);  - оценка числа ошибок в ПО в начале тестирования;  - оценка числа прогнозированных ошибок;  - оценка среднего времени до следующего отказа;  - оценка среднего времени до завершения тестирования;  - оценка дисперсии;  - функция надежности ПО;  - функция риска в момент времени между и - отказами; - коэффициент пропорциональности;  - частота обнаружения ошибок. Далее рассматриваются несколько моделей роста надежности, основанные на этих предположениях и использовании результатов тестирования программ в части отказов, времени между ними и др. Модель Джелинского-Моранды. В этой модели используются исходные данные, приведенные выше, а также: - число обнаруженных отказов за время тестирования; - интервалы времени между отказами;  - продолжительность тестирования. Функция риска имеет вид: в момент времени расположена между и где ; Эта функция считается ступенчатой кусочнопостоянной функцией с постоянным коэффициентом пропорциональности и величиной ступени - . Оценка параметров и производится с помощью системы уравнений: При этом суммарное время тестирования вычисляется так: Выходные показатели для оценки надежности относительно указанного времени включают:  число оставшихся ошибок ;   среднее время до текущего отказа ; среднее время до завершения тестирования и его дисперсию При этом функция надежности вычисляется по формуле: при и числе ошибок, найденных и исправленных на каждом интервале тестирования, равным единице. Модель Шика-Вулвертона. Модель используется тогда, когда интенсивность отказов пропорциональна не только текущему числу ошибок, но и времени, прошедшему с момента последнего отказа. Исходные данные для этой модели аналогичны выше рассмотренной модели ДжелинскиМоранды:  - число обнаруженных отказов за время тестирования,  - интервалы времени между отказами,  - продолжительность тестирования. Функции риска в момент времени между определяются следующим образом: и отказами Эта функция является линейной внутри каждого интервала времени между отказами, возрастает с меньшим углом наклона. Оценка c и N вычисляется из системы уравнений: К выходным показателям надежности относительно продолжительности относятся:  число оставшихся ошибок ;  среднее время до следующего отказа MTт = (р / (2 (N - m) c) )1/2;  среднее время до завершения тестирования и его дисперсия Функция надежности вычисляется по формуле: Модели пуассоновского типа базируются на выявлении отказов и моделируются неоднородным процессом, который задает - неоднородный пуассоновский процесс с функцией интенсивности , что соответствует общему количеству отказов ПС за время его использования . Модель Гоело-Окумото. В основе этой модели лежит описание процесса обнаружения ошибок с помощью неоднородного пуассоновского процесса, ее можно рассматривать как модель экспоненциального роста. В этой модели интенсивность отказов также зависит от времени. Кроме того, в ней количество выявленных ошибок трактуется как случайная величина, значение которой зависит от теста и других условных факторов. Исходные данные этой модели:  - число обнаруженных отказов за время тестирования;  - интервалы времени между отказами;  - продолжительность тестирования. Функция среднего числа отказов, обнаруженных к моменту , имеет вид где - интенсивность обнаружения отказов и показатель роста надежности . Функция интенсивности отказа равна Оценка и в зависимости от времени работы до получаются из решения уравнений: Выходные показатели надежности относительно времени определяют: 1. среднее число ошибок, которые были обнаружены в интервале , по формуле 2. функцию надежности , В этой модели обнаружение ошибки трактуется как случайная величина, значение которой зависит от теста и операционной среды. В других моделях количество обнаруженных ошибок рассматривается как константа.В моделях роста надежности исходной информацией для расчета надежности являются интервалы времени между отказами тестируемой программы, число отказов и время, для которого определяется надежность программы при отказе. На основании этой информации по моделям определяются показатели надежности вида:  вероятность безотказной работы;  среднее время до следующего отказа;  число необнаруженных отказов (ошибок);  среднее время дополнительного тестирования программы. Модель анализа результатов прогона тестов использует в своих расчетах общее число экспериментов тестирования и число отказов. Эта модель определяет только вероятность безотказной работы программы и выбрана для случаев, когда предыдущие модели нельзя использовать (мало данных, некорректность вычислений). Формула определения вероятности безотказной работы по числу проведенных экспериментов имеет вид где - число ошибочных экспериментов, - число проведенных экспериментов для проверки работы ПС. Таким образом, можно сделать вывод о том, что модели надежности ПС основаны на времени функционирования и/или количестве отказов (ошибок), полученных в программах в процессе их тестирования или эксплуатации. Модели надежности учитывают случайный марковский и пуассоновский характер соответственно процессов обнаружения ошибок в программах, а также характер и интенсивность отказов. Раздел 3 Тестирование программного продукта Виды и методы тестирования 4 ч лекций, 2 ч лабораторных работ Краткое содержание: Терминология: тестирование, отладка, дефект, отказ, сбой. Объекты тестирования. Роль тестирования в различных процессах разработки ПО. Уровни и виды тестирования: модульное (unit testing), интеграционное (integration testing), системное (system testing). Регрессионное тестирование, smoke testing. Тестирование белого и черного ящика. Виды дефектов, обнаруживаемые на каждом уровне. Нисходящее и восходящее тестирование. Категории тестов системного тестирования: полнота решения функциональных задач; тестирование целостности; стрессовое тестирование; корректность использования ресурсов; оценка производительности; эффективность защиты от искажения данных и некорректных действий; проверка инсталляции и конфигурации на разных платформах; корректность документации. Проблемы регрессионного тестирования. Приемочное тестирование. В фундаментальную концепцию проектирования ПС входят базовые положения, стратегии, методы, которые применяются на процессах ЖЦ и обеспечивают тестирование (верификацию) на множестве тестовых наборов данных. К методам проектирования ПС относятся структурные, объектноориентированные и др. Их основу составляют теоретические, инструментальные и прикладные средства, которые влияют на процесс тестирования. Теоретические средства определяют процесс программирования и тестирования программного продукта. К ним относятся методы верификации и доказательства правильности спецификации программ (см. лекцию 6), метрики измерения (Холстеда, цикломатичная сложность Маккейба и др.) в качестве отдельных характеристик как формализованных элементов теории определения правильности и гарантии свойств конечного ПО. Например, концепция " чистая комната " базируется на формализмах доказательства и изучения свойств процессов кодирования и тестирования программ. Что касается тестирования как процесса, то это проверка правильности работы программы по заданным описаниям тестов и покрытия данными соответствующих критериев программы [7.1-7.5]. Инструментальные средства - это способы поддержки кодирования и тестирования (компиляторы, генераторы программ, отладчики и др.), а также организационные средства планирования и отбора тестов для программ, которые обеспечивают обработку текста на ЯП и подготовку для них соответствующих тестов. При проверке правильности программ и систем рассматриваются процессы верификации, валидации и тестирования ПС, которые регламентированы в стандарте ISO/IEC 12207 [7.7] жизненного цикла ПО. В некоторой зарубежной литературе процессы верификации и тестирования отождествляются. С теоретической точки зрения верификация была рассмотрена в лекции 6, здесь же будут определены задачи и действия, соответствующих процессов ЖЦ. Тестирование - это процесс обнаружения ошибок в ПО путем исполнения выходного кода ПС на тестовых данных, сбора рабочих характеристик в динамике выполнения в конкретной операционной среде, выявления различных ошибок, дефектов, отказов и изъянов, вызванных нерегулярными и аномальными ситуациями или аварийным прекращением работы ПО. тладка — этап разработки компьютерной программы, на котором обнаруживают, локализуют и устраняют ошибки. Чтобы понять, где возникла ошибка, приходится :  узнавать текущие значения переменных;  выяснять, по какому пути выполнялась программа. Существуют две взаимодополняющие технологии отладки.  Использование отладчиков — программ, которые включают в себя пользовательский интерфейс для пошагового выполнения программы: оператор за оператором, функция за функцией, с остановками на некоторых строках исходного кода или при достижении определённого условия.  Вывод текущего состояния программы с помощью расположенных в критических точках программы операторов вывода — на экран, принтер, громкоговоритель или в файл. Вывод отладочных сведений в файл называется журналированием. Ошибка – несоответствие между объектом или явлением, принятым за эталон (материальный объект, решение задачи, действие, которое привело бы к желаемому результату), и объектом/явлением, сопоставленным первому. Т.е., несоответствие между описанной в техзадании функцией и ее реальной работе в ПО. В зависимости от этапа ПО, на котором выявляется ошибка, выделяют  синтаксические ошибки (распознаваемые в качестве таковых транслятором и делающие компиляцию невозможной) - например отсутствие несоответствие открывающей и закрывающей скобок; предупреждения (warnings) компилятора - например использование неинициализированной переменной. В этом случае компилятор может заметить, что программист делает что-то необычное (вероятно неверное), и сообщает об этом, однако программист сам принимает решение игнорировать сообщение или нет;  ошибки времени исполнения, смысловые ошибки (семантические) например вычитание переменных вместо сложения или ошибка сегментации. В зависимости от характера ошибки, программы и среды исполнения, ошибка может проявляться сразу или наоборот - долгое время оставаться незамеченной (например Проблема 2038 года). Также она может проявляться в виде уязвимости, делающей возможным несанкционированный доступ к системе или DoS-атаку. Дефект – изъян или недостаток в ПО. Чаще всего это неработающая функция ПО, которая была заявлена в техзадании или неправильно выбранные методы реализации функции. Важное место в проведении верификации и тестирования занимают организационные аспекты - деятельность группы специалистов, осуществляющих планирование этих процессов, подготовку тестовых данных и наблюдение за тестированием.  Рисунок – Схема появления и обнаружения ошибок и дефектов Стандарт IEEE 829 Software Test Documentation - «задает планку» для индустрии ИТ по организации процесса тестирования. Этот стандарт разрабатывался с 1977 года и был утвержден в 1983 году, а затем вновь подтвержден в 1991 и 1998 годах. Несмотря на свою зрелость, он актуален и в 21-м веке. Стандарт «ложится» как на каскадную, так и на спиральную, итерационную модель жизненного цикла (ЖЦ) разработки и сопровождения программного обеспечения, а также стандарт не противоречит идеологии объектно-ориентированного подхода. IEEE STD 829 предлагает основу достаточный набор документов для того, чтобы: · упорядочить работы по этапам, стадиям; · разделить ответственность и объем работ; · унифицировать документы в проекте или в организации. Место и роль процесса тестирования в жизненном цикле разработки и сопровождения ПО описаны во многих стандартах, в том числе и в стандарте ГОСТ Р ИСО/МЭК 12207. При тестировании на этапах «белого», «серого» и «черного ящиков» могут быть разные исполнители в рамках одного проекта, различная структура процессов, но перечень документов сохраняется. Тестирование «белого» и «серого ящиков» подразумевает полное или частичное тестирование кода программного обеспечения, подобное тестирование модулей (компонент) обычно рекомендуется выполнять силами программистов-авторов. Функциональное тестирование («черного ящика») это системное тестирование на соответствие функциональным требованиям к разрабатываемому ПО. В системном тестировании выделяют нагрузочное тестирование - испытание производительности системы, которое может включать калибровочные испытания, стрессовое тестирование, тестирование на больших объемах данных, тестирование производительности при растущей нагрузке на систему и т.п. Данный стандарт относится к динамическому тестированию, т.е. с выполнением кода ПО, и не относится к менее популярному статическому тестированию. Состав документов, рекомендованных в стандарте IEEE STD 829: план тестирования, проект теста, спецификация тестового сценария, спецификация тестовой процедуры, отчет о ходе тестирования, протокол тестирования, отчет о найденных ошибках, итоговый отчет о тестировании. Рекомендованный состав плана тестирования: название, введение, тестируемые элементы, перечень тестируемых свойств системы, нетестируемые свойства системы, подходы к тестированию, критерии успеха/неудачи тестов, критерии остановки и требования для возобновления, выходные тестовые материалы, тестовые задачи, необходимое окружение, ответственности персонала, требования по квалификации персонала и необходимость обучения, график работ, риски и действия по их снижению, согласование. Спецификация сценария теста: Название, тестируемые элементы, спецификации входных и выходных данных, необходимая среда тестирования, специальные требования к процедуре, взаимосвязи. Спецификация тестовой процедуры: Название, цель, специальные требования, шаги выполнения процедуры. Использование стандарта IEEE STD 829 в реальных проектах. За последние три года данный стандарт эффективно использовался Центром тестирования департамента консалтинга компании АйТи в следующих проектах: нагрузочное тестирование биллинговых систем, функциональное тестирование CRM-системы, внедрение стандарта предприятия для учреждения Банк. Большой эффект экономии ресурсов и средств дает использование отработанных, адаптированных шаблонов документов, перечисленных в стандарте. Для каждого проекта можно определить степень стандартизации - создание СТП, методики или простое использование шаблона. По практике данных работ видно, что стандарт можно дополнить, например, если используется объектно-ориентированное проектирование (ООП), то можно добавить следующие документы: описание тестовых классов, тестовых пакетов. Экономия при использовании шаблонов не только в том, что есть образец, но и в том, что логика и состав документа тщательно продуманы и проработаны, как оп смыслу, так и по оформлению, т.е. не нужно «изобретать велосипед». А для случаев, когда выполняется заказная работа, эти шаблоны готовы для рассмотрения и согласования с Заказчиком с первых дней и часов с начала работ. Для больших и/или достаточно формализованных проектов (RUP) требуется полный или расширенный список документов, а для малых проектов, которые очень распространены в последнее время в связи с популярностью аутсортинга, методологий RAD, XP - список документов может быть сокращен или упрощен. Плюсы внедрения стандарта - унификация (ускорение работ, единая корпоративная структура), смысловая полнота. Минусы - бюрократизация работ - требуется соблюдать трудовую дисциплину, что не всегда и не всеми приветствуется в коллективах. Конечно, в стандарте не используются подходы и стратегии тестирования, например, тестирование по критериям «Риск», «Надежность», «Производительность», хотя начало тестирования с самых критичных сценариев дает большой, в том числе экономический, эффект, так как стоимость исправления ошибки на поздних стадиях возрастает в сотни и тысячи раз по сравнению с ранними этапами разработки ПО. Подчеркнем, что кроме планирования для тестирования важными процессами являются управление требованиями, управление ошибками, управление версиями (конфигурациями), управление изменениями, в том числе отслеживание ошибок. Рассматриваемый стандарт рекомендуется использовать не только для планирования и выполнения работ по тестированию, но и для разработки стандарта предприятия, программы и методики испытаний, а также для создания методик по отдельным видам тестирования (функциональному, нагрузочному, стрессовому, приемочному и т.п.). В этом случае можно также использовать ГОСТ 19.301-79 Программы и методики испытаний. Стандарты предприятий рекомендовано создавать для разработчиков ПО, для служб сопровождения (тиражные системы). Программы и методики испытаний для служб эксплуатации систем (биллинг, ERP, CRM). Ресурсные затраты на разработку одинакового типа шаблона могут отличаться для разных организаций: создание в первый раз - от 8 часов, при наличие подходящего образца и опыта, до нескольких дней; адаптация отработанного шаблона для нового проекта - от 1 часа до 1дня. Некоторые методологии и пакеты инструментальных средств предлагают наборы типовых шаблонов по разным процессам, в том числе и для тестирования. Как известно простое использование стандарта не является залогом успеха. Да и процесс тестирования является, в достаточной мере, творческим процессом. Каждое новое тестирование своеобразно, всегда требуется индивидуальный подход не только к решению задач, но и в целом к процессу. Поэтому в основном ограничиваются стандартизацией документирования данного процесса - это не так уж и мало. 7.1. Процессы ЖЦ верификация и валидация программ Верификация и валидация, как методы, обеспечивают соответственно проверку и анализ правильности выполнения заданных функций и соответствия ПО требованиям заказчика, а также заданным спецификациям. Они представлены в стандартах [7.7-7.8] как самостоятельные процессы ЖЦ и используются, начиная от этапа анализа требований и кончая проверкой правильности функционирования программного кода на заключительном этапе, а именно, тестировании. Для этих процессов определены цели, задачи и действия по проверке правильности создаваемого продукта (рабочие, промежуточные продукты) на этапах ЖЦ. Рассмотрим их трактовку в стандартном представлении. Процесс верификации. Цель процесса - убедиться, что каждый программный продукт (и/или сервис) проекта отражает согласованные требования к их реализации. Этот процесс основывается:  на стратегии и критериях верификации применительно ко всем рабочим программным продуктам;  на выполнении действий стандарта по верификации;  на устранении недостатков, обнаруженных в программных (рабочих и промежуточных) продуктах;  на согласовании результатов верификации с заказчиком. Процесс верификации может проводиться исполнителем программы или другим сотрудником той же организации, или сотрудником другой организации, например заказчиком. Этот процесс включает в себя действия по его внедрению и выполнению. Внедрение процесса заключается в определении критических элементов (процессов и программных продуктов), которые должны подвергаться верификации, в выборе исполнителя верификации, инструментальных средств поддержки процесса верификации, в составлении плана верификации и его утверждении. В процессе верификации выполняются задачи проверки условий: контракта, процесса, требований, интеграции, проекта, кода и документации.При верификации согласно плану и требований заказчика проверяется правильность выполнения функций системы, интерфейсов и взаимосвязей компонентов, а также доступа к данным и к средствам защиты. Процесс валидации. Цель процесса - убедиться, что специфические требования для программного продукта выполнены, и осуществляется это с помощью:  разработанной стратегии и критериев валидации для всех рабочих продуктов;  оговоренных действий по проведению валидации;  демонстрации соответствия разработанных программных продуктов требованиям заказчика и правилам их использования;  согласования с заказчиком полученных результатов валидации. Процесс валидации может проводиться самим исполнителем или другим лицом, например, заказчиком, осуществляющим действия по внедрению и проведению этого процесса по плану, в котором отражены элементы и задачи проверки. При этом используются методы, инструментальные средства и процедуры выполнения задач процесса для установления соответствия тестовых требований и особенностей использования программных продуктов проекта. На других процессах ЖЦ выполняются дополнительные действия:  проверка и контроль проектных решений с помощью методик и процедур просмотра хода разработки;  обращение к CASE-системам [7.10], которые содержат процедуры проверки требований к продукту;  просмотры и инспекции промежуточных результатов на соответствие их требованиям для подтверждения того, что ПО имеет корректную реализацию требований и удовлетворяет условиям выполнения системы. Таким образом, основные задачи процессов верификации и валидации состоят в том, чтобы проверить и подтвердить, что конечный программный продукт отвечает назначению и удовлетворяет требованиям заказчика. Эти процессы взаимосвязаны и определяются, как правило, одним общим термином "верификация и валидация" или "Verification and Validation" (V&V) [7.7]. V&V основаны на планировании их как процессов, так и проверки для наиболее критичных элементов проекта: компонент, интерфейсов (программных, технических и информационных), взаимодействий объектов (протоколов и сообщений), передач данных между компонентами и их защиты, а также оставленных тестов и тестовых процедур. После проверки отдельных компонентов системы проводятся их интеграция и повторная верификация и валидация интегрированной системы, создается комплект документации, отображающий правильность проверки формирования требований, результатов инспекций и тестирования. 7.2. Тестирование программ Тестирование можно рассматривать, как процесс семантической отладки (проверки) программы, заключающийся в исполнении последовательности различных наборов контрольных тестов, для которых заранее известен результат. Т.е. тестирование предполагает выполнение программы и получение конкретных результатов выполнения тестов [7.1-7.5, 7.11, 7.12]. Тесты подбираются так, чтобы они охватывали как можно больше типов ситуаций алгоритма программы. Менее жесткое требование выполнение хотя бы один раз каждой ветви программы. Исторически первым видом тестирования была отладка. Отладка - это проверка описания программного объекта на ЯП с целью обнаружения в нем ошибок и последующее их устранение. Ошибки обнаруживаются компиляторами при их синтаксическом контроле. После этого проводится верификация по проверке правильности кода и валидация по проверке соответствия продукта заданным требованиям. Целью тестирования - проверка работы реализованных функций в соответствии с их спецификацией. На основе внешних спецификаций функций и проектной информации на процессах ЖЦ создаются функциональные тесты, с помощью которых проводится тестирование с учетом требований, сформулированных на этапе анализа предметной области. Методы функционального тестирования подразделяются на статические и динамические. 7.2.1. Статические методы тестирования Статические методы используются при проведении инспекций и рассмотрении спецификаций компонентов без их выполнения. Техника статического анализа заключается в методическом просмотре (или обзоре) и анализе структуры программ, а также в доказательстве их правильности. Статический анализ направлен на анализ документов, разработанных на всех этапах ЖЦ и заключается в инспекции исходного кода и сквозного контроля программы. Инспекция ПО - это статическая проверка соответствия программы заданным спецификациями, проводится путем анализа различных представлений результатов проектирования (документации, требований, спецификаций, схем или исходного кода программ) на процессах ЖЦ. Просмотры и инспекции результатов проектирования и соответствия их требованиям заказчика обеспечивают более высокое качество создаваемых ПС. При инспекции программ рассматриваются документы рабочего проектирования на этапах ЖЦ совместно с независимыми экспертами и участниками разработки ПС. На начальном этапе проектирования инспекция предполагает проверку полноты, целостности, однозначности, непротиворечивости и совместимости документов с исходными требованиями к программной системе. На этапе реализации системы под инспекцией понимается анализ текстов программ на соблюдение требований стандартов и принятых руководящих документов технологии программирования. Эффективность такой проверки заключается в том, что привлекаемые эксперты пытаются взглянуть на проблему "со стороны" и подвергают ее всестороннему критическому анализу. Эти приемы позволяют на более ранних этапах проектирования обнаружить ошибки или дефекты путем многократного просмотра исходных кодов. Символьное тестирование применяется для проверки отдельных участков программы на входных символьных значениях. Кроме того, разрабатывается множество новых способов автоматизации символьного выполнения программ. Например, автоматизированное средство статического контроля для языков ориентированной разработки, инструменты автоматизации доказательства корректности и автоматизированный аппарат сетей Петри. 7.2.2. Динамические методы тестирования Динамические методы тестирования используются в процессе выполнения программ. Они базируются на графе, связывающем причины ошибок с ожидаемыми реакциями на эти ошибки. В процессе тестирования накапливается информация об ошибках, которая используется при оценке надежности и качества ПС. Динамическое тестирование ориентировано на проверку корректности ПС на множестве тестов, прогоняемых по ПС, в целях проверки и сбора данных на этапах ЖЦ и проведения измерения отдельных показателей (число отказов, сбоев) тестирования для оценки характеристик качества, указанных в требованиях, посредством выполнения системы на ЭВМ. Тестирование основывается на систематических, статистических, (вероятностных) и имитационных методах. Дадим краткую их характеристику. Систематические методы тестирования делятся на методы, в которых программы рассматриваются как "черный ящик" (используется информация о решаемой задаче), и методы, в которых программа рассматривается как "белый ящик" (используется структура программы). Этот вид называют тестированием с управлением по данным или управлением по входувыходу. Цель - выяснение обстоятельств, при которых поведение программы не соответствует ее спецификации. При этом количество обнаруженных ошибок в программе является критерием качества входного тестирования. Цель динамического тестирования программ по принципу "черного ящика" - выявление одним тестом максимального числа ошибок с использованием небольшого подмножества возможных входных данных. Методы "черного ящика" обеспечивают:  эквивалентное разбиение;  анализ граничных значений;  применение функциональных диаграмм, которые в соединении с реверсивным анализом дают достаточно полную информацию о функционировании тестируемой программы. Эквивалентное разбиение состоит в разбиении входной области данных программы на конечное число классов эквивалентности так, чтобы каждый тест, являющийся представителем некоторого класса, был эквивалентен любому другому тесту этого класса. Классы эквивалентности выделяются путем перебора входных условий и разбиения их на две или более групп. При этом различают два типа классов эквивалентности: правильные, задающие входные данные для программы, и неправильные, основанные на задании ошибочных входных значений. Разработка тестов методом эквивалентного разбиения осуществляется в два этапа: выделение классов эквивалентности и построение тестов. При построении тестов, основанных на выборе входных данных, проводится символическое выполнение программы. Итак, методы тестирования по принципу "черного ящика" используются для тестирования функций, реализованных в программе, путем проверки несоответствия между реальным поведением функций и ожидаемым поведением с учетом спецификаций требований. Во время подготовки к этому тестированию строятся таблицы условий, причинноследственные графы и области разбивки. Кроме того, подготавливаются тестовые наборы, учитывающие параметры и условия среды, которые влияют на поведение функций. Для каждого условия определяется множество значений и ограничений предикатов, которые тестируются. Метод "белого ящика" позволяет исследовать внутреннюю структуру программы, причем обнаружение всех ошибок в программе является критерием исчерпывающего тестирования маршрутов потоков (графа) передач управления, среди которых рассматриваются:  (а) критерий покрытия операторов - набор тестов в совокупности должен обеспечить прохождение каждого оператора не менее одного раза;  (б) критерий тестирования ветвей (известный как покрытие решений или покрытие переходов) - набор тестов в совокупности должен обеспечить прохождение каждой ветви и выхода, по крайней мере, один раз. Критерий (б) соответствует простому структурному тесту и наиболее распространен на практике. Для удовлетворения этого критерия необходимо построить систему путей, содержащую все ветви программы. Нахождение такого оптимального покрытия в некоторых случаях осуществляется просто, а в других является более сложной задачей. Тестирование по принципу "белого ящика" ориентировано на проверку прохождения всех путей программ посредством применения путевого и имитационного тестирования. Путевое тестирование применяется на уровне модулей и графовой модели программы путем выбора тестовых ситуаций, подготовки данных и включает тестирование следующих элементов:  операторов, которые должны быть выполнены хотя бы один раз, без учета ошибок, которые могут остаться в программе иззабольшого количества логических путей и необходимости прохождения подмножеств этих путей;  путей по заданному графу потоков управления для выявления разных маршрутов передачи управления с помощью путевых предикатов, для вычисления которого создается набор тестовых данных, гарантирующих прохождение всех путей. Однако все пути протестировать бывает невозможно, поэтому остаются не выявленные ошибки, которые могут проявиться в процессе эксплуатации;  блоков, разделяющих программы на отдельные частиблоки, которые выполняются один раз или многократно при нахождении путей в программе, включающих совокупность блоков реализации одной функции либо нахождения входного множества данных, которое будет использоваться для выполнения указанного пути. "Белый ящик" базируется на структуре программы, в случае "черного ящика", о структуре программы ничего неизвестно. Для выполнения тестирования с помощью этих "ящиков" известными считаются выполняемые функции, входы (входные данные) и выходы (выходные данные), а также логика обработки, представленные в документации. 7.2.3. Функциональное тестирование Цель функционального тестирования - обнаружение несоответствий между реальным поведением реализованных функций и ожидаемым поведением в соответствии со спецификацией и исходными требованиями. Функциональные тесты должны охватывать все реализованные функции с учетом наиболее вероятных типов ошибок. Тестовые сценарии, объединяющие отдельные тесты, ориентированы на проверку качества решения функциональных задач. Функциональные тесты создаются по внешним спецификациям функций, проектной информации и по тексту на ЯП, относятся к функциональным его характеристикам и применяются на этапе комплексного тестирования и испытаний для определения полноты реализации функциональных задач и их соответствия исходным требованиям. В задачи функционального тестирования входят:  идентификация множества функциональных требований;  идентификация внешних функций и построение последовательностей функций в соответствии с их использованием в ПС;идентификация множества входных данных каждой функции и определение областей их изменения;  построение тестовых наборов и сценариев тестирования функций;  выявление и представление всех функциональных требований с помощью тестовых наборов и проведение тестирования ошибок в программе и при взаимодействии со средой. Тесты, создаваемые по проектной информации, связаны со структурами данных, алгоритмами, интерфейсами между отдельными компонентами и применяются для тестирования компонентов и их интерфейсов. Основная цель - обеспечение полноты и согласованности реализованных функций и интерфейсов между ними. Комбинированный метод "черного ящика" и "прозрачного ящика" основан на разбиении входной области функции на подобласти обнаружения ошибок. Подобласть содержит однородные элементы, которые все обрабатываются корректно либо некорректно. Для тестирования подобласти производится выполнение программы на одном из элементов этой области. Предпосылки функционального тестирования:  корректное оформление требований и ограничений к качеству ПО;  корректное описание модели функционирования ПО в среде эксплуатации у заказчика;  адекватность модели ПО заданному классу. 7.3. Инфраструктура процесса тестирования ПС Под инфраструктурой процесса тестирования понимается:  выделение объектов тестирования;  проведение классификации ошибок для рассматриваемого класса тестируемых программ;  подготовка тестов, их выполнение и поиск разного рода ошибок и отказов в компонентах и в системе в целом;  служба проведения и управление процессом тестирования;  анализ результатов тестирования. бъекты тестирования - компоненты, группы компонентов, подсистемы и система. Для каждого из них формируется стратегия проведения тестирования. Если объект тестирования относится к "белому ящику" или "черному ящику", состав компонентов которого неизвестный, то тестирование проводится посредством ввода внего входных тестовых данных для получения выходных данных. Стратегическая цель тестирования состоит в том, чтобы убедиться, что каждый рассматриваемый входной набор данных соответствует ожидаемым выходным выходных данным. При таком подходе к тестированию не требуется знания внутренней структуры и логики объекта тестирования. Проектировщик тестов должен заглянуть внутрь "черного ящика" и исследовать детали процессов обработки данных, вопросы обеспечения защиты и восстановления данных, а также интерфейсы с другими программами и системами. Это способствует подготовке тестовых данных для проведения тестирования. Для некоторых типов объектов группа тестирования не может сгенерировать представительное множество тестовых наборов, которые демонстрировали бы функциональную правильность работы компоненты при всех возможных наборах тестов. Поэтому предпочтительным является метод "белого ящика", при котором можно использовать структуру объекта для организации тестирования по различным ветвям. Например, можно выполнить тестовые наборы, которые проходят через все операторы или все контрольные точки компонента для того, чтобы убедиться в правильности их работы. 7.3.1. Методы поиска ошибок в программах Международный стандарт ANSI/IEEE-729-83 разделяет все ошибки в разработке программ на следующие типы. Ошибка (error) - состояние программы, при котором выдаются неправильные результаты, причиной которых являются изъяны (flaw) в операторах программы или в технологическом процессе ее разработки, что приводит к неправильной интерпретации исходной информации, следовательно, и к неверному решению. Дефект (fault) в программе - следствие ошибок разработчика на любом из этапов разработки, которая может содержаться в исходных или проектных спецификациях, текстах кодов программ, эксплуатационной документация и т.п. В процессе выполнения программы может быть обнаружен дефект или сбой. Отказ (failure) - это отклонение программы от функционирования или невозможность программы выполнять функции, определенные требованиями и ограничениями, что рассматривается как событие, способствующее переходу программы в неработоспособное состояние из-за ошибок, скрытых в ней дефектов или сбоев в среде функционирования [7.6, 7.11]. Отказ может быть результатом следующих причин:  ошибочная спецификация или пропущенное требование, означающее, что спецификация точно не отражает того, что предполагал пользователь;  спецификация может содержать требование, которое невозможно выполнить на данной аппаратуре и программном обеспечении;  проект программы может содержать ошибки (например, база данных спроектирована без средств защиты от несанкционированного доступа пользователя, а требуется защита);  программа может быть неправильной, т.е. она выполняет несвойственный алгоритм или он реализован не полностью. Таким образом, отказы, как правило, являются результатами одной или более ошибок в программе, а также наличия разного рода дефектов. шибки на этапах процесса тестирования.Приведенные типы ошибок распределяются по этапам ЖЦ и им соответствуют такие источники их возникновения [7.12]:  непреднамеренное отклонение разработчиков от рабочих стандартов или планов реализации; спецификации функциональных и интерфейсных требований выполнены без соблюдения стандартов разработки, что приводит к нарушению функционирования программ;  организации процесса разработки - несовершенная или недостаточное управление руководителем проекта ресурсами (человеческими, техническими, программными и т.д.) и вопросами тестирования и интеграции элементов проекта. Рассмотрим процесс тестирования, исходя из рекомендаций стандарта ISO/IEC 12207, и приведем типы ошибок, которые обнаруживаются на каждом процессе ЖЦ. Процесс разработки требований. При определении исходной концепции системы и исходных требований к системе возникают ошибки аналитиков при спецификации верхнего уровня системы и построении концептуальной модели предметной области. Характерными ошибками этого процесса являются:  неадекватность спецификации требований конечным пользователям;- некорректность спецификации взаимодействия ПО со средой функционирования или с пользователями;  несоответствие требований заказчика к отдельным и общим свойствам ПО;  некорректность описания функциональных характеристик;  необеспеченность инструментальными средствами всех аспектов реализации требований заказчика и др. Процесс проектирования.Ошибки при проектировании компонентов могут возникать при описании алгоритмов, логики управления, структур данных, интерфейсов, логики моделирования потоков данных, форматов ввода-вывода и др. В основе этих ошибок лежат дефекты спецификаций аналитиков и недоработки проектировщиков. К ним относятся ошибки, связанные:  с определением интерфейса пользователя со средой;  с описанием функций (неадекватность целей и задач компонентов, которые обнаруживаются при проверке комплекса компонентов);  с определением процесса обработки информации и взаимодействия между процессами (результат некорректного определения взаимосвязей компонентов и процессов);  с некорректным заданием данных и их структур при описании отдельных компонентов и ПС в целом;  с некорректным описанием алгоритмов модулей;   с определением условий возникновения возможных ошибок в программе; с нарушением принятых для проекта стандартов и технологий. Этап кодирования.На данном этапе возникают ошибки, которые являются результатом дефектов проектирования, ошибок программистов и менеджеров в процессе разработки и отладки системы. Причиной ошибок являются:  бесконтрольность значений входных параметров, индексов массивов, параметров циклов, выходных результатов, деления на 0 и др.;  неправильная обработка нерегулярных ситуаций при анализе кодов возврата от вызываемых подпрограмм, функций и др.;  нарушение стандартов кодирования (плохие комментарии, нерациональное выделение модулей и компонент и др.);  использование одного имени для обозначения разных объектов или разных имен одного объекта, плохая мнемоника имен;- несогласованное внесение изменений в программу разными разработчиками и др. Процесс тестирования.На этом процессе ошибки допускаются программистами и тестировщиками при выполнении технологии сборки и тестирования, выбора тестовых наборов и сценариев тестирования и др. Отказы в программном обеспечении, вызванные такого рода ошибками, должны выявляться, устраняться и не отражаться на статистике ошибок компонент и программного обеспечения в целом. Процесс сопровождения.На процессе сопровождения обнаруживаются ошибки, причиной которых являются недоработки и дефекты эксплуатационной документации, недостаточные показатели модифицируемости и удобочитаемости, а также некомпетентность лиц, ответственных за сопровождение и/или усовершенствование ПО. В зависимости от сущности вносимых изменений на этом этапе могут возникать практически любые ошибки, аналогичные ранее перечисленным ошибкам на предыдущих этапах. Все ошибки, которые возникают в программах, принято подразделять на следующие классы [7.12]:  логические и функциональные ошибки;  ошибки вычислений и времени выполнения;  ошибки вводавывода и манипулирования данными;  ошибки интерфейсов;  ошибки объема данных и др. Логические ошибки являются причиной нарушения логики алгоритма, внутренней несогласованности переменных и операторов, а также правил  программирования. Функциональные ошибки - следствие неправильно определенных функций, нарушения порядка их применения или отсутствия полноты их реализации и т.д. Ошибки вычислений возникают по причине неточности исходных данных и реализованных формул, погрешностей методов, неправильного применения операций вычислений или операндов. Ошибки времени выполнения связаны с необеспечением требуемой скорости обработки запросов или времени восстановления программы. Ошибки ввода-вывода и манипулирования данными являются следствием некачественной подготовки данных для выполнения программы, сбоев при занесении их в базы данных или при выборке из нее. Ошибки интерфейса относятся к ошибкам взаимосвязи отдельных элементов друг с другом, что проявляется при передаче данных между ними, а также при взаимодействии со средой функционирования. Ошибки объема относятся к данным и являются следствием того, что реализованные методы доступа и размеры баз данных не удовлетворяют реальным объемам информации системы или интенсивности их обработки. Приведенные основные классы ошибок свойственны разным типам компонентов ПО и проявляются они в программах по разному. Так, при работе с БД возникают ошибки представления и манипулирования данными, логические ошибки в задании прикладных процедур обработки данных и др. В программах вычислительного характера преобладают ошибки вычислений, а в программах управления и обработки - логические и функциональные ошибки. В ПО, которое состоит из множества разноплановых программ, реализующих разные функции, могут содержаться ошибки разных типов. Ошибки интерфейсов и нарушение объема характерны для любого типа систем. Анализ типов ошибок в программах является необходимым условием создания планов тестирования и методов тестирования для обеспечения правильности ПО. На современном этапе развития средств поддержки разработки ПО (CASE-технологии, объектно-ориентированные методы и средства проектирования моделей и программ) проводится такое проектирование, при котором ПО защищается от наиболее типичных ошибок и тем самым предотвращается появление программных дефектов. Связь ошибки с отказом.Наличие ошибки в программе, как правило, приводит к отказу ПО при его функционировании. Для анализа причинноследственных связей "ошибкаотказ" выполняются следующие действия: идентификация изъянов в технологиях проектирования и программирования;  взаимосвязь изъянов процесса проектирования и допускаемых человеком ошибок;  классификация отказов, изъянов и возможных ошибок, а также дефектов на каждом этапе разработки;- сопоставление ошибок человека, допускаемых на определенном процессе разработки, и дефектов в объекте, как следствий ошибок спецификации проекта, моделей программ;  проверка и защита от ошибок на всех этапах ЖЦ, а также обнаружение дефектов на каждом этапе разработки;  сопоставление дефектов и отказов в ПО для разработки системы взаимосвязей и методики локализации, сбора и анализа информации об отказах и дефектах;  разработка подходов к процессам документирования и испытания ПО. Конечная цель причинно-следственных связей "ошибкаотказ" заключается в определении методов и средств тестирования и обнаружения ошибок определенных классов, а также критериев завершения тестирования на множестве наборов данных; в определении путей совершенствования организации процесса разработки, тестирования и сопровождения ПО. Приведем следующую классификацию типов отказов:  аппаратный, при котором общесистемное ПО не работоспособно;  информационный, вызванный ошибками во входных данных и передаче данных по каналам связи, а также при сбое устройств ввода (следствие аппаратных отказов);  эргономический, вызванный ошибками оператора при его взаимодействии с машиной (этот отказ - вторичный отказ, может привести к информационному или функциональному отказам);  программный, при наличии ошибок в компонентах и др. Некоторые ошибки могут быть следствием недоработок при определении требований, проекта, генерации выходного кода или документации. С другой стороны, они порождаются в процессе разработки программы или при разработке интерфейсов отдельных элементов программы (нарушение порядка параметров, меньше или больше параметров и т.п.). Источники ошибок.Ошибки могут быть порождены в процессе разработки проекта, компонентов, кода и документации. Как правило, они обнаруживаются при выполнении или сопровождении программного обеспечения в самых неожиданных и разных ее точках.  Некоторые ошибки в программе могут быть следствием недоработок при определении требований, проекта, генерации кода или документации. С другой стороны, ошибки порождаются в процессе разработки программы или интерфейсов ее элементов (например, при нарушении порядка задания параметров связи - меньше или больше, чем требуется и т.п.). Причиной появления ошибок - непонимание требований заказчика; неточная спецификация требований в документах проекта и др. Это приводит к тому, что реализуются некоторые функции системы, которые будут работать не так, как предлагает заказчик. В связи с этим проводится совместное обсуждение заказчиком и разработчиком некоторых деталей требований для их уточнения. Команда разработчиков системы может также изменить синтаксис и семантику описания системы. Однако некоторые ошибки могут быть не обнаружены (например, неправильно заданы индексы или значения переменных этих операторов). 7.3.2. Классификация ошибок и тестов Каждая организация, разрабатывающая ПО общесистемного назначения, сталкивается с проблемами нахождения ошибок. Поэтому приходится классифицировать типы обнаруживаемых ошибок и определять свое отношение к устранению этих ошибок. На основе многолетней деятельности в области создания ПО разные фирмы создали свою классификацию ошибок, основанную на выявлении причин их появления в процессе разработки, в функциях и в области функциональной деятельности ПО. Известно много различных подходов к классификации ошибок, рассмотрим некоторые из них. Фирма IВМ разработала подход к классификации ошибок, называемый ортогональной классификацией дефектов [7.4]. Подход предусматривает разбиение ошибок по категориям с соответствующей ответственностью разработчиков за них. Схема классификации не зависит от продукта, организации разработки и может применяться ко всем стадиям разработки ПО разного назначения. табл. 7.1 дает список ошибок согласно данной классификации. Используя эту таблицу, разработчик имеет возможность идентифицировать не только типы ошибок, но и места, где пропущены или совершены ошибки. Предусмотрены ситуации, когда найдена неинициализированная переменная или инициализированной переменной присвоено неправильное значение. Ортогональность схемы классификации заключается в том, что любой ее термин принадлежит только одной категории. Таблица 7.1. Ортогональная классификация дефектов IBM Контекст ошибки Классификация дефектов Функция Ошибки интерфейсов конечных пользователей ПО, вызванные аппаратурой или связаны с глобальными структурами данных Интерфей Ошибки во взаимодействии с другими компонентами, в вызовах, макросах, управляющих блоках или в списке параметров Логика Ошибки в программной логике, неохваченной валидацией, а также в использовании значений переменных Присваив Ошибки в структуре данных или в инициализации переменных отдельных частей программы Зациклив Ошибки, вызванные ресурсом времени, реальным временем или разделением времени Среда Ошибки в репозитории, в управлении изменениями или в контролируемых версиях проекта Алгоритм Ошибки, связанные с обеспечением эффективности, корректности алгоритмов или структур данных системы с ание ание Документ Ошибки в записях документов сопровождения или в ация публикациях Другими словами, прослеживаемая ошибка в системе должна находиться в одном из классов, что дает возможность разным разработчикам классифицировать ошибки одинаковым способом. Фирма Hewlett-Packard использовала классификацию Буча, установив процентное соотношение ошибок, обнаруживаемых в ПО на разных стадиях разработки (рис. 7.2) [7.12]. Это соотношение - типичное для многих фирм, производящих ПО, имеет некоторые отклонения. Исследования фирм IBM показали, чем позже обнаруживается ошибка в программе, тем дороже обходится ее исправление, эта зависимость близка к экспоненциальной. Так военновоздушные силы США оценили стоимость разработки одной инструкции в 75 долларов, а ее стоимость сопровождения составляет около 4000 долларов. Рис. 7.2. Процентное соотношение ошибок при разработке ПО Согласно данным [7.6, 7.11] стоимость анализа и формирования требований, внесения в них изменений составляет примерно 10%, аналогично оценивается стоимость спецификации продукта. Стоимость кодирования оценивается более чем 20%, а стоимость тестирования продукта составляет более 45% от его общей стоимости. Значительную часть стоимости составляет сопровождение готового продукта и исправление обнаруженных в нем ошибок. пределение теста.Для проверки правильности программ специально разрабатываются тесты и тестовые данные. Под тестом понимается некоторая программа, предназначенная для проверки работоспособности другой программы и обнаружения в ней ошибочных ситуаций. Тестовую проверку можно провести также путем введения в проверяемую программу отладочных операторов, которые будут сигнализировать о ходе ее выполнения и получения результатов. Тестовые данные служат для проверки работы системы и составляются разными способами: генератором тестовых данных, проектной группой на основе внемашинных документов или имеющихся файлов, пользователем по спецификациям требований и др. Очень часто разрабатываются специальные формы входных документов, в которых отображается процесс выполнения программы с помощью тестовых данных [7.11]. Создаются тесты, проверяющие:  полноту функций;  согласованность интерфейсов; корректность выполнения функций и правильность функционирования системы в заданных условиях;- надежность выполнения системы;  защиту от сбоев аппаратуры и не выявленных ошибок и др. Тестовые данные готовятся как для проверки отдельных программных элементов, так и для групп программ или комплексов на разных стадиях процесса разработки. На рис. 7.3. приведена классификация тестов проверки по объектам тестирования на основных этапах разработки.  увеличить изображение Рис. 7.3. Классификация тестов проверки Многие типы тестов готовятся заказчиком для проверки работы программной системы. Структура и содержание тестов зависят от вида тестируемого элемента, которым может быть модуль, компонент, группа компонентов, подсистема или система. Некоторые тесты зависят от цели и необходимости знать: работает ли система в соответствии с ее проектом, удовлетворены ли требования и участвует ли заказчик в проверке работы тестов и т.п. В зависимости от задач, которые ставятся перед тестированием программ, составляются тесты проверки промежуточных результатов проектирования элементов на этапах ЖЦ, а также создаются тесты испытаний окончательного кода системы. Тесты интегрированной системы.Тесты для проверки отдельных элементов системы и тесты интегрированной системы имеют общие и отличительные черты. Так, на рис. 7.4 в качестве примера приведена схема интеграции готовых оттестированных элементов. В ней заданы связи между разными уровнями тестирования интегрируемой ПС. Рис. 7.4. Интегрированное тестирование компонент Рассмотрим этот процесс более подробно. Каждый компонент этой схемы тестируется отдельно от других компонентов с помощью тестов, включающих наборы данных и сценарии, составленные в соответствии с их типами и функциями, специфицированные в проекте системы. Тестирование проводится в контрольной операционной среде на предопределенном множестве тестовых данных и операциях, производимых над ними. Тесты обеспечивают проверку внутренней структуры, логики и граничных условий выполнения для каждого компонента. Согласно приведенной схеме сначала тестируются компоненты А, В, D независимо друг от друга и каждый с отдельным тестом. После их проверки выполняется проверка интерфейсов для последующей их интеграции, суть которой заключается в анализе выполнения операторов вызова А -> E, B -> C, D -> G, на нижних уровнях графа: компоненты Е, С, G. При этом предполагается, что указанные вызываемые компоненты, так же должны быть отлажены отдельно. Аналогично проверяются все обращения к компоненту F, являющемуся связывающим звеном с вышележащими элементами. При этом могут возникать ошибки, в случае неправильного задания параметров в операторах вызова или при вычислениях процедур или функций. Возникающие ошибки в связях устраняются, а затем повторно проверяется связь с компонентом F в виде троек: компонент-интерфейскомпонент. Следующим шагом тестирования комплексной системы является проверка функционирования системы с помощью тестов проверки функций и требований к ним. После проверки системы на функциональных тестах происходит проверка на исполнительных и испытательных тестах, подготовленных согласно требованиям к ПО, аппаратуре и выполняемым функциям. Испытательному тесту предшествует верификация и валидация ПО. Тест испытаний системы в соответствии с требованиями заказчика проверяется в реальной среде, в которой система будет в дальнейшем функционировать. 7.3.1. Служба тестирования ПС За функциональные и исполнительные тесты несут ответственность разработчики заказчик, он больше влияет на составление тестов испытаний и инсталляции системы [7.6]. Для этих целей, как правило, создается служба проверяющих ПС команда тестировщиков, которая не зависит от штата разработчиков ПС. Некоторые члены этой команды - опытные или даже профессионалы в этой области. К ним относятся аналитики, программисты, инженерытестировщики, которые посвящают в проблемы тестирования систем с начала разработки. Они имеют дело не только со спецификациями, но и с методами и средствами тестирования, организуют создание и выполнение тестов. С самого начала создания проекта тестировщики составляют планы тестирования, тестовые данные и сценарии, а также графики выполнения тестов. Профессиональные тестировщики работают совместно с группой управления конфигурацией, чтобы обеспечить их документацией и другими механизмами для связи между собой тестов с требованиями проекта, конфигурацией и кодом. Они разрабатывают методы и процедуры тестирования. В эту команду включаются дополнительные специалисты, которые знакомы с требованиями системы или с подходами к их разработке. Аналитиков включают в команду, так как они понимают проблемы определения спецификаций заказчиков. Многие специалисты сравнивают тестирование системы с созданием новой системы, в которой аналитики отражают потребности и цели заказчика, работая совместно с проектировщиками и добиваясь реализации идей и принципов работы системы.Проектировщики системы сообщают команде тестировщиков проектные цели, чтобы они знали декомпозицию системы на подсистемы и ее функции, а также принципы их работы. После проектирования тестов и тестовых покрытий, команда тестировщиков проводит анализ возможностей системы. Так как тесты и тестовые сценарии являются прямым отражением требований и проекта в целом, перспективы управления конфигурацией системы определяются именно этой командой. Обнаруживаемые в программе ошибки и изменения в системе отражаются в документации, требованиях, проекте, а также в описаниях входных и выходных данных или в других разрабатываемых артефактах. Вносимые изменения в процессе разработки приводят к модификации тестовых сценариев или в большей части к изменению планов тестирования. Специалисты по управлению конфигурацией учитывают эти изменения и координируют составление тестов. В команду тестировщиков входят также пользователи. Они оценивают получаемые результаты, удобство использования, а также высказывают свое мнение о принципах работы системы. Уполномоченные заказчика планируют работы для тех пор, пока используется и сопровождается система. При этом они могут привнести некоторые изменения в проект из-за неполноты заданных требований и сформулировать системные требования для проведения верификации системы и принятия решений о ее готовности и полезности. План тестирования.Для проведения тестирования создается план (Test Plan), в котором описываются стратегии, ресурсы и график тестирования отдельных компонентов и системы в целом. В плане отмечаются работы для разных членов команды, которые выполняют определенные роли в этом процессе. План включает также определение роли тестов в каждом процессе, степень покрытия программы тестами и процент тестов, которые выполняются со специальными данными. Тестовые инженеры создают множество тестовых сценариев (Test Cases), каждый из которых проверяет результат взаимодействия между актором и системой на основе пред- и постусловий использования таких сценариев. Сценарии в основном относятся к тестированию по типу белого "ящика" и ориентированы на проверку структуры и операций интеграции компонентов системы. Для проведения тестирования тестовые инженеры предлагают процедуры тестирования (Test Procedures), включающие валидациюобъектов и верификацию тестовых сценариев в соответствии с планом графикам. Оценка тестов (Test Evaluation) заключается в оценке результатов тестирования, степени покрытия программ сценариями и статуса полученных ошибок. На рис. 7.5. приведен круг обязанностей инженератестировщика. Рис. 7.5. Ответственности инженера-тестировщика Тестировщик интегрированной системы проводит тестирование интерфейсов и дает оценку результатов выполнения соответствующих тестов с помощью создаваемых им системных тестов, выполняет анализ результатов тестирования, проведенного с отдельными элементами системы. При выполнении системных тестов, как правило, находятся дефекты, как результат глубоко скрытых погрешностей в программах, обнаруживаемых при длительной прогонке системы на тестовых данных и сценариях. 7.3.2. Управление процессом тестирования Все способы тестирования ПС объединяются базой данных, где помещаются результаты тестирования системы. В ней содержатся все компоненты, тестовые контрольные данные, результаты тестирования и информация о документировании процесса тестирования. База данных проекта поддерживается специальными инструментальными средствами типа CASE, которые обеспечивают ведение анализа ПрО, сборку данных об их объектах, потоках данных и тому подобное. База данных проекта хранит также начальные и эталонные данные, которые используются для сопоставления данных,накопленных в базе, с данными, которые получены в процессе тестирования системы. При тестировании выполняются разные виды расчетов характеристик этого процесса и способы планирования и управления. 1. Расчет продолжительности выполнения функций путем сбора средних показателей скорости выполнения операторов без выполнения программы на машине. Выявляются компоненты, которые требуют большого времени выполнения в реальной среде. 2. Управление выполнением тестирования путем подбора тестов проверки, их выполнения, селекции результатов тестирования и проведения сопоставления с эталонными значениями. Результаты данного процесса отображаются на дисплее, например, в графической форме (пути прохождения по графу программы), в виде диаграмм UML, данных об отказах и ошибках или конкретных значений исходных параметров программы. Эти данные анализируются разработчиками для формулирования выводов о направлениях дальнейшей проверки правильности программы или их завершении. 3. Планирование тестирования предназначено для распределения сроков работ по тестированию, распределения тестировщиков по отдельным видам работ и составления ими тестов проверки системы. Определяются стратегия и пути тестирования. В диалоге запрашиваются данные о реальных значениях процесса выполнения системы, структуре ветвления вершин графа и параметрах циклов. Проверенные циклы, как правило, изымаются из путей выполнения программы. При планировании путей выполнения создаются соответствующие тесты, критерии и входные значения. Документирование результатов тестирования в соответствии с действующим стандартом ANSI/IEEE 829 включает:  описание задач, назначение и содержание ПС, а также перечень функций в соответствии с требованиями заказчика;  технологии разработки системы;  планов тестирования различных объектов, необходимых ресурсов, соответствующих специалистов для проведения тестирования и технологических способов;  тестов, контрольных примеров, критериев и ограничений, оценки результатов программного продукта, а также процесса тестирования;  учета процесса тестирования, составление отчетов об аномальных событиях, отказах и дефектах в итоговом документе системы. Таким образом, были рассмотрены современные методы и процессы верификации и тестирования ПС, основанные на понятии программы "белый ящик" и "черный ящик", а также на анализе реализованных в ПС функций. Определены критерии тестирования, типы ошибок, обнаруживаемых в программах, а также отказы и ошибки на этапах ЖЦ процесса тестирования. Сформулированы цели и задачи группы тестировщиков. Раздел 4 Документирование программного обеспечения Когда программист-разработчик получает в той или иной форме задание на программирование, перед ним, перед руководителем проекта и перед всей проектной группой встают вопросы: что должно быть сделано, кроме собственно программы? что и как должно быть оформлено в виде документации? что передавать пользователям, а что — службе сопровождения? как управлять всем этим процессом? Кроме упомянутых вопросов есть и другие, например, что должно входить в само задание на программирование? Прошло много лет, программирование происходит в среде совершенно новых технологий, многие программисты, работая в стиле drag-and-drop, могут годами не видеть текст своих программ. Это не значит, что исчезла необходимость в их документировании. Более того, вопросы о наличии хоть какой-то системы, регламентирующей эту сторону создания программных средств, продолжают задавать постоянно. Спрашивают и о том, есть ли обязательные для применения стандарты (особенно остро стоит этот вопрос, когда разработка выполняется по заказу государственной организации или предприятия). Интересуются и тем, где можно купить имеющиеся стандарты. Качество программного обеспечения, наряду с другими факторами, определяется полнотой и качеством пакета документов, сопровождающих ПО. К программным документам относятся документы, содержащие сведения, необходимые для разработки, изготовления, сопровождения программ и эксплуатации. 1. Анализ стандартов программной документации Регламентация проектной деятельности основывается на стандартах и методологиях, среди которых в настоящее время наиболее популярны как стандарты ГОСТ 34-й и 19-й серий, определяющие требования к разрабатываемой документации, так и новые стандарты ГОСТ Р ИСО/МЭК 12207-99 и ГОСТ Р ИСО/МЭК 14764-2002, определяющие процессы жизненного цикла программных средств. Одной из наиболее развитых и популярных методологий, описывающих процессы жизненного цикла (ЖЦ) программного средства (ПС), является Rational Unified Process (RUP), разработанный компанией Rational Software и соответствующий ГОСТ Р ИСО/МЭК 12207-99. При этом необходимо отметить, что RUP ориентирован прежде всего на разработку ПС и без предварительной адаптации не может использоваться для задач процесса сопровождения [8]. Сейчас складывается ситуация, когда многие коллективы, разрабатывающие программные средства, переходят на использование технологий, основанных на методологии RUP. В то же время, большинство Заказчиков, как внешних, так и внутренних, продолжают использовать стандарты серии ГОСТ 19 и 34 как основные при приемке программных средств от разработчика. Таким образом, возникает необходимость поддерживать двойную технологию, ориентируясь при разработке на методологию RUP, а при сдаче результатов – на стандарты ГОСТ 19 и 34 [8]. Сравнительный анализ зарубежного и российского приведены в таблице 1. Таблица 1 Сравнительный анализ стадий RUP и ГОСТ Стадии RUP Стадии ГОСТ 34.601-90 Обследование (Inception) Формирование требований Разработка концепции Техническое задание стандартов Технический проект (Elaboration) Эскизный проект Технический проект Рабочий проект (Construction) Рабочая документация Передача в эксплуатацию (Transition) Ввод в действие Сопровождение[8] Техническое задание Техническое задание. Требование к содержанию и оформлению. Напомним, что техническое задание (ТЗ) содержит совокупность требований к ПС и может использоваться как критерий проверки и приемки разработанной программы. Поэтому достаточно полно составленное (с учетом возможности внесения дополнительных разделов) и принятое заказчиком и разработчиком, ТЗ является одним из основополагающих документов проекта программного средства. Техническое задание на разработку ПО должно включать следующие разделы: введение; основания для разработки; назначение разработки; требования к программе; требования к программной документации; технико-экономические показатели; стадии и этапы разработки; порядок контроля и приемки; приложения. В зависимости от особенностей разрабатываемого ПО стандарт допускает уточнение содержания разделов, введение новых разделов или их объединение. В разделе “Введение” указывается наименование, краткая характеристика области применения ПО. В разделе “Основания для разработки” указывается: документ (документы), на основание которых ведется разработка; организация, утвердившая документ, и дата утверждения; наименование (условное обозначение) темы разработки. В разделе Назначение разработки должно быть указано функциональное и эксплуатационное назначение ПО. Например, UML – как универсальный язык моделирования. Может использоваться и для постановки технического задания. Внешние и внутренние языки спецификации В процессе разработки ПО появляются следующие документы, перечисленные ниже в хронологическом порядке: Соглашение о требованиях; Внешняя спецификация; Внутренняя спецификация. Документ “Соглашение о требованиях” должен содержать первое письменное соглашение между заказчиком и разработчиком о том, что будет сделано, и что не будет делаться при разработке и выпуске программного обеспечения. В отличие от него спецификация предполагает наличие более точных и исчерпывающих формулировок и определений. При этом, первые два документа содержат информацию о том, что представляет собой ПО; а третий должен объяснять, как ПО устроено и как достигаются установленные для него цели и требования. Все документы имеют схожую структуру для облегчения контроля над проектом, а также для обеспечения прослеживаемости всех технических решений от требований до их реализации. По мере продвижения проекта разделы документа либо просто копируются в соответствующие разделы следующего создаваемого документа, либо расширяются описаниями технических решений текущего этапа. Ниже приведена общая структура документа “Внешняя спецификация”, с развернутыми комментариями в тех пунктах, которые касаются технической стороны дела 1. ОПИСАНИЕ ПРОГРАММНОГО ИЗДЕЛИЯ 1.1. Наименование и шифры ПО (полное наименование, сокращенные наименования, шифры ПО и проекта). 1.2. Краткое описание ПО (включая сведения об авторском праве, иерархию документов, с указанием документов вышестоящих уровней). 1.3. Результирующие компоненты ПО (оформляется в виде таблицы или другой формы и включает в себя, перечень спецификаций, другой документации и компонентов программного обеспечения). 2. ЦЕЛИ Этот раздел содержит причины выпуска ПО с указанием различного типа заявок, планов и т.п. и носит полностью управленческий характер. 3. СТРАТЕГИЯ 3.1. Соглашения относительно представления материала. 3.1.1. Обозначения (определяются все обозначения, используемые в требованиях: например, если применяются индексы, то дается пример их использования и определяется принцип индексации). 3.1.2. Терминология (особенно специфическая для данного изделия). 3.1.3. Синтаксис (приводятся, если необходимо, синтаксические правила для дальнейшего описания требований). 3.2. Генерируемое программное обеспечение (классифицируется как вспомогательное и порождаемое описываемым изделием). 3.3. Системное программное обеспечение (все остальное ПО, включая ОС, утилиты, пакеты прикладных программ, которое классифицируется как основное, поскольку оно генерирует ПО предыдущего пункта). Примечание. Причина такой расстановки пунктов состоит в том, что при правильном проектировании сверху вниз генерируемое программное обеспечение является основной целью проектирования и должно быть описано раньше, чем его генератор. Другими словами, структура генерируемых программ должна определять структуру генератора, а не наоборот. Если все ПО является основным, то в п.3.2. делается пометка не используется и опускаются все его подпункты. Структура подпунктов п.п. 3.2 и 3.3 полностью дублируется и далее для простоты используется нумерация только п.п. 3.3. 3.3.n. Общие характеристики функции n. Если технически затруднительно и неестественно рассматривать ПО как один большой функциональный модуль, то следует привести его функциональную декомпозицию, показав связи между функциями (функциональными модулями) и присвоив каждой функции некоторое уникальное имя n. Затем для каждой функции отводится подраздел раздела 3.3 (т.е. 3.3.1, 3.3.2 и т.д.), в заглавии которого используется слово функция с последующим именем функционального модуля. Такая функциональная декомпозиция не указывает, как именно ПО будет фактически разбито на программные модули (это составляет содержание документа Внутренняя спецификация). Для удобства работы, конечно, полезно иметь некоторое соответствие функционального и фактического разбиения, но это не является требованием и не должно уводить с правильного пути проектирования изделия. 3.3.n.1. Внешние ограничения. 3.3.n.1.1. Стандарты (список используемых промышленных стандартов и собственных стандартов предприятия). 3.3.n.1.2. Ограничения на совместимость. Необходимо рассматривать несколько аспектов совместимости: исходный язык, машинный язык, форматы данных и сообщений, форматы отчетов, форматы листингов и т.п. Специально должна оговариваться совместимость со следующими программными изделиями: изделиями-предшественниками (т.е. такими, которые пользователь может заменить новым изделием; если число функций при такой замене уменьшается, то следует привести обоснование этому); изделиями-компаньонами (т.е. относящимися к той же группе средств и являющимися альтернативой); подобными изделиями (т.е. выполняющих похожие функции в других программных изделиях); конкурирующими изделиями (других организаций). 3.3.n.1.3. Программные ограничения. Описываются программное окружение разрабатываемого ПО, включая указание средств для его загрузки и запуска. Также отмечаются все действующие программные ограничения, например использование вычислений с удвоенной точностью для некоторых функций. 3.3.n.1.4. Аппаратные ограничения. Приводится перечень устройств, необходимых для работы ПО (с указанием минимальной, оптимальной и максимальной конфигурации). Указываются все действующие ограничения на оборудование, например, физические характеристики терминала или требование запрещения использования звукового сигнального устройства. 3.3.n.2. Внешние характеристики. Примечание. Если разрабатываемое ПО является расширением уже существующего, то описываются, главным образом, его дополнительные характеристики. В любом случае наибольшее внимание должно уделяться самым важным для конечного пользователя вопросам. Эти разделы являются основой документа и содержат полное и окончательное описание всех свойств программного изделия. 3.3.n.2.1. Результаты. Описываются все выходные данные ПО с точки зрения их функционального содержания и назначения (например, файлы, сообщения, программно устанавливаемые сигналы и прерывания). При этом должны быть рассмотрены все возможные в системе носители и средства отображения информации. Указываются тип, структура, формат, объем, расположение и диапазон изменения. Для всех выходных данных, читаемых людьми (сообщения и отчеты) должны быть приведены образцы. 3.3.n.2.2. Процессы обработки. Описываются операции, выполняемые ПО в целом или функциональными модулями, рассматриваемыми как черный ящик. Если обсуждение идет на уровне модулей или этапов разработки, указываются также модули или этапы, требуемые для получения определенной выходной информации. Точно определяются все возможные ошибки, потенциальные условия их возникновения и способы рестарта и восстановления. Подраздел должен описывать инициацию, преобразование данных, все варианты завершения работы (нормального и аварийного). 3.3.n.2.3. Входы. Описание подобно п. 3.3.2.1 3.3.n.3. Эргономические характеристики. Примечание. Этот раздел описывает свойства, обеспечивающие надежность, комфорт и продуктивность работы пользователей и операторов, а также вопросы безопасности, секретности, восстанавливаемости после сбоев, мобильности ПО. Остановимся более подробно на двух подразделах: Надежность и Рабочие характеристики. В разделе Надежность (это свойство программы понимается здесь как способность к восстановлению нормальной работы при ошибках и сбоях в работе оборудования) рассматриваются следующие вопросы: защита данных пользователя; степень защиты программ от ошибок, возникающих в других частях системы (например, работающих одновременно с данной программой в другой области памяти). Следует рассмотреть, как могут повлиять на работу предлагаемых программных средств такие ошибки, учитывая следующие моменты: распределение ресурсов памяти (указать, если предусмотрено обеспечение изоляции отводимых областей памяти); связь программ через общие аппаратные ресурсы. Раздел “Рабочие характеристики” описывает основные параметры или принципы, по которым должна оцениваться эффективность работы программы, по возможности в количественном виде с указанием возможных допусков. Все параметры должны быть измеряемыми, к их числу могут относиться быстродействие, пропускная способность, скорость передачи данных, расход машинных ресурсов, время реакции (или задержки) и т.д. 3.3.n.4. Внутренние характеристики (этот раздел полностью расширяется в документе “Внутренняя Спецификация”, однако частично может быть заполнен с целью полного описания соответствующих внешних свойств). 3.4. Внутренние ограничения (здесь речь идет о тех свойствах, которые пользователю логично ожидать, но которые по тем или иным причинам будут исключены из программного изделия или потенциально оставлены на усмотрение разработчика: например, неполная взаимозаменяемость носителей, отсутствие поддержки каких-либо возможностей оборудования, и т.п.). 4. ИСПОЛЬЗУЕМЫЕ МАТЕРИАЛЫ (в т.ч. справочные) 5. ПЕРЕДАЧА ЗАКАЗЧИКУ И ВВОД В ДЕЙСТВИЕ Руководство пользователя Под документацией пользователя понимается документация, которая обеспечивает конечного пользователя информацией по установке и эксплуатации программного пакета. Под информацией на упаковке понимают информацию, воспроизводимую на внешней упаковке программного пакета. Ее целью является предоставление потенциальным покупателям первичных сведений о программном пакете. Пользовательская документация программного средства объясняет пользователям, как они должны действовать, чтобы применить данную программу. Она необходима, если программа предполагает какое-либо взаимодействие с пользователями. К такой документации относятся документы, которыми руководствуется пользователь при установке программы с соответствующей настройкой на среду применения, при применении программы для решения своих задач и при управлении программой (например, когда данное программное средство взаимодействует с другими системами). Эти документы частично затрагивают вопросы сопровождения программного средства, но не касаются вопросов, связанных с модификацией программ. В связи с этим следует различать две категории пользователей: ординарных пользователей программы и администраторов. Ординарный пользователь программы (end-user) использует программу для решения своих задач (в своей предметной области). Это может быть инженер, проектирующий техническое устройство, или кассир, продающий железнодорожные билеты с помощью данной программы. Он может и не знать многих деталей работы компьютера или принципов программирования. Администратор программны (system administrator) управляет использованием программы ординарными пользователями и осуществляет сопровождение программного средства, не связанное с модификацией программ. Например, он может регулировать права доступа к программе между ординарными пользователями, поддерживать связь с поставщиками программы или выполнять определенные действия, чтобы поддерживать программу в рабочем состоянии, если оно включено как часть в другую систему. Состав пользовательской документации зависит от аудиторий пользователей, на которые оно ориентировано, и от режима использования документов. Под аудиторией здесь понимается контингент пользователей, у которого есть необходимость в определенной пользовательской документации. Удачный пользовательский документ существенно зависит от точного определения аудитории, для которой он предназначен. Пользовательская документация должна содержать информацию, необходимую для каждой аудитории. Под режимом использования документа понимается способ, определяющий, каким образом используется этот документ. Обычно пользователю достаточно больших программных систем требуются либо документы для изучения программного средства (использование в виде инструкции), либо для уточнения некоторой информации (использование в виде справочника). Можно считать типичным следующий состав пользовательской документации для достаточно больших программных средств: Общее функциональное описание программного средства. Дает краткую характеристику функциональных возможностей программного средства. Предназначено для пользователей, которые должны решить, насколько необходимо им данное программного средства. Руководство по инсталяции программного средства. Предназначено для системных администраторов. Он должен детально предписывать, как устанавливать системы в конкретной среде. Он должен содержать описание машинно-считываемого носителя, на котором поставляется программное средство, файлы, представляющие программное средство, и требования к минимальной конфигурации аппаратуры. Инструкция по применению программного средства. Предназначена для ординарных пользователей. Содержит необходимую информацию по применению программного средства, организованную в форме удобной для ее изучения. Справочник по применению программного средства. Предназначен для ординарных пользователей. Содержит необходимую информацию по применению программного средства, организованную в форме удобной для избирательного поиска отдельных деталей. Руководство по управлению программным средством. Предназначено для системных администраторов. Оно должно описывать сообщения, генерируемые, когда программные средства взаимодействует с другими системами, и как реагировать на эти сообщения. Кроме того, если программное средство использует системную аппаратуру, этот документ может объяснять, как сопровождать эту аппаратуру. Разработка пользовательской документации начинается сразу после создания внешнего описания. Качество этой документации может существенно определять успех программы. Она должна быть достаточно проста и удобна для пользователя (в противном случае это программное средство, вообще, не стоило создавать). Поэтому, хотя черновые варианты (наброски) пользовательских документов создаются основными разработчиками программного средства, к созданию их окончательных вариантов часто привлекаются профессиональные технические писатели. Кроме того, для обеспечения качества пользовательской документации разработан ряд стандартов, в которых предписывается порядок разработки этой документации, формулируются требования к каждому виду пользовательских документов и определяются их структура и содержание. Руководство программиста Документация по сопровождению программного средства (system documentation) описывает программное средство с точки зрения ее разработки. Эта документация необходима, если программное средство предполагает изучение того, как оно устроена (сконструирована), и модернизацию его программ. Как уже отмечалось, сопровождение - это продолжающаяся разработка. Поэтому в случае необходимости модернизации программного средства к этой работе привлекается специальная команда разработчиков-сопроводителей. Этой команде придется иметь дело с такой же документацией, которая определяла деятельность команды первоначальных (основных) разработчиков программного средства, - с той лишь разницей, что эта документация для команды разработчиков-сопроводителей будет, как правило, чужой (она создавалась другой командой). Команда разработчиков-сопроводителей должна будет изучать эту документацию, чтобы понять строение и процесс разработки модернизируемого программного средства, и внести в эту документацию необходимые изменения, повторяя в значительной степени технологические процессы, с помощью которых создавалось первоначальное программное средство. Документация по сопровождению программного средства можно разбить на две группы: 1. документация, определяющая строение программ и структур данных ПС и технологию их разработки; 2. документацию, помогающую вносить изменения в программное средство. Документация первой группы содержит итоговые документы каждого технологического этапа разработки программного средства. Она включает следующие документы: Внешнее описание программного средства (Requirements document). Описание архитектуры программного средства (description of the system architecture), включая внешнюю спецификацию каждой ее программы. Для каждой программы программного средства - описание ее модульной структуры, включая внешнюю спецификацию каждого включенного в нее модуля. Для каждого модуля - его спецификация и описание его строения (design description). Тексты модулей на выбранном языке программирования (program source code listings). Документы установления достоверности программного средства (validation documents), описывающие, как устанавливалась достоверность каждой программы программного средства и как информация об установлении достоверности связывалась с требованиями к программному средству. Документы установления достоверности включают прежде всего документацию по тестированию (схема тестирования и описание комплекта тестов), но могут включать и результаты других видов проверки программного средства, например, доказательства свойств программ. Документация второй группы содержит Руководство по сопровождению программного средства (system maintenance guide), которое описывает известные проблемы вместе с программным средством, описывает, какие части системы являются аппаратно- и программно-зависимыми, и как развитие программного средства принято в расчет в его строении (конструкции). Общая проблема сопровождения программного средства - обеспечить, чтобы все его представления шли в ногу (оставались согласованными), когда программное средство изменяется. Чтобы этому помочь, связи и зависимости между документами и их частями должны быть зафиксированы в базе данных управления конфигурацией. Вид эксплуатационного документа Содержание эксплуатационного документа Ведомость эксплуатационных документов Перечень эксплуатационных документов на программу. Формуляр Основные характеристики программы, комплектность и сведения об эксплуатации программы. Описание применения Сведения о назначении программы, области применения, классе решаемых задач, применяемых методах, ограничениях для применения, минимальной конфигурации технических средств. Руководство системного программиста Сведения для проверки, обеспечения функционирования и настройки программы на условия конкретного применения. Руководство программиста Сведения для эксплуатации программы. Руководство оператора Сведения, необходимые для осуществления действий, связанных с выполнением программы вычислительной системой. Описание языка Описание синтаксиса и семантики языка. Руководство по техническому обслуживанию Сведения для применения текстовых и диагностических программ при обслуживание технических средств. Рассмотрим виды документации, указанные выше, подробнее 2. Документирование программных изделий При разработке программных средств (ПС) создается и используется большой объем разнообразной документации. Она необходима как средство передачи информации между разработчиками ПС, как средство управления разработкой ПС, и как средство передачи пользователям информации, необходимой для применения и сопровождения ПС. На создание этой документации приходится большая доля стоимости ПС [3]. Эту документацию можно разбить на две группы:  документы управления разработкой ПС;  документы, входящие в состав ПС [5]. Документы documentation) управления управляют разработкой и протоколируют ПС (software процессы process разработки и сопровождения ПС, обеспечивая связи внутри коллектива разработчиков ПС и между коллективом разработчиков и менеджерами ПС (software managers) - лицами, управляющими разработкой ПС [9]. Эти документы могут быть следующих типов:  планы, оценки, расписания. Эти документы создаются менеджерами для прогнозирования и управления процессами разработки и сопровождения ПС.  отчеты об использовании ресурсов в процессе разработки. Создаются менеджерами.  стандарты. Эти документы предписывают разработчикам, каким принципам, правилам, соглашениям они должны следовать в процессе разработки ПС. Эти стандарты могут быть как международными или национальными, так и специально созданными для организации, в которой ведется разработка ПС.  рабочие документы. Это основные технические документы, обеспечивающие связь между разработчиками. Они содержат фиксацию идей и проблем, возникающих в процессе разработки, описание используемых стратегий и подходов, а также рабочие (временные) версии документов, которые должны войти в ПС.  заметки и переписка. Эти документы фиксируют различные детали взаимодействия между менеджерами и разработчиками [4]. Документы, входящие в состав ПС (software product documentation), описывают программы ПС как с точки зрения их применения пользователями, так и с точки зрения их разработчиков и сопроводителей (в соответствии с назначением ПС). Следует отметить, что эти документы будут использоваться не только на стадии эксплуатации ПС (в ее фазах применения и сопровождения), но и на стадии разработки для управления процессом разработки (вместе с рабочими документами). Во всяком случае, они должны быть проверены (протестированы) на соответствие программам ПС [6]. Эти документы образуют два комплекта с разным назначением:  пользовательская документация ПС (П-документация).  документация по сопровождению ПС (С-документация) [2]. 3. Пользовательская документация программных средств Пользовательская документация ПС (user documentation) объясняет пользователям, как они должны действовать, чтобы применить разрабатываемое ПС. Она необходима, если ПС предполагает какое-либо взаимодействие документы, с пользователями. которыми должен К такой документации руководствоваться относятся пользователь при инсталляции ПС (при установке ПС с соответствующей настройкой на среду применения ПС), при применении ПС для решения своих задач и при управлении ПС взаимодействовать (например, с другими когда разрабатываемое системами). Эти ПС документы будет частично затрагивают вопросы сопровождения ПС, но не касаются вопросов, связанных с модификацией программ [9]. В связи с этим следует различать две категории пользователей ПС: ординарных пользователей ПС и администраторов ПС. Ординарный пользователь ПС (end-user) использует ПС для решения своих задач (в своей предметной области). Он может не знать многих деталей работы компьютера или принципов программирования. Администратор ПС (system administrator) управляет использованием ПС ординарными пользователями и осуществляет сопровождение ПС, не связанное с модификацией программ. Например, он может регулировать права доступа к ПС между ординарными пользователями, поддерживать связь с поставщиками ПС или выполнять определенные действия, чтобы поддерживать ПС в рабочем состоянии, если оно включено как часть в другую систему [8]. Состав пользовательской документации зависит от аудиторий пользователей, на которые ориентировано разрабатываемое ПС, и от режима использования документов. пользователей ПС, Под у которого аудиторией есть понимается необходимость контингент в определенной пользовательской документации ПС. Удачный пользовательский документ существенно зависит от точного определения аудитории, для которой он предназначен. информацию, Пользовательская необходимую для документация каждой должна аудитории. Под содержать режимом использования документа понимается способ, определяющий, каким образом используется этот документ. Обычно пользователю достаточно больших программных систем требуются либо документы для изучения ПС (использование в виде инструкции), либо для уточнения некоторой информации (использование в виде справочника) [5]. Можно считать типовым составом следующий состав пользовательской документации для достаточно больших ПС:  общее функциональное описание ПС. Дает краткую характеристику функциональных возможностей ПС. Предназначено для пользователей, которые должны решить, насколько необходимо им данное ПС.  руководство по инсталляции ПС. Предназначено для администраторов ПС. Оно должно детально предписывать, как устанавливать системы в конкретной среде, в частности, должно содержать описание компьютерно-считываемого носителя, на котором поставляется ПС, файлы, представляющие ПС, и требования к минимальной конфигурации аппаратуры.  инструкция по применению ПС. Предназначена для ординарных пользователей. Содержит необходимую информацию по применению ПС, организованную в форме удобной для ее изучения.  справочник по применению ПС. Предназначен для ординарных пользователей. Содержит необходимую информацию по применению ПС, организованную в форме удобной для избирательного поиска отдельных деталей.  руководство по управлению ПС. Предназначено для администраторов ПС. Оно должно взаимодействует описывать с другими сообщения, системами, генерируемые, и как должен когда ПС реагировать администратор на эти сообщения. Кроме того, если ПС использует системную аппаратуру, этот документ может объяснять, как сопровождать эту аппаратуру [10]. Разработка пользовательской документации начинается сразу после создания внешнего описания. Качество этой документации может существенно определять успех ПС. Она должна быть достаточно проста и удобна для пользователя. И хотя черновые варианты (наброски) пользовательских документов создаются основными разработчиками ПС, к созданию их окончательных вариантов часто привлекаются профессиональные технические писатели. Кроме того, для обеспечения качества пользовательской документации разработан ряд стандартов, в которых предписывается порядок разработки этой документации, формулируются требования к каждому виду пользовательских документов, определяются их структура и содержание [4]. 4. Документация по сопровождению программных средств Документация по сопровождению ПС (system documentation) описывает ПС с точки зрения ее разработки. Эта документация необходима, если ПС предполагает изучение того, как оно устроено (сконструировано), и модернизацию его программ. Сопровождение - это продолжающаяся разработка. Поэтому в случае необходимости модернизации ПС к этой работе привлекается специальная команда разработчиков-сопроводителей. Этой команде приходиться иметь дело с такой же документацией, которая определяла деятельность команды первоначальных (основных) разработчиков ПС, с той лишь разницей, что эта документация для команды разработчиков-сопроводителей будет, как правило, чужой (она создавалась другой командой). Чтобы понять строение и процесс разработки модернизируемого ПС, команда разработчиков-сопроводителей должна изучить эту документацию, а затем внести в нее необходимые изменения, повторяя в значительной степени технологические процессы, с помощью которых создавалось первоначальное ПС [6]. Документация по сопровождению ПС можно разбить на две группы:  документацию, определяющую строение программ и структур данных ПС и технологию их разработки;  документацию, помогающую вносить изменения в ПС [5]. Документация первой группы содержит итоговые документы каждого технологического этапа разработки ПС. Она включает следующие документы:  внешнее описание ПС (Requirements document);  описание архитектуры ПС (description of the system architectture), включая внешнюю спецификацию каждой ее программы (подсистемы).  для каждой программы ПС описание ее модульной структуры, включая внешнюю спецификацию каждого включенного в нее модуля;  для каждого модуля спецификацию и описание его строения (design description);  тексты модулей на выбранном языке программирования (program source code listings);  документы установления достоверности ПС (validation documents), описывающие, как устанавливалась достоверность каждой программы ПС, и как информация об установлении достоверности связывалась с требованиями к ПС [7]. Документы установления достоверности ПС включают, прежде всего, документацию по тестированию (схема тестирования и описание комплекта тестов), но могут включать и результаты других видов проверки ПС, например, доказательства свойств программ. Для обеспечения приемлемого качества этой документации полезно следовать общепринятым рекомендациям и стандартам [3]. Документация сопровождению ПС второй (system группы содержит maintenance guide), руководство которое по описывает особенности реализации ПС (в частности, трудности, которые пришлось преодолевать) и как учтены возможности развития ПС в его строении (конструкции). В нем также фиксируются, какие части ПС являются аппаратно- и программно-зависимыми [1]. Общая проблема сопровождения ПС - обеспечить, чтобы все его представления оставались согласованными, когда ПС изменяется. Чтобы этому помочь, связи и зависимости между документами и их частями должны быть отражены в руководстве по сопровождению, и зафиксированы в базе данных управления конфигурацией [6]. Создание и использование пакета прикладных программ (ППП) от формирования концепции и требований к первой версии до изъятия его из эксплуатации сопровождается документированием объектов и процессов жизненного цикла ППП [4]. По своему назначению документацию ППП можно классифицировать как:  технологическую документацию процесса разработки, включающую подробные технические описания для специалистов, ведущих проектирование, разработку и сопровождение ППП, обеспечивающую возможность отчуждения, детального освоения, развития и корректировки ими программ и баз данных на всем жизненном цикле ППП;  эксплуатационную (пользовательскую) документацию программного продукта, создаваемую для конечных пользователей пакета и позволяющую им осваивать и квалифицированно применять его для решения конкретных прикладных задач [8]. Технологическая документация включает:  проектную документацию;  документацию тестирования компонентов и комплексов программ;  документацию испытаний ППП;  документацию сопровождения и управления конфигурацией ППП [10]. В состав проектной документации входят:  отчет по обследованию предметной области, для которой предназначен разрабатываемый ППП, с описанием комплекса задач;  описание концепции проектирования;  техническое задание на проектирование;  план-график работ;  спецификации эскизного и технического проекта;  документация на разработанные программные модули пакета;  общее описание программного обеспечения, используемого при разработке и функционировании пакета (описание выбранной технологии автоматизированного проектирования ППП, операционной системы, других программных средств) [5]. В состав документации тестирования входят:  исходные данные для проведения тестирования (методы тестирования, тестовые наборы, эталонные значения, реальные ресурсы тестирования - временные, аппаратно-программные, людские, критерии полноты и качества тестирования);  программа (сценарии) тестирования;  журнал тестирования;  итоговый отчет о результатах тестирования [7]. В состав документации испытаний входят:  программа испытаний;  описание методов и методик испытаний;  протоколы испытаний;  акт завершения работ;  акт приемки ППП в эксплуатацию [3]. В состав документации сопровождения управления конфигурацией входят:  отчеты пользователей о выявленных дефектах и предложения по корректировке программ;  журнал выявленных дефектов и предложений по совершенствованию и развитию версии ППП;  журнал подготовленных и утвержденных корректировок, а также реализованных изменений в новой версии пакета;  отчет о результатах эксплуатации снятой с сопровождения версии пакета;  журнал тиражирования и характеристик базовых версий, поддерживаемых сопровождением [2]. Пользовательская документация включает в себя:  паспорт на программное средство, где содержатся общие сведения о ППП, его основные характеристики, комплектность, акт о приемке, гарантии изготовителя (поставщика);  общее описание информационной системы (ИС), в составе которой будет использоваться ППП (назначение и описание взаимосвязей ППП с другими составляющими ИС); ИС, описание  руководство администратора программного средства, которое регламентирует функции администрирования, процедуры по инсталляции и подготовке ППП к эксплуатации, порядок и средства ведения базы данных и восстановления информации при сбоях;  руководства оперативных пользователей с требованиями к уровню подготовки пользователя, описание функций. Описан порядок подготовки ППП к работе и действия пользователя в аварийных ситуациях, приведены рекомендации по освоению пакета, включая описание контрольного примера, правила его запуска и выполнения [8]. После передачи заказчику по акту ППП наступает этап его внедрения на предприятии заказчика, в процессе которого происходит инсталляция пакета, его интеграция в существующую информационную систему и обучение персонала. Затем программное изделие переходит в стадию промышленной эксплуатации (возможна промежуточная стадия опытной эксплуатации). Сопровождение внедренного пакета может осуществляться как силами специалистов предприятия-заказчика, так и фирмой- разработчиком. Целью сопровождения является выявление и устранение обнаруженных ошибок в программах и данных, введение новых функций и компонентов, анализ состояния и корректировка документации, тиражирование и контроль распространения версий ППП, актуализация и обеспечение сохранности документации и т.д. [9]. В процессе сопровождения в программы вносятся различные программ, выдающих изменения:  исправление ошибок - корректировка неправильные результаты в условиях, ограниченных техническим заданием и документацией;  модернизация - расширение функциональных возможностей или улучшение качества решения отдельных задач в соответствии с новым или дополнительным техническим заданием на ППП;  адаптация, регламентированная документацией, к условиям конкретного использования, обусловленным характеристиками внешней среды или конфигурацией аппаратуры [2]. Выход коммерческого программного продукта на рынок программных средств связан с организацией продаж массовому пользователю. Как правило, для каждого программного продукта существует своя форма кривой продаж, которая отражает на рисунке 1 спрос V во времени t [6]. Вначале продажа программного продукта идет вверх - возрастающий участок кривой. Затем наступает стабилизация. Далее происходит падение объема продаж, что является сигналом к изменению маркетинговой политики фирмы в отношении данного программного продукта, требуется модификация продукта, изменение цены или снятие с продажи [3]. Эксплуатация программного продукта идет параллельно с его сопровождением, при этом эксплуатация программ может начинаться и в случае отсутствия сопровождения, или продолжаться в случае завершения сопровождения еще какое-то время. После снятия программного продукта с продажи его сопровождение может выполняться определенное время [10]. Рисунок 1 Кривая продаж программного продукта Сопровождение коммерческого программного продукта производится в форме устранения обнаруженных ошибок путем выпуска программных «заплаток» - патчей. Эти программы выкладываются на Web-сайте разработчика и предлагаются пользователям. Обновление обычно происходит в автоматическом режиме при загрузке патча. Кроме этого, ведется и модернизация разработчик предлагает программ. В процессе пользователям эксплуатации приобрести новые фирмаверсии программного продукта. специализированными Сопровождение также осуществляется фирмами-распространителями программного продукта (дистрибьюторами) [9]. Снятие программного продукта с продажи и отказ от сопровождения происходят, как правило, в случае изменения технической политики фирмыразработчика, неэффективности работы программного продукта, наличия в нем неустранимых ошибок, отсутствия спроса [4]. Длительность жизненного цикла для различных программных продуктов неодинакова. Для большинства современных программных продуктов длительность жизненного цикла измеряется двумя-тремя годами. Хотя достаточно часто встречаются и давно снятые с производства программные продукты [7]. Существуют программного другие продукта, варианты кроме легального коммерческого, распространения которые появились с использованием глобальных или региональных сетей: freeware - бесплатно распространяемые и поддерживаемые самим пользователем программы; shareware - условно-бесплатные программы. Ими можно пользоваться бесплатно некоторое время, а при условиях регулярного использования требуется внести определенную сумму разработчику программы; demoверсии (демонстрационная и пробная программы). Это версии коммерческих программ, специально подготовленные разработчиком для бесплатного распространения в рекламных целях. Демонстрационная версия, как правило, рассчитана на неограниченное время пользования, но представляет собой урезанный вариант платной программы, то есть в ней реализованы не все функции. Пробная версия обычно полнофункциональна, но остается работоспособной лишь в течение небольшого промежутка времени, достаточного для ознакомления с ней (несколько дней или недель, либо определенное количество запусков). После этого работоспособность программы блокируется или же она превращается в демонстрационную версию; ad ware - программа, показывающая рекламу. Бесплатная программа такого типа, как правило, сохраняет все функции коммерческой версии и остается работоспособной в течение неограниченного времени, однако она постоянно показывает пользователю рекламные окна - баннеры. Чтобы «отключить» назойливую рекламу, необходимо оплатить коммерческую версию; OEM (Original Equipment Manufacturer) - программы, поставляемые с купленной компьютерной техникой по OEM-контракту между фирмойразработчиком и продавцом ПК (или другого hardware). Их стоимость меньше, чем стоимость retail-программ, в «коробочном» исполнении [5]. поставляемых в розницу Список использованных источников 1. Вельдер С.Э., Лукин М.А., Шалыто А.А., Яминов Б.Р. Верификация автоматных программ. [Текст] СПб: Наука, 2011. 242 с. 2. Камаев В.А., Костерин В.В. технологии программирования – новый учебник [Текст] // Современные проблемы науки и образования. 2005. № 2. URL: www.science-education.ru/39-1486 (дата обращения: 19.03.2014). 3. Касихин В. В. Как стать создателем компьютерных игр. Краткое руководство [Текст] Издательство: Вильямс Год: 2006. 4. Ковалевская Е.В. МЕТОДЫ ПРОГРАММИРОВАНИЯ [Текст]: учебнометодический комплекс / Е.В. Ковалевская, Н.В. Комлева. М. : Изд. центр ЕАОИ, 2010. 320 с. 5. Лупин С. А., Посыпкин М. А. Технологии параллельного программирования [Текст] Издательство: Форум, Инфра-М 2011 ISBN: 9785-8199-0336-0, 978-5-16-003155-2. 6. Монографии [Электронный ресурс] Режим доступа: http://www.rae.ru/monographs/141-4630. 7. Ричард Гербер, Арт Бик, Кевин Смит, Ксинмин Тиан Оптимизация ПО. Сборник рецептов [Текст] Издательство: Питер, Год: 2010 ISBN: 978-5-38800131-3, 0976483211. 8. Роберт Мартин Чистый код. Создание, анализ и рефакторинг [Текст] Издательство: Питер Год: 2010. 9. Эрик Эванс Предметно-ориентированное проектирование (DDD): структуризация сложных программных систем [Текст] Издательство: Вильямс Год: 2011. 10. Энди Орам, Грег Уилсон Идеальный код [Текст] Издательство: Питер Год: 2011. Размещено на Allbest.ru
«Технологии программирования» 👇
Готовые курсовые работы и рефераты
Купить от 250 ₽
Решение задач от ИИ за 2 минуты
Решить задачу
Помощь с рефератом от нейросети
Написать ИИ
Получи помощь с рефератом от ИИ-шки
ИИ ответит за 2 минуты

Тебе могут подойти лекции

Смотреть все 588 лекций
Все самое важное и интересное в Telegram

Все сервисы Справочника в твоем телефоне! Просто напиши Боту, что ты ищешь и он быстро найдет нужную статью, лекцию или пособие для тебя!

Перейти в Telegram Bot