вторник, 23 июля 2013 г.

Записки программиста #2. Портативные библиотеки классов или совместное использование кода в различных проектах.

Разрабатывая приложения для Windows Phone 8 и Windows 8 часто встает вопрос, как сделать так, чтобы написанный один раз код, работал везде, хоть они и основаны на одном и том же ядре Windows 8 и Microsoft пытается всячески сократить разрыв между ними, но различий довольно много. А если встает вопрос о поддержке проекта на IOS и Android по средствам Mono, то порой хочется плакать… Ведь в самом худшем сценарии, придется поддерживать как минимум 4 проекта и изменение в одном, несут большое количество изменений в другом, те большое количество ручного труда. Именно такой и встал у меня вопрос в начале разработке, ведь об этом стоит подумать заранее. До этого я с этим сталкивался только вскользь.
В целом, для решения этого рода задач, существует два метода:
Портативный библиотек классов
Совместное использование кода

Портативный библиотек классов
Одна из ключевых частей взаимодействия между платформами является концепция портативной библиотеки классов (или PCL). Портативная библиотека классов является компонентом, который можно добавлять в обе платформы, но к сожалению, не все можно уместить туда.
Туда можно написать различную бизнес логику, но к сожалению, как пример, туда нельзя написать код доступа к файловой системе, та обе платформы имеют различный API. В целом все не плохо, но чем больше кода Вы пишите, тем больше возникает такого рода проблем. Так же не стоит забывать, что визуальное представление отнимает также большое количество времени.
Что же такое PCL, хорошо показано на рисунке:

А если добавит Xbox получите что-то вроде этого:

Как вы уже поняли, чем больше целевых платформ, тем меньше вы получаете доступа к API. Для решения этой проблемы используются интерфейсы, которые будут реализованы уже на каждой платформе в отдельности.
В таблице ниже дается обзор того, что поддерживается в PCL:

Feature
.NET Framework
Windows Store
Silverlight
Windows Phone
Xbox 360
Core BCL
Да
Да
Да
Да
Да
Core XML
Да
Да
Да
Да
Да
Core WCF
Да
Да
Да
Да

Core networking
Да
Да
Да
Да

XML Serialization
Да
Да
Да
Да

JSON serialization
Да
Да
Да
Да

Datacontract serialization
Да
Да
Да
Да

IQueryable
Да
Да
Да
7.5  и выше

dynamic keyword
4.5
Да
Да


View Models
4.5
Да
Да
Да

Data Annotations
4.03 и выше
Да
Да
Да

LINQ
Да
Да
Да
Да

XLINQ
4.0.3  и выше
Да
Да
Да
Да
MEF
Да
Да
Да


System.Numerics
Да
Да
Да


Совместное использование кода
Другая форма повторного использования через единый исходный код.  Для того чтобы сделать это, Вы должны добавить существующий файл с исходным кодом в качестве ссылки. Это позволит добавить файл в проект, но сам файл все еще живет внутри каталога с исходным проектом.  Если вы обновите его, то она будет изменен в обеих библиотеках. 
Используя данный подход Вы все еще ограниченны общим API библиотек. Так как исходный файл должен работать в нескольких проектах.  Однако, существует еще один метод, который можно использовать, чтобы обойти это: директивы препроцессора.

Когда использовать первый способ, а когда второй?
Я бы рекомендовал использовать PCL в небольших проектах, где идет большое количество одинакового кода минимально привязанного к платформе. Как правило это бизнес приложения для Windows 8 и Windows Phone7/8 где интерфейсами заменяются критические части и реализовываются для каждой платформы отдельно, как я писал выше.
Если Ваш код одинаковый для обеих платформ, но PCL не поддерживает его.  Это случается иногда, когда оба API живут в разных пространствах имен. То проще всего использовать директивы препроцессора, чтобы преодолеть это.
Но когда код пишется под разные платформы и очень часто поведение многих частей отличается для каждой платформы, я бы советовал использовать смесь этих двух подходов. Суть этого заключается в следующем, пишется ядро кода в PCL, создаются проекты для каждой платформы и наполняются ссылками на код из PCL и уже потом как надстройка используются директивы препроцессора. Пока данных подход в моем новом проекте меня радует. Единственное, не гонитесь сразу за многими платформами, поддерживайте одну, а лишь потом переносите код на другие. Объясню почему, когда Вы только начинаете писать код, Вы создаете большое количество новых классов, что-то удаляете, что-то меняете и как следствие Все их нужно переносить в другие проекты, если их 4 + библиотека PCL где все изменения, то это увеличит время разработки и создаст некоторый дискомфорт. Но как не крутите это намного лучше, чем 4 независимых проекта.

