"Программирование мобильных устройств на платформе .NET Compact Framework" - читать интересную книгу автора (Салмре Иво)

Эту книгу я посвящаю своим учителям, как формальным, так и неформальным, но в первую очередь — родителям, Эйр (Aire) и Уильяму Салмре (William Salmre). Если мне и удалось взглянуть на кое-что по-новому и изложить свои мысли с пользой для дела, так это только благодаря доброте и терпению тех, кто не пожалел времени на то, чтобы провести меня вверх по склону горы и указать правильное направление. Спасибо вам всем.
Благодарности издательства Издательский дом "Вильямс" благодарит Ерофеева Сергея и Кущенко Сергея за большой вклад в подготовку издания книги.

Управляемый код

Термин "управляемый код" (managed code) относится к программному коду, выполняющемуся в управляемой среде (managed environment), будь то среда сервера, персонального компьютера, мобильного устройства или встроенной системы. Диспетчер среды времени выполнения (runtime engine), или просто —среды выполнения, отвечает за распределение ресурсов, управление выполнением потоков и необходимую синхронизацию, а также обеспечивает безопасность типов выполняющегося кода, предотвращая несанкционированный доступ к памяти. Этот уровень абстракции располагается выше уровня собственного кода, что позволяет значительно повысить производительность труда разработчиков и надежность кода. Время существования объектов и других типов, размещенных в памяти выполняющимся кодом, отслеживается диспетчером среды выполнения, что избавляет разработчика от необходимости решения этой задачи. В результате компиляции управляемого кода генерируются двоичные коды инструкций, которые включают в себя метаданные с подробными описаниями классов, типов, переменных и другую информацию, необходимую для управления выполнением кода. Содержащиеся в метаданных описания кодов диспетчер среды выполнения использует для реализации своих административных и контрольных функций. Именно богатый набор метаданных и является ключевым отличием управляемого кода от собственных кода. К числу других характеристик, являющихся общими для многих управляемых сред выполнения, относятся следующие: 

#9632; Независимость от процессора. При компиляции программы, написанной с использованием управляемого кода, получаются не специфические для процессора машинные команды, а программа на промежуточном языке. Для промежуточного языка (intermediate language) часто используют сокращение IL, а в некоторых средах времени выполнения его называют "байтовыми кодами" ("byte codes"); оба эти термина имеют один и тот же смысл. Впоследствии этот промежуточный код преобразуется в мобильном устройстве в соответствующий формат исполняемого кода. Компиляция программы в формат IL обеспечивает возможность выполнения одного и того же скомпилированного кода не только на различных процессорах, но и с использованием адресов различного размера. Так, один и тот же IL-компонент может выполняться и на 32-, и на 64-разрядных процессорах, поскольку инструкции не зависят от размера адресных полей процессора. 

#9632; Независимость от операционной системы. Среды выполнения управляемого кода вместе с их библиотеками обеспечивают разработчикам возможность написания программ на уровне абстракции, расположенном поверх базовой операционной системы. Учитывая тот факт, что пользовательские интерфейсы и модели взаимодействия с пользователем для классов устройств, в которых применяются различные степени абстрагирования верхних уровней, значительно отличаются друг от друга, принцип разработки программ "пишется однажды, выполняется везде" ("write once, run everywhere") вряд ли можно считать практически осуществимым, однако операционная система все еще остается весьма полезным средством обеспечения переносимости приложений на устройства разных классов. Кроме того, возможность создавать автономные (автономные (headless) — не имеющие пользовательского интерфейса) компоненты, способные выполняться на различных устройствах без перекомпиляции, оказывается очень полезной при построении повторно используемых модулей. После того как автономные компоненты заполнены общим кодом, остается лишь реализация зависящих от конкретного типа устройства пользовательских интерфейсов, в которых используются общие модули такого типа. 

#9632; JIT-компиляция (just-in-time — оперативная) и/или интерпретация кода. Существует два метода выполнения управляемого кода: 1) JIT-компиляция, когда IL сначала транслируется в собственные машинные команды процессора, а затем выполняется, и 2) интерпретация, когда просматривается каждая инструкция IL, и для выполнения предусмотренных ею действий вызываются предопределенные библиотеки. Код, получаемый в результате JIT-компиляции, работает быстрее, однако интерпретаторы легче создавать, поскольку они не обязаны знать, как генерировать специфические для процессора команды. Во многих случаях сначала создают интерпретатор, с помощью которого можно быстро перенести управляемый код времени выполнения на новый процессор, и лишь затем создают JIT-компиляторы, позволяющие оптимизировать код для конкретных типов наиболее распространенных процессоров. Один и тот же IL-код может либо интерпретироваться, либо JIT-компилироваться; окончательный выбор остается за теми, кто реализует исполняемый код. 

