Возможности Visual Studio 2013 и их использование для облачных вычислений

Обзор возможностей .NET

Показывать лекцию целиком

Цель лекции

Ознакомление с принципами архитектуры и использованием платформы .NET, новыми возможностями .NET 4.5.1.

3.1. Введение

Данная лекция знакомит с платформой .NET и возможностями новой версии .NET 4.5.1.

Рассмотрены Web-сервисы .NET, на которых базируется архитектура и реализация платформы облачных вычислений Microsoft Azure.

3.2. Обзор архитектуры .NET

.NET [7, 12] - платформа надежного и безопасного многоязыкового программирования.

Она основана на единой для всех языков инфраструктуре (CLI), общей системе типов (CTS), общей системе поддержки выполнения (CLR).

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

Исполнение программы в CLR реализовано как последовательность вызовов методов и just-in-time (динамическая) компиляция каждого метода в native-код при первом вызове, с последующими вызовами native-кода откомпилированного метода.

Метаданные могут быть аннотированы атрибутами, как встроенными, так и пользовательскими.

На использовании метаданных основан динамический контроль типов и безопасности, выполняемый CLR.

Подчеркнем, что, в отличие от Java-технологии (стандарты которой принаждежат корпорации Oracle), платформа .NET первоначально появилась в виде набора международных стандартов ECMA и ISO [13]. То есть, сам термин .NET обозначает именно набор этих стандартов на язык C#, CLI, CIL, CTS и структуру библиотек. Согласно этим стандартам, была реализована платформа Microsoft.NET - реализация стандартов .NET корпорацией Microsoft для ОС семейства Windows.

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

