Wednesday, September 30, 2009

Портируемость С#(ложка дегтя)

Продолжение поста .
Портируемость С# достаточно иллюзорна, да есть реализация под linux, но основа любого приложения не язык на котором она написана, а логика работы и интерфейс общения с внешним миром. Вот в это и есть проблемы приложение под C#(десктоп, про ASP судить не могу) пишется обычно с использованием WinForms который является сугубо пропретарным продуктом. В результате мы получаем приложение которое под Mono не только выглядит по другому (выглядит как белая ворона под Linux, не интегрируется не в один диспетчер окон), имеет другую логику работы и другие глюки фичи(частично это вызвано тем что сделать точно также как Microsoft нельзя: закрыты полные спецификации, но и нежелательно, сразу попадаем под область возможных судебных тяжб, реализуем все заново). В общем это не так страшно - но может привести к большому проценту переписанного кода.

Проблемы лицензии при создании приложений на C#.

Сам фреймворк бесплатен для использования в программах, отчислений за его использование как мне известно не нужно. Разрабатывать можно в SharpDevelop с использованием для создания пакетов установки Wix это покрывает 90% потребностей при разработке. Если нужно студия можно использовать Express версию (для которой есть одно существенное отличие - отсутствие пакетов установки) в сумме это дает полное покрытие по средствам разработки.

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

В общем как временное решение использовать можно - но лучше использовать действительно портируемые языки без возможных изменений лицензирования или хотя-бы использовать Gtk# вместо WinForms.

P.S. :
  • Обратите внимание стили окошек под mono отличаются от подразумеваемых в WinForms (BorderStyle), могут быть проблемы с диалогами они появляются под формочками, а так как на панели задач они не отображаются, может казаться, что приложение наглухо зависло.
  • Может и не нужно никакое портирование попробуйте запустить под wine с установленным .Net(у меня не получилось - приложение просто выходило без ошибок , но с большим количеством warn - но попробовать стоит).

Saturday, September 19, 2009

HAL и монтирование устройств

В последнее время у меня при попытке при попытке монтирования устройств пользователем появлялось сообщение:
org.freedesktop.hal.storage.mount-removable no <-- (action, result)
Лечиться исправление файла /etc/PolicyKit/PolicyKit.conf.

Thursday, September 10, 2009

Неоднозначности Google AppEngine

Мелкие несоответствия в документации Google AppEngine
или мелкие, но неприятные особености.

Загрузка файлов.

  • В документации в примере работы с фотографиями указано, что по умолчанию для параметров загрузки файлов выдается их содержимое. В действительности выдается исходное имя файла, поэтому нужно вместо:
     self.request.get('uploadfile') 
    , использовать
     self.request.params.get('cvs').file.read() 

Кодировка строк.

  • Параметры возвращаемые self.request.get() возвращаются в виде unicode строк;
  • В базу данных тоже нужно сохранять unicode строки;
  • При редиректе нужно использовать для строк содержащих символы не входящие в ASCII выражение вида:
    sub_path = self.request.get('path')
    self.redirect('/forum?path=' + cgi.escape(sub_path.encode('utf-8')))
    , то есть перед выполнением редиректа нужно преобразовать в обычную строку.

Особенности базы данных

  • Пока обнаружил только, что желательно добавлять и удалять маленькими порциями. В первом случае можно наткнуться на ограничение во времени (5 секунд) и нагрузке при обработке запроса. В втором случае удалить более 300 объектов за раз нельзя. Цифры примерные - точные цифры получить не пытался, известно только, что за зараз можно добавить 600 объектов и раза в два меньше объектов удалить.
  • Нагрузки на процессорное время при первом получении результатов (не созданы индексы) может достигать на простых операциях вида: получить первые 25 результатов с сортировкой по дате ключу, может занять до 10 абстрактных секунд(30 секунд реальных) при последующих запросах значения падают на порядок.
  • Добавление 600 записей может использовать до 1% процессорного времени выданного для бесплатного аккаунта.
  • База основана на технологии map/reduce, и не поддерживает команды SQL кроме select. Но удобнее, как по мне, использовать нативные методы order, filter, put, fetch.
  • Можно только сравнивать на равенство больше/меньше и включение(in), операции like и под запросы не поддерживаются.
  • Для реализации операций соответствия признаку (или поиск слов, тегов) можно использовать разбиение исходного предложения на минимальные единицы с последующим сохранением этого списка, как отдельного поля в записи (можно в поле записи сохранять список), а потом при поиске использовать вхождение. Конечно, это немного не то, если нужен like, но вполне быстро срабатывает.
  • Включение работает как пересечение, то есть если есть общие элементы, то возвращается истина.
В общей сумме бесплатного аккаунта вполне хватает для маленького тестового сайтика, чтобы поэкспериментировать. В минимальной поставке идет(без дополнительных телодвижений): Django 0.96(используется как шаблонизатор), поддержка базы данных, memcached и библиотека преобразования изображений.

Monday, September 7, 2009

Уникальные идентификаторы для контента

В принципе можно решать как общую задачу создания уникальных идентификаторов:
  • использовать данные генератора случайных чисел (не удобно так как не возможно четко контролировать результат);
  • использовать псевдослучайные значения, например время, процесс/поток с последующим преобразованием в символьное имя;
  • символьное имя очень полезно - так как позволяет лучше при отладке отличать идентификаторы (числа в любом виде хуже отображают отличия);
, а можно учитывать специфику:
  • имена должны поддерживаться файловой системой(запрет на использование спец символов);
  • максимально короткие эффективные имена(снижение затрат памяти), использование всего пространства допустимых символов,
  • близкие по времени создания и исходному значению имена должны быть максимально случайны по результату - то есть использовать максимально эффективный хеш-функцию - обычно достигается использованием хеш значений от псевдослучайных факторов времени создания, процесса/потока и идентификатора хранилища;
  • решение противоречивой в общем-то задачи:
    • максимального разброса имени контента для сохранения;
    • и возможности по имени определить максимально быстро наиболее вероятное хранилище в распределенной системе можно использовать 2 имени - внутреннее и внешнее;
    • внутреннее должно быть максимально эффективно дробить множество доступных вариантов размещения в локальной системе с разбиением на подкатологи с минимальной вероятностью превышения пределов на одновременное количество вложенных каталогов. Это ограничение возникает как из-за временных затрат при работе с большими каталогами, вытекающее иногда в невозможность добавления данных в каталог, и удобства конечного владельца системы, хоть и редко, но удобнее ходить по маленьким каталогам. Также при максимальном разбросе можно разместить часть каталогов на другом разделе и реализовать дешёвое подобие RAID.
    • внешнее - не противоречить правилам для протокола доступа, например не содержать спец символов специфичных для http и html разметки. Позволять легко определить максимально вероятное место расположения в распределенной системе для быстрого выявления не корректно отвечающей части, также при дублировании на другие ресурсы - можно легко удалить данные не специфичные узлу при окончании ресурсов.
Очень желательно, чтобы в внутреннем имени присутствовали хеш функция от размера данных (можно просто выделение остатка от деления на какое-то число с получением base64 + как подкаталог base64 от полного размера) и его контента (для снижение количества коллизий лучше сразу два хеш значения от контента). В результате можно быстро найти подобный контент найдя подобную запись в списке преобразований внутреннее имя <-> внешнее имя или, что должно работать гораздо быстрее при большом количестве разнообразного контента, присутствия такого каталога на диске. В дальнейшем можно проверить его содержимого на совпадение с добавляемыми данными. Как результат мы не будем забивать хранилище дубликатами и при желании сможем сообщать, что пользователь пытается снизить энтропию вселенной.