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

  • Ключевые слова

  • 1 Модели качества программного обеспечения

  • Функциональные возможности

  • 2 Метрики качества программного обеспечения Классификация метрик качества программ

  • Классификация метрик сложности программ

  • Метрики размера программ

  • Метрики сложности потока управления программ

  • Метрики сложности потока данных программ

  • Некоторые общие замечания по стратегии и тактике обеспечения надежности

  • вв. Лекция -06_2020. Лекция Модели качества программного обеспечения Цель лекции курса. План лекции


    Скачать 0.7 Mb.
    НазваниеЛекция Модели качества программного обеспечения Цель лекции курса. План лекции
    Дата25.12.2022
    Размер0.7 Mb.
    Формат файлаpdf
    Имя файлаЛекция -06_2020.pdf
    ТипЛекция
    #863609

    Лекция 6. Модели качества программного обеспечения
    Цель лекции: курса.
    План лекции:
    Введение.
    1 Модели качества программного обеспечения
    2 Метрики качества программного обеспечения
    3 Стратегия и тактика обеспечения надежности и безопасности различных видов программного обеспечения
    Заключение
    Контрольные вопросы
    Ключевые слова: [выбрать самостоятельно].
    Содержание лекции:
    Введение
    В основу инженерных методов в программировании положена идея повышения качества ПО, для реализации которой сформировались методы определения требований к качеству ПО, подходы к выбору и усовершенствованию моделей метрического анализа показателей качества ПО, методы количественного измерения показателей качества на этапах жизненного цикла ПО.
    Качество ПО — это совокупность свойств, определяющих полезность изделия
    (программы) для пользователей в соответствии с функциональным назначением и предъявленными требованиями. При этом требования могут трактоваться довольно широко, что порождает целый ряд независимых определений понятия «качество». Чаще всего используется определение ISO 9001, согласно которому качество есть «степень соответствия присущих характеристик требованиям». Качество ПО — это относительное понятие, которое имеет смысл только при учете реальных условий применения ПО.
    Поэтому требования, предъявляемые к качеству ПО, ставятся в соответствии с условиями и конкретной областью применения ПО.
    1 Модели качества программного обеспечения
    Модели качества ПО имеют следующие четыре уровня представления.
    Первый уровень соответствует определению характеристик (показателей) качества
    ПО, каждая из которых отражает отдельную точку зрения пользователя на качество.
    Согласно стандартам ГОСТ Р ИСО/МЭК 9126—93, ГОСТ Р ИСО/МЭК 12119—2000, ГОСТ
    28195—89, в модель качества входит шесть характеристик, или шесть основных показателей качества, которые перечислим в порядке их значимости для большинства пользователей:
    функциональные возможности;
    функциональная надежность;
    удобство применения;
    эффективность;
    сопровождаемость;
    переносимость.
    Второй уровень. Данному уровню соответствуют атрибуты для каждой характеристики качества, которые детализируют разные аспекты конкретной характеристики. Набор атрибутов характеристик качества используется при оценке качества.

    Рассмотрим наборы атрибутов для каждого из перечисленных показателей качества
    (рис. 6.1).
    Рис. 6.1. Характеристики и атрибуты качества ПО

    Функциональные возможности – совокупность свойств, определяющих способность программного обеспечения выполнять предусмотренные функции в заданной среде в соответствии с заданными требованиями. Под функцией понимается некоторая упорядоченная последовательность действий для удовлетворения потребительских свойств. Функции бывают целевые (основные) и вспомогательные.
    К атрибутам функциональных возможностей относятся:
    защищенность атрибут, который показывает способность ПО предотвращать
    несанкционированный доступ (случайный или умышленный) к программам и
    данным;
    интероперабельность атрибут, который показывает возможность
    взаимодействия данного ПО со специальными системами и средами (операционные
    системы, вычислительные сети);
    функциональная полнота атрибут, который показывает меру достаточности
    основных функций для решения задач в соответствии с назначением данного ПО.
    Функциональная надежность. К атрибутам функциональной надежности ПО относятся:
    безошибочность

    атрибут,
    который
    определяет
    способность
    ПО
    функционировать без ошибок;
    правильность атрибут, который показывает меру достижения правильных
    результатов;
    контролируемость атрибут, который характеризует полноту и эффективность
    обнаружения ошибок в промежуточных и выходных результатах
    устойчивость к ошибкам — атрибут, который характеризует способность ПО
    правильно выполнять функции при аномальных условиях (сбой аппаратуры, ошибки
    в данных и интерфейсах и др.);
    безотказность атрибут, который характеризует способность ПО не вызывать
    функциональные отказы информационной системы;
    пригодность к восстановлению атрибут, который характеризует способность
    программы к устранению программной ошибки и к перезапуску для повторного
    выполнения и восстановления данных в случае функционального отказа;
    готовность атрибут, который показывает способность программы по
    произвольной заявке безошибочно выполнить предусмотренное преобразование.
    Удобство применения характеризуется множеством атрибутов, которые указывают на необходимые и пригодные условия использования ПО заданным кругом пользователей для получения соответствующих результатов. В стандарте [
    1
    ] удобство применения определено как специфическое множество атрибутов программного продукта, характеризующих его эргономичность.
    К атрибутам удобства применения относятся:
    понимаемость атрибут, который определяет усилия, затрачиваемые на
    распознавание логических концепций и условий применения ПО;
    изучаемостъ (легкость изучения) атрибут, который определяет усилия
    пользователей, направленные на определение применимости ПО путем
    использования операционного контроля, диагностики, а также процедур, правил и
    документации;
    оперативность атрибут, который показывает реакцию системы при выполнении
    операций и операционного контроля.
    Эффективность – совокупность атрибутов, которые определяют взаимосвязь уровней выполнения ПО, использования ресурсов (средства, аппаратура, материалы – бумага для печатающего устройства и др.) и услуг, выполняемых штатным обслуживающим персоналом и др.
    1
    ГОСТ P ИСО/МЭК 12119—2000. Информационные технологии. Пакеты программ. Требования к качеству и тестирование.

    К атрибутам эффективности ПО относятся:
    реактивность атрибут, который показывает время отклика, обработки и
    выполнения функций;
    эффективность
    ресурсов

    атрибут,
    показывающий
    количество
    и
    продолжительность используемых ресурсов при выполнении функций ПО;
    согласованность атрибут, который показывает соответствие данной
    характеристики заданным стандартам, правилам и предписаниям.
    Сопровождаемость – совокупность свойств, которые характеризуют усилия, которые надо затратить на проведение модификаций, включающих корректировку, усовершенствование и адаптацию ПО при изменении среды, требований или функциональных спецификаций.
    Сопровождаемость включает следующие атрибуты:
    анализируемость атрибут, определяющий необходимые усилия для диагностики
    отказов или идентификации частей, которые будут модифицироваться;
    стабильность атрибут, указывающий на постоянство структуры и риск ее
    модификации;
    тестируемость атрибут, указывающий на усилия при проведении валидации и
    верификации с целью обнаружения несоответствий требованиям, а также на
    необходимость проведения модификации ПО и сертификации;
    изменяемость атрибут, который определяет возможность удаления ошибок в
    ПО или внесение изменений для их устранения, а также введение новых
    возможностей в ПО или в среду функционирования.
    Переносимость – множество показателей, указывающих на способность ПО адаптироваться к работе в новых условиях среды выполнения. Среда может быть организационной, аппаратной и программной. Поэтому перенос ПО в новую среду выполнения может быть связан с совокупностью действий, направленных на обеспечение его функционирования в среде, отличной от той среды, в которой оно создавалось, с учетом новых программных, организационных и технических возможностей.
    Переносимость включает атрибуты:
    адаптивность атрибут, определяющий усилия, затрачиваемые на адаптацию к
    различным средам;
    настраиваемость (простота инсталляции) атрибут, который определяет
    необходимые усилия для запуска данного ПО в специальной среде;
    сосуществование атрибут, который определяет возможность использования
    специального ПО в среде действующей системы;
    заменяемость атрибут, который характеризует возможность переноса ПО с
    одной инструментальной среды в другую с необходимой инсталляцией или
    адаптацией ПО.
    Третий уровень предназначен для измерения качества с помощью метрик, каждая из которых определяется как комбинация метода измерения атрибута и шкалы измерения значений атрибутов. Для оценки атрибутов качества на этапах жизненного цикла (при просмотре документации, программ и результатов тестирования программ) используются метрики с заданным оценочным весом для нивелирования результатов метрического анализа совокупных атрибутов конкретного показателя и качества в целом. Атрибут качества определяется с помощью одной или нескольких методик оценки на этапах жизненного цикла и на завершающем этапе разработки ПО.
    Четвертый уровень – это оценочный элемент метрики (вес), который используется для оценки количественного или качественного значения отдельного атрибута показателя качества ПО. В зависимости от назначения, особенностей и условий сопровождения ПО, выбираются наиболее важные характеристики качества и их атрибуты. Выбранные атрибуты и их приоритеты отражаются в требованиях на разработку систем, либо
    используются соответствующие приоритеты эталона класса ПО, к которому это ПО относится.
    2 Метрики качества программного обеспечения
    Классификация метрик качества программ
    Для измерения характеристик качества используют метрики. Метрика программного обеспечения – это мера, позволяющая получить численное значение некоторого свойства программного обеспечения или его спецификаций. Поскольку количественные методы хорошо зарекомендовали себя в других областях, многие теоретики и практики информатики пытались перенести данный подход и в разработку программного обеспечения.
    Метрика качества программ – система измерений качества программ. Измерения характеристик можно выполнить объективно и достоверно. Однако не следует исключать того, что оценка качества ПО в целом может быть связана с субъективной интерпретацией получаемых оценок.
    В зависимости от характеристик и особенностей применяемых метрик им ставятся в соответствие различные измерительные шкалы:
    номинальной шкале соответствуют метрики, классифицирующие программы на
    типы по признаку наличия или отсутствия некоторой характеристики без учета
    градаций;
    порядковой шкале соответствуют метрики, позволяющие ранжировать
    некоторые характеристики путем сравнения с опорными значениями, т.е.
    измерение по этой шкале фактически определяет взаимное положение конкретных
    программ;
    интервальной шкале соответствуют метрики, которые показывают не только
    относительное положение программ, но и то, как далеко они отстоят друг от
    друга;
    относительной шкале соответствуют метрики, позволяющие не только
    расположить программы определенным образом и оценить их положение
    относительно друг друга, но и определить, как далеко оценки отстоят от границы,
    начиная с которой характеристика может быть измерена.
    Все метрики ПО разделяются на два класса:
    a) метрики, характеризующие наиболее специфические свойства программ, т.е.
    метрики оценки качества самого ПО;
    b) метрики оценки технических характеристик и факторов разработки программ,
    т.е. метрики оценки условий разработки программ[
    2
    ].
    В настоящее время в мировой практике используется несколько сотен метрик программ. Существующие измерения качества программ можно сгруппировать по шести направлениям:
    1) измерения топологической и информационной сложности программ (производятся
    с помощью соответствующих метрик и представляют собой косвенные оценки
    надежности);
    2) оценки функциональной надежности программных систем, позволяющие
    прогнозировать проявление ошибок в программе (производятся непосредственно с
    помощью моделей надежности);
    3) измерения производительности ПО и оценки повышения его эффективности путем
    выявления ошибок проектирования;
    4) измерения уровня языковых средств и оценки их применения;
    2
    Предмет обсуждения данного раздела – свойства программ. Условия и специфика разработки программ находятся за рамками обсуждаемых вопросов.

    5) измерения восприятия и понимания программных текстов, ориентированные на
    психологические факторы, существенные для сопровождения и модификации
    программ;
    6) измерения производительности труда программистов для прогнозирования сроков
    разработки программ и планирования работ по созданию программных комплексов.
    Классификация метрик сложности программ
    Уменьшение сложности ПО обеспечивает снижение трудоемкости проектирования, разработки, испытаний и сопровождения, обеспечивает простоту и надежность производимого ПО и информационной системы в целом. Целенаправленное снижение сложности ПО представляет собой многошаговую процедуру и требует предварительного исследования существующих показателей сложности, проведения их классификации и соотнесения с типами программ и их местоположением в жизненном цикле. В настоящее время многообразие показателей, в той или иной степени описывающих сложность программ, столь велико, что для их употребления требуется предварительное упорядочение.
    При оценке сложности программ, как правило, выделяют три основные группы метрик:
    метрики размера программ;
    метрики сложности потока управления программ;
    метрики сложности потока данных программ.
    Метрики размера программ
    Оценки первой группы метрик наиболее просты и, очевидно, поэтому получили широкое распространение. Традиционной характеристикой размера программ является количество строк исходного текста. Под строкой понимается любой оператор программы, поскольку именно оператор, а не отдельно взятая строка является тем интеллектуальным
    «квантом» программы, опираясь на который можно строить метрики сложности ее создания. Непосредственное измерение размера программы, несмотря на свою простоту, дает хорошие результаты. Конечно, оценка размера программы недостаточна для принятия решения о ее сложности, но вполне применима для классификации программ, существенно различающихся объемами. При уменьшении различий в объеме программ на первый план выдвигаются оценки других факторов, оказывающих влияние на сложность. Таким образом, оценка размера программы есть оценка по номинальной шкале, на основе которой определяются только категории программ без уточнения оценки для каждой категории.
    Типичным представителем этой группы метрик является метрика Холстеда [
    3
    ].
    Основу метрики Холстеда составляют четыре измеряемые характеристики программы:
    η
    1
    – число уникальных операторов программы, включая символы-разделители, имена процедур и знаки операций (словарь операторов);
    η
    2
    – число уникальных операндов программы (словарь операндов);
    N
    1
    – общее число операторов в программе;
    N
    2
    – общее число операндов в программе.
    Опираясь на эти характеристики, получаемые непосредственно при анализе исходных текстов программ, Холстед вводит следующие оценки:
    словарь программы η = η
    1
    + η
    2
    , длина программы N = N
    1
    + N
    2
    ;
    объем программы V = N log
    2
    η (бит), где под битом подразумевается логическая
    единица информации – символ, оператор, операнд;
    η* - теоретический словарь программы, т.е. словарный запас, необходимый для
    написания программы, с учетом того, что необходимая функция уже реализована
    в данном языке и, следовательно, программа сводится к вызову этой функции.
    Используя длину η*, Холстед вводит оценку
    3
    Холстед, М. Начало науки о программах / М. Холстед. – М.: Финансы и статистика, 1981.

    𝑉̂ = 𝜂

    log
    2
    𝜂

    ,
    (6.1) с помощью которой описывается потенциальный объем программы, соответствующий максимально компактному тексту программы, реализующей данный алгоритм.
    Метрики сложности потока управления программ
    Вторая наиболее представительная группа оценок сложности программ – это метрики сложности потока управления программ. Типичными представителями этой группы является метрика МакКейба. Как правило, с ее помощью оперируют либо плотностью управляющих переходов внутри программ, либо взаимосвязями этих переходов. И в том и в другом случае стало традиционным представление программ в виде управляющего ориентированного графа
    G = {V, E} где V – вершины, соответствующие операторам; Е – дуги, соответствующие переходам.
    Метрика МакКейба.
    Впервые графическое представление программ было предложено Т. Дж. МакКейбом
    [
    4
    ]. В ее основе лежит идея оценки сложности ПО по числу базисных путей в управляющем графе, т.е. таких путей, компонуя которые можно получить всевозможные пути из входа графа в выходы. Основной метрикой сложности МакКейб предлагает считать цикломатическую сложность графа программы, или, как ее еще называют, цикломатическое число МакКейба, характеризующее трудоемкость тестирования программы.
    Для вычисления цикломатического числа МакКейба Z(G) применяется формула
    Z(G) = m – n + 2r,
    (6.2) где m – количество дуг (ребер) ориентированного графа G; n – количество вершин; r – количество компонент связности графа.
    Количество компонент связности графа можно рассматривать как количество дуг, которые необходимо добавить для преобразования графа в сильносвязный. Сильносвязным называется граф, любые две вершины которого взаимно достижимы. Для графов корректных программ, т.е. графов, не имеющих недостижимых от точки входа участков и
    «висячих» точек входа и выхода, сильносвязный граф, как правило, получается путем замыкания дугой вершины, обозначающей конец программы, на вершину, обозначающую точку входа в эту программу. По сути, Z(G) определяет количество линейно независимых контуров в сильносвязном графе. Иначе говоря, цикломатическое число МакКейба показывает требуемое количество проходов для покрытия всех контуров сильносвязного графа или количество тестовых прогонов программы, необходимых для исчерпывающего тестирования по критерию «работает каждая ветвь».
    К достоинствам меры относят простоту ее вычисления и повторяемость результата, а также наглядность и содержательность интерпретации. В качестве недостатков можно отметить: нечувствительность к размеру ПО, нечувствительность к изменению структуры
    ПО, отсутствие корреляции со структурированностью ПО, отсутствие различия между конструкциями «развилка» и «цикл», отсутствие чувствительности к вложенности циклов.
    Недостатки цикломатической меры привело к появлению ее модификаций, а также принципиально иных мер сложности.
    4
    Watson, Arthur Н. Structured Testing: ATesting Methodology Using Cyclomatic Complexity Metric [Электронный ресурс] / Arthur H. Watson, Thomas J. McCabe // NIST Special Publication 500-235.—1996. — URL: http://hissa.nist.gov/HHRFdata/ Artifacts/ITLdoc/235/title.htm.

    Метрика Майерса. Г. Майерс предложил расширение метрики МакКейба. Суть подхода Г. Майерса [
    5
    ] состоит в следующем. В качестве меры сложности предложен интервал [v
    1
    ; v
    2
    ], где v
    1
    – цикломатическая мера, v
    2
    – количество отдельных условий плюс единица. При этом оператор DO принимается в качестве одного условия, а оператор CASE с n исходами принимается за (n – 1) условий. Введенная мера получила название интервальной меры.
    Метрики сложности потока данных программ
    Характерными представителями группы метрик сложности потока данных, т.е. использования, конфигурации и размещения данных в программах, являются метрики спена, Чепина, Кафура. Рассмотрим кратко эти метрики.
    Метрика спена.
    Определение спена основывается на локализации обращений к данным внутри каждой программной секции. Спен – это количество утверждений, содержащих данный идентификатор, между его первым и последним появлением в тексте программы.
    Следовательно, идентификатор, появившийся n раз, имеет спен, равный n – 1. При большом спене усложняется тестирование и отладка [
    6
    ].
    Метрика Чепина.
    Суть метрики состоит в оценке информационной прочности отдельно взятого программного модуля с помощью анализа характера использования переменных из списка ввода-вывода [
    7
    ].
    Все множество переменных, составляющих список ввода-вывода, разбивается на четыре функциональные группы:
    1) V вводимые переменные для расчетов и обеспечения вывода. Примером может
    служить используемая в программах лексического анализатора переменная,
    содержащая строку исходного текста программы, т.е. сама переменная не
    модифицируется, а только содержит исходную информацию;
    2) М модифицируемые (создаваемые внутри программы) переменные;
    3) U переменные, участвующие в управлении работой программного модуля
    (управляющие переменные);
    4) L не используемые в программе (паразитные) переменные. Поскольку каждая
    переменная может выполнять одновременно несколько функций, необходимо
    учитывать ее в каждой соответствующей функциональной группе.
    Далее вводится значение метрики Чепина:
    CH = ω
    1
    V + ω
    2
    M +ω
    3
    U + ω
    4
    L,
    (6.3) где ω
    i
    – весовые коэффициенты, i = 1, 2, 3, 4.
    Весовые коэффициенты использованы для выражения различного влияния на сложность программы каждой функциональной группы. По мнению автора метрики, наибольший вес, равный трем, имеет функциональная группа U, так как она влияет на поток управления программы. Весовые коэффициенты остальных групп распределяются следующим образом: ω
    1
    = 1, ω
    2
    = 2, ω
    3
    = 3, ω
    4
    = 0,5. Весовой коэффициент группы L не равен нулю, поскольку паразитные переменные не увеличивают сложность потока данных программы, но иногда затрудняют ее понимание. С учетом весовых коэффициентов выражение (6.3) принимает вид
    5
    Myers, G. An Extension to the Cyclomatic Measure of Program Complexity / G. Myers // SIGPLAN Notices. —
    1977. — October.
    6
    Милютин, А. Метрики кода программного обеспечения [Электронный ресурс] / А. Милютин. — URL: http://www.viva64.eom/ru/a/0045/
    7
    Новичков, А. Метрики кода и их практическая реализация в IBM Rational [Электронный ресурс] / А.
    Новичков. — URL: http://www.viva64.com/ go.php?url=241.

    CH = V + 2M + 3U +0,5L.
    (6.4)
    Метрика Кафура – метрика, основанная на учете потока данных [
    8
    ]. Вводятся понятия локального и глобального потока.
    Локальный поток информации из A в В существует, если:
    модуль А вызывает модуль В (прямой локальный поток);
    модуль В вызывает модуль А и модуль А возвращает модулю В значение, которое
    используется в В (непрямой локальный поток);
    модуль С вызывает модули А, В и передает результат выполнения модуля А в
    модуль В.
    Глобальный поток информации из модуля А в модуль В через глобальную структуру данных D существует, если модуль А помещает информацию в D, а модуль В использует информацию из D. На основе этих понятий вводится величина I — информационная сложность процедуры:
    I = length (fan_in · fan_out)
    2
    ,
    (6.5) где length – сложность текста процедуры (измеряется через какую-нибудь из метрик объема, типа метрик Холстеда, МакКейба, LOC и т.п.); fan_in – количество локальных потоков внутрь процедуры плюс количество структур данных, из которых процедура берет информацию; fan_out – количество локальных потоков из процедуры плюс количество структур данных, которые обновляются этой процедурой.
    Можно определить информационную сложность модуля как сумму информационных сложностей, входящих в него процедур.
    Следующий шаг – определение информационной сложности модуля относительно некоторой структуры данных. Информационная мера сложности модуля относительно структуры данных представима как
    I = WR + WWrRd + WrRdR + WrRd (WrRd – 1),
    (1) где W – число процедур, которые только обновляют структуру данных; R – число процедур, которые только читают информацию из структуры данных; WrRd – число процедур, которые и читают, и обновляют информацию в структуре данных.
    Следует отметить, что рассмотренные метрики сложности программ основаны на анализе исходных текстов программ и графов, что обеспечивает единый подход к автоматизации их расчетов.
    Некоторые общие замечания по стратегии и тактике обеспечения надежности
    и безопасности различных видов программного обеспечения
    Приведенный выше краткий обзор системного и прикладного ПО для ИС и специфических встроенных систем позволяет высказать некоторые замечания по поводу стратегии и тактики расчета, прогнозирования и оценивания функциональной надежности программных средств.
    Функциональная надежность ПО не может моделироваться с помощью детерминированных моделей. Это принципиально важно, поскольку, несмотря на систематический характер ошибок в тексте программы, их проявление в процессе исполнения программы носит случайный характер вследствие случайного характера набора входных данных, случайного выбора ветви программы, случайного характера заявок на выполнение программы и др.
    Для исследования функциональной надежности как системного, так и прикладного
    ПО, включая программы встроенных систем, наряду с вероятностными моделями
    8
    Kafura, D. The Use of Software Complexity Metrics in Software Maintenance / D. Kafura, G. Reddy // IEEE
    Transactions on Software Engineering. – 1987. – March.
    перспективно применение моделей, построенных с помощью математических методов нечетких множеств и интервальных средних. Последние типы моделей особенно перспективны при неполной и/или недостоверной информации.
    Стратегия испытаний всех видов программных средств состоит в том, чтобы подавляющий объем испытаний проводился автономно от инструментальной среды. Это особенно характерно для процессов верификации отдельных программ и программных модулей. На завершающем (интеграционном) этапе должна проводиться валидация программно-аппаратных комплексов.
    Наиболее реальный метод испытаний функциональной надежности и функциональной безопасности программных средств встроенных систем — метод ускоренных натурных испытаний на основе внесения искажений в промежуточные результаты выполнения информационных процессов и внесения «помех» на входы составных цифровых устройств в реальном масштабе времени при условии доказательства подобия результатов ускоренных испытаний практическим данным.
    Для повышения эффективности оценивания функциональной надежности программных средств следует сочетать результаты их испытаний с расширенным аудитом выполнения в проверяемых программных средствах требований соответствующих стандартов в отношении архитектуры этих программных средств, использованных языков программирования, способов обнаружения ошибок и диагностирования, примененных методов верификации и валидации и др.
    Заключение
    При испытаниях функциональной безопасности программных средств следует установить типовую номенклатуру и метрики функциональной безопасности ПО, модели оценивания ПО, методы тестирования и экспертизы модификаций ПО. Цель испытаний при этом состоит в оценке соответствия ПО требованиям функциональной безопасности согласно установленному для данного объекта испытаний уровню полноты безопасности
    9
    Контрольные вопросы
    Смотри руководство по организации самостоятельной работы магистрантов.
    9
    Смотри Лекцию 10


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