среда, 26 июня 2013 г.

Записки программиста #1. Физика

Как я уже говорил в прошлой статье из цикла «Записки программиста» передо мной встал серьезный вопрос, использовать готовый движок или допиливать свой в игре «AlienStorm».
Пару слов о существующем движке, «земля» создается случайно исходя из минимальных и максимальных характеристик. Ландшафт не равномерный, неровности, располагаются случайно и в случайном количестве, за финальный проход неровности сглаживаются. Минус такого подхода - на каждую карту создается свой атлас неровностей и их маска. Конечно, можно использовать и попиксельную проверку, но тк массив для проверки довольно большой выходит, то на основании полученной маски мы создаем прямоугольники, по которым уже с которым мы уже и считаем пересечения.
Для движения по ним, мы соединяем центры этих прямоугольников, напомню, что прямоугольники уже сглажены по определенным условиям.  Пример этого и показан на рисунке:



Любой движущийся по ним объект имеет две нижние, крайние точки.  Схема не особо сложная и она удовлетворяла начальным условиям, но запросы стали расти.
Для 2д + XNA есть два физических движка: box2d и farseer.
Они оба базируются на С++ версии box2d, но farseer довольно давно двигается в свою сторону, да и шустро. Так что для сравнения я взял farseer.
«+» готового движка (исключительно для меня):
  • покрытие всех задач связанных с физикой;
  • код более-менее уже стабильный;

«-» готового движка:
  • непонимание его работы;
  • отсутствие опыта работы с ним и как следствие возможные не предвиденные проблемы;
  • сложность его внедрения в существующую архитектуру;
  • непонятные вопросы как сделано то, или иное;
  • вопрос с производительность;

Минусов оказалось больше и конечно эти минусы можно назвать притянутыми, но для меня они все-таки минусы. Было решено допиливать свой движок.
Шла осень, проблемы в финансовом плане на работе становились все острее, к счастью поступило предложение, о новой работе, от которого я не смог отказаться. Новая работа, это новый коллектив, новые требования к работе, новые задания. Задания довольно интересные и времени на свои проекты совершенно не осталось, но не спеша я стал решать задачу со своим физическим движком. Так плавно подступила зима, время пролетело незаметно, иногда конечно приходилось отвлекаться на другие свои проекты и идеи. В новогодние праздники я решил вплотную заняться физикой, это уже была 7 версия данного движка. Если в начале, я старался писать и придумывать все сам, с нуля, то теперь я стал все больше смотреть, как это сделано у других. В результате через некоторое время я вернулся к первому своему вопросу, продолжать допиливать движок или взять готовый, правда и изменились и минусы, с большинством я уже разобрался, пока писал свой…
Остался только последний, вопрос производительности, подходя к делу с некоторым недоверием, я сперва посмотрел демонстрации, и поскольку, не зная способа лучше, стал его «трогать».
В целом он мне понравился, и было решено использовать его в качестве основы, и все-таки пришлось решать много новых задач, но процесс двигался, жалко, что новогодние праздники такие короткие. Итог моих новогодних каникул:



Как итог новогодних каникул - с физикой определился, но снова работа, семейная жизнь, работа над приложением «Слова любимым» - ни минутки покоя  =)
 Работа встала на не определенный срок.
