Текст книги "Программирование мобильных устройств на платформе .NET Compact Framework"
Автор книги: Иво Салмре
Жанр:
Программирование
сообщить о нарушении
Текущая страница: 7 (всего у книги 69 страниц)
• Все базовые элементы языков программирования и широко используемые библиотеки программ. Мы не могли исключить ни такие предоставляемые любым современным объектно-ориентированным языком программирования возможности, как механизм наследования или обработка структурных исключений, ни такие низкоуровневые библиотечные функции, как функции ввода-вывода файлов, основанные на потоках. Разработчик рассчитывает на то, что эти средства программирования будут всегда находиться у него под рукой, и в случае их отсутствия у него возникает чувство, будто его лишили самого необходимого, тогда как он должен всегда работать в комфортных условиях и быть во всеоружии.
7. Возможность доступа к средствам базовой операционной системы, если в этом возникает необходимость. Осознав всю важность фактора межплатформенной переносимости, мы поняли, что разработчики не должны быть ограничены доступом только к тем средствам, которые были нами первоначально запланированы. Наша основная задача заключалась в том, чтобы предоставить разработчикам удобное подмножество средств платформы .NET Framework, предназначенной для настольных компьютеров, которое было бы пригодным для создания тех видов приложений, о которых говорили сами разработчики, однако можно было предполагать, что неизбежно возникнут случаи, когда предусмотренной нами функциональности разработчикам окажется мало. Какой смысл в том, чтобы предоставлять разработчику возможность создать 90 процентов мобильного приложения с использованием управляемого кода, если он зайдет в тупик из-за недостатка необходимых средств при создании остальных 10 процентов приложения. Поэтому предоставление разработчикам удобного способа, обеспечивающего возможность вызова собственных кодов, было сочтено важным фактором, позволяющим разработчикам обойти трудности, связанные с отсутствием в .NET Compact Framework той или иной функциональности. Вот четыре примера: в настоящее время вызовы собственных кодов (или поставляемых независимыми разработчиками библиотечных функций, служащих оболочками для вызовов собственных кодов) нужны для явного управления сетевыми соединениями, набора телефонных номеров, воспроизведения звука и доступа к API-интерфейсам шифрования; эти функциональные возможности требуются далеко не каждому разработчику, но те, кому они действительно необходимы, будут чувствовать себя стесненными в своих действиях, если не смогут получить доступ к указанным средствам из-за невозможности использования вызовов собственных кодов
Чем объясняется присвоение первому выпуску NET Compact Framework номера версии 1.1, а не 1.0?
Дотошный читатель мог заметить, что при ссылках на первый выпуск .NET Compact Framework в качестве номера версии используется не номер 1.0, а номер 1.1. На то имеются свои основания.
Первый выпуск .NET Compact Framework проектировался так, чтобы обеспечивалась его совместимость с версией 1.1 .NET Framework для настольных компьютеров и серверов, и предполагался к поставке одновременно с ней. Версия 1.0 .NET Framework поставлялась в 2002 году вместе с Visual Studio.NET 2002. Версия 1.1 .NET Framework и NET Compact Framework поставлялись вместе с Visual Studio .NET 2003. В согласии со смыслом номеров версий, номер 1.1 соответствует младшему выпуску продукта, функциональность которого обновлена по сравнению с версией 1.0.
По причинам, обусловленным совместимостью версий на уровне двоичных кодов и рыночными соображениями, было решено синхронизировать номера версий .NET Framework и .NET Compact Framework. Таким образом, версию 1.1 .NET Compact Framework можно рассматривать как совместимое на уровне двоичных кодов подмножество функциональности, предоставляемой версией 1.1 выпуска .NET Framework, предназначенной для настольных компьютеров и серверов.
Заранее приносим свои извинения за возможные недоразумения по этому поводу.
.NET Compact Framework как подмножество платформы для настольных компьютеров
Приступая к проектированию .NET Compact Framework, мы знали, что в конечном счете должны получить некое совместимое подмножество среды .NET Framework, предназначенной для настольных компьютеров, которое удовлетворяло бы требованиям разработчиков. Вопрос о том, каким именно образом следовало определить это подмножество, стал предметом серьезного обсуждения. Следует ли отталкиваться от платформы .NET Framework, постепенно исключая из нее все то, что не нужно, или же лучше начать проектирование новой платформы с нуля, включая в нее только те средства, которые являются действительно необходимыми? Будучи не в состоянии решить эту философскую дилемму, мы остановились на том, чтобы использовать оба подхода и посмотреть, какой из них окажется более приемлемым. Такой способ действий требовал большего времени и ресурсов, однако, по моему мнению, только с его помощью и можно было окончательно разрешить указанные разногласия. Действуя в направлении сверху вниз, мы могли определить максимальный состав тех ключевых возможностей, поддержку которых мы хотели бы обеспечить, тогда как подход, соответствующий продвижению снизу вверх, позволял нам составить хорошее представление о том, какой может быть минимальная реализация и как влияет на размерные показатели и производительность добавление тех или иных возможностей. (Ради справедливости замечу, что лично я принадлежал к числу тех проигравших участников дебатов, которые рекомендовали использовать для создания библиотек программ разработку в направлении сверху вниз. Эта модель оказалась полезной в отношении понимания того, что же именно мы хотим создать, но не могла обеспечить необходимую производительность. Единственным путь, гарантирующий достижение этой цели, был связан с осуществлением разработки по принципу "снизу вверх".)
В конце концов, ситуация с определением наиболее оптимального варианта решения значительно прояснилась. Единственным способом достижения максимальной производительности при сохранении приемлемого размера платформы была ее разработка с нуля и постепенная достройка в направлении снизу вверх путем постепенного добавления только тех типов, классов, методов и свойств, введение которых было необходимым или оправданным. Но даже при таком подходе объем платформы намного превышал тот, который первоначально предсказывался большинством участников группы, хотя полученное решение и отличалось ясностью и оптимальностью. Мне кажется, что отсюда можно сделать один общий вывод: при проектировании подмножеств каркасов, компонентов или приложений для мобильных устройств на основе версий, предназначенных для настольных компьютеров или серверов, для получения прототипов на ранних стадиях разработки целесообразно отталкиваться от имеющихся версий, постепенно исключая из них те или иные элементы для получения лучшего представления о том, какой именно результат вы хотите получить; однако если речь идет о фактической реализации, то наиболее ясное и хорошо проработанное решение обеспечивается разработкой в направлении снизу вверх. В процессе анализа мыслите, переходя от более общих категорий к менее общим, тогда как в процессе реализации начинайте с разработки мелких деталей, постоянно оценивая эффективность каждого своего шага.
Управляемый код и собственный код
Размер кода большинства приложений значительно меньше размера выполняющегося под ним кода среды времени выполнения и операционной системы. Особенно это касается приложений с графическим пользовательским интерфейсом, при создании которых разработчик имеет дело с высокоуровневыми абстракциями, в то время как значительную часть остального выполняющегося кода составляет низкоуровневый библиотечный код, обеспечивающий функционирование пользовательского интерфейса. Отсюда становится очевидным, насколько важную роль играет хорошо спроектированная и высокопроизводительная среда времени выполнения.
При проектировании сред выполнения управляемого кода возможны два подхода:
1. Реализация как можно большей части среды времени выполнения и библиотек программ с использованием собственных кодов и последующее создание тонкого интерфейсного слоя управляемого кода, обеспечивающего доступ разработчиков приложений и компонентов к этой части. Привлекательной стороной такого подхода является то, что он позволяет добиться максимально высокой производительности, а отрицательной стороной – сложность и потенциально более низкая надежность среды выполнения, которая в этом случае не использует всех преимуществ, предоставляемых выполнением полностью управляемого кода.
2. Реализация с использованием собственных кодов лишь в самых необходимых случаях, тогда как вся остальная функциональность обеспечивается применением управляемого кода. Такой подход может улучшить характеристики переносимости и надежности и позволяет выжать из исполнительного механизма управляемого кода максимально возможную производительность, поскольку этот механизм будет использоваться подавляющей частью кода.
Везде, где только это было возможно, функциональность .NET Compact Framework реализовывалась за счет управляемого кода; с использованием собственных кодов написано лишь 20-30 процентов общего объема кода .NET Compact Framework. Для написания всех библиотек программ применялся управляемый код. Лишь сам исполнительный механизм и небольшая часть графической подсистемы написаны с использованием собственных кодов.
Использование управляемого кода во всех библиотеках программ позволяет осуществлять их загрузку и компиляцию, а также управление памятью теми же методами, что и в случае любых других библиотек. Схема логического разделения .NET Compact Framework на отдельные составляющие, написанные с использованием управляемого и собственного кодов, представлена на рис. 3.1.