Имеются и другие реализации стандартов .NET:

  • Shared Source Common Language Infrastructure (SSCLI, или Rotor) - академическая версия .NET с открытым исходным кодов, реализованная для операционных систем Windows, UNIX FreeBSD и MacOS;
  • Mono - открытая реализация .NET международным распределенным сообществом программистов, ориентированная, прежде всего, на ОС Linux, но также работающая и для Windows;
  • DotGNU.
  • 3.3. Основные идеи и принципы .NET

    Основные идеи и принципы .NET следующие. Это компиляция с любого языка в промежуточный двоичный код MSIL (CIL) - постфиксную форму представления программ; генерация компилятором так называемых метаданных - информации о типах, определяемых и используемых в программном модуле для .NET. Промежуточный код, метаданные, плюс так называемый манифест (список содержимого бинарного кода) составляют сборку (assembly) - логическую единицу представления бинарного кода в .NET. Во время выполнения программы, при первом вызове каждого метода, его промежуточный код компилируется специальным компилятором (just-in-time, или JIT, компилятором) в платформно-зависимый (native) код аппаратной платформы (машины), на которой исполняется программа. Де-факто стандартом для представления конфигурационной информации и передачи данных через сеть в .NET является XML.

    3.4. Преимущества подхода .NET

    Преимуществом подхода .NET является независимость бинарного кода (CIL) от конкретной аппаратной платформы. Также .NET выполняет код в особом режиме - управляемого выполнения (managed execution), при котором гарантируется полный контроль типов и безопасности, что обеспечивает надежность и безопасности программ, в отличие от использования более старых языков и платформ, например, Си. При этом, например, невозможно преобразование типа какого-либо объекта к другому типу или присваивание переменной объектного типа ссылки на объект какого-либо другого типа, за исключением вариантов, разрешенных методологией ООП.

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

    Повышенные требования к безопасности - еще одна характерная черта .NET. Используются следующие виды безопасности:

  • безопасность доступа к коду (code access security): при проверке наличия полномочий безопасности для выполнения определенных действий (например, для открытия файла) у какого-либо метода какой-либо сборки наличие этих полномочий проверяется не только у самого этого метода, но и у всей цепочки вызовов методов, вызванных в данный момент на стеке текущего потока; подобная стратегия носит название security stack walk (прогулка по стеку) и обеспечивает отсутствие атак, связанных с превышением привилегий (elevation of privilege), когда злонамеренный код пытается воспользоваться для превышения полномочий вызовом "чужого" метода;
  • безопасность, основанная на свидетельствах (evidence-based security) - проверки безопасности ("благонадежности") сборки: наличия у нее соответствующей цифровой подписи, надежного авторства сборки (например, принадлежность сборки компании Microsoft, и т.д.;
  • безопасность, основанная на ролях (role-based security) - возможность определения для какого-либо пользователя некоторой роли, обозначаемой строкой (например, "second-line manager") и связывания с этой ролью определенного набора полномочий.
  • Наконец, .NET имеет удобные современные механизмы поддержки Web-программирования - Web-сервисы, рассмотренные позже в данной лекции.

    3.5. Архитектура .NET Framework

    На рис 3.1 приведена архитектура базовой библиотеки классов (BCL) .NET. Их использование ясно из их названий. Особенно важно, что все эти классы могут быть использованы при программировании на любом языке .NET - C#, Visual Basic, Managed C++ и др.

    Например, пространство имен System.Web реализует поддержку Web-сервисов, а пространство имен System.Security - поддержку установки, проверки и конфигурирования полномочий безопасности сборок.

    (рис 3.1) Классы .NET Framework

    3.6. Общая система типов .NET

    Общая система типов .NET (CTS) - унификация систем типов данных современных языков программирования. Подчеркнем, что такая унификация необходима в .NET для поддержки многоязыкового программирования (CLR должна "понимать" типы каждого языка одинаково).

    Различаются следующие разновидности типов в CTS.

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

    Простые типы (int, double, unsigned int, native int и др.), разумеется, относятся к типам-значениям.

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

    Указатели (managed pointers) - разновидность указателей, на которой базируются проверки типов и безопасности. Управляемый указатель в .NET содержит ссылку на тип объекта (на метаданные), благодаря чему тип и атрибуты любого объекта можно проверить во время выполнения. Как альтернатива, в .NET также возможно использование более традиционных неуправляемых указателей (unmanaged pointers) - фактически, обычных адресов без явного хранения типа содержащейся в памяти по этим адресам информации. Однако на платформе .NET работа с неуправляемыми указателями возможна только в небезопасном режиме (unsafe). При этом "за последствия отвечает программист" (как было раньше в языках C и C++), и никакого контроля типов или сборки мусора для таких неуправляемых объектов не производится.

    В общем случае, на платформе .NET разрешен запуск неуправляемого кода (unmanaged code) - например, традиционного exe-файла для Windows - из управляемого кода сборки .NET, так как иногда удобно использовать уже существующий унаследованный код (legacy code), разработанный традиционными методами на традиционных языках. Однако при этом необходимо учитывать, что платформа .NET не обепечиват дополнительный контроль типов, безопасности и сборку мусора при запуске неуправляемого кода.

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

    Интерфейсы - также стандартная концепция для современных языков ООП - Java, C#, VB и др. Интерфейс - совокупность заголовков методов. Интерфейс может быть реализован одним или несколькими классами. Например, интерфейс Stack может содержать заголовки методов Push и Pop. Допускается любое число реализаций интерфейса различными классами.

    Делегаты и события - типы данных для обработки событий. Тип делегата описывает типовую структуру заголовка обработчика события, представленного в виде callback-метода. При описании события указывается конкретный тип делегата.

    3.7. Язык C#: Определение классов

    Язык C# разработан специально для платформы .NET, хотя отнюдь не является обязательным и единственным для этой платформы. Классы в C# определяются традиционным для ООП образом - как набор полей и методов. В дополнение к другим языкам, определение класса может также содержать свойства (обобщенные поля с операциями get и set); индексаторы; события; делегаты.

    Пример класса:

    public class Person :IPersonAge
    {
       private int YOB;
       public Person() 
       {
       }
       public int YearOfBirth
       {
          get { return YOB; }; 
          set { YOB = value; };
       } 
       public int GetAgeToday()
       { 
          return Today()- YearOfBirth; 
       }; 
    }
        

    В классе определены свойство YearOfBirth и метод GetAgeToday.

    3.8. Web-сервисы в .NET

    Концепция Web-сервиса в .NET поддерживает сервисы в виде классов, интерфейс которых доступен через Web, соблюдающие ряд стандартов (WSDL, SOAP, XML). Реализация Web-сервисов основана на библиотеке классов .NET Framework, она представлена в виде набора классов пространства имени System.Web.

    На рис 3.2 приведена структура распределенного Web-приложения.

    (рис 3.2) Структура распределенного Web-приложения

    Приложение состоит из клиентской и серверной частей. Web-сервис должен удовлетворять определенному контракту (реализовывать определенный интерфейс).

    Инфраструктура Web-сервисов представлена на рис 3.3.

    (рис 3.3) Инфраструктура Web-сервиса в .NET

    Web-сервис может обрабатывать несколько видов запросов Web-клиентов.

    При обнаружении (открытии) сервиса клиент передает запрос вида vsdisco, в ответ на который сервисы открытия (UDDI - Universal Discovery, Description and Integration) сообщают о месте расположения Web-сервиса. Сервис UDDI представлен в виде сайта.

    В ответ на другой запрос - wsdl - сервис сообщает клиенту структуру своего интерфейса в формате XML с соблюдением стандарта WSDL (Web Service Description Language). В ответ на запрос asmx Web-сервис посылает свой файл реализации в формате XML.

    На рис 3.4 приведен простой пример кода Web-сервиса, выполняющего вычитание двух чисел и выдающего результат, на рис 3.3 представлена структура WSDL-спецификации Web-сервисов, состоящей из сервисов, портов и сообщений.

    (рис 3.4) Простой пример кода Web-сервиса .NET

    Пример WSDL-описания Web-сервиса:

    <definitions name="http://namespacePath"
             location="serviceName">
     <import namespace="http://namespacePath"
             location="http://path/fileName.wsdl">
     <portType name="serviceNamePortType">
       <operation name="opName""
          <input message="msgNameInput" />
          <output message="msgNameOutput" />
       </operation>
     </portType>
     <binding name="serviceNameSoapBinding">
        <soap:operation soapAction="http://..." />
     </binding>
     <service name="serviceName">
       <port name="serviceNamePort" binding="bindingName">
          <soap:address location="http://..." />
       </port>
     </service>
    </definitions>
        

    Использование Web-сервисов основано на следующих принципах. Полностью разделена логика размещения и вызова: сервис представлен в виде пары файлов - aspx и .aspx.cs (или .aspx.vb). Файлы .aspx предназначены для дизайнеров, файлы .aspx.cs - для программистов. Таким образом достигается легкость сопровождения приложения. Файл кода на C# или VB.NET, реализующий обработчики событий, связанных с обработкой Web-страницы, называется code-behind.

    Фрагмент кода Web-сервиса:

    <%@ Import Namespace="MathServiceSpace" %>
                <script language="C#" runat="server">
               public void Submit_Click(Object S, EventArgs E) {
              service.Add(operand1, operand2);
                ...
               </script>
                     ...
           <input OnServerClick="Submit_Click" runat="server" ...>
        

    3.9. Новые возможности .NET Framework 4.5.1

    Как и Microsoft Azure, платформа .NET - основа ее реализации - постоянно эволюционирует: улучшается производительность, реализуются новые возможности параллельных вычислений, сетевой коммуникации и т.п. Отметим, что многие нововведения в .NET 4.5.1, несомненно, вызваны в значительной степени потребностями развития и совершенствования Microsoft Azure и оказывают положительное влияние на производительность облака. Эти новые возможности мы и рассмотрим.

    Основные новые возможности .NET 4.5.1

    Следующие нововведения .NET 4.5.1 весьма важны для реализации Microsoft Azure:

  • Поддержка разработки приложений .NET для магазина Windows.
  • Поддержка разработки переносимых библиотек классов (в том числе - для Windows Phone и для магазина Windows).
  • Поддержка больших массивов (более 2 Гб).
  • Фоновая сборка мусора для серверов.
  • Фоновая JIT-компиляция для многоядерных процессоров.
  • Улучшенная производительность при извлечении ресурсов приложений.
  • Новые возможности для параллельных вычислений.
  • Автоматическая переадресация привязки для сборок. В Visual Studio 2013, при компиляции приложения, ориентированного на .NET Framework 4.5.1, в файл конфигурации приложения можно добавить переадресации привязок, если приложение или его компоненты ссылаются на несколько версий одной и той же сборки. Можно также включить эту функцию для проектов, предназначенных для более старых версий платформы .NET Framework.
  • Возможность сбора диагностической информации, чтобы помочь разработчикам повысить производительность серверных и облачных приложений.
  • Возможность явно уплотнять кучу больших объектов во время сборки мусора.
  • Дополнительные улучшения производительности, например, приостановка приложений ASP.NET, усовершенствования многоядерного JIT и более быстрый запуск приложений после обновления платформы .NET Framework.
  • Новые возможности отладки в .NET Framework 4.5.1

  • Возвращаемые значения в отладчике Visual Studio. При отладке управляемого приложения в Visual Studio 2013 в окне "Видимые" отображаются возвращаемые типы и значения для методов. Эти сведения доступны для приложений для настольных систем, приложений для Магазина Windows и приложений Windows Phone.
  • Функция "Изменить и продолжить"(fix-and-continue) для 64-разрядных приложений. Visual Studio 2013 поддерживает команду "Изменить и продолжить" для 64-разрядных управляемых приложений для настольных систем, приложений Магазина Windows и приложений Windows Phone.
  • Отладка с поддержкой асинхронности (Async-aware debugging). Чтобы упростить отладку асинхронных приложений в Visual Studio 2013, в стеке вызовов скрывается код инфраструктуры, предоставляемый компиляторами для поддержки асинхронного программирования, а также цепочки логических родительских записей активации, что упрощает прослеживание логики выполнения программы. В окне "Задачи", которое заменяет собой окно "Параллельные задачи", отображаются задачи, относящиеся к определенной точке остановки, а также все другие задачи, которые в данный момент активны или запланированы в приложении.
  • Усовершенствованная поддержка исключений для компонентов среды выполнения Windows. В Windows 8.1 исключения, возникающие в приложениях для Магазина Windows, сохраняют сведения об ошибке, которая вызвала исключение, даже при переходе через границу языка.
  • Новые возможности ASP.NET 4.5.1

    ASP.NET - набор библиотек для поддержки разработки Web-приложений и Web-сайтов. Следующие новые возможности ASP.NET, реализованные в версии 4.5.1, особенно важны для реализации Microsoft Azure:

  • Поддержка новых типов форм HTML5 (напомним, что HTML 5 специально разработан для поддержки облачных вычислений).
  • Поддержка связывателей моделей в веб-формах. Они позволяют привязать элементы управления данными непосредственно к методам доступа к данным и автоматически преобразуют ввод данных пользователем в типы данных платформы .NET Framework и из них.
  • Поддержка "ненавязчивого" JavaScript в клиентских скриптах проверки.
  • Улучшенная обработка клиентского скрипта посредством связывания и минимизации, обеспечивающих повышенную производительность при работе со страницами.
  • Интегрированные подпрограммы кодировки из библиотеки AntiXSS (ранее - внешняя библиотека) для защиты от атак межсайтовых скриптов.
  • Поддержка протокола WebSockets.
  • Поддержка чтения и записи HTTP-запросов и ответов в асинхронном режиме.
  • Поддержка асинхронных модулей и обработчиков.
  • Поддержка резервирования сети распределения содержимого (Content Delivery Network - CDN) в элементе управления ScriptManager.
  • Новые сетевые возможности .NET 4.5.1

    Следующие новые сетевые возможности .NET наиболее важны для реализации Microsoft Azure:

  • .NET Framework 4.5.1 обеспечивает новый интерфейс программирования для приложений HTTP.Дополнительные сведения приведены в описании пространства имен System.Net.Http и System.Net.Http.Headers.
  • Также предусмотрена поддержка нового интерфейса программирования для приема и взаимодействия с соединением WebSocket с помощью существующего класса HttpListener и связанных с ним классов.Дополнительные сведения приведены в новом пространстве имен System.Net.WebSockets и классе HttpListener.
  • Кроме того, в .NET Framework 4.5.1 сетевые функции усовершенствованы следующим образом:

  • RFC-совместимая поддержка URI.
  • Поддержка синтаксического анализа интернационализированных доменных имен (Internationalized Domain Name, IDN).
  • Поддержка интернационализации адресов электронной почты (Email Address Internationalization, EAI). Дополнительные сведения см. в описании пространства имен System.Net.Mail.
  • Улучшенная поддержка протокола IPv6 (новой версии Интернет-протокола), Дополнительные сведения см. в описании пространства имен System.Net.NetworkInformation.
  • Поддержка сокета с двойным режимом. Дополнительные сведения см. в описаниях классов Socket и TcpListener.
  • Новые возможности Windows Communication Foundation (WCF) в версии 4.5.1

    В .NET Framework 4.5.1 были добавлены следующие функции, чтобы упростить создание и сопровождение приложений Windows Communication Foundation (WCF).

    Следующие новые возможности WCF наиболее важны для облачных вычислений в Microsoft Azure:

  • Упрощение созданных файлов конфигурации.
  • Поддержка разработки "по контракту", т.е. контракт сервиса становится отправной точкой разработки.
  • Возможность более простой настройки режима совместимости ASP.NET.
  • Изменения значений свойств транспорта по умолчанию для снижения вероятности необходимости их настройки.
  • Проверка файлов конфигурации WCF за счет Visual Studio как часть процесса построения, поэтому можно обнаружить ошибки конфигурации перед запуском приложения.
  • Новая поддержка асинхронной потоковой передачи.
  • Новое сопоставление протокола HTTPS, облегчающее предоставление конечной точки по HTTPS с помощью служб IIS.
  • Возможность создавать метаданные в одном документе WSDL путем добавления ?singleWSDL к URL-адресу службы.
  • Поддержка Websockets, чтобы включить истинно двунаправленную связь по портам 80 и 443 с характеристиками производительности, схожими с транспортом TCP.
  • Поддержка настройки служб в коде.
  • Всплывающие подсказки редактора XML.
  • Поддержка кэширования ChannelFactory.
  • Поддержка сжатия двоичным кодировщиком.
  • Поддержка транспорта UDP, которая позволяет разработчикам писать службы, использующие обмен сообщениями по принципу "отправить и забыть". Клиент отправляет сообщение службе и не ожидает ответа от службы.
  • Возможность поддерживать несколько режимов аутентификации на одной конечной точке службы WCF при использовании транспорта HTTP и безопасности транспорта.
  • Поддержка служб WCF, использующих интернационализированные доменные имена (IDN).
  • 3.10. Резюме

    Microsoft.NET - активно развивающаяся объектно-ориентированная многоязыковая платформа для разработки программ. Она основана на следующих принципах: использование общей инфраструктуры языков (CLI), общей среды поддержки выполнения (CLR), общей системы типов (CTS), единого промежуточного языка (CIL). Единицей компиляции в .NET является бинарная сборка, содержащая бинарный CIL-код и метаданные - информацию о типах, определяемых и используемых сборкой. Компилятор с любого языка, реализованного в .NET (C#, Managed C++, Visual Basic.NET и др.) транслирует исходный код на данном языке в бинарную сборку. Метаданные содержит атрибуты (аналог аннотаций кода), которые могут быть как встроенными в .NET, так и определяемыми пользователем, что позволяет представлять, хранить в сборке и использовать специфичную для различных утилит информацию. Начиная с выпуска первой версии Microsoft.NET в 2000 г., платформа .NET активно развивается. В наиболее новой версии .NET Framework 4.5.1 реализовано большое число усовершенствований, касающихся сети, облачных вычислений и др.

    Ключевые термины

    .NET - объектно-ориентированная многоязыковая платформа программирования, стандартизированная международными стандартами ISO и имеющая несколько реализаций, в том числе - Microsoft.NET, разработанную фирмой Microsoft
    CLI (Common Language Infrastructure) - общая инфраструктура языков платформы .NET
    CIL (Common Intermediate Language) - единый промежуточный язык платформы .NET, бинарная форма постфиксной записи инструкций виртуальной машины .NET
    CTS (Common Type System) - общая система типов платформы .NET
    C# - новейший объектно-ориентированный язык программирования, разработанный и активно развиваемый фирмой Microsoft, являющийся основным языком программирования для платформы .NET
    Visual Basic - язык программирования, объектно-ориентированное расширение языка Basic, разработанный и развиваемый фирмой Microsoft
    Visual C++ - язык программирования, расширение языка C++, разработанное и развиваемое фирмой Microsoft
    Visual FoxPro - один из ранних объектно-ориентированных языков программирования, разработанный фирмой Microsoft, содержащий средства обращения к базам данных, совместимым с языком запросов SQL
    Visual Studio - интегрированная среда разработки фирмы Microsoft
    WSDL (Web Service Description Language) - синхронный протокол для реализации Web-сервисов и взаимодействия с ними, используемый, в частности, для платформы .NET

    Краткие итоги

    Microsoft.NET - активно развивающаяся объектно-ориентированная многоязыковая платформа для разработки программ. Она основана на следующих принципах: использование общей инфраструктуры языков (CLI), общей среды поддержки выполнения (CLR), общей системы типов (CTS), единого промежуточного языка (CIL). Единицей компиляции в .NET является бинарная сборка, содержащая бинарный CIL-код и метаданные - информацию о типах, определяемых и используемых сборкой. Компилятор с любого языка, реализованного в .NET (C#, Managed C++, Visual Basic.NET и др.) транслирует исходный код на данном языке в бинарную сборку. Метаданные содержит атрибуты (аналог аннотаций кода), которые могут быть как встроенными в .NET, так и определяемыми пользователем, что позволяет представлять, хранить в сборке и использовать специфичную для различных утилит информацию. Начиная с выпуска первой версии Microsoft.NET в 2000 г., платформа .NET активно развивается. В наиболее новой версии .NET Framework 4.5.1 реализовано большое число усовершенствований, касающихся сети, облачных вычислений и др.

    Набор для практики

    Вопросы

  • Что такое .NET?
  • В чем разница между .NET и Microsoft.NET?
  • Каковы основные принципы .NET?
  • Что такое общая система типов .NET?
  • Что такое общая система поддержки выполнения .NET?
  • Что такое единый промежуточный язык .NET?
  • Какие основные разновидности типов входят в общую систему типов .NET?
  • Каковы особенности определения классов в C#?
  • На каких стандартах базируются Web-сервисы .NET?
  • Назовите основные виды запросов к Web-сервису .NET.
  • Каковы основные новые возможности новой версии .NET (4.5.1), наиболее важные для реализации Azure?
  • Упражнения

  • Скачайте и инсталлируйте .NET Framework 4.5.1 - новую версию платформы .NET - и пропустите на ней простой пример типа "Hello World" на языке C#, используя компилятор и другие инструменты .NET Framework.
  • Сравните, по Вашему опыту, возможности платформ .NET и Java
  • Темы для курсовых работ, рефератов, эссе

  • Обзор архитектуры .NET (реферат).
  • Обзор системы типов .NET (реферат).
  • Обзор языка C# (реферат).
  • Обзор языка Visual Basic.NET (реферат).
  • Обзор языка Managed C++ (реферат).
  • Web-сервисы в .NET (реферат).
  • ASP.NET - инструмент построения и использования Web-сервисов (реферат).
  • Дополнительные материалы, презентации

    Презентация к данной лекции: VS_2013_Course_3.pptx.

    Вернуться к учебному плану