Главная страница
Навигация по странице:

  • 4.6. СВОЙСТВА

  • ОПРЕДЕЛЕНИЕ ОБЛАСТИ ВИДИМОСТИ КЛАССА

  • 4.8. ПРИНЦИПЫ РАБОТЫ ОБЪЕКТНО-ОРИЕНТИРОВАННЫХ ПРОГРАММ

  • ТЕСТИРОВАНИЕ, ОТЛАДКА И ОПТИМИЗАЦИЯ ПРОГРАММ 5.1. ПРОГРАММНЫЕ ОШИБКИ

  • 5.2. ТЕСТИРОВАНИЕ

  • 5.3. ХОД ТЕСТИРОВАНИЯ

  • 5.4. АВТОНОМНОЕ ТЕСТИРОВАНИЕ МОДУЛЕЙ ПРОГРАММЫ

  • 5.5. МЕТОДЫ ТЕСТИРОВАНИЯ

  • Лекции по программированию. Основные понятия классификация программного обеспечения


    Скачать 1.57 Mb.
    НазваниеОсновные понятия классификация программного обеспечения
    АнкорЛекции по программированию.doc
    Дата15.01.2018
    Размер1.57 Mb.
    Формат файлаdoc
    Имя файлаЛекции по программированию.doc
    ТипДокументы
    #14117
    КатегорияИнформатика. Вычислительная техника
    страница4 из 6
    1   2   3   4   5   6

    var

    MyObject: TMyClass; begin

    MyObject.IntField := 0; {Ошибка! Объект не создан

    конструктором}

    MyObject := TMyClass.Create; //Нужно создать объект MyObject.IntField := 0; //и обратиться к его полю

    MyObject.Free; //Уничтожаем ненужный объект

    end;

    Особенность вызова конструктора заключается в том, что он вы­зывается с помощью ссылки на класс, а не на объект. В этом заложен глубокий смысл, так как экземпляр класса в момент вызова конст­руктора еще не создан. Однако код конструктора класса TMyClassнаходится в памяти и поэтому такой вызов вполне корректен.

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

    С помощью метода Free() освобождается выделенная для объ­екта память после его использования. Этот метод проверяет, не ра­вен ли объект значению Nill, и затем вызывает деструктор объек­та - метод Destroy(), который освобождает всю выделенную память и выполняет другие действия по освобождению захваченных кон­структором объекта ресурсов. В отличие от вызова конструктора, вызов метода Free() выполняется с помощью ссылки на экземпляр, а не на класс.

    Большинство конструкторов реализует некоторые действия, не­обходимые для правильной работы объекта. Поэтому в конструк­торе класса потомка следует сначала вызвать конструктор своего родителя, а затем уже осуществлять дополнительные действия. Вы­зов любого метода родительского класса достигается с помощью ключевого слова Inherited (унаследованный). Например:

    Constructor TmyClass.Create(Value: Integer);

    //Возможная реализация конструктора

    begin

    Inherited Create; {Вызываем унаследованный

    конструктор}

    IntField := Value; {Реализуем дополнительные действия} end;
    В большинстве примеров, поставляемых вместе с Delphi, нет вы­зовов конструкторов и деструкторов. Это объясняется тем, что лю­бой компонент, попавший при визуальном проектировании в при­ложение из палитры компонентов, включается в определенную ие­рархию, которая замыкается на форме TForm, а для всех ее составных частей конструкторы и деструкторы вызываются автома­тически. Создает и уничтожает формы глобальный объект с именем Application. Для объектов, создаваемых динамически (во время вы­полнения приложения), обязательно нужен вызов конструктора.

    4.6. СВОЙСТВА

    Свойства объекта представляют собой специальный механизм классов, регулирующий доступ к полям объекта. По от­ношению к компонентам свойства являются теми элементами, све­дения о которых отображаются в окне ObjectInspector.

    Свойства объявляются с помощью зарезервированных слов property, read и write. Слова read и write считаются зарезер­вированными только в контексте объявления свойства. Обычно свойство связано с некоторым полем и указывает те методы класса, которые должны использоваться при записи в это поле или при чтении из него. Например:

    type

    TaClass = class

    IntField: Integer;

    function GetField: Integer;

    procedure SetField(Value: Integer);

    property IntegerValue: Integer read GetField

    write SetField; end;

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

    aClass.IntField := NewValue;

    Разница между этим оператором и оператором aCIass.IntegerValue := NewValue;

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

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

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

    4.7. ОПРЕДЕЛЕНИЕ ОБЛАСТИ ВИДИМОСТИ КЛАССА

    ObjectPascalпредоставляет дополнительный контроль над доступностью членов классов (полей и методов) с помощью директив private, protected, public, published. Синтаксис использования этих директив следующий:

    type

    TMyClass = class private

    AprivateVariable: Integer; AnotherPrivateVariable: Boolean; protected

    procedure AProtectedProcedure; function ProtectMe: Byte; public

    constructor APublicContructor; destructor APublicKiller; published property AProperty

    read AprivateVariable write APrivateVariable; end;

    За каждой из директив может следовать любое необходимое количество объявлений полей или методов. Эти директивы имеют следующий смысл.

    private - эта часть объекта доступна только для кода, нахо­дящегося в одном модуле с другим кодом данного объекта. Директива private скрывает особенности реализации объекта от поль­зователей и защищает члены этого объекта от непосредственного доступа и изменения извне.

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

    public - описанные подобным образом члены объекта доступ­ны в любом месте данной программы. В этой секции всегда описы­ваются конструкторы и деструкторы.

    published - для этой части объекта при компиляции будет сгенерирована информация о типе времени исполнения. Это даст возможность другим частям приложения получать информацию о части объекта, описанной в этой секции. В частности, подобная информация используется утилитой ObjectInspectorпри построе­нии списков свойств объектов.

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

    4.8. ПРИНЦИПЫ РАБОТЫ

    ОБЪЕКТНО-ОРИЕНТИРОВАННЫХ ПРОГРАММ

    Технология объектно-ориентированного программиро­вания предполагает, что любая процедура или функция в програм­ме представляет собой метод объекта некоторого класса, причем класс должен формироваться в программе, как только возникает необходимость описания новых объектов программирования. Каж­дый новый шаг в разработке алгоритма также должен представлять собой разработку нового класса на основе уже существующих классов. Таким образом, формируется иерархия классов и, в конце концов, вся программа будет представлять собой объект некоторо­го класса с единственным методом run(выполнить).

    В технологии объектно-ориентированного программирования схема взаимодействия методов и данных принципиально иная, чем при технологии структурного программирования: метод, вызывае­мый для одного объекта, как правило, не вызывает другой метод непосредственно. Для начала он должен иметь доступ к другому объекту (создать, получить указатель, использовать внутренний объект в текущем объекте и т. д.), после чего он уже может вызвать для него один из известных методов. Таким образом, структура программы определяется взаимодействием объектов различных классов между собой. Взаимосвязь между объектами осуществля­ется посредством сообщений.

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

    К достоинствам объектно-ориентированного программирова­ния следует отнести:

    исключение избыточного кода;

    возможность защиты объектов от кода других частей программы;

    поддержка повторного использования отдельных составляю­щих программ;

    создание более открытых систем;

    экономия времени за счет построения программы из готовых, отлаженных частей;

    К недостаткам объектно-ориентированного программирования относят:

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

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

    Тем не менее, достоинства объектно-ориентированных систем, как правило, перевешивают перечисленные недостатки. Опыт так­же показывает, что размер исполнимых модулей таких систем обычно меньше.
    ТЕСТИРОВАНИЕ, ОТЛАДКА И ОПТИМИЗАЦИЯ ПРОГРАММ

    5.1. ПРОГРАММНЫЕ ОШИБКИ

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

    Входные данные 1%

    Ошибки пользователя 5%

    Аппаратура 1%

    Системное программное обеспечение 3%

    Разработка системы 15%

    Программирование 75%

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

    Существуют два типа программных ошибок:

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

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

    5.2. ТЕСТИРОВАНИЕ

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

    Тестирование программы (programtesting) - проверка, которая проводится в ходе прогона программы с целью убедиться, работает ли она так, как требуется. Это осуществляется при выполнении од­ного или нескольких тестовых прогонов, при которых в программ­ную систему подаются входные (тестовые данные), а реакция сис­темы фиксируется для последующего анализа. Может осуществ­ляться как с ЭВМ, так и без ЭВМ.

    Один из главных законов тестирования гласит: «Тестирование программы или ее отдельных модулей не должен осуществлять программист (группа программистов), создавший эту программу или модуль».

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

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

    Статистика свидетельствует, что стоимость тестирования со­ставляет не менее 50% всей стоимости начальной разработки.

    Сколько бы сил, времени и денег не было потрачено на тести­рование, один из главных законов программирования действует с неотвратимостью рока: «Тесты могут доказать наличие ошибок в программе, но они не могут доказать их отсутствия» (Э. Дейкстра «Заметки по структурному программированию»).

    При тестировании могут возникать следующие вопросы:

    1. Искать все ошибки или грубейшие?

    2. Если не все, то как установить порог допустимости ошибки?

    3. Когда завершать тестирование?

    1. Что делать, если сроки поджимают или нет ресурсов на дальнейшее тестирование?

    1. Где остановиться в документировании тестов?

    Ответы на них во многом зависят от того, что считать качест­венной программой?

    Качественная программа - это программа, выполняющая зара­нее объявленные действия известным способом и не выполняющая никаких необъявленных действий.

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

    5.3. ХОД ТЕСТИРОВАНИЯ

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

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

    Проектирование тестов. Является наиболее ответст­венным процессом. Очень часто тест создается вручную. Иногда применяют генераторы тестовых данных - специальные програм­мы, формирующие данные в соответствии со спецификациями, задаваемыми программистом. Тестовые данные могут систематиче­ски или случайно выбираться из другого заданного набора данных для уменьшения их общего количества.

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

    Изучение результатов тестирования. Выявление и устранение ошибок часто имеет циклический характер. Устране­ние одной ошибки может порождать другие ошибки. Особенно это касается работы с глобальными переменными, которые коварны тем, что нельзя сказать с полной уверенностью, что где-то на ниж­нем уровне подпрограмм изменение состояния переменной не при­ведет к новой ошибке.

    5.4. АВТОНОМНОЕ ТЕСТИРОВАНИЕ МОДУЛЕЙ ПРОГРАММЫ

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

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

    Автономное тестирование модуля должно как минимум обес­печивать прохождение всех путей вычислений. Проектная проце­дура тестирования модуля состоит из следующих действий:

    1. по внешним спецификациям модуля готовятся тесты для ка­ждой ситуации и каждого недопустимого условия;

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

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

    2. проверяется текст модуля, чтобы определить его чувствитель­ность к особым значениям данных. Наиболее опасные числа это ноль и единица. В случае необходимости нужно добавить тесты.

    5.5. МЕТОДЫ ТЕСТИРОВАНИЯ

    Существует два крайних подхода к проектированию тестов. Сторонники первого подхода создают тесты, исследуя вне­шние спецификации сопряжения программы или модуля, который необходимо протестировать. В этом случае программа является как бы «черным ящиком». Необходимо проверить все возможные ком­бинации и значения на входе. Обычно их слишком много даже для простейших алгоритмов. Для программы расчета среднего арифме­тического четырех чисел надо готовить 107 тестовых данных.

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

    Чтобы построить разумную стратегию тестирования надо ра­зумно сочетать оба этих подхода и пользоваться математическими доказательствами.

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

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

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

    Метод большого скачка. Каждый модуль тестируется автономно. По окончании автономного тестирования все модули интегрируются в готовую программную систему. Этот метод при­меняется, если программа мала и хорошо спроектирована по со­пряжениям.

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

    Модифицированный метод сэндвича. Нижние мо­дули тестируются снизу вверх, а модули верхних модулей сначала тестируются автономно, а затем собираются нисходящим методом.
    1   2   3   4   5   6


    написать администратору сайта