Рис. 3.1. Компоненты .NET Compact Framework, написанные с использованием собственного и управляемого кодов
Исполнительный механизм
Исполнительный механизм NET Compact Framework представляет собой низкоуровневый код, отвечающий за загрузку, JIT-компиляцию и выполнение управляемого кода, а также управление памятью. Ему приходится брать на себя всю черновую работу, обеспечивающую выполнение управляемого кода.
Исполнительный механизм написан на языках C/C++ и компилируется в собственные команды процессора. На этот механизм дополнительно возлагается задача трансляции .NET Compact Framework и приложений конечного пользователя в исполняемый формат во время выполнения. Этот процесс известен под названием JIT– компиляции (just-in-time – оперативная). С помощью этого же механизма обрабатываются любые переходы из управляемого кода в собственный код, например, вызовы функций основанного на собственном коде API-интерфейсов базовой операционной системы; этот процесс называется переключением (thunking).
Поскольку именно исполнительный механизм осуществляет обработку любого низкоуровневого взаимодействия с базовой операционной системой, значительная доля усилий на стадиях проектирования и тестирования направляется на то, чтобы сделать этот механизм как можно более надежным.
Библиотеки управляемого кода
Библиотеки управляемого кода .NET Compact Framework являются той программной частью, с которой взаимодействуют разработчики. Как и в случае варианта .NET Framework для настольных компьютеров, библиотеки .NET Compact Framework размещены в нескольких DLL-файлах. Эти библиотеки присутствуют на настольных компьютерах во время проектирования, а также устанавливаются на целевых устройствах для использования во время выполнения.
Для работы с этими библиотеками во время проектирования используются имена System.DLL, Systems.Windows.Form.DLL и System.Xml.DLL. На устройствах эти файлы могут иметь другие имена в зависимости от потребностей целевых устройств, связанных с именованием и учетом версий файлов. В процессе компиляции библиотеки управляемого кода используются аналогично тому, как заголовочные файлы используются компиляторами C/C++ или библиотеки типов используются прежними (полученными с применением VB6 и более ранних версий) кодами на языке Visual Basic для передачи информации об интерфейсах и типах, используемых компилируемым кодом.
Тот факт, что эти файлы имеют то же DLL-расширение, что и файлы библиотек собственных кодов C/C++, объясняется исключительно желанием сохранить привычный подход к именованию файлов; природа их двоичного содержимого совершенно другая, и в состав их имен с равным успехом может быть включено любое другое удобное расширение. То, что имена файлов .NET Compact Framework обычно совпадают с именами соответствующих файлов .NET Framework, также объясняется только соображениями удобства. В действительности эти файлы могут быть дополнительно разделены на еще большее количество файлов или объединены в один файл, если в этом возникнет необходимость. В будущих реализациях для систем, отличных от Windows, может быть выбран именно такой вариант, если это окажется более предпочтительным.
Обычно детали реализации в приложениях учитываться не должны, поскольку задачи поиска, загрузки и управления общими библиотеками, присутствующими на устройстве, решаются средой времени выполнения.
С точки зрения программирования каждый из этих DLL-файлов предоставляет разработчику набор иерархических пространств имен, содержащих классы и типы. Примерами пространств имен, содержащих классы и типы, могут служить:
System.*
System.Xml.*
System.Data.*
System.Drawing.*
и тому подобные.
DLL-файлы и пространства имен связаны между собой отношениями типа "многие ко многим"; один DLL-файл может предоставлять имена сразу для нескольких пространств имен (например, если это потребуется, файл Foo.DLL может содержать типы, относящиеся как к пространству имен MyNamespace.*, так и к пространству имен SomeOtherNamespace.SomethingElse.*), а несколько DLL-файлов могут предоставлять имена для одних и тех же пространств имен (например, при необходимости одновременно оба файла Foo.DLL и Bar.DLL могут предоставлять типы для пространств имен MyNamespace.* и SomeOtherNamespace.SomethingElse.*). Во время компиляции приложения компилятору передается набор имен файлов, подлежащих просмотру с целью поиска классов и типов, которые пользователь намеревается применять в своем приложении; эти имена принято называть ссылками (references). Если в коде разработчика или библиотеках, на которые имеются ссылки, некоторые типы/методы/свойства найти не удается, генерируется сообщение об ошибке времени компиляции. Кроме того, в случае обнаружения нескольких версий типов в разных библиотеках также генерируется сообщение об ошибке времени компиляции, связанной с неоднозначностью определения типа.
Во всех остальных случаях, не связанных с периодом компиляции, когда компилятору предоставляется список файлов, используемых для поиска классов, на которые имеются ссылки, разработчикам можно не беспокоиться о том, в каком файле находится тот или иной класс. Вместо этого они должны думать лишь о логической иерархии используемых пространств имен, тогда как вопрос о фактическом размещении конкретных типов в указанных файлах их заботить не должен.
Библиотеки базовых классовБазовые классы – это квинтэссенция программирования. В них содержатся распространенные типы и функциональность, которые используются разработчиками при реализации большинства алгоритмов обработки данных. Базовые классы имеют следующий состав:
■ Все основные типы данных, к которым, например, относятся целые числа, строки, числа с плавающей запятой, дата/время, массивы и коллекции.
■ Средства файлового ввода-вывода, потоки, сетевые сокеты.
■ Средства поиска типов, методов и свойств в сборках и привязки к ним во время выполнения. Эти возможности называют отображением (reflection).
■ Средства, позволяющие учитывать в приложениях региональную и местную специфику. Эти возможности называют глобализацией (globalization).
Вышеперечисленные функциональные возможности вместе с дополнительными базовыми классами инкапсулированы в следующих иерархических пространствах имен:
System.*
System.Collections.*
System.ComponentModel.*
System.Diagnostics.Globalization.*
System.IO.*
System.Net.Sockets.*
System.Security.*
System.Text.*
System.Threading.*
При создании библиотек пользовательского интерфейса преследовались две цели: 1) предоставить разработчикам возможность создавать многофункциональные приложения уровня предприятия с использованием таких современных высокоуровневых элементов управления пользовательского интерфейса, как Button, PictureBox, ListView, TreeView, TabControl и так далее, и 2) предоставить разработчикам возможность выполнения низкоуровневых операций рисования на мобильных устройствах с использованием расширенного набора операций для обработки растровых изображений, позволяющего рисовать такие, например, двумерные объекты, как линии, многоугольники, текст и изображения.
Описанные функциональные возможности предлагаются в двух иерархических пространствах имен:
■ System.Drawing.* – средства создания двумерных рисунков.
■ System.Windows.* – элементы управления пользовательского интерфейса и вспомогательные функциональные средства.
Библиотеки клиентов Web-службWeb-службы – стандартный способ организации связи между приложениями, выполняющимися на различных платформах. По существу, сервер Web-службы – это Web-сервер, предоставляющий приложениям программные интерфейсы, для доступа к которым в качестве языка общения используется XML. Синтаксис такого общения на языке XML определяется протоколом SOAP, название которого представляет собой аббревиатуру от Simple Object Access Protocol – простой протокол доступа к объектам. Клиент Web-службы – это приложение, которое может осуществлять вызовы с целью создания запросов, посылаемых серверам Web-служб, и интерпретировать получаемые ответные сообщения SOAP. Для описания предоставляемых интерфейсов серверы Web-служб в ответ на соответствующий запрос возвращают WSDL-документы. WSDL – это аббревиатура от Web Service Description Language (язык описаний Web-служб), и, подобно SOAP, этот язык представляет собой синтаксис, построенный поверх XML. WSDL описывает предоставляемый Web-службой программный интерфейс; для создания запросов этих интерфейсов используется протокол SOAP.
Ключевой особенностью платформы .NET Framework для настольных компьютеров и серверов, равно как и инструмента разработки Visual Studio .NET, является простота создания Web-служб и получения соответствующих услуг. В Visual Studio .NET предусмотрена возможность синтаксического анализа WSDL-документов и генерации простых в использовании клиентских классов-заместителей (proxy classes), при помощи которых разработчики могут получать доступ к Web-службам. Благодаря наличию упомянутых классов-заместителей вызов Web-службы концептуально сводится к простой процедуре создания объекта и вызова его метода.
При проектировании .NET Compact Framework специально ставилась задача поддержки достаточно многофункционального набора классов, свойств и методов, обеспечивающих компиляцию вышеупомянутых клиентских классов-заместителей, автоматически генерируемых Visual Studio .NET. Эта задача была успешно решена, и теперь организовать работу приложений на мобильных устройствах в качестве клиентов Web-служб столь же просто, как и в случае их аналогов, выполняющихся на настольных компьютерах и серверах.
Функциональные средства этой категории предоставляются пространством имен System.Net.*.
Библиотеки XMLПочему XML придается настолько большое значение? Чтобы в этом разобраться, необходимо рассмотреть все "за" и "против" двух способов обмена данными между приложениями, использующих, соответственно, двоичный и текстовый форматы данных.
Обмен двоичными данными требует соблюдения всеми сторонами строгих договоренностей относительно способа форматирования и интерпретации данных. Двоичные форматы требуют тщательного планирования управления их версиями всеми сторонами, использующими эти форматы. Все это значительно снижает гибкость данного метода; любое изменение двоичного формата, которое предварительно не было согласовано со всеми сторонами, приведет к нарушению работы приложений, использующих эти данные. Как бы в качестве компенсации этого недостатка, двоичные форматы предлагают возможность более компактного представления данных. Тем самым обеспечивается снижение расхода памяти и увеличение скорости обработки данных.
Решение, которое традиционно обеспечивали текстовые файлы, совершенно противоположно по своему характеру: оно повышает гибкость взаимодействия между различными сторонами за счет использования более свободных договоренностей между ними и более подробного описания формата кодирования данных. В качестве метода хранения простых данных и организации обмена ими XML заменил традиционные текстовые файлы во многих областях применения. XML-файлы представляют собой обычные текстовые файлы, отличающиеся тем, что в них содержится дополнительная информация относительно собственной структуры. Это позволяет упростить их обработку стандартными способами и облегчает их повторное использование. Разработчики останавливают свой выбор на текстовых форматах по той причине, что с ними проще работать, ибо они более терпимы к изменениям схемы организации данных и облегчают учет специфики различных версий. XML поднимает текстовый способ хранения данных на более высокий уровень.
XML предлагает достижение разумного компромисса между чрезмерно сложным и чрезмерно упрощенным подходами к структуризации информации. Такое наполовину структурированное хранение данных обеспечивает значительные преимущества по сравнению с обычными текстовыми файлами. Данные сохраняются в иерархическом текстовом формате с использованием дескрипторов (tags), предоставляющих информацию о структуре содержимого. Например, информация о шрифте может быть сохранена посредством фрагмента текста ххх , который позволяет приложению, интерпретирующему текст, легко определить, что означает этот элемент данных. Приложения, работающие с XML-данными, могут выбирать лишь те порции текста, которые представляют для них интерес или смысл которых для них понятен. Таким образом, XML является важным усовершенствованием по сравнению с предыдущими текстовыми форматами, такими как файлы *.INI, контейнеры PropertyBag или HTML-текст, так как обеспечивает одновременно и больший объем структурной информации, и большую гибкость.
Поскольку в настоящее время XML очень широко используется в качестве средства обмена информацией, наличие его поддержки является весьма важной характеристикой любой современной программной среды. Не будь ее, каждый разработчик был бы вынужден самостоятельно писать собственные наборы функций для синтаксического анализа текстовых файлов и извлечения или сохранения необходимых данных. Такое решение было бы крайне неэффективным и значительно увеличило бы вероятность появления в приложениях ошибок, которых можно было бы избежать. Поскольку большинство разработчиков заняты созданием приложений, а не синтаксических анализаторов, "самодеятельные" варианты реализации обычно способны выполнять то, что требуется, лишь в минимальном объеме и почти во всех случаях не подвергаются достаточно тщательному тестированию. Более того, в случае пользовательской реализации достижение максимальной производительности почти всегда приносится в жертву сокращению сроков разработки. В результате этого пользовательские варианты реализации оказываются, как правило, менее надежными и менее эффективными по сравнению с профессиональными решениями, предназначенными для широкого использования.
Ввиду вышесказанного вам уже должно быть ясно, что для чтения и записи XML-данных гораздо лучше использовать библиотечные функции, специально разработанные для этой цели и прошедшие строгое тестирование. Преимущество этих функций заключается в том, что они проектировались, создавались и тестировались группой специалистов, способных с полным знанием дела справиться с задачей создания наиболее быстрого и надежного механизма для работы с XML.
Для работы с XML-документами в .NET Compact Framework предлагается двухуровневый подход:
■ Средства однонаправленного чтения и записи XML-документов. Для максимально быстрого выполнения однонаправленного (forward-only) чтения/записи XML-документов без применения кэширования используются классы XmlReader и XmlWriter. Задачей этих классов является чтение или запись XML-данных соответственно из потоков или в потоки с поддержкой лишь минимально необходимого объема информации о состоянии. Этими возможностями могут воспользоваться разработчики, имеющие дело с XML-документами большого объема, когда на первый план выступает необходимость обеспечения высокой производительности приложений.
■ XML DOM (Document Object Model – объектная модель документов). Класс XmlDocument используется для представления создаваемого в памяти дерева объектов, описывающего XML-документ. XmlDocument и связанные с ним классы представляют объектную модель документов, обеспечивающую легкий доступ к элементам представляемых деревьев XML. Документ считывается только в прямом направлении с использованием обсуждавшегося выше класса XmlReader, на основании чего создается дерево элементов, представляющее XML-документ в памяти. Аналогичным образом, данные из XML-дерева могут быть записаны в поток; для выполнения этой задачи используется класс XmlReader. Возможности класса XmlDocument больше всего подходят тем разработчикам, которые либо имеют дело с XML-документами небольших или средних размеров, либо хотят вносить как можно меньше усложнений при работе с XML-документами
Концептуально соответствующая функциональность концептуально представлена в пространстве имен System.Xml.*.