#9632; Сборка мусора. Сборка мусора — это операция, избавляющая разработчиков приложений от необходимости заниматься утилизацией памяти, используя низкоуровневые функции. Существует множество различных стратегий сборки мусора, каждая из которых оптимизирована для сценариев определенного типа. Исследования в этой области продолжаются, приводя к нахождению все более оптимальных стратегий для самых важных сценариев. Обычной стратегией, применяемой в средах выполнения на мобильных устройствах, является стратегия "отслеживания и очистки" ("mark and sweep"), суть которой состоит в том, что среда выполнения периодически составляет список всех переменных, находящихся в данный момент в области видимости, и отслеживает все объекты, на которые эти объекты ссылаются. Каждый из обнаруженных таким способом объектов снабжается "меткой", указывающей на то, что объект все еще используется. На основании этой схемы создается дерево активных объектов (live-object tree), представляющее полный набор всех объектов, к которым код приложения может получить доступ. После того как все активные объекты отмечены, выполняется операция очистки, которая освобождает все объекты, являющиеся для приложения недоступными. Программы, осуществляющие сборку мусора, представляют собой чрезвычайно сложные системы, так что для оптимизации производительности серверов, настольных компьютеров и мобильных устройств всегда остается масса возможностей. В организациях, занимающихся разработкой сред выполнения управляемых кодов, значительная доля усилий направляется на повышение эффективности стратегий сборки мусора до уровня, способного обеспечить получение максимально возможных производительности и надежности. 

#9632; Контроль версий. Помимо всего прочего метаданные можно использовать для передачи обширной информации, касающихся номера версии компонента и номеров версий компонентов, от которых он зависит. Среды выполнения управляемых кодов, располагающие возможностями контроля версий, способны обеспечивать корректную работу нескольких версий одних и тех же компонентов на одной и той же машине, позволяя каждому компоненту связываться именно с теми компонентами, с которыми он создавался и тестировался. Этот фактор имеет большое значение для обеспечения долговременной устойчивой работы устройств, на которых выполняется множество приложений. Встроенная поддержка контроля версий позволяет избежать конфликтов между ними и предотвратить возникновение как малозначительных, так и явно выраженных проблем, к которым может привести отсутствие надлежащего контроля версий. 

#9632; Поддержка безопасности объектов. Наконец, управляемый код может расширить возможности политик безопасности, используемых на устройстве. Среды выполнения управляемого кода с развитой поддержкой средств безопасности могут установить политику, определяющую, какие именно полномочия предоставляются тем или иным разновидностям кода. Такой подход часто называют обеспечением безопасности путем явной проверки полномочий. Примерами политик безопасности подобного рода могут служить следующие: "Код, подписанный заслуживающей доверия третьей стороной, может выполняться без каких-либо ограничений", "Код, присутствующий в локальной файловой системе, может получать доступ к файлам, находящимся в указанном наборе папок" или "Загруженный из Internet код, не снабженный подписью заслуживающей доверия третьей стороны, имеет минимальные права доступа без возможности выполнения типовых операций файлового ввода-вывода". В разных средах выполнения поддержка средств безопасности различна; так, поддержка средств безопасности платформой J2ME отличается от той, которая обеспечивается платформой .NET Compact Framework v1.1. Политики безопасности, поддерживаемые платформой .NET Compact Framework v1.1, являются подмножеством политик безопасности, поддерживаемых платформой .NET Framework.

Двумя наиболее распространенными средами выполнения управляемого кода на мобильных устройствах являются J2ME (Java Mobile Edition) и .NET Compact Framework. В данной книге для иллюстрации принципов разработки программного обеспечения для мобильных устройств используется платформа .NET Compact Framework, хотя большинство обсуждаемых положений справедливы по отношению к любым разновидностям методов разработки мобильных программ, включая разработку программ с использованием собственных кодов

Преимущества управляемого кода трудно переоценить. Руководствуйтесь следующим общим правилом: если имеется хоть малейшая возможность использовать для разработки проекта управляемый код, воспользуйтесь ею. Благодаря этому значительно сократятся сроки разработки кода и количество ошибок в нем, облегчится перенос кода на новые устройства, повысятся его безопасность и устойчивость, а сопровождать его будет гораздо легче, чем аналогичный собственный код. Разрабатывать приложения с использованием собственных кодов имеет смысл лишь тогда, когда это диктуется соображениями производительности или необходимостью получения низкоуровневого доступа к устройствам. Но и в этих случаях лучше всего написать на собственном коде лишь небольшие критические участки программы, а во всей остальной ее части использовать высокоуровневый управляемый код. Как будет показано далее в этой книге, использование проверенных методов проектирования мобильного программного обеспечения в сочетании с управляемой средой времени выполнения, поддерживающей JIT-компиляцию, приводит к тому, что необходимость в привлечении собственных кодов возникает лишь в редких случаях. Возможностей управляемого кода чаще всего будет вполне достаточно даже для создания динамичных игр с высокой долей анимации. Преимущества высокоуровневых абстракций управляемого кода невозможно оспаривать. Пару десятков лет тому назад программисты переходили при разработке программ от языка ассемблера к языку С, оставляя ассемблерный код лишь для решения узкоспециальных или критических задач. Такой переход на более высокий уровень абстракции позволил разрабатывать намного более сложные приложения, отличающиеся повышенной надежностью, в гораздо более короткие сроки. В настоящее время совершается аналогичный переход от собственных кодов C/C++ к средам с управляемым кодом.