23 марта 2011 г.

Adobe AIR URL schemes: доступ к локальным ресурсам.

В Adobe AIR существует 2 схемы УРЛов, необходимых для того, чтобы обращаться к локальным ресурсам по относительным путям, а не по захардкоденным абсолютным:

  1. app:/ Соответствует пути к директории установки приложения. Например, app:/settings.xml будет соответствовать файлу settings.xml, расположенному в директории установки приложения.
  2. app-storage:/ Соответствует пути к директории, где приложения хранят свои данные. На ОС Windows 7 эта директория соответствует c:\Users\<username>\Application Data.

18 марта 2011 г.

Подборка статей о производительности MongoDb, MongoDb vs Redis и прочее

На данный момент тема NOSQL (not only SQL) хранилищ поднимается всё чаще. В NOSQL видят решение для многих приложений, т.к. считается, что такие решения более производительны и позволяют казалось бы проще делать репликацию данных, масштабировать веб-приложение.
Я остановил свой выбор на MongoDb по ряду причин:
  1. Приемлемая производительность, которая выще, чем у реляционных баз, но всё же ниже, чем у in-memory data grid решений.
  2. Полноценный язык запросов, а не map-reduce механизм, что позволяет писать приложения практически также, как и на SQL.
  3. Простота, наличие готовых коннекторов, прекрасная поддержка.
Следует отметить, что в MongoDb я вижу прежде всего замену персистентным хранилищам, т.е. хранилищам для бизнес-данных приложения, а не скажем данных сессий. Как показывает вот этот анализ производительности, MongoDb хоть и кажется более производительным, обладает рядом ограничений.
  1. Преаллокация места под файлы данных может существенно увеличивать потребляемое место на диске при большом количестве маленьких баз данных, поэтому подход «один клиент - одна база данных» уже перестаёт работать (попросту требует заметно больше места).
  2. Неожиданные блокировки: удаление строк или формирование индексов делает всю базу недоступной на время выполнения операции.
  3. Медленное восстановление данных на уровне отдельных баз, а не таблиц, как в MySQL.
  4. Максимальное использование RAM. Это означает, что чем больше оперативной памяти у сервера, тем выше производительность, т.к. MongoDb старается загружать в ОЗУ как можно больше данных, фактически выступая в роли memcached.
  5. MongoDb не атомарна. Это означает, что при определенных условиях, данные могут попросту не записаться. Согласитесь, это может быть неприемлемо для платежных систем, однако для систем логирования может быть вполне неплохим решением. 
Redis vs MongoDb
Глупо сравнивать memcached и Oracle! Если вам нужно кешировать данные и обращаться к ним по ключу, а также важно, чтобы эти данные были персистентны — Redis для вас. 
Redis это чуть больше, чем memcached. А MongoDb это другая парадигма.
Если же вам нужно хранить слабоструктурированные данные, документы — используйте объектно-ориентированные базы данных, например MongoDb.
Если же ваше приложение требует атомарности, то MongoDb не для вас.
Решайте сами. 

Парадигма Redis и парадигма MongoDb
Точка зрения MongoDb: что происходит с реляционными базами данных, когда они используются для более простых задач, не требующих того функционала, который в них есть? Они становятся раздутыми, медленными, их тяжело реплицировать/shard'ить. Но модель данных с таблицами, индексами и комплексными запросами над этими данными, удобна и хороша.
Точка зрения Redis: проблемы реляционных баз данных обусловлены немасштабируемой моделью данных.

Простой тест производительности MongoDb vs Redis

Используя данный тест на языке Python я получил следующие результаты. Нужно признаться, что тест достаточно синтетический, но кратное различие в скорости дают возможность примерно сравнить эти две базы данных для работы с кешем.

$ ./cache_benchmark.py 10000 
Completed mongo_set: 10000 ops in 1.47 seconds : 6802.7 ops/sec 
Completed mongo_get: 10000 ops in 2.34 seconds : 4273.5 ops/sec 
Completed redis_set: 10000 ops in 0.83 seconds : 12048.2 ops/sec 
Completed redis_get: 10000 ops in 0.92 seconds : 10869.6 ops/sec

Ссылки о Redis, MongoDb и Redis vs MongoDb
  1. http://antirez.com/post/MongoDB-and-Redis.html - мысли о MongoDb и Redis
  2. http://blog.boxedice.com/2009/07/25/choosing-a-non-relational-database-why-we-migrated-from-mysql-to-mongodb/ - история миграции веб-приложения http://serverdensity.com с MySQL на MongoDb. При этом используется и MySQL там, где нужна транзакционность.
  3. http://milancermak.posterous.com/benchmarking-tornados-sessions-0 - реализация механизма сессий с использованием встроенных функций Tornado Web Server, а также с использованием MongoDb, Redis, MySQL
  4. http://blog.jasonmooberry.com/2009/08/mongodb-and-symfony-yes-part-1-inserts/http://blog.jasonmooberry.com/2009/08/mongodb-and-symfony-yes-part-2-simple-queries/- MongoDb и PHP-фреймворк Symfony
  5. http://habrahabr.ru/blogs/webdev/74683/ - MongoDb vs MySQL в Ruby и PHP


Цифровые издания для iPad с помощью Adobe InDesign

На сайте Adobe Creative появилась интересная публикация о том, как подготовить цифровое издание для iPad.
С помощью известного пакета Adobe InDesign, который используют для дизайна веб-страниц и интернет-порталов и печатных изданий, открываются новые возможности в публикации контента цифровых изданий прямо на iPad с использованием Adobe AIR.
InDesign позволяет буквально в два щелчка мыши превратить подготовленные макеты в электронную книгу для iPad, добавив мультимедийный и интерактивный контент: панорамы, видео, а также интерактивные flash-ролики и flash-игры, а также баннеры.
InDesign создаёт готовые к публикации в AppStore приложения, а также обладает необходимыми функциями для подготовки макетов в ландшафтной и портретной ориентации.
Использование платформы AIR теоретически позволяет публиковать это приложение не только на iPad, но и на другие устройства. На данный момент AIR Mobile SDK поддерживает Android, iPhone & iPad, Blackberry.
Интересный видео-урок о том, как подготовить цифровое издание для iPad можно посмотреть на официальном сайте Adobe Creative.

15 марта 2011 г.

Инъекция зависимости, инверсия контроля, xp party в Самаре

Совсем недавно отошёл от минувшей xp.party в Самаре. Это классное место, где собираются программисты из разных технологий, разных сфер разработки и совмещают применение на практике методик экстремального программирования (agile, scrum, TDD, pair-programming etc.) для изучения методологии с интересным общением и обсуждением почерпнутого как в ходе мероприятия, так и в повседневной работе.
Специально для мероприятия я готовил доклад на тему: «Инъекция зависимости, Google Guice».
Инъекция зависимости и Инверсия Контроля
View more presentations from Владимир Игнатьев.

Что такое Инъекция зависимости (Dependency Injection)?
Это всего лишь паттерн проектирования, позволяющий снять ответственность за зависимости класса с него самого. Зависимостями в общем случае являются аггрегированные и композированные классы и объекты. А реализуется этот паттерн в общем случае посредством выноса создания зависимостей в отдельный класс и передачей сформированных зависимостей в конструктор, причем прототип конструктора содержит только интерфейсы классов-зависимостей. // Это проще понять по слайдам
Этот паттерн используют там, где необходимо, к примеру, подменять реализации тех или иных составных частей класса. Простой пример - использование mock'ов и заглушек вместо реальных классов в компонентах, осуществляющих транзакции через платежные системы, чтобы при тестовой конфигурации приложения случайно не расплатиться за ошибки программистов реальными деньгами :-)

Что такое Инверсия Контроля (IoC)? Что такое IoC-контейнер?
Инверсия контроля в контексте Dependency Injection означает эффект того, что класс больше не отвечает за свои зависимости.
Более того, этот термин часто связан с термином IoC-контейнер. IoC-контейнер это такой класс, который содержит описание связей классов и инъекторы, т.е. объекты, которые непосредственно осуществляют подстановку зависимостей в классы.
В силу того, что часто карту зависимостей хранят не в коде, а в XML-файле, который используется IoC-фреймворком для формирования зависимостей, получается такой эффект, что «данные управляют кодом». Иначе говоря, различные конфигурации приложения собираются вне кода приложения. Это позволяет писать код приложения не зависящим от конкретных конфигураций и улучшить покрытие кода тестами, а также получить менее связываемую архитектуру и легко переносимый код.

Что такое аспектно-ориентированное программирование?
Аспектно-ориентированное программирование (АОП) — это парадигма программирования, косвенно связанная  с использованием DI/IoC. АОП говорит нам о том, что функциональность приложения должна быть разделена на сущности, называемые аспектами. Примерами аспектов являются:
  • кеширование
  • логирование
  • поддержка транзакций
  • авторизация
  • фильтрация данных и т.д.
Такой подход позволяет извлечь из кода блоки, которые напрямую не связаны с реализацией бизнес-логики в отдельное место.
АОП также связывают часто с контрактным программированием. Простой пример разработки, основанной на "контрактах", это когда некоторый класс-вебсервис, работает с полученными данными так, как если бы они были отфильтрованы от нежелательного ввода. Сам же код, реализующий эту фильтрацию находится вне этого веб-сервиса. Таким образом, считается что между этими двумя компонентами [фильтрация и бизнес-логика веб-сервиса] осуществляется контракт, предусловиям которого является фильтрация необходимых полей от некорректного ввода.

Использование Посредника (Mediator) в event-driven архитектурах
В презентации частично был затронут и этот вопрос. Например, во Flex и HTML/Javascript существует иерархия графических объектов, которые умеют как принимать события, так и посылать их во вне, в иерархию. События обладают bubbling'ом, т.е. объект-инициатор создаёт событие, которое может быть получено всеми вышестоящими объектами.
Фактически, такой подход позволяет создавать уединенные компоненты пользовательского интерфейса, которые могут быть связаны через глобальный диспетчер событий, выступающий фактически в роли посредника между компонентами. 
Несмотря на то, что такой подход используется в основном для UI, глобальный диспетчер-посредник или "общую шину" используют все известные фреймворки на Flex, как и например Mate Framework. 
Этот подход удобен для создания слабосвязанной архитектуры, для чего применяется и DI/IoC, и в небольших проектах может выступать даже альтернативой DI/IoC, особенно если бизнес-логику удаётся локализовать в одном контроллере. Однако, в более-менее серьёзных приложениях, где контроллеры представляют собой некоторый «слой» всё же лучше подойдёт DI/IoC.

Фреймворки Dependency Injection (DI)  для ActionScript/Flex
Mate - красивый с IoC-контейнером, Swiz - простой, Parsley - разносторонний и большой!


Фреймворки Dependency Injection (DI)  для Java
Гигант Spring Framework, прекрасная кроха Google Guice

Фреймворки Dependency Injection (DI)  для PHP

Фреймворки Dependency Injection (DI)  для Python

Код-сниппеты

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

Как повернуть MovieClip? Как вращать объекты в ActionScript вокруг центра?
Напомню, что все объекты, являющиеся DisplayObject'ами вращаются заданием свойства rotation. Однако, такой поворот происходит относительно левой верхней точки Sprite или MovieClip.
Чтобы сделать вращение относительно центра, к примеру, нам понадобится такая функция:

package inputControllers.basics
{
import flash.geom.Matrix;


public class FlexMatrixTransformer
{
public static function rotateAroundExternalPoint(m:Matrix, x:Number, y:Number, angleDegrees:Number):void
{
m.translate(-x, -y);
m.rotate(angleDegrees*(Math.PI/180));
m.translate(x, y);
}
}
}

И вот как её использовать.

FlexMatrixTransformer.rotateAroundExternalPoint(backMatrix, VIEWPORT_WIDTH / 2, VIEWPORT_HEIGHT / 2, BACK_ROTATION_SPEED);
back.transform.matrix = backMatrix; 

Если этот код вызывать каждый кадр, то объект back, являющийся Sprite'ом, будет вращаться вокруг центра на BACK_ROTATION_SPEED за каждый кадр.

Если необходимо фиксировано задавать вращение, то в функцию rotateAroundExternalPoint в самом начале добавляем m.identity() - это приведет к сбросу матрицы преобразования объекта в единичную, т.е. без преобразований.



Как случайно перемешать массив в ActionScript?
Для этого опишем функцию randomSort в глобальном пространстве имён приложения и вызовем функцию sort над массивом, где в качестве функции-компаратора подставим функцию randomSort.

Создадим файл ShuffleMachine.as следующего содержания:

package model
{
public class ShuffleMachine
{
public static function shuffle(source:Array):Array
{
return source.sort(randomSort);
}
}
}



function randomSort(a:Object, b:Object):int { //функция в глобальном пространстве имен
return Math.random() > 0.5 ? 1: -1;
}

Как сделать вероятностную функцию? Функция случайного события в ActionScript.


Пусть функция случайного события pRand при её вызове возвращает 0 или 1 в зависимости от того, произошло ли это событие в данный момент с заданной вероятностью p или нет, а функция pRandVariant указывает произошедшей случайное событие из списка несовместимых событий с заданными вероятностями. Код, реализующий эти функции приведен ниже.



public class MathUtils
{
public static const ERROR:int = -1;
public static const TRUE:int = 1;
public static const FALSE:int = 0;

/**
* Возвращает 0 или 1 в зависимости от того, произошло ли случайное событие с вероятностью p или нет.
* */
public static function pRand(p:Number):int
{
var random:Number = Math.random();
return random < p? TRUE:FALSE;
}

/**
* Возвращает индекс выпавшего варианта при заданной функции вероятности p
* */
public static function pRandVariant(p:Array):int
{
var random:Number = Math.random();
var a:Number = 0;
var b:Number = 0;
for (var i:uint = 0; i < p.length; i++) {
b = b + p[i];
if (random >= a && random < b) {
return i;
}
a = b;
}
return ERROR;
}
}



14 марта 2011 г.

Иконка в приложении для Blackberry

Как добавить иконку приложения на Blackberry AIR SDK?
Чтобы добавить иконку приложения, необходимо создать в корне своего проекта, в папке src, файл с названием blackberry-tablet.xml следующего содержания:

<qnx>
  <initialWindow>
    <systemChrome>none</systemChrome>
    <transparent>true</transparent>
  </initialWindow>
  <publisher>Vladimir Ignatev</publisher>
  <category>core.games::Games</category>
  <icon>
   <image>assets/icon86x86.png</image>
  </icon>
</qnx>

Здесь значение тега <image> указывает на путь к иконке.
Иконка приложений в BlackBerry должна быть размерами 86х86 пикселей, при этом в отличие от iOS, QNX не добавляет иконкам глянец и скругленные уголки. Придется нарисовать их самому или сделать дизайн без их использования, т.к. многие приложения в QNX имеют иконки в другом стиле.

Категории приложений в Blackberry
Не долго поискав на официальном форуме поддержки, я нашел следующие категории приложений:

core.all::All
core.downloads::Downloads
core.internet::Internet
core.games::Games
core.utils::Utilities
core.ent::Entertainment
core.social::Social Networking
core.prod::Productivity
core.life::Lifestyle
core.ref::Reference
core.travel::Travel
core.news::News
core.photo::Photography
core.business::Business
core.edu::Education
core.books::Books
core.medical::Medical
core.media::Media
core.flash::Flash Apps
core.graphics::Graphics


Пару заметок о работе с текстом в Actionscript и о Blackberry AIR SDK

Привет всем! К сожалению, тематику блога решил сделать более разнообразной, т.к. писать в той узкой области, о которой заявил с самого начала, представляется весьма трудным: публикации в голове рождаются реже, чем происходит процесс Веселой разработки :-)

Недавно писал приложение под Blackberry, используя Blackberry AIR SDK.
Стоит заметить, что с текстом я почти не работал во Adobe Flash и наткнулся на такую проблему: если обычный текст (TextField) повернуть, указав ему свойство rotation, то он перестаёт отображаться.


Также обнаружил такую проблему с Blackberry AIR SDK: неправильно отображаются картинки в приложении, а именно получают неверный масштаб и непонятно сдвигаются.


Как заэмбедить, подключить шрифт в Actionscript, Flash
В классическом Adobe Flash это проблема решается через embedding шрифта в приложение. Вот пример класса, который использует embedded шрифт:



package views
{
import flash.display.MovieClip;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;

public class GameTextView extends MovieClip
{
[Embed(source="assets/ARIAL.TTF", fontFamily="Arial", 
fontWeight= "light", fontStyle = "italic", mimeType="application/x-font-truetype")]
private var MyFont:String;

public function addTextFieldOnStage():void {
var defaultTextFormat:TextFormat = new TextFormat();
defaultTextFormat.color = 0x6d3832;
defaultTextFormat.size = 18;
defaultTextFormat.font = "Arial";


var field:TextField = new TextField();


field.embedFonts = true;


field.width = 112;
field.height = 112;
field.autoSize = TextFieldAutoSize.CENTER;
field.selectable = false;


field.x = 100;
field.y = 100;


field.multiline = true;


field.defaultTextFormat = defaultTextFormat;
field.setTextFormat(defaultTextFormat);
field.rotation = 90;
this.addChild(field);
}
}
}



Как повернуть текст в ActionScript
Код, показанный выше, позволяет вращать текст, при этом он будет корректно отображаться флешом.

Однако, как показала практика, для BlackBerry SDK всё немного иначе.

Во-первых, нужно добавить в метатег поле  embedAsCFF="false", а во вторых в Project Properties->ActionScript Compiler (в параметрах компиляции проекта) нужно добавить -managers flash.fonts.AFEFontManager

Вот после этого шрифт будет нормально цепляться и текст можно будет вращать в Blackberry AIR SDK.

Как сделать приложение для Blackberry, чтобы картинки работали правильно
Если вы выполнили все шаги вот отсюда: http://maxpavlov.blogspot.com/2011/02/air-blackberry-playbook.html, то до создания своего первого приложения осталось совсем чуть-чуть!
Главный класс приложения, когда создаём ActionScript проект следует наследовать от MovieClip, а в заголовок класса добавить следующий метатег:

[SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")]
public class Main extends MovieClip...

Иначе у вас возникнут проблемы с позиционированием объектов на stage главного MovieClip'а.