И только поздней весной удалось снова к нему вернуться. Поскольку прошло довольно много времени, осмысление проекта стало более явно. Все это время я старался все идеи, мысли записывать, тем самым появилась точная цель,  что же я хочу видеть в итоге и когда, это что-то должно появиться на свет.
Если раньше целевая платформа была Windows Phone 7, то хорошо подумав, стало ясно, что делать уже нужно Windows Phone 7/8 + Windows 8, так же следовало сразу рассмотреть вопрос о портировании на другие платформы. О этих тяжких думах я расскажу в следующей статье.

пятница, 21 июня 2013 г.

Записки программиста #0. Введение

Речь пойдет о создание игры AlienStorm, которая на момент написания статьи находится до сих пор в разработке. Я долго думал, стоит ли вести дневник разработки или нет, но все-таки пришел к мысли, что стоит. Это упорядочивает мысли, да и читатели иногда дают очень дельные советы. И надеюсь, помогут в будущем с тестированием игры.
Все началось в конце зимы прошлого года, с другом мы решили создать игру наподобие Worms, только основные действующие лица танки и инопланетяне. Тогда и родилось название AlienStorm, случайно наткнувшись на то, что такое название уже использовалось в гейм деве в 90 годах для сеги, немного смутило, но решили оставить как есть. Игра для простоты должна была стать 2д, целевая платформа Windows Phone. Создав первый прототип игры и  поигравшись с управлением, пришли к мысли, что создание пошаговой игры не совсем то, что хотелось, подумали о гибридной системе, некоторые бои реал-тайм, некоторые пошаговые, но тоже не понравилась, с тех пор игра стала реал-тайм.
Потом начались проблемы на работе, поскольку этот человек был мой коллега, они коснулись и его и разработка на время встала. Приходилось поправлять свое финансовое состояние, писать диплом. Новая работа у моего прошлого уже коллеги, занимала его целиком, и ему постепенно пришлось, отказался, я же не сдавался. Шла весна и мне нужен был художник и такой человек быстро нашелся, он не только рисовал, что требовалось, но и постоянно приносил в проект, что-то новенькое.
Защитив диплом, на работе я выпросил отпуск и целиком погрузился в проект.
Художник же тоже не пропадал и игра постепенно, приобретала лицо:



появлялись новые карты:



Были разработаны основные положения, что танки можно покупать, улучшать, появилась система скилов, появилось осмысление UI при игре:


Через некоторое время мы взялись за модели. Модели решено было делать в 3д, чтобы дальнейшее их использование было более простым. И тут стали понимать, что мы не используем потенциала созданных моделей, стало как всегда хотеться больше, чтобы гусеницы двигались, колеса крутились и тд.
До этого мы использовали самописный движок, в котором из физики есть гравитация, а земля представляем собой набор прямоугольников, при движении по которым углы сглаживаются.

Мы стали понимать, что с движком нужно, что-то делать и пришли к тому, что следует доводить до ума движок и вводить нормальную физику. Об этом я расскажу в следующих циклах статей «Записки программиста».

четверг, 13 июня 2013 г.

Push уведомления и их эффективность.

Месяц назад я решил в своем новом обновлении приложения «Слова любимым» добавить функцию Push уведомлений. Прошел месяц, настал праздник, День России – чем не повод испытать эти уведомления и увидеть их эффективность.
Поговорим немного о Push’ах.
Основная причина использования Push Notifications со стороны разработчика, это оповещения пользователей о каких либо событиях, напомнить пользователю о Вашем замечательном приложении, лишний раз запустить его, что согласитесь довольно таки важно.
В структуре Push Notifications существует специальный сервис в облаке, который делает возможность работы уведомлений. Когда устройство хочет получать уведомления, то обращается к этому сервису и устанавливает с ним постоянное соединение. В ответ на это сервис выдает этому устройству уникальный URI, используя который можно отправить по протоколу HTTP некоторое сообщение. Это сообщение получает тот самый сервис в облаке и пересылает его соответствующему устройству. Логично, что для каждого устройства и приложения этот URI будет уникальный. Таким образом, работу уведомлений в Windows Phone  можно описать так:
  • Устройство устанавливает соединение с сервером Microsoft и получает уникальный HTTP-адрес;
  • Устройство передает этот HTTP-адрес тому, кто будет уведомлять устройство о чем-либо;
  • Когда необходимо уведомить устройство о чем-либо, приложение, которому был передан HTTP-адрес отправляет специальное HTTP-сообщение на этот адрес;
  • Сервис Microsoft получает это сообщение и по возможности доставляет его на устройство. Если доставить сообщение на устройство не удалось, то отправитель получит соответствующее сообщение.
Схематически этот алгоритм можно изобразить следующим образом.


Согласитесь, все довольно просто и понятно.
Существуют четыре разных вида уведомлений для Windows Phone:

  • Tile Notifications – если ваше приложение закреплено на начальном экране, вы можете обновить Tile (плитку) вашего приложения. Например, вы можете изменить фон картинки, используя диапазон чисел 0-99. При отправке уведомления указывается URL некоторого изображения, расположенного в сети. Когда устройство получает уведомление оно самостоятельно загружает изображение из сети и обновляет его на рабочем столе устройства.
  • Toast Notifications – при получении этого типа уведомления на экране устройства всплывает небольшое сообщение, содержащее текст уведомления. При этом приложение в данный момент может быть неактивным. При нажатии на это сообщение пользователь может быстро переключиться к соответствующему уведомлению.
  • Raw Notifications – при получении этого типа уведомления его содержимое передается непосредственно приложению. Приложение в праве обработать содержимое уведомление так, как считает нужным по своему собственному алгоритму. Это наиболее гибкий способ получения уведомлений от внешних сервисов.
  • Voip Notifications – этот тип уведомлений появился в Windows Phone 8. Служит оповещение о входящем звонке для Voip приложений. Он подобен Raw Notifications, но обрабатывается фоновым агентом.
Рассмотрим все описываемые случаи смысла нету, тк в интернете полно литературы как и что происходит, как на русском языке так и на английском.

Для своего маленького эксперимента я использовал Toast Notifications Push.
За месяц работы приложения было собрано 39219 устройств.  
В самом начале я допустил одну маленькую ошибку, которая чуть не вылилась в большую. Не оценив количество устройств, я начал отправлять сообщения в порядке очереди, дожидаясь  отправки предыдущего или ошибки, в результате отправка продолжалась с 11 до 18 часов.

В ответ от сервера нам приходят:
  • 18256 запросов вернулось различными ошибками от сервера (Exeption). В будущем я хочу их дублировать  раза 3 через некоторое время. Считаем, что они не доставлены.
  • 13910 запросов вернулось со статусами: NotificationStatus: Received, NotificationChannelStatus: Active, DeviceConnectionStatus: Connected (RAC) будем считать, что такое сообщение дошло до цели.
  • 7041 запрос вернулся со статусом: NotificationStatus: Received, NotificationChannelStatus: Active, DeviceConnectionStatus: TempDisconnected (RAT). Считаем, что они не доставлены.
  • 10 запросов вернулось со статусами: NotificationStatus: Suppressed, NotificationChannelStatus: Active, DeviceConnectionStatus: Connected (SAC). Считаем, что они не доставлены.
  • 2 запроса вернулись со статусами: NotificationStatus: Suppressed, NotificationChannelStatus: Active, DeviceConnectionStatus: TempDisconnected (SAT).  Считаем, что они не доставлены.

В среднем за это время посещают приложение 1664 пользователя, в результате Push уведомлений мы получили 4735 пользователя, что на 3071 больше. Не все пользователи замечают Toast уведомления, не все переходят, в результате 22% от считавшимися удачными, а если добавить еще RAT, SAC, SAT с которыми не все понятно, то 14,5%. Я рассчитывал на меньшее и очень доволен результатами данного опыта.

Если у Вас есть вопросы, задавайте в комментариях, постараюсь ответить.