Что не является характеристикой программного модуля

Основные характеристики программного модуля. Не всякий программный модуль способствует упрощения программы

Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля

Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля

· сцепление с другими модулями;

· рутинность модуля (независимость от предыстории обращений к нему).

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

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

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

Высшими по прочности классами модулей являются следующие рекомендуемые классы.

Функционально-прочный модуль — это модуль, выполняющий (реализующий) одну какую-либо определенную функцию. При реализации этой функции такой модуль может использовать и другие модули.

В модульных языках программирования как минимум имеются средства для задания функционально-прочных модулей (например, модуль типа FUNCTION в языке ФОРТРАН). Средства же для задания информационно-прочных модулей в ранних языках программирования отсутствовали. Эти средства появились только в более поздних объектно-ориентированных языках.

Сцепление модуля — это мера его зависимости по данным от других модулей. Оно характеризуется способом передачи данных. Чем слабее сцепление модуля с другими модулями, тем сильнее его независимость от других модулей.

Худшим видом сцепления модулей является сцепление по содержимому. Таким является связь двух модулей, когда один из них имеет прямые ссылки на содержимое другого модуля (например, на константу, содержащуюся в другом модуле). Такое сцепление модулей недопустимо.

Не рекомендуется также сцепление по общей области ( COMMON- области, реализованные в языках типа FORTRAN).

Рутинность модуля — это его независимость от предыстории обращений к нему. Модуль называется зависящим от предыстории обращений, если результат его работы зависит от его внутреннего состояния. Технология программирования не рекомендует использовать нерутинные (непредсказуемые) модули, однако эта рекомендация является неконструктивной, т.к. во многих случаях именно зависящий от предыстории модуль является лучшей реализацией информационно прочного модуля.

Источник

Основные характеристики программного модуля

Как разработать хороший модуль, который действительно будет способствовать упрощению программы?

В литературе приводятся различные критерии оценки приемлемости модуля. Были предложены следующие критерии:

• хороший модуль снаружи проще, чем внутри;

• хороший модуль проще использовать, чем построить.

Предлагается использовать следующие характеристики программного модуля для оценки его приемлемости: размер модуля, прочность модуля, сцепление с другими модулями и рутинность модуля.

Размер модуля измеряется числом содержащихся в нем операторов.

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

Прочность модуля — это мера его внутренних связей.

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

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

Высшей степенью прочности обладает информационно прочный

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

Сцепление модуля — это мера его зависимости по способу передачи данных от других модулей. Чем слабее сцепление модуля с другими модулями, тем сильнее его независимость от других модулей. Для оценки степени сцепления существует шесть видов сцепления модулей по:

• общей области данных;

Худшим видом сцепления модулей является сцепление по содержимому. Таким является сцепление двух модулей, когда один из них имеет прямые ссылки на содержимое другого модуля (например, на константу, содержащуюся в другом модуле). Такое сцепление модулей недопустимо.

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

Сцепление по образцу предполагает, что модули обмениваются данными, объединенными в структуры. Этот тип обеспечивает неплохие характеристики по сравнению с предыдущими. Недостаток заключается в том, что конкретные передаваемые данные «спрятаны» в структуры, и потому уменьшается «прозрачность» связи между модулями. Кроме того, при изменении структуры передаваемых данных необходимо модифицировать все использующие ее модули.

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

Сцепление по внешним ссылкам предполагает, что модули ссылаются на один и тот же глобальный элемент данных [1].

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

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

Рутинность модуля — это его независимость от предыстории обращений к нему. Модуль будем называть рутинным, если результат обращения к нему зависит только от значений его параметров и не зависит от результатов предыдущих обращений к нему. Модуль будем называть зависящим от предыстории, если результат обращения к нему зависит от внутреннего состояния этого модуля, хранящего следы предыдущих обращений к нему. В книге Майерса [45] не рекомендуется использовать зависящие от предыстории модули, так как они провоцируют появление в программах неуловимых ошибок. Однако во многих случаях именно зависящий от предыстории модуль является наиболее информационно прочным. Поэтому более приемлема следующая рекомендация:

• всегда следует использовать рутинный модуль, если это не приводит к плохим сцеплениям модулей;

• зависящие от предыстории модули следует использовать только в случае, когда это необходимо для обеспечения параметрического сцепления;

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

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

Различают следующие виды связности (в порядке убывания уровня) [1]:

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

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

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

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

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

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

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

В табл. 3.1 представлены характеристики различных видов связности по экспертным оценкам [1, 62, 63].

Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля

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

Источник

Основные характеристики программного модуля

Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля

Цель модульного программирования.

— обозримый по размеру и сложности программный элемент.

Таким образом, модули содержат определение доступных для обработки данных, операции обработки данных, схемы взаимосвязи с другими модулями.

Модульное программирование является воплощением в процессе разработки программ обоих общих методов борьбы со сложностью и обеспечение независимости компонент системы, и использование иерархических структур. Для воплощения первого метода формулируются определенные требования, которым должен удовлетворять программный модуль, т.е. выявляются основные характеристики «хорошего» программного модуля. Для воплощения второго метода используют древовидные модульные структуры программ (включая деревья со сросшимися ветвями).

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

— хороший модуль снаружи проще, чем внутри;

— хороший модуль проще использовать, чем построить.

Майерс предлагает использовать более конструктивные характеристики программного модуля для оценки его приемлемости: размер модуля; прочность модуля; сцепление с другими модулями; рутинность модуля (независимость от предыстории обращений к нему).

Размер модуля измеряется числом содержащихся в нем операторов (строк). Модуль не должен быть слишком маленьким или слишком большим. Маленькие модули приводят к громоздкой модульной структуре программы и могут не окупать накладных расходов, связанных с их оформлением. Большие модули неудобны для изучения и изменений, они могут существенно увеличить суммарное время повторных трансляций программы при отладке программы. Обычно рекомендуются программные модули размером от нескольких десятков до нескольких сотен операторов.

Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля

— всегда следует использовать рутинный модуль, если это не приводит к плохим (не рекомендуемым) сцеплениям модулей;

— зависящие от предыстории модули следует использовать только в случае, когда это необходимо для обеспечения параметрического сцепления;

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

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

Источник

Основные характеристики программного модуля.

РАЗРАБОТКА СТРУКТУРЫ ПРОГРАММЫ И

МОДУЛЬНОЕ ПРОГРАММИРОВАНИЕ

Цель разработки структуры программы. Понятие программного модуля. Основные характеристики программного модуля. Методы разработки структуры программы. Спецификация программного модуля. Контроль структуры программы.

Цель модульного программирования.

Модульное программирование является воплощением в процессе разработки программ обоих общих методов борьбы со сложностью (см. лекцию 3, п. 3.5): и обеспечение независимости компонент системы, и использование иерархических структур. Для воплощения первого метода формулируются определенные требования, которым должен удовлетворять программный модуль, т.е. выявляются основные характеристики «хорошего» программного модуля. Для воплощения второго метода используют древовидные модульные структуры программ (включая деревья со сросшимися ветвями).

Основные характеристики программного модуля.

Не всякий программный модуль способствует упрощению программы [7.2]. Выделить хороший с этой точки зрения модуль является серьезной творческой задачей. Для оценки приемлемости выделенного модуля используются некоторые критерии. Так, Хольт [7.4] предложил следующие два общих таких критерия:

· хороший модуль снаружи проще, чем внутри;

· хороший модуль проще использовать, чем построить.

Майерс [7.5] предлагает для оценки приемлемости программного модуля использовать более конструктивные его характеристики:

· сцепление с другими модулями,

· рутинность модуля (независимость от предыстории обращений к нему).

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

