СТАТЬЯ |
11.11.02
|
© Илья
Хейфец , AGAVA
Статья была опубликована в журнале "Программист"
Летом на конференции Professional Developer's Conference 2000 Microsoft представила миру платформу .NET, которая предлагает новый путь разработки программного обеспечения. .NET – это платформа для построения интегрированных, сервис-ориентированных приложений, отвечающих современным потребностям Интернет коммерции. Она позволяет быстро строить Web сервисы и приложения, оперирующие информацией из многих источников, и независящие от платформ и языков программирования. Платформа .NET не привязана к операционной системе Windows и впоследствии может быть реализована для других операционных систем.
.NET платформа упрощает разработку приложений и повышает надежность кода. В частности, она обеспечивает автоматическое управление временем жизни объектов, нейтральные к языкам библиотеки классов и пересекающие границы языков наследование, обработку исключений и отладку.
Архитектура .NET изображена на рисунке
[Рисунок взят с сайта Microsoft.]
Common Language Runtime опирается на системные сервисы операционной системы и управляет выполнением кода, написанного на любом современном языке программирования. Набор базовых классов дает доступ к сервисам платформы, которые разработчики могут использовать из любого языка программирования. Common Language Runtime и базовые классы вместе составляют основу .NET платформы. Эта архитектура очень похожа на архитектуру C runtime, Visual Basic runtime или виртуальной машины Java.
.NET предлагает также высокоуровневые сервисы:
-
|
ADO+ - новое поколение ADO, которое использует XML и SOAP для обмена данными |
-
|
ASP+ - новая версия ASP, позволяющая использовать любой (.NET совместимый) язык для программирования Web страниц |
-
|
Win Forms и Web Forms – набор классов для построениения пользовательского интерфейса локальных и Web-ориентированны приложений. Отдельно упомянем C# (произносится «си шарп») - новый объектно-ориентированный язык, нацеленный на создание приложений для платформы .NET. |
CLR предоставляет исполняемому коду определенный набор сервисов. Например,
CLR поддерживает создание и манипулирование потоками. Поэтому любой язык, который
может использовать CLR, сможет использовать потоки.
Код, который нуждается в CLR во время выполнения, называется “управляемый” (managed)
код. Ответственность за такие задачи как создание объектов и вызов методов возлагается
на CLR. Код, который не нуждается в CLR, называется “неуправляемый” (unmanaged)
код.
Microsoft предоставляет 4 компилятора, которые генерируют код для .NET CLR: C++, C#, Visual Basic (включая VBScript и Visual Basic for Applications) и JScript. Visual C++ - это единственный компилятор, который может генерировать неуправляемый код. Остальные компиляторы могут производить только управляемый код, и поэтому код, написанный на этих языках, всегда нуждается в CLR. Несколько компаний также производят компиляторы управляемого кода. Например, Rational планирует создать такой компилятор для Java. Рассмотрим основные понятия .NET и сервисы CLR
Одна из наиболее частых ошибок заключается в том, что приложение не освобождает ресурсы или пытается их использовать после освобождения. CLR автоматически отслеживает использование ресурсов, гарантируя их своевременное освобождение.
Сегодня имеются много различных версий Windows. Написаное и собранное управляемое .NET приложение сможет выполняться на любой платформе, которая поддерживает .NET CLR.
Модель программирования .NET упрощает конструкции Win32 и COM. Программисты больше не должны заботится о деталях реестра, GUID, IUnknown, AddRef, Release, HRESULTS и тому подобного. .NET не просто инкапсулирует эти понятия; на новой платформе они вовсе отсутствуют.
Отметим также, что в .NET все сообщения об ошибках передаются единым способом: через исключения.
.NET CLR конролирует доступ к объектам и гарантирует, что доступ производится в соответствии с типом этих объектов. Также CLR не позволит создать указатель на произвольный адрес в памяти и выполнить код по этому адресу. Это, в частности, исключает возникновение множества типичных ошибок программирования и классических атак по методу переполнения буфера.
COM позволяет взаимодействовать компонентам на различных языках программирования. .NET интегрирует языки друг с другом. Например, можно создать Си++ класс, который наследует классу, реализованному на Visual Basic. Это означает, что программисты, использующие библиотеку классов, больше не ограничены в выборе языка языком этой библиотеки. Исключение может быть вызвано из кода, написанного на одном языке и обработано в коде, написанном на другом языке. Операции отладки и профилирования (profiling) работают, плавно пересекая границы языков. Такая интеграция становится возможной, поскольку .NET определяет и предоставляет систему типов, общую для всех языков.
Формальная спецификация системы типов, реализованной CLR, называется Common Type System (CTS). Основная задача системы типов – обеспечение интеграции языков.
Чтобы писать управляемый код не нужно знать правила CTS, поскольку выбранный язык предоставит собственный синтаксис и правила типов и отобразит свой синтаксис в синтаксис CLR в процессе компиляции. Например, CTS поддерживает только одиночное наследование, а Cи++ поддерживает классы, которые наследуют от нескольких базовых классов. Чтобы помочь разработчикам, компилятор Visual C++ сообщит об ошибке, если заметит, что вы пытаетесь использовать множественное наследование в управляемом коде.
Еще одно правило CTS гласит, что все базовые классы должны наследовать классу System.Object. Object – это имя типа, определенного в пространстве имен System. (Более подробно базовые классы описываются ниже).
[assembly – новый термин, который раньше употреблялся только в отношении языка ассемблера. По сути это «пакет» или «комплект», но я думаю, что лучше или оставить английское написание, или перевести как асембл (по аналогии со словом stub, которое сейчас правильно переводится как «стаб», а раньше пытались переводить как «заглушка»). Но managed я перевел как «управляемый», поскольку вряд ли приживется слово «менеджед». CLR тоже сложно переводить.]
.NET использует новую модель расположения приложений, которая упрощает инсталляцию и отслеживание версий. Ключевое понятие этой модели – асембл (assembly). Assembly – это набор ресурсов и типов, а также метаданные, описывающие типы и методы, реализованные assembly. Т.о. assembly – это самоописанный компонент. Основное преимущество таких компонентов в том, что для их использования не нужны никакие другие файлы. Заголовочные файлы, IDL файлы, библиотеки типов и прокси-стабы не требуются, чтобы получить доступ к компоненту из любого языка - необходимая информация заключена в метаданных компонента.
Assemblies могут принадлежать одному приложению или разделяться между несколькими приложениями. CLR может загружать различные версии одного assembly для двух различных приложений, которые выполняются одновременно. Поскольку assembly самоописаны, никакая их регистрация в операционной системой не требуется и инсталляция приложения представляет простое копирование файлов. Assemblies также играют роль в .NET системе безопасности, где assembly является единицей, на которую запрашиваются и предоставляются разрешения.
CLR предоставляет сервисы безопасности, контролирующие доступ пользователей к ресурсам и действия программ. Поскольку CLR используется, чтобы загружать код, создавать объекты и вызывать методы, он может управлять безопасностью и предписывать политики безопасности. Обеспечение безопасности в .NET возможно на двух уровнях: на уровне кода (code access security) и на уровне ролей пользователей (role-based security).
Программисты определяют требуемые привилегии, которые должен иметь код для выполнения работы. Например, код нуждается в разрешении, чтобы писать в файл или читать переменные среды. Эта информация хранится в assembly, наряду с информацией относительно подлинности кода. Политики для предоставления разрешений устанавливаются администраторами системы на основании данных относительно происхождения кода и прочих. Разрешения могут выдаваться также исходя из данных пользователя. Роли представляют собой категории пользователей и могут быть определены во время разработки или в процессе инсталляции.
Когда файлы с исходными текстами готовы, вы запускаете компилятор и получаете EXE или DLL. Эти EXE или DLL файлы очень похожи на PE (Portable Executable – портируемые выполняемые) файлы, по сути дела они и есть PE файлы с некоторыми отличиями.
Первое отличие заключается в том, что код в управляемых PE файлах не является командами процессора x86 или другим машинным кодом. Вместо этого компилятор создает код на Промежуточном Языке Microsoft (Microsoft intermediate language - MSIL). PE файл, содержащий MSIL может выполняться на платформе любого процессора, если операционная система, предоставляет .NET CLR.
Второе отличие заключается в том, что этот файл содержит метаданные, которые используются CLR для обнаружения и загрузки типов из файла, разположения объектов в памяти, вызова методов, управления ссылками, перевода MSIL в машинные коды, контроля за безопасностью и множества других задач.
Еще одно отличие – то что полученные компоненты не просто EXE или DLL файлы. Единица использования и размещения в .NET – это assembly. В зависимости от опций компилятора можно получить однофайловый assembly или модуль с управляемым кодом, распространяемый как часть многофайлового assembly. С точки зрения клиента, assembly – это именованная коллеция экспортируемых типов и ресурсов. С точки же зрения разработчика assembly, – это коллекция PE файлов, файлов ресурсов, phtmlL страниц, картинок и т.п.
MSIL – это процессоронезависимый промежуточный язык, созданный Microsoft. MSIL - язык более высокого уровня, чем большинство машинных языков. Он понимает типы объектов и имеет инструкции для создания и инициализации объектов, вызова виртуальных методы и непосредственной манипуляции элементами массива. Он даже имеет инструкции, которые оперируют исключениями. Как и любой другой машинный язык, MSIL может быть написан на ассемблере. Microsoft предоставляет ассемблер и дизассемблер для MSIL.
Когда вы собираете управляемую программу, модуль импортирует функцию _CorExeMain из .NET CLR (MSCorEE.dll). Когда пользователь запускает программу, загрузчик операционной системы переходит к точке входа внутри выполняемого блока. Код в выполняемом блоке просто передает управление функции _CorExeMain, содержащейся внутри MSCorEE.dll. CLR находит точку входа управляемого модуля и затем начинает выполнять управляемый код MSIL выполняемого блока.
Перед тем, как выполнять управляемый код CLR должен сначала скомпилировать управляемые MSIL инструкции в инструкции процессора. Здесь возникает типичная проблема: когда пользователь запускает программу, он не намерен ждать пока вся программа скомпилируется, тем более, что большинство функций программы не будут вызваны. Поэтому CLR, компилирует MSIL код в инструкции процессора, когда функции непосредственно вызваны. Всякий раз, когда такая функция вызывается в будущем, сразу выполняется машинный код (а компилятор уже не вовлекается в процесс). Поскольку MSIL компилируется только в нужный момент (just-in-time - JIT), этот компонент CLR часто упоминается как JIT компилятор (JIT compiler) или JITter.
(картинка с сайта Microsoft)
(Перевод: исходный код-> компилятор -> exe/dll (IL и метаданные) –> загрузчик класса -> JIT компилятор с необязательной проверкой -> машинные коды -> выполнение -> проверки безопасности; runtime engine; Библиотеки класов (IL и метаданные); безопасный прекомпилированный код; вызов некомпилированного метода)
Программисты на низкоуровневых языках типа C или Cи++ возможно думают об эффективности выполнения описанной схемы. Ведь неуправляемый код компилируется сразу в инструкции процессора и при вызове просто выполняется. А в управляемом окружении чтобы выполнить код, MSIL должен компилироваться в инструкции процессора в реальном времени, потребляя большое количество памяти и мощности процессора.
Действительно, управляемый код выполняется медленнее и имеет больше накладных расходов, чем неуправляемый код. Но Microsoft предлагает инструмент, позволяющий выполнять полную компиляцию assembly в машинные коды и сохранять результат на диске. Когда assembly загрузится в следующий раз, будет использована эта сохраненная версия и приложение стартует быстрее.
Отметим особо, что в приложении можно совмещать фрагменты управляемого и неуправляемого кода. Неуправляемый код следует использовать для критичных к времени выполнения функций.
Над CLR в архитектуре .NET находится инфраструктура сервисов (services framework). Эта инфраструктура предоставляет классы, которые могут быть использованы из любого языка программирования. Каждый класс дает доступ к некоторому элементу основной платформы.
Для примера приведем несколько пространств имен (namespaces) и их классы.
Пространство имен
|
Назначение содержащихся классов
|
Пример классов
|
System |
Реализация типов, используемых каждым приложением |
Object, Byte, Array, Int32, Exception, String |
System.Collections |
Управление наборами данных |
ArrayList, Dictionary, Hashtable, Queue |
System.Data |
Работа с базами данных |
DataBinding, DataTable, DataSource |
System.IO |
Чтение и запись |
ByteStream, File, FileStream, MemoryStream |
System.Net |
Сетевые взаимодействия |
WebRequest, UdpClient, Sockets |
System.Web.UI.WebControls |
Построение пользовательского интерфейса для приложений,
ориентированных на Web |
DataGrid, HyperLink, ListBox, RadioButton, Table |
System.WinForms |
Построение пользовательского интерфейса для локальных
приложений |
Button, CheckBox, DataGrid, FileDialog, ListBox,
MainMenu |
Имеются также классы для рисования (GDI+), работы с потоками, национальной поддержки, криптографии, сериализации, и т.д.
Также есть, например, классы, предназначенные для инструментов разработки и позволяющие выполнять такие функции как отладка-трассировка, создание ресурсов, конфигурирование-инсталляция, получение лога событий и оценка эффективности.
Методы класса могут быть перегружены, поэтому методы, отличающиеся лишь немного по поведению, имеют идентичные имена и различается только прототипами. Например, класс может предлагать три различных версии метода CreatePen с разными наборами параметров.
.NET - полностью объектно-ориентированная платформа. Программисты могут создавать собственные пространства имен, содержащие их собственные классы. Это значительно упрощает разработку программного обеспечения по сравнению с классическими Windows парадигмами программирования. Так как все услуги платформы предлагаются через объектно-ориентированную парадигму, разработчики должны иметь некоторое понимание объектно-ориентированного программирования.
С# вобрал в себя все лучшее из таких популярных языков как Си++, Visual Basic, Java и Object Pascal. С# обеспечивает быструю разработку, в то же время позволяет писать эффективный код. Перечислим особенности нового языка:
- автоматическая уборка мусора
- возможность манипулировать указателями и иметь непосредственный доступ к памяти
- поддержка свойств и событий (аналогично VB)
- поддержка атрибутов
- встроенная поддержка основных типов (строка, массив, ...)
- множественное наследование возможно только от интерфейсов (как в Java)
- поддержка С API, Windows API и COM+ на уровне языка
- поддержка assembly
- контроль типов
- автоматическая инициализация переменных
Атрибуты являются новым механизмом. С их помощью можно ввести новые типы описательной
информации для классов и методов и получать эту информацию во время выполнения.
Единственное чего не хватает в новом языке – это шаблонов, так полюбившихся
программистам на Си++ за последние несколько лет.
Приведем код традиционной прграммы «Hello, world»
using System;
class Hello
{
static void Main()
{
Console.WriteLine("Hello, world");
}
}
Как можно заметить синтаксис определения классов похож на Java.
Microsoft сделала стандарт С# открытым для широкого использования. Компилятор
С# для платформы .NET будет доступен в следующей версии Visual Studio.
Похоже, что С# станет идеальным языком создания приложений для новой платформы.
Дополнительная информация
За дополнительной информацией обращайтесь в компанию Interface Ltd.
INTERFACE Ltd. |
|