Программирование мобильных устройств на платформе .NET Compact Framework - Иво Салмре
Шрифт:
Интервал:
Закладка:
Учет перечисленных выше факторов играет важную роль в процессе проектирования приложений для мобильных устройств, но не может заменить тестирование приложения на реальном оборудовании. По существу, единственным способом реального тестирования пользовательского интерфейса вашего приложения может быть его тестирование на том оборудовании, для выполнения на котором оно предназначено.
На рис. 13.3 иллюстрируется, каким образом переход от эмулятора к физическому устройству может повлиять на пригодность пользовательского интерфейса. В качестве примера взята программа для изучения иностранных слов, в которой анимированный персонаж перемещается по экрану в зависимости от того, правильно или неправильно пользователь ответил на заданный вопрос, выбрав по своему усмотрению ответ из нескольких предложенных вариантов. Когда для проектирования и тестирования приложения используется эмулятор устройства, все выглядит прекрасно: варианты выбора отлично размещаются на экране, а навигация в пределах приложения не составляет никакого труда.
Вместе с тем, тестирование на реальном устройстве позволяет выявить ряд существенных проблем. По мере того как пользователь перемещает руку над экраном для выбора нужного варианта ответа, он невольно закрывает ею вопрос и игровое поле. Таким образом, выбирая вариант ответа, самого вопроса пользователь не видит.
Рис. 13.3. Сравнение удобства использования пользовательского интерфейса на эмуляторе и физическом устройстве
Кроме того, чтобы увидеть результаты своего выбора, пользователь должен убрать руку с экрана; если он не сделает это достаточно быстро, то может пропустить часть действия, происходящего в это время на экране, что в некоторой мере лишит его удовольствия от общения с приложением. Совершенно очевидно, что такую ситуацию нельзя считать самой оптимальной, но это становится очевидным лишь при условии, что тестирование выполняется на физическом устройстве, поскольку при работе с эмулятором, выполняющемся на экране ПК, рука пользователя экрана не закрывает.
На рис. 13.4 проиллюстрированы два возможных способа улучшения рассматриваемого нами интерфейса. Оба способа обеспечивают для пользователя лучшие условия обзора игрового поля, причем предпочтение следует отдать экрану справа, поскольку он позволяет видеть вопрос в процессе выборе варианта ответа; в то же время, в реальных условиях этот фактор может не иметь большого значения. Проблемы, связанные с тем, каким именно образом располагаются руки пользователя в промежутках между выполнением операций выбора нужного варианта, и каковы условия физического равновесия устройства, когда оно удерживается в руке, являются важными факторами оптимального дизайна. В данном случае, именно из этих соображений и после длительного тестирования, я выбрал вариант интерфейса, представленный на рисунке слева.
Рис. 13.4. Более удобные альтернативные варианты компоновки экрана, основанные на результатах тестирования приложения на физическом устройстве
Привлечение программных эмуляторов устройств может значительно сократить сроки разработки и отладки приложения, и эту возможность следует использовать при всяком удобном случае, но это не избавляет вас от необходимости тщательного тестирования того, насколько удобно будет пользоваться интерфейсом на физическом устройстве. При этом вы будете каждый раз удивляться, как много пищи для размышлений может дать такое тестирование.
Проектируйте код пользовательского интерфейса мобильного приложения таким образом, чтобы его можно было легко тестировать и модифицировать
Проектирование пользовательского интерфейса — это итеративный процесс. Вы должны быть готовы к тому, что проект придется пересматривать несколько раз в процессе разработки и тестирования приложения по мере того, как будет становиться все более понятным, насколько приложение удобно в использовании. Если код пользовательского интерфейса тесно переплетен с логикой приложения, то выполнить это будет очень трудно; внесение изменений в пользовательский интерфейс потребует кропотливого изучения всей логики приложения с той целью, чтобы выявить все его части, которые могут влиять на пользовательский интерфейс. Вследствие этого изменить поведение интерфейса вам будет весьма трудно. Отыскивать в коде пользовательского интерфейса, насыщенном различного рода взаимозависимостями, ошибки, появляющиеся в результате его изменения, и устранять их, не нарушая работоспособности приложения, очень трудно, поскольку они будут разбросаны по всему приложению, а не сконцентрированы в одном месте и надежно инкапсулированы.
В высшей степени целесообразно проектировать логику приложения таким образом, чтобы отделить ее от пользовательского интерфейса. Обе части должны взаимодействовать между собой посредством небольшого и четко определенного набора интерфейсов. На рис. 13.5 показано, как реализовать эту идею за счет использования двух механизмов.
1. Использование конечного автомата для контроля функционирования элементов управления. Конечный автомат великолепно подходит для управления всеми нуждами пользовательского интерфейса мобильного приложения. Экран мобильного приложения является ценным и дефицитным ресурсом, и этот ресурс требует весьма бережливого отношения. Необходимо следить за эффективным использованием экранного пространства в процессе того, как пользователь переводит приложение из одного состояния в другое. При наличии конечного автомата, который показывает, скрывает и перемещает элементы управления по экрану в соответствии с необходимостью, эту задачу можно решить весьма эффективно. Абстрагирование всех режимов работы пользовательского интерфейса в одном конечном автомате обеспечивает максимальную гибкость процесса внесения изменений в модель экранного дисплея, избавляя вас от необходимости просматривать и изменять множество кода, распределенного между различными функциями и обработчиками событий пользовательского интерфейса.
2. Использование косвенных функций для обновления пользовательского интерфейса. Изменение информации, отображаемой на экране мобильного устройства, может осуществляться двумя способами: 1) непосредственно, путем использования встроенного кода (например, Label1.Text = newText) и 2) косвенно (например, UpdateDownloadStatusText(newText);). Преимущество косвенного подхода заключается в том, что он позволяет вашему коду отделить фактически используемый элемент управления от того обновления, которое вы хотите выполнить. Косвенная функция UpdateDownloadStatusText(newText); сегодня может обновлять элемент Label1, но, возможно, завтра вы решите, что лучше будет отобразить текст поверх растрового изображения или вывести его в виде текста, прокручиваемого в узкой полоске экрана. На рис 13.5 показана стрелка, направленная вниз от пользовательского интерфейса (ПИ) к блоку функций обновления ПИ, а также стрелки, направленные вверх от блока логики приложения. Стрелка, направленная вниз от пользовательского интерфейса, представляет код обновления дисплея, который выполняется в результате обработки событий, генерируемых пользовательским интерфейсом. Например, обычной реакцией на щелчок на кнопке может быть обновление текста в ярлыке или окне списка. Вместо того чтобы выполнять это обновление непосредственно в обработчике событий кнопки, можно поступить гораздо более гибко и воспользоваться вызовом обобщенной функции UpdateXXXXXXX(), которая и выполнит всю работу. Введение промежуточной функции позволяет разорвать прочную связь между обоими элементами управления и при необходимости использовать другую реализацию одного из них. Проектируя пользовательский интерфейс своего мобильного приложения, вы должны избегать тесного связывания как элементов управления с логикой приложения, так и отдельных элементов управления, являющихся частью пользовательского интерфейса, между собой. Наличие единственного уровня косвенности позволяет устранить такое тесное связывание.
Использование конечного автомата и косвенных функций обновления элементов управления пользовательского интерфейса не только позволяет вам легко пересматривать уровень представления вашего мобильного приложения, но и существенно облегчает перенос приложения между устройствами различных классов. Тесная связь между кодом пользовательского интерфейса и логикой приложения затрудняет задачу переноса приложения на устройства с другим форм-фактором. И наоборот, хорошо определенный набор функций, который управляет взаимодействиями между логикой вашего приложения и его уровнем представления, намного облегчает адаптацию приложения при переходе от одного класса устройств к другому. Этот фактор очень важен, если вы заинтересованы в обеспечении гибкости сопровождения новых типов устройств в будущем. Как обсуждалось ранее в этой главе, концепция "пишется однажды — выполняется везде" не особенно благоприятствует тому, чтобы единственное приложение в двоичной форме могло обеспечивать богатый интерфейс на различных классах устройств, но это вовсе не означает, что вы не имеете возможности проектировать свое мобильное приложение таким образом, чтобы обеспечивалась его легкая переносимость. Вы можете и должны это делать.