по отношению к нему части программы и, следовательно, тем больший вклад в упрощение программы он может внести. Для оценки степени прочности модуля Майерс [7.5] предлагает упорядоченный по степени прочности набор из семи классов модулей. Самой слабой степенью прочности обладает модуль, прочный по совпадению. Это такой модуль, между элементами которого нет осмысленных связей. Такой модуль может быть выделен, например, при обнаружении в разных местах программы повторения одной и той же последовательности операторов, которая и оформляется в отдельный модуль. Необходимость изменения этой последовательности в одном из контекстов может привести к изменению этого модуля, что может сделать его использование в других контекстах ошибочным. Такой класс программных модулей не рекомендуется для использования. Вообще говоря, предложенная Майерсом упорядоченность по степени прочности классов модулей не бесспорна. Однако, это не очень существенно, так как только два высших по прочности класса модулей рекомендуются для использования. Эти классы мы и рассмотрим подробнее.

В модульных языках программирования как минимум имеются средства для задания функционально прочных модулей (например, модуль типа FUNCTION в языке ФОРТРАН). Средства же для задания информационно прочных модулей в ранних языках программирования отсутствовали. Эти средства появились только в более поздних языках. Так в языке программирования Ада средством задания информационно прочного модуля является пакет [7.6].

· всегда следует использовать рутинный модуль, если это не приводит к плохим (не рекомендуемым) сцеплениям модулей;

· зависящие от предыстории модули следует использовать только в случае, когда это необходимо для обеспечения параметрического сцепления;

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

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

Источник

Основные характеристики программного модуля.

Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля

РАЗРАБОТКА СТРУКТУРЫ ПРОГРАММЫ И МОДУЛЬНОЕ ПРОГРАММИРОВАНИЕ

Цель модульного программирования.

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

5. обозримый по размеру и сложности программный элемент.

Таким образом, модули содержат определение доступных для обработки данных, операции обработки данных, схемы взаимосвязи с другими модулями.

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

Модульное программирование является воплощением в процессе разработки программ обоих общих методов борьбы со сложностью и обеспечение независимости компонент системы, и использование иерархических структур. Для воплощения первого метода формулируются определенные требования, которым должен удовлетворять программный модуль, т.е. выявляются основные характеристики «хорошего» программного модуля. Для воплощения второго метода используют древовидные модульные структуры программ (включая деревья со сросшимися ветвями).

Основные характеристики программного модуля.

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

· хороший модуль снаружи проще, чем внутри;

· хороший модуль проще использовать, чем построить.

Майерс предлагает использовать более конструктивные характеристики программного модуля для оценки его приемлемости: размер модуля; прочность модуля; сцепление с другими модулями; рутинность модуля (независимость от предыстории обращений к нему).

Размер модуля измеряется числом содержащихся в нем операторов (строк). Модуль не должен быть слишком маленьким или слишком большим. Маленькие модули приводят к громоздкой модульной структуре программы и могут не окупать накладных расходов, связанных с их оформлением. Большие модули неудобны для изучения и изменений, они могут существенно увеличить суммарное время повторных трансляций программы при отладке программы. Обычно рекомендуются программные модули размером от нескольких десятков до нескольких сотен операторов.

Что не является характеристикой программного модуля. Смотреть фото Что не является характеристикой программного модуля. Смотреть картинку Что не является характеристикой программного модуля. Картинка про Что не является характеристикой программного модуля. Фото Что не является характеристикой программного модуля

· всегда следует использовать рутинный модуль, если это не приводит к плохим (не рекомендуемым) сцеплениям модулей;

· зависящие от предыстории модули следует использовать только в случае, когда это необходимо для обеспечения параметрического сцепления;

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

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

1.3.3. Модульная структура программных продуктов

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

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

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

2. принятие основных решений в алгоритме выносится на максимально «высокий» по иерархии уровень;

3. для использования одной и той же функции в разных местах алгоритма создается один модуль, который вызывается на выполнение по мере необходимости. В результате дальнейшей детализации алгоритма создается функциональномодульная схема (ФМС) алгоритма приложения, которая является основой для программирования.

Состав и вид программных модулей, их назначение и характер использования в программе в значительной степени определяются инструментальными средствами. Например, применительно к средствам СУБД отдельными модулями могут быть:

1. экранные формы ввода и/или редактирования информации базы данных;

2. отчеты генератора отчетов;

4. стандартные процедуры обработки информации;

5. меню, обеспечивающее выбор функции обработки и др.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *