пятница, 9 июля 2010 г.

Synchronet.ru

Недавно компания «Синхро системс», в которой я работаю ведущим Flash-разработчиком, объявила о запуске своего нового продукта Synchronet.ru.

Synchronet.ru – это единственный, насколько мне известно, интернет-сервис в российском сегменте сети, позволяющий пользователю синхронизировать персональную информацию (контакты, календари, закладки, заметки) и файлы на множестве мобильных (и не только) устройств, будь то мобильные телефоны, КПК, нетбуки, стационарные ПК или что-то еще.

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

Управлять всем  этим функциональным великолепием пользователь может в окне браузера, при помощи клиента, разработанного на базе платформы Adobe Flash. Собственно, я как раз и занимался разработкой этого клиента. Работал я не один, а в сотрудничестве с еще двумя Flash-разработчиками. С этими товарищами приятно работать, за что я им искренне благодарен.

Вообще, процесс разработки получился весьма интересным как с технологической, так и с методологической точки зрения. Например, наряду с каскадным планированием в процесс органично вплелись элементы eXtreme Programming. Что бы там не говорил Кент Бек (Kent Beck), XP с успехом можно внедрять частично, не загоняя весь процесс в рамки этой концепции.

Руководству, на уровне всего проекта, особенно в самом начале, привычней мыслить  категориями неглубокого каскадного планирования. Это позволяет крупно оценить сроки, размер финансирования и прочие вещи, которые относятся к проекту в целом. В то же время моя команда всегда работает короткими итерациями, постоянно взаимодействуя с руководством и командой разработчиков сервера, каждодневно обсуждая требования к новому функционалу или изменения уже существующего. Это экономит нам массу времени, избавляя от ненужного формализма, характерного для каскадного подхода.

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

Парное программирование мы практикуем не постоянно, а лишь для решения затруднительных ситуаций, в которые может попасть один из разработчиков. Таким образом, мы избегаем продолжительных roadblock-ов т.к. в паре любая проблема решается с феноменальной скоростью, а активный обмен опытом уменьшает риск возникновения проблем в будущем. Помимо того, эта практика поддерживает принцип коллективного владения кодом: работая в разных парах, разработчики знакомятся со всеми частями кода, с упором на проблемные места.

Как я уже говорил, технологическая сторона проекта тоже оказалась очень интересной. Разрабатывать Flash-клиент я решил на основе фреймворка PureMVC MultiCore и совершенно об этом не жалею. Да, PureMVC имеет особенность, которую условно можно посчитать недостатком – работая с ним необходимо писать, на первый взгляд, избыточное количество кода. Грубо говоря, то, что можно прототипировать за пару часов, в базисе PureMVC может раскладываться пару дней. Но это является серьезной проблемой лишь на первый взгляд. Достоинства фреймворка начинаешь понимать, когда требования к функционалу начинают активно изменяться и дополняться. Ты не задумываешься, как правильнее ввести новый функционал или изменить уже имеющийся, сколько кода придется переписать, как удержать в голове все внутренние зависимости кода, как объяснить коллеге, чего ты тут понаписал и т.д. Ты просто программируешь согласно концепции, которую диктует PureMVC и пребываешь в полной уверенности в том, что все будет хорошо.

Поскольку клиентская и серверная части разрабатываются параллельно, иногда возникает ситуация, когда на сервере пока отсутствует интерфейс, необходимый для отладки функционала, который в данный момент разрабатывается на клиенте. В таких ситуациях мы используем mock-объекты на основе пакета ASMock, имитирующие полноценные PureMVC-прокси, которые ведут себя так, словно они взаимодействуют с сервером. Конечно, можно было обойтись без ASMock и написать заглушки вручную, но mock-объекты проще программировать и они располагают к модульному тестированию, необходимость в котором вот-вот назреет.

С точки зрения UI, мы, по большей части, обошлись стандартными компонентами Adobe Flex, изредка вворачивая элементы FlexLib или что-то уж совсем оригинальное. А вот наш дизайнер периодически нас озадачивал. Дело в том, что его фантазия никак не увязана с техническими ограничениями скинирования во Flex. Так что иногда мы использовали пакет Degrafa, а в особо клинических случаях – психологическое давление на дизайнера.

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

среда, 20 мая 2009 г.

Интеграция Adobe Flex и IBM WebSphere Portal

Integrating Adobe Flex and IBM WebSphere Portal - статья под таким названием была недавно опубликована на сайте компании IBM в разделе developerWorks инженерами подразделения IBM China.

Статья представляет собой подробную инструкцию по созданию клиент-серверного приложения на базе Adobe Flex и IBM WebSphere Portal. В ней рассматриваются такие моменты как создание проектов в Adobe Flex Builder и IBM Rational Software Architecture. Особое внимание уделяется процедуре упаковки Flex-приложения, Web-компилятора, пакета BlazeDS и Java-классов удаленного сервиса в один портлет и развертыванию его на сервере приложений IBM WebSphere. Вскользь упоминается возможность сокращения размера конечного WAR-файла за счет использования разделяемых библиотек.

Не вижу смысла разбирать эту статью более подробно. При желании вы можете сами с ней ознакомиться. Материал там подается достаточно доходчиво и сопровождается примерами. Примечательным же, на мой взгляд, является сам факт появления такой статьи на сайте компании IBM. Я склонен рассматривать это как сигнал партнерам и клиентам IBM о том, что Adobe Flex можно и нужно использовать в проектах на базе продуктов семейства IBM WebSphere. Если учесть, что основными потребителями продуктов такого класса в России являются такие гиганты как Центральный банк РФ, ОАО "РЖД", РАО "ЕЭС России", Альфа-банк и подобные им, то можно предположить, что Flash-платформу ждет большое будущее уровня enterprise.

P.S. В августе 2008 года в беседе с Константином Ковалёвым я предположил что-то подобное. Это была всего лишь ироничная шутка, но ирония оказалась глубже.

пятница, 30 января 2009 г.

Очередь асинхронных ShaderJob не работает никак, потому что она не существует.

...По крайней мере, в документации я на сей счет ничего вразумительного не обнаружил, а на вопрос из моей предыдущей заметки не смогли ответить даже на форуме Adobe. Таким образом, я пришел к выводу, что очередь нужно реализовывать самому.

Задача оказалась довольно простой.

Вот пример класса, реализующего очередь:

package ru.dmitrykrasnov.service.shader {
  import flash.display.ShaderJob;
  import flash.events.ShaderEvent;

  public class ShaderJobQueue {
      public static const INSTANCE:ShaderJobQueue = new ShaderJobQueue();

      private var queue:Vector.<ShaderJob>;
      private var inProgress:Boolean;

      public function ShaderJobQueue() {
          if (INSTANCE != null) throw new Error("Сonstructor is locked.");
          queue = new Vector.<ShaderJob>();
      }

      public function addToQueue(shaderJob:ShaderJob):void {
          queue.push(shaderJob);
          if (!inProgress) {
              inProgress = true;
              run();
          }
      }

      private function run():void {
          var shaderJob:ShaderJob = queue.shift();
          shaderJob.addEventListener(ShaderEvent.COMPLETE, shaderJobCompleteHandler);
          shaderJob.start();
      }

      private function shaderJobCompleteHandler(event:ShaderEvent):void {
          event.target.removeEventListener(ShaderEvent.COMPLETE, shaderJobCompleteHandler);
          if (queue.length > 0) {
              run();
          } else {
              inProgress = false;
          }
      }
  }
}

При необходимости, этот класс можно использовать самостоятельно, вставив в свой код строку:

ShaderJobQueue.INSTANCE.addToQueue(shaderJob);

Но это некрасиво. Эстетики ради, можно немного усовершенствовать класс ShaderJob:

package ru.dmitrykrasnov.service.shader {
  import flash.display.Shader;
  import flash.display.ShaderJob;

  public class ShaderJobEnhanced extends ShaderJob{
      private var addedToQueue:Boolean;

      public function ShaderJobEnhanced(shader:Shader = null, target:Object = null, width:int = 0, height:int = 0) {
          super(shader, target, width, height);
      }

      public override function start(waitForCompletion:Boolean = false):void {
          if (waitForCompletion || addedToQueue) {
              super.start(waitForCompletion);
          } else {
              addedToQueue = true;
              ShaderJobQueue.INSTANCE.addToQueue(this);
          }
      }
  }
}

Тогда метод ShaderJobEnhanced.start() будет полностью соответствовать документации метода ShaderJob.start().

Честно говоря, сейчас я даже рад, что Adobe не предоставила готовую реализацию очереди т.к. у нас есть возможность сделать эту реализацию сколь угодно специфичной (например, сейчас мне нужна очередь с динамической сортировкой). Только надо было как-то более адекватно отразить это в документации.

среда, 14 января 2009 г.

Как работает очередь асинхронных ShaderJob?

То ли  я недостаточно сообразителен, то ли документация не совсем соответствует действительности. Вобщем, суть проблемы такова:

В документации по ShaderJob.start() сказано:

Русская версия: "Одновременно может выполняться только одна фоновая операция ShaderJob. Все операции затенения помещаются в очередь и выполняются последовательно. При вызове метода start() во время выполнения операции затенения еще одна операция добавляется в конец очереди. Впоследствии, когда наступает очередь, она выполняется."

Английская версия: "Only one background ShaderJob operation executes at a time. Shader operations are held in a queue until they execute. If you call the start() method while a shader operation is executing, the additional operation is added to the end of the queue. Later, when its turn comes, it executes."

Но в реальности, при запуске нескольких ShaderJob...

shaderJob1.start();
shaderJob2.start();
shaderJob3.start();

...выполняется только shaderJob1 и все. Никакой очереди и последовательного выполнения.

В чем дело? Что может быть не так?

Буду весьма признателен вам за любую помощь.

пятница, 26 декабря 2008 г.

Об именовании Flash-специалистов.

Меня всегда сильно смущало, принятое в нашем сообществе, деление Flash-специалистов на "флешеров" и "флексеров" по странному, на мой взгляд, принципу: если в твоей работе много графики и анимации и немного (технически несложной, но иногда весьма впечатляющей) интерактивности, то ты - "флешер". А если ты создаешь бизнес-приложения, клиент-серверные решения, сервисы и прочие "большие и серьезные вещи", изобилующие сотнями килобайт кода и ветвистыми объектными структурами, то ты - "флексер", и точка.

Когда-то Flash был лишь технологией ограниченно программируемой векторной графики и анимации. Любой работающий с ней человек, спустя короткое время, получал полный и исчерпывающий пакет знаний по этой технологии. Если этот человек обладал, ко всему, еще и способностями художника или дизайнера, то он мог с чистой совестью называть себя Flash-специалистом или попросту "флешером". Он знал о Flash почти все и умел этим пользоваться. Чем не специалист-то? Для того времени - специалист - не вопрос. Но сейчас-то ситуация совсем другая. Flash, сохранив свои прежние возможности, развился до мощной клиентской платформы с полноценным языком программирования, оброс кучей библиотек и фреймворков, а "флешеры" до сих пор владеют лишь технологией ограниченно программируемой векторной графики и анимации. Так может им следует называть себя как-то иначе? Flash-художник/аниматор/дизайнер. И для посторонних людей будет звучать понятно и солидно.

Flex - фреймворк (или технология, как угодно), позволяющий быстро создавать развитый GUI для приложений на базе Flash-платформы. Именно появление Flex позволило всерьез говорить о Flash, как о платформе для бизнес-приложений. И вот, люди, освоившие этот фреймворк, стали называть себя "флексерами". Сделали они это, по всей видимости, для того, чтобы выбиться из массы "флешеров" и заявить о своей "серьезности". Любопытно то, что они продолжают так себя называть даже сейчас, после того как поняли, что Flex - один из многих фреймворков, которые приходится использовать в работе.

На мой взгляд, все это очень глупо. Глупо называть себя по имени платформы, когда не собираешься (и не в состоянии) изучать и использовать все ее возможности. Это, как и "компьютерщик", пахнет дилетантством. Глупо программисту называть себя по имени одного из фреймворков, используемых в повседневной работе. Представте, к примеру, что Java-программисты начнут называть себя "свингерами". Думаю, ряд, весьма забавных и даже пикантных, недоразумений им гарантирован.

Если бы этим заблуждением страдали только новички и дилетанты, это было бы простительно, хотя и опасно. Но ведь и серьезные специалисты (возможно, не осознавая этого) нередко сами несут эту чушь в массы своими высказываниями в блогах, подкастах и форумах. Слова этих людей имеют ощутимый вес, как в сообществе, так и за его пределами. К ним прислушиваются, в том числе и люди, принимающие бизнес-решения т.е. наши потенциальные заказчики и работодатели. Они не склонны к разбору тонкостей терминологии и могут по-разному толковать сложившеюся неоднозначность. Будьте уверенны, в большинстве случаев, толкование будет самым неправильным. Замечу, что для этих людей это не вопрос о том, кто и как называется, это вопрос об имидже и возможностях специалистов, и платформы в целом.

Нужно что-то менять.

понедельник, 9 июня 2008 г.

Очередное обновление технологической демо-версии проекта CYCLOPicture

  • Увеличена скорость обработки панорамы. Прирост составил около 50%.
  • Ликвидирована загрузка процессора во время простоя. Перерисовка теперь происходит только при необходимости.
  • Изменена подсистема динамического сглаживания и перспективной коррекции.
  • Угол зрения (FOV) теперь составляет 90 градусов.

Ознакомиться с технологической демо-версией можно на странице проекта.

понедельник, 26 мая 2008 г.

Обновлена технологическая демо-версия проекта CYCLOPicture

  • На 70% увеличено разрешение панорамы на выходе текстурного преобразователя. По моим данным, это математический максимум того, что можно выжать из текстурного преобразователя без потери качества.
  • Изменен алгоритм интерполяции. Качество панорамы на выходе текстурного преобразователя теперь не уступает оному таких профессиональных продуктов как PTGui Pro и пр.
  • На 30% повышена скорость обработки панорамы.

Ознакомиться с технологической демо-версией можно на странице проекта.

вторник, 13 мая 2008 г.

Старт проекта CYCLOPicture

Простите, я довольно долго ничего здесь не писал. Дело в том, что недавно я озадачился парой идей: Во-первых, мне захотелось создать проигрыватель интерактивных панорам и виртуальных туров, обладающий рядом полезных для потенциального заказчика функций, но отсутствующих в других продуктах этого класса. А во-вторых, я хотел успеть сделать хоть что-нибудь до конца приема работ на Russian Flash Awards.

Создать за месяц готовый коммерческий продукт я, конечно же, не успел, но технологическая демо-версия получилась неплохая, я считаю. Вышел эдакий публичный сервис просмотра эквидистантных панорамных фотографий, размещенных на других ресурсах (например, на сайте Flickr, в группе Equirectangular можно найти обширную коллекцию эквидистантных панорамных фотографий). Впрочем, посмотрите сами.

Теперь бы попасть в каталог Russian Flash Awards и моему счастью не будет предела.

Мысли, посещавшие меня по ходу разработки, а также планы по развитию этого проекта будут опубликованы позже.

понедельник, 18 февраля 2008 г.

Трансформация объекта относительно произвольной точки

Недавно столкнулся с задачей трансформации (масштабирование, поворот или наклон) объекта относительно произвольной точки. Предлагаю к ознакомлению свое решение этой задачи.

package com.dmitrykrasnov.research {
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.geom.Matrix;
    import flash.geom.Point;

    public class TransformationAboutPoint extends Sprite {
        public function TransformationAboutPoint() {

            // Для примера, нарисуем квадрат.
            var myBox : Shape = new Shape();
            myBox.graphics.lineStyle(1, 0x000000);
            myBox.graphics.beginFill(0x000000);
            myBox.graphics.drawRect(16, 16, 32, 32);
            myBox.graphics.endFill();

            // Возьмем его матрицу трансформации и повернем ее на 45 градусов.
            // Заметьте, поворот произойдет относительно начала координат.
            var myMatrix : Matrix = myBox.transform.matrix;
            myMatrix.rotate(Math.PI / 4);

            // Выберем точку вращения (пусть это будет центр нашего квадрата).
            var axisPoint : Point = new Point(32, 32);

            // Выясним, куда она сместилась в результате поворота.
            var newPoint : Point = myMatrix.transformPoint(axisPoint);

            // Вычислим относительное смещение.
            var deltaX : Number = axisPoint.x - newPoint.x;
            var deltaY : Number = axisPoint.y - newPoint.y;

            // Компенсируем относительное смещение.
            myMatrix.translate(deltaX, deltaY);

            // Применим трансформации к нашему квадрату.
            myBox.transform.matrix = myMatrix;

            // Посмотрим на результат.
            addChild(myBox);

            // На всякий случай, нарисуем проверочные направляющие.
            var guideLines : Shape = new Shape();
            guideLines.graphics.lineStyle(1, 0xFF0000);
            guideLines.graphics.moveTo(0, axisPoint.y);
            guideLines.graphics.lineTo(64, axisPoint.y);
            guideLines.graphics.moveTo(axisPoint.x, 0);
            guideLines.graphics.lineTo(axisPoint.x, 64);
            addChild(guideLines);
        }
    }
}

Если кому-то известно более изящное решение, пожалуйста, опишите его в комментариях.

воскресенье, 17 февраля 2008 г.

Впечатления от 3-й встречи RAFPUG

Сегодня я посетил 3-ю встречу RAFPUG, которая проходила в московском офисе Adobe. Так что спешу поделиться впечатлениями от этого мероприятия. Они, скажу сразу, не особо положительные, но уж какие есть.

Началось все с того, что я пришел несколько раньше положенного, спросил, где можно повесить куртку и где у них курят, после чего вышел на улицу, покурить. Через какое-то время следом за мной вышел молодой человек (я сознательно не буду называть его имени, давая ему возможность извиниться) и, обращаясь ко мне на "ты", с нескрываемым удивлением приподняв брови, спросил: "А ты что, тоже программист?" Выяснив, что он разговаривает все-таки с разумной особью, молодой человек оборвал беседу и спешно удалился. Я, конечно, могу его понять, так же как и те люди, которые меня знают, или хотя бы видели, но, по-моему, подобное поведение является как минимум бестактностью граничащей с хамством, и уж точно не свидетельствует о большом уме человека.

Первым в программе встречи был анонс конкурса Russian Flash Awards, в ходе которого был продемонстрирован видеоролик, смонтированный из работ участников конкурса прошлого года. Все бы ничего, только впечатление портило то, что многие работы были вставлены в ролик вместе с окном браузера, в котором они работали. На мой взгляд - это не профессионально.

Далее был катастрофически занудный доклад Александра Козловского в котором он пытался продемонстрировать построение несложного AIR-приложения с использованием Papervision3D. Не знаю, сколько он готовился к этому докладу, но в процессе, то и дело случались какие-то заминки и сбои, что приводило к частым длительным паузам, во время которых скучающая аудитория была вынуждена наблюдать судорожные метания Александра в попытках сделать хоть что-нибудь. Сути и общих принципов в этом докладе было минут на 5, а хоть сколько-нибудь вдохновляющего результата я вообще не увидел, если не считать 3-х тормозных кубиков, которые предлагалось использовать в качестве меню. В общем, во время этого безобразия я постоянно клевал носом, а под конец и вовсе задремал и чуть не упал с кресла. Положение спасал только Артемий Малков (если я не ошибаюсь), который периодически коротко объяснял суть того, что в данный момент происходило или, по крайней мере, должно было происходить.

Вдохновенность Артемия Малкова, который во время "Hands-on" повествовал о layout-ах и binding-ах, могла бы, как минимум, удивить человека, хотя бы раз видевшего Delphi. Ну а я лишь невесело усмехнулся, встал и ушел.