вторник, 21 декабря 2010 г.

Про Git на пальцах

Очень толковая статья о git на хабре: Про Git на пальцах (для переходящих с SVN)

P.S.: К сожалению, я сам пока не готов переходить на git, а на работе (что еще печальнее) не все толком освоили SVN (и это с TortoiseSVN).

четверг, 16 декабря 2010 г.

Метод прогрессивного джипега

Agile наступает по всем направлениям. Недавно, известный дизайнер Артемий "изобрел" метод прогрессивного джипега.

Адептам должно показаться, что идея в чем-то не новая. =)

пятница, 10 декабря 2010 г.

Инвентаризация

Уматная песня на знакомый мотив. Поют замечательные Pr-Mex!

Новый день к обеду мчится
Полечу в буфет как птица
Полечу как птица я.
Шеф увидит хрен на блюде
Но работать мы не будем
Переиндексация
Подождем ещё немного
Полный пересчет итогов
Переиндексация...

P.S.: Еще много на sysadminday.com.ru

понедельник, 29 ноября 2010 г.

Qt-эпос ч.4 (финал)

В предыдущих сериях: пытаемся собрать проект при помощи Qt так, чтобы он запускался без дополнительных библиотек.
Как вы уже понимаете, у меня все получилось, а вот вам пример: Qt-static-test.zip
Просто окно с пустой панелькой. EXE-шник сжат UPX-ом и должен запускаться у всех.

пятница, 26 ноября 2010 г.

Qt-эпос ч.3.1

Краткое содержание предыдущих серий: пытаемся поставить Qt Creator (и всю начинку), а рядышком поставить Qt и пересобрать его в static.

Успешно собрался отдельный статический Qt для компиляции статических проектов. Так же легко оказалось добавить его в профили компиляции в Qt Creator. Кстати, MinGW  отдельно ставить не надо, Qt успешно использует существующий (путь спросит при установке).

Не удивительно, что простейший EXEшник весит около 8 метров. Там же все графические библиотеки и прочее. По сравнению с тем же .NET это очень мало.

Есть куча способов "обезжирить" проект на Qt и этим, возможно нужно будет заняться.

UPD.: Тот же UPX сжимает файл вдвое на минимальном уровне компрессии. Уже неплохо.

UPD.2: Продолжение...

четверг, 25 ноября 2010 г.

Qt-эпос ч.3

Краткое содержание предыдущих серий: успешно скомпилили Qt в static и теперь пытаемся скомпилить в Qt проект в static.

При попытке скомпилить в новом Qt проект, оно ругается:

/mingw32/bin/ld.exe: cannot find -lQtGuid
Выяснилось, что если qt собран с опцией release, то и проект надо собирать только в release.

В таком случае проект собирается нормально, но при этом при запуске требует libgcc_s_dw2-1.dll
Решение этой проблемы нашлось там же, где и предыдущей:
QMAKE_LFLAGS *= -static-libgcc
Эту опцию можно добавить в файл проекта или в mkspecs/win32-g++/qmake.conf, если вы не хотите добавлять ее в каждый проект.

То-есть пока это почти win, но не совсем, так как исчез режим отладки.

Теперь задача-минимум поставить чистый Qt Creator для девелопмента, отдельно поставить Qt и собрать его в static, а в creator добавить профиль сборки в static, чтобы при необходимости можно было собирать такие проекты.

UPD.: Продолжение...

Qt-эпос ч.2

Краткое содержание предыдущих серий: пытаюсь собрать qt, чтобы тот собирал мне проект в static.

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

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

Сначала я всё удалил, потом это же всё поставил заново. Вторая попытка увенчалась успехом, несмотря на то, что исходные данные были почти такие же, как и в первый раз. Кроме того, что я добавил в path путь к cygwin (он у меня всегда стоит на всякий случай) и добавил путь к папке %path_qt%/bin

Несмотря на то, что отконфигурилось и собралось оно вполне успешно, работать оно от этого не начало.

Вот, сейчас тупо собираю еще раз с теми же условиями. Исходя из принципа "может, со второго раза дойдет". Если не поможет, попробую качать и ставить Qt Creator кусками. Отдельно creator, отдельно qt, отдельно мухи с котлетами.

UPD.: Продолжение...

среда, 24 ноября 2010 г.

Тупик аутсорсинга

Интересная статья опубликована на любимом developers.org.ua под назавнием "Тупик аутсорсинга". В целом, возможно кэп и прав, но с другой стороны... Выводы спорные, настроения упаднические, а количество статей у автора - одна. Ох, что-то тут не так.

вторник, 23 ноября 2010 г.

Qt-эпос

Мои мучения с Visual Studio 2003/2008 привели меня к Qt Creator. Наверное, я еще недостаточно профессионал.

0. Скачать

Скачать эту IDE (и всякую начинку в комплекте) можно на официальном сайте: http://qt.nokia.com/

1. Установить

Ставится оно в один присест, запускается с полпинка и сразу работает и даже компилирует программу с пустым окошком (ну или с кнопочками). Вообщем работает.

2. Использовать

Первая фигня, с которой я столкнулся это сломал полмозга пытаясь добавить кнопочку на панель кнопок (QToolBar). Справка упорно твердила мне, что надо "Tools - ActionEditor". В меню "Инструменты" ничего даже близко похожего не находилось.
Через усиленное битье головой об монитор я его нашел, а сейчас покажу вам:
Дальше дело пошло на лад...

3. Static или mingwm10.dll

После того, как кнопочка была успешно "заборена", мне показалось, что было бы хорошо, если бы скомпилированный exe-файл перестал бы, наконец, требовать mingwm10.dll для запуска.
Это оказалось просто, но были и подводные камни.
Хороший ман о том, как это можно сделать лежит тут: http://www.qtcentre.org/wiki/index.php?title=Building_static_Qt_on_Windows
Но в мане почему-то не сказано, что для того, чтобы утилита configure перестала ругаться:
execute: File or path is not found (mingw32-make)
Cleaning qmake failed, return code -1
Необходимо:
  1. прописать в переменную path путь: %path_qt%\qt\bin\
  2. прописать в path путь: %path_qt%\mingw\bin
где %path_qt% - папка, куда вы поставили Qt

Ну, и к тому же перед сборкой оно пишет, что:
WARNING: Using static linking will disable the use of plugins.
         Make sure you compile ALL needed modules into the library.
Еще не знаю что за плагины оно мне отключило, потому не слишком беспокоюсь.
Собирается оно приличное время, и зачем-то цепляет мои папки "Program Files\Visual Studio". Вот, все еще собирается, посмотрим чем это закончится...

UPD.: Продолжение...

четверг, 18 ноября 2010 г.

О совместимости 1С

Фирма 1С напоминает об условиях совместимости своих продуктов:

В связи с поступающими вопросами об использовании программных продуктов системы "1С:Предприятие 7.7" с новыми версиями операционной системы Microsoft Windows и системы управления базами данных Microsoft SQL Server фирма "1С" считает важным довести до пользователей и партнеров следующую информацию.

Программные продукты системы "1С:Предприятие 7.7" разрабатывались в период с 1999 по 2003 год. Они предназначены для использования со следующими операционными системами:
  • Microsoft Windows 95,
  • Microsoft Windows 98,
  • Microsoft Windows NT 4.0,
  • Microsoft Windows 2000,
  • Microsoft Windows XP,
  • Microsoft Windows Server 2003.
Продукты "1С:Предприятие 7.7 для SQL" поддерживают работу со следующими версиями СУБД Microsoft SQL Server:
  • Microsoft SQL Server 6.5,
  • Microsoft SQL Server 7.0,
  • Microsoft SQL Server 2000.

вторник, 16 ноября 2010 г.

Профессионалы или будни сапорта

Утром с одного из наших филиалов поступил звонок.
- Горячая линия! - привычно отозвался я.
- Мы тут делаем первичную выгрузку через УРБД, скажите, какое должно быть имя файла? - вопрошает меня немолодой женский голос.
- Вы читали страницу посвященную УРБД в нашей базе знаний? - задаю вполне резонный вопрос.
- Нет, я профессионал! - возмущенно. - Я это читать не буду!

Далее следует несколько вопросов (из тех, что описаны на странице в базе знаний) и вежливые ответы с легким сожалением в голосе о том, что что профессионалы не читают документаций.

Вечер, телефон красный, я - само спокойствие. Достойный потомок BOTH.

- Горячая линия.
- Я тут не поняла почему у меня в номере файла один ноль? Должно же быть три? Или не должно? - вопрошает все тот же профессионал.
- У нас принято ставить автонумерацию файлов выгрузки, а вы не поставили. - тяжело вздыхаю в трубку. - Об этом тоже сказано в базе знаний.
- Я так и поняла, что вам ответить тяжело было! - с чувством гордости за свою понятливость отвечает профессионал и кладет трубку.

Профессионалы - они такие профессионалы.

А вам такие встречались?

понедельник, 8 ноября 2010 г.

Пол Локхард. Плач математика

Музыкант просыпается от кошмарного сна. Во сне он видел, будто музыкальное образование стало обязательным. «Мы помогаем ученикам вступить в этот заполненный звуками мир», — преподаватели, школьная система и государство принялись за этот жизненно важный проект. Проводятся исследования, образуются комиссии, принимаются решения… И все это без единого совета музыканта или композитора!

Дальше тут: http://nbspace.ru/math/

О математике, о преподавании и о том, почему люди становятся математиками вопреки школьному образованию.

Universe fairless

Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning.

(c)ibor

понедельник, 1 ноября 2010 г.

Ричард Фейнман

Одна из самых замечательных книг, которые я прочел за последнее время это книга "Вы, конечно, шутите, мистер Фейнман!"
А, вот, сегодня узнал, что есть видеозаписи с Ричардом Фейнманом.

пятница, 29 октября 2010 г.

MySQL: История о том, как достичь 750,000 запросов в секунду

Прочел интересную статью под названием "Использование MySQL как NoSQL — История о том, как достичь 750,000 запросов в секунду".

Насколько я понял, основной принцип увеличения быстродействия, это обращение к движку InnoDB, напрямую, в обход SQL-слоя. Автор способа (Yoshinori Matsunobu) рекомендует для частых запросов использовать именно такой способ, поскольку при его использовании экономится время, на разбор SQL-запроса, открытие/закрытие таблиц и т.д. При этом для больших и сложный запросов, которые выполняются редко, остается по-прежнему доступным обращение через обычный SQL.

среда, 27 октября 2010 г.

Где в сети хранить бэкапы

Недавно товарищ посоветовал мне интересный сервис: "Dropbox". Зарегистрировавшись, вы получаете бесплатных 2Gb свободного места и утилиту для синхронизации локальной папки с данными в сети. Причем к вашему аккаунту может быть подключено несколько компьютеров и меняя файлы на одном, утилита синхронизации сначала отправит их на сервер, а откуда они утилитой другого компьютера будут перетянуты на него.
Так вы можете не заморачиваясь использовать одни и те же файлы на работе и дома, например.

Из плюсов можно отметить бесплатность (вообще, там есть и платные тарифные планы, где места больше), простоту установки и использования, стабильность работы. Хочется отдельно сказать о простоте использования - установил и все работает. Не надо ничего нажимать или настраивать.
Так же приятно, что продуман механизм разрешения коллизий. Если файл менялся в двух местах, то при синхронизации будут сохранены обе версии их которых вы сможете выбрать нужную (так же как, например в svn).

Есть и некоторые недостатки. Если меняется большой файл, то он будет отправлен на сервер целиком, а не только та часть, которая поменялась. На медленных каналах это может быть проблемой. В этом смысле разработчикам хорошо было бы поучиться у того же svn или rsync Папка, которая синхронизируется с сетью может быть всего одна. Конечно, было бы лучше, если бы в утилите можно было указать список папок для синхронизации. А так все важное сначала приходится руками собирать в одном месте. Каких-то еще недостатков я не заметил.

Лично у себя я настроил бэкапы следующим образом. На одной машине у меня есть двухгектарный TrueCrypt-овский диск, который я раз в сутки размонтирую, бью на куски по два метра и закидываю в папку dropbox-а. Таким образом я решаю проблему синхронизации больших файлов, каждый раз синхронизируются только те куски, которые поменялись, а это далеко не все 2Gb.
Для контроля на другой, совершенно посторонней машине, я так же поставил синхронизацию с моим dropbox и раз в сутки пытаюсь собрать из двухметровых кусков один двухгиговый файл. Если сборка проходит удачно (проерка по хэшу), я отправляю себе на мыло отчет и делаю копию удачно собранного файла. Если неудачно только отчет. Получается достаточно надежно.

Вообщем, если вам нужно место в сети, где вы могли бы хранить свои данные, добро пожаловать в dropbox: http://www.dropbox.com/

P.S.: Там же есть реферальная программа и если регистрироваться по приглашению, то оба участника получают дополнительных 250Мб. Так, что если хотите, регистрируйтесь по моей ссылке: http://www.dropbox.com/referrals/NTEyNzQ5MDg0OQ

вторник, 26 октября 2010 г.

Рейтинг компаний

Администрация сообщества developers.org.ua, наконец-то опубликовала итоги рейтинга компаний 2010.

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

Среди небольших компаний подозрительно часто упоминается Initto.

GlobalLogic занимает достаточно скромные позиции, зато в нескольких городах. Ну, мы знаем о многих эффектах глобализации и стандартизации, в том числе и о неприятных.

Кто победил, говорить не буду - пойдите и посмотрите сами.

понедельник, 18 октября 2010 г.

Условия и запросы

При составлении запросов часто бывает так, что нужно вставить условие отбора в запрос в зависимости от того, пустое значение отбора или оно заполнено.

Например, нужно получить список всех товаров по складу, но если в качестве склада передано пустое значение, то необходимо получить список товаров по всем складам (т.е. склад не выбран).

Как правило в таких случаях модифицируют текст запроса "на лету" примерно таким образом:
Запрос.Текст =
"ВЫБРАТЬ
|   Учет.Товар,
|   Учет.Количество
|ИЗ
|   Документ.Учет КАК Учет
|"
+ ?(ЗначениеЗаполнено(Склад),"ГДЕ Учет.Склад.Ссылка = &Склад","");

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

Однако, единственный ли это способ достичь желаемого, сделать так, чтобы склад не учитывался в отборе, если он не заполнен? Не единственный! Если немного пораскинуть мозгами очень просто перенести условную конструкцию внутрь самого запроса, например вот так:
Запрос.Текст =
"ВЫБРАТЬ
|   Учет.Товар,
|   Учет.Количество
|ИЗ
|   Документ.Учет КАК Учет
|ГДЕ
|   (&Склад = ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка)
|           ИЛИ Учет.Склад.Ссылка = &Склад)"
;

Никакого волшебства, всего-лишь банальное использование оператора "ИЛИ". Если склад не заполнен то и все выражение всегда будет истинным, а значит в выборку попадут все склады.

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

Что же с производительностью? Действительно, производительность в таком случае немного падает. Я сделал небольшую конфигурацию, чтобы сделать замеры. Желающие могут скачать ее и попробовать померить производительность самостоятельно (1C 8.2.10.77).

Исходные данные: 20 документов, 7 товаров, 3 склада, ~10000 вызовов запроса (5000 с пустым и 5000 с заполненным складом).

Запрос в котором условие подставляется в текст средствами языка 1С:


Как видите, 10002 запроса (строка 15) выполняется за 8,2 секунды.

А вот, результаты выполнения запроса с внесенным внутрь условием:

Результат (59-я строка) выполнения - 11,4 секунды.

То-есть 3,2 секунды на ~10000 запросов. Можно было бы провести замеры с вложенными запросами и соединениями или с другими объемами данных, но в целом понятно что для простых случаев потеря производительности несущественная. К тому же запросы-монстры не часто вызываются по 10000 раз за один раз.

Какой из способов использовать, конечно, решать вам.
А я хочу пожелать вам хорошего дня и хорошего кода.

Спасибо за внимание.

P.S.: Статья получила множество отзывов и уважаемое сообщество насоветовало еще кучу способов борьбы с условиями.

Уважаемый alexk-is советует использовать построитель отчета:
ПостроительОтчета.Текст ="ВЫБРАТЬ
|   Учет.Товар,
|   Учет.Количество
|ИЗ
|   Документ.Учет КАК Учет
|{ГДЕ
|   Учет.Склад.*}"
;ПостроительОтчета.ПолучитьЗапрос().Выполнить();
Yashazz ставит комментарии, выполняет поиск и замену в тексте запроса перед выполнением, но сокрушается, что конструктор режет комментарии:
ТекстЗапроса =
"ВЫБРАТЬ
|   Учет.Товар,
|   Учет.Количество
|ИЗ
|   Документ.Учет КАК Учет
|ГДЕ
|Склад = &УсловныйСклад
|//УсловиеНаТовар//"
;
...
СтрЗаменить(ТекстЗапроса,"//УсловиеНаТовар//","И Товар = &УсловныйТовар");
Зато Alias прекрасно развивает идею и советует делать так:
Запрос.Текст =
"ВЫБРАТЬ
| Учет.Товар,
| Учет.Количество
|ИЗ
| Документ.Учет КАК Учет
|ГДЕ
| &УсловиеСклада"
;

Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеСклада",?(ЗначениеЗаполнено(ВыбСклад),"Учет.Склад.Ссылка = &Склад","Истина"));
Без сомнения в способе куча плюсов - и конструктор не режет ничего и запрос читается нормально и тормозов нет.
4ish использует выбор:
Запрос.Текст =
"ВЫБРАТЬ
| Учет.Товар,
| Учет.Количество
|ИЗ
| Документ.Учет КАК Учет
|ГДЕ
|ВЫБОР
|   КОГДА &Склад <> ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка)
|       ТОГДА ПоступлениеТоваровУслугТовары.Ссылка.Склад = &Склад
|   ИНАЧЕ ИСТИНА
|КОНЕЦ"
;
Тоже хороший способ.
А Vit aka proger изящно применяет "в иерархии":
Запрос.Текст =
"ВЫБРАТЬ
| Учет.Товар,
| Учет.Количество
|ИЗ
| Документ.Учет КАК Учет
|ГДЕ
| Учет.Склад в иерархии( &Склад))"
;
Всем спасибо за замечательные подсказки, я обязательно возьму кое-что себе на вооружение.
Ну, и, конечно обсуждение еще продолжается.

Публикация на Инфостарт

воскресенье, 17 октября 2010 г.

Резонанс

Недавно пришло письмо от одного из участников developers.org.ua смысл которого сводился к тому, что некий аноним оставил негативный отзыв об одной девелоперской компании, который администрация сайта удалила по просьбе упоминаемой компании.

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

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

Конечно, все это лишь мои личные рассуждения, но мне кажется, что открытость в данном случае (да, как и во многих других) это единственный путь выйти с достоинством из этой неприятной ситуации.

P.S.: По результатам переписки с develpoers понятно, что администрация в принципе готова отвечать на вопросы и разъяснять неразъясненное. Могу посоветовать всем заинтересованным лицам писать письма, приезжать в офисы, звонить и задавать вопросы. И на вопросы будут ответы.

четверг, 7 октября 2010 г.

Суперпозиция котов.

Шрёдингер ходил по комнате в поисках нагадившего котёнка, а тот сидел в коробке ни жив ни мертв.

понедельник, 4 октября 2010 г.

Cочинение 7-летнего Тараса

Кем я хочу стать когда буду большим

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

Думаю, что они должны уметь читать тоже, что бы знать в чем дело, когда все напереполох.

Программисты должны быть смелыми, что бы не пугаться, когда все перепуталось так что никто не разберет, или если придется разговаривать на английском языке по-иностранному, что бы знать, что надо делать.

У программистов должно быть хорошее зрение, что бы видеть сквозь одежду и что бы не бояться секретарш, потому что с ними приходиться работать.

Еще мне нравитса зарплата, которую программисты получают.
Они получают столько денег, что не успевают их все тратить.
Это происходит потому, что все считают работу программиста трудной, кроме программистов, которые знают, как это просто.

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

Надеюсь, что у меня нет аллергии на офисную пыль, потому что на нашу собаку у меня аллергия.

Eсли у меня будет аллергия на офисную пыль, программиста из меня не получится и придется искать настоящую работу.

Оригинал тут.

P.S.: Все так и есть, все так и есть!!!

Авто-фокус

Об интересной системе управления собственным списком задач пишет Алексей Рубцов.
Встречайте - Авто-фокус.

среда, 29 сентября 2010 г.

Мензоберранзан. Отчет скрам-мастера.

Начало
Среди мастеров ролевых игр, так же как и среди разработчиков, бывает так, что появляются проблемы коммуникации внутри команды. Но, если у разработчиков есть тот самый волшебный scrum, то для мастерских команд пока нет каких-то универсальных рецептов-фреймверков.
И вот, совсем недавно благодаря уважаемой Юлии Владимировне, у меня появилась возможность попробовать одну из техник методологии scrum на ролевом проекте Мензоберранзан – технику «daily scrum» или, как ее еще называют «мастерские планерки».

Адаптация
Для начала была сделана адаптация ко временным рамкам. Если у разработчиков итерация длится 2-3 недели, то тут срок всего проекта 4-5 дней. Логически было удобно представить, что один день это одна итерация. В итерацию изначально мы решили включить 4 планерки (последняя совмещенная с ретроспективой). Так же пришлось немного изменить последний из трех вопросов («Что мешает?») на «Хоз.вопросы». Это было нужно, так как мастера по-сути высший «решающий орган» на полигоне и если откинуть ответ «мешают игроки», то останется только влияние окружающей среды, погода и хоз.часть.
Так же отдельно было оговорено проведение «медленной» части планерки, что для девелоперов, как правило, очевидно.
Подробности можно посмотреть в полном scrum-манифесте для этого проекта, который был опубликован в самом начале, как основной документ.

Практика
Для начала несколько слов о технике.

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

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

В целом же, как мне кажется, практика прошла вполне успешно, было несколько моментов дискоммуникации, которые решились благодаря планеркам (например, про количество золота в игре), но не обошлось и без «багов».

Баги
Одной из самых серьезных проблем в отношении планерок было то, что мастера люди, а не роботы. :)

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

2. Некоторые мастера недостаточно ответственно относились к своей очереди выступления и в свой рассказ включали только общие фразы вроде «делал все то же самое, буду делать это же». Зато вставляли множество дополнений в рассказы других мастеров с комментарием «о, я забыл что…»
Это тоже пагубно отражалось на времени, кроме того имело еще один серьезный побочный эффект. Тот, кто чаще всего говорил «о, я забыл что» посреди чужого рассказа в итоге сам не слышал остальных, так как был сосредоточен не на том, что говорит другой, а на том, что ему нужно добавить.

3. И третье это, наверное, не бага мастеров, но тоже важный момент. Очень мало внимания уделялось второму вопросу «Что будет?» (или «Что буду делать?»). Понятно, что игра развивается непредсказуемо и у многих, например, у мастера боевки, не может быть особых планов, если неизвестно будут ли вообще боевые эпизоды. Поэтому этот пункт планерки нужно обсудить. Если он не нужен, возможно, исключим его или преобразуем в нечто полезное.

Спасибо!
И, конечно, я хотел бы поблагодарить всю мастерскую группу за понимание и сотрудничество.
Мне кажется, что для первого раза (использования планерок) результат – выше среднего.
Давайте шлифовать, общаться и вместе достигать поставленных целей.

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

Я обязательно напишу о том, что из этого получится, следите за обновлениями.

понедельник, 27 сентября 2010 г.

В спину капитану (культпросвет)


Кстати, такое поведение, когда выражение вычисляется только в том случае, когда результат его вычисления необходим для дальнейших расчетов называется "Ленивые вычисления".
Пишут, что Haskell весьма хорош в них.

Программист или убийца?

Забавный тест (хоть и баян) на тему "кто-кого видит издалека".



Спасибо Александру за ссылку.

четверг, 23 сентября 2010 г.

Эскалационные письма

Недавно послушал увлекательный вебинар "Составление эскалационных писем" (Luxoft, Дудкина Анна).
До вебинара я понятия не имел что это такое - эскалационное письмо. А яндекс с википедией предательски молчали.
Теперь же, я с полной ответственностью могу рассказать что:

Эскалационное письмо это такое письмо, в котором ты эскалируешь руководству какую-то проблему, которую невозможно решить на твоем уровне. По нашему - кляуза.

понедельник, 20 сентября 2010 г.

Вебкамера на орбите

Митч пишет, что на МКС установили веб-камеру.
Посмотреть на землю в режиме реального времени можно по ссылке:
mms://a1709.l1856953708.c18569.g.lm.akamaistream.net/D/1709/18569/v0001/reflector:53708
Этот адрес нужно задать любому плееру, поддерживающему потоковое вещание. Лично я воспользовался способом "Пуск - Выполнить" и вставил ссылку в строку команды. Медиа-плеер распознал и открыл ссылку.

Так же интересно было почитать блог космонавта, который он писал прямо с орбиты.

пятница, 17 сентября 2010 г.

IE9

biz.liga.net сообщает, что "15 сентября 2010 года корпорация "Microsoft" во время мероприятия в Сан-Франциско представила публичную бету своего браузера "Internet Explorer 9". В Украине презентация состоялась на день позже и...
Чтобы участники киевского события смогли проникнуться духом нового продукта, собственно, рассказ о новых качествах браузера предварял небольшой перформанс: сама презентация проходила в галерее, а для большей наглядности свойства IE9 демонстрировались не только в рабочем режиме на экране, но и "в танце".

А так как сами представители microsoft утверждают, что...
"Internet Explorer 9" в 11 раз быстрее, чем предыдущая, восьмая версия.
То по логике вещей девушка, демонстрирующая ИЕ9 должна была танцевать в 11 раз быстрее...

Да.

А девушка изображающая ИЕ6 - лежать и под музыку дергаться в конвульсиях.

среда, 15 сентября 2010 г.

IT-Jam 2010

В эти выходные успешно прошел и закончился IT-Jam 2010.
Событие большое во всех смыслах. Большое по количеству участников (~1200 участников), по значимости для развития IT в Украине и для меня лично.

Все было очень замечательно и я рад что был на таком отличном мероприятии. Очень понравилась Business Value Game (Тим прекрасен, да), были хорошие доклады и отличная IT Jam Music Session.

Ну, и на закуску обо мне. Кажется, что мне пора иначе воспринимать подобные мероприятия и вливаться в "формат". Некоторое время назад такие конференции и base-camp'ы были более "домашними" и более "локальными". Наполненными атмосферой некоторого уюта. Сейчас же на каждой все больше и больше людей, докладчиков и все меньше и меньше времени. Теперь нужно быть еще более активным, быстрее ориентироваться в бурлящей среде докладов и, как ни жаль, еще более избирательным в темах докладов. Потому что никак не получается объять необъятное. Хотя и хочется.

Ссылки на разные отчеты есть на официальном сайте.
А вот кадр с Business Value Game:
 Наша команда знакомится с заказчиками на карточках.

вторник, 14 сентября 2010 г.

CEE SECR 2010

Очень хочу поехать на CEE SECR 2010. Послушать Бьярна Страуструпа и Стива Тодда.

Здесь и сейчас

Мария Евграшина знакомит нас с концепцией "Здесь и теперь" в блоге tim.com.ua.
 Мне нравится этот настрой, как и любые идеи, возвращающие в реальность.

понедельник, 13 сентября 2010 г.

вторник, 7 сентября 2010 г.

Почти по Орлову

На своих замечательных выступлениях Александр Орлов любит повторять, что:
"...это куда интереснее и сложнее шахмат. Вот, представьте себе - играете, а тут у вас конь демотивировался..."

Чувствую себя примерно так же - демотивированный конь.

четверг, 2 сентября 2010 г.

DrupalCamp'2009

Друпал такой друпал!
Obrygan's community в полном составе:

четверг, 26 августа 2010 г.

Условия и переменные (заметки Кэпа)

Решил я как-то проверить каким образом вычисляются составные условия в 1С 8.1
Не думаю, что профи найдут для себя в этой статье нечто новое или интересное, но Капитан Очевидность продолжает вещать.
Первое, что пришлось проверить - не инициализированные переменные:

На код вроде:
    А = 1;

    Если (
А=1) и (Б=1) Тогда
       
Сообщить("Ок!");
    КонецЕсли;

Выругался сам "компилятор" при попытке сохранить обработку. Логично, так как переменная Б нигде не определена. Но, если обмануть синтаксический контроль следующим образом:
    А = 1;

    Если
0=1 Тогда  // заведомо ложное условие
       
Б=1;        // никогда не выполняющийся код
   
КонецЕсли;

    Если (
А=1) и (Б=1) Тогда
       
Сообщить("Ок!");
    КонецЕсли;

В этом случае при сохранении ошибки синтаксиса не будет, а при запуске надписи "Ок!" не появляется. По логике следования кода мы нигде не определяли переменную Б, но код успешно выполняется.
Что говорит нам отладчик?
Обратите внимание, что в самом начале, когда ни одна переменная еще не определена память под них уже зарезервирована и им назначен тип "Неопределено", в отличии от переменной В, которая вообще не упоминается в процедуре.
Сделаем пару шагов:

Теперь все очевидно. Условие совершенно корректно и дает на выходе ложь, так как единица не равна "Неопределено" и вообще разных типов.

Итак, предварительный вывод:
Под переменные, которые могут быть инициализированы, внутри своей области видимости память выделяется в самом начале и они неявно инициализируются типом "Неопределено".

Чисто теоретически следующий код мог бы работать:
    А = 1;

    Если (
А=1) и (Б=1) Тогда
       
Сообщить("Ок!");
    КонецЕсли;

    Если
0=1 Тогда
       
Б=1;
    КонецЕсли;

Но нет. Не проходит синтаксический контроль, что вообщем-то правильно.

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

Однако, неявная инициализация это не совсем то, что я собирался выяснить с самого начала и я вернулся к условиям.

Следующий код работает как положено и выдает правильный результат:
    Товар = Справочники.Номенклатура.НайтиПоКоду("00000026");

    Если  (
ТипЗнч(Товар) <> Тип("Неопределено")) и (Товар.Наименование = "Тест") Тогда
       
Сообщить("Ок!");
    КонецЕсли;

В описании функции "НайтиПоКоду" написано, что:
Если не существует ни одного элемента с требуемым кодом, то будет возвращена пустая ссылка.
Если код не задан, то будет возвращено Неопределено.
Если честно, я не смог сразу добиться от функции возврата значения "Неопределено" и потому поступил проще:
    //Товар = Справочники.Номенклатура.НайтиПоКоду("00000026");
   
Товар = Неопределено;

    Если  (
ТипЗнч(Товар) <> Тип("Неопределено")) и (Товар.Наименование = "Тест") Тогда
       
Сообщить("Ок!");
    КонецЕсли;

Запускаем - бинго! Все работает, несмотря на то, что в составном условии есть обращение к реквизиту переменной "Товар", к "Наименованию", которого у типа "Неопределено" быть не может.
Для проверки попробуем еще два вида условия:
1.
    Если  (ТипЗнч(Товар) <> Тип("Неопределено")) или (Товар.Наименование = "Тест") Тогда
2.
    Если (Товар.Наименование = "Тест") и (ТипЗнч(Товар) <> Тип("Неопределено")) Тогда

В первом случае мы поменяли "и" на "или" в условии, во-втором поменяли местами части условия.

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

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

В первом случае, когда мы заменили "и" на "или" необходимость проверять все выражение возникла снова так как в определении "или" говорится, что истинным должен быть "хотя бы один" из операндов. Но пытаясь вычислить второй операнд мы сталкивались с ошибкой о которой я писал выше.

Во-втором варианте, результат выполнения так же изменился, несмотря на то, что операция "и" коммутативная. Теперь проверка начинала выполняться с первого, заведомо провального операнда.

Такое поведение, на мой взгляд оправдано и удобно. Сравните, например с похожим кодом в платформе 7.7:
    //Товар = СоздатьОбъект("Справочник.Номенклатура");
    //Товар.НайтиПоКоду(" 52200");
   
Товар = ПолучитьПустоеЗначение();

    Если (ПустоеЗначение(
Товар) = 0) и (Товар.Наименование = "Тест") Тогда
        Сообщить(
"Ок!");
    КонецЕсли;

В отличии от 8.1 он не будет работать, так как проверяются все операнды операции "и", а второй у нас будет выдавать ошибку.
 

Для платформы 7.7 пришлось бы применить следующее:
    Если (ПустоеЗначение(Товар) = 0) Тогда
        Если (
Товар.Наименование = "Тест") Тогда
            Сообщить(
"Ок!");
        КонецЕсли;
    КонецЕсли;

Что на мой взгляд является неоправданным (хоть и небольшим) усложнением структуры кода.

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

Спасибо за внимание и хорошего вам кода!

среда, 18 августа 2010 г.

Сила слова

На секлабе очередная статья про ужасного хакера подозреваемого во взломе банка. Статья уныла, но каменты жгут:

Гость: гик 17.08.2010 10:00:06

Уж сколько раз твердили миру, что если подразумевается негативный смысл, то надо говорить "кракер" или "крекер", или "крэкер".

Как всегда всё опошлили, на этот благородное слово "хакер", теперь все думают, что "хакер" - это плохо.
Гость: 23404 17.08.2010 11:31:47
если подразумевается негативный смысл, то нужно говорить: "кракен".

вторник, 17 августа 2010 г.

it-jam 2010

Очередной IT-Jam, на этот раз в Харькове.

среда, 4 августа 2010 г.

Сам я считаю, что дефектом многих существующих учебников по технологиям программирования (это относится не только к COM, но и вообще к любой технологии излагаемой в современных учебниках) является то, что они начинаются "сверху" - "вызовите Wizard, отметьте в нём... поставьте... Wizard сгенерировал вам код...". Но в учебнике очень невнятно объясняется, почему Wizard сгенерировал именно такой код! Что означают те или иные макросы по ходу текста, как выглядит и сам протокол к которому Wizard строит реализацию. Словом, современные учебники пытаются обучить сложению используя в качестве наглядного пособия калькулятор - а как калькулятор выполняет сложение учебник не объясняет. С моей точки зрения это - тяжелейший порок, поскольку квалификация программиста определяется прежде всего пониманием философии, основ, концепций. Писать реально работающие программы, конечно, нужно с применением соответствующих инструментов. Писать вручную - анахронизм, часто выдающий дремучесть программиста. Но и владея распрекрасным инструментом всё равно нужно знать, как работает механизм, потому, что в какой-то момент времени может обнаружиться ошибка в самом инструменте, произойти несчастливое стечение обстоятельств и параметров, а тогда программист должен суметь, пользуясь своим общим знанием, отыскать то самое место, в котором возникает ошибка и исправить её.
(с) Михаил Безверхов, "Технология COM"

понедельник, 26 июля 2010 г.

1С 8.2: Отключить сортировку в динамическом списке

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

Номенклатура:
Тапки10 грн.
Сапоги83 грн.
Мокасины2000 грн.

Тут и без заголовков очевидно какая колонка что означает.

Еще можно применить трикс и сделать элемент списка, который при вашей сортировке всегда будет вверху, а в его реквизиты записать название колонок, но имейте ввиду, что это все-равно, что чесать левое ухо левой рукой через жопу. Используйте возможности платформы по назначению и будет вам счастье!

воскресенье, 25 июля 2010 г.

Обработка проверки заполнения константы. Контекст превыше всего!

Сегодня речь пойдет о "модуле менеджера значения" у объекта "константа". Зачем нужен этот модуль и как его применять? Конечно, в нем можно описать произвольную экспортную процедуру или функцию и вызывать ее из любого места вашей конфигурации, получив предварительно модуль менеджера значения вашей константы. Вызов может выглядеть, например, так:

Константы.<ИмяВашейКонстанты>.СоздатьМенеджерЗначения().<ИмяВашейПроцедуры>();

Но это не главное свойство этого модуля. Его самая приятная особенность в том, что в нем могуть быть описаны такие события, как:
  • ОбработкаПроверкиЗаполнения
  • ПриЗаписи
  • ПередЗаписью
(синтакс-помощник, раздел "Прикладные объекты/Константы/КонстантаМенеджерЗначения.<ИмяКонстанты>/События")

Рассмотрим событие "ОбработкаПроверкиЗаполнения". Это очень хорошее событие, чтобы убедиться в том, что константа заполнена правильно. Синтакс-помощник сообщает нам об этом событии следующее:
Вызывается расширением формы при необходимости проверки заполнения реквизитов при записи в форме, а также при выполнении метода ПроверитьЗаполнение.
Позволяет разработчику конфигурации самостоятельно реализовать проверку заполнения в обработчике события. При этом в обработчике можно полностью отказаться от системной обработки (очистив список проверяемых реквизитов), отказаться от проверки системой части реквизитов (выполнив проверку отдельных реквизитов особенным образом и исключив эти реквизиты из списка), а также добавить для проверки другие реквизиты, проверка которых не была указана.
И декларирует, что на вход функции-события передается два параметра:  <Отказ> и <ПроверяемыеРеквизиты>.
Не слишком понятное описание (как на мой взгляд) запутывающее смысл вот этим "список проверяемых реквизитов". О каком списке идет речь, если у нас одна константа? Непонятно. Очевидно, что раздел просто дублирует описание аналогичного события модуля объекта справочника, где список действительно имеется.
Однако, не будем отвлекаться. Как же проверить значение и где его (это самое значение) взять? (Если честно, я несколько поломал над этим голову, и мне кажется, что момент не вполне очевидный для начинающих). Параметром оно не передается, объекта как бы и нет...
И тут необходимо применить один из основных способов, заложенных в саму парадигму платформы 8.2:
Нужно понять в каком именно контексте вызывается событие.
Синтакс-помощник говорит нам, что событие вызывается в контексте этого самого объекта "КонстантаМенеджерЗначения.<Имя константы>", а значит, можно предположить, что свойства и методы объекта будут доступны. И действительно, следующий код прекрасно работает:

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)

   
Сообщить(Значение);

КонецПроцедуры

Сообщает нам значение, которое было установлено в константу, но еще не было записано в базу (для случая, когда проверка вызывается автоматически перед записью).
Этот же контекст используется для событий "ПередЗаписью" и "ПриЗаписи".

Теперь вы можете добавить свой обработчик, который поможет проверить верно ли заполнено значение константы. Я, например, таким образом реализовал проверку на возможность изменения базовой валюты, которую нельзя менять, если в регистрах денег уже есть движения, а так же запретил константе "ВалютаПоУмолчанию" быть пустой.

Так же следует помнить, что событие "ОбработкаПроверкиЗаполнения" вызывается автоматически только при интерактивном изменении константы на форме констант. Для контроля программного изменения лучше использовать событие "ПередЗаписью", которое вызывается в обоих случаях.

Спасибо за внимание и хорошего вам кода!

среда, 21 июля 2010 г.

Assembla vs GitHub

Перевез свой rlinkf с GitHub на assembla.com
Намного удобнее и функциональнее.

вторник, 20 июля 2010 г.

Софт за 24 часа

Зарегистрировался на флешмобном сумасшествии "Софт за 24 часа". Интересно, что из этого всего получится?

воскресенье, 18 июля 2010 г.

Quick sort

Сегодня разминки ради скрипел мозгами над quick sort.

Накнопал вот такой прекрасный код:
#include <iostream>
#include <stack>

using namespace std;

void showM(int M[], int l, int r)
{
 for(int i = l; i <= r; i++) cout << M[i] << " ";
 cout << endl;
}

int main ()
{

 const int size = 8;
 int M[size] = {1,5,2,4,5,3,2,0};

 stack<int> st;

 int ret_flag = 0; int t;

 int s = 0, e = size-1;

 showM(M, 0, size-1);

func:
 int l = s, r = e;
 
 int G = M[l];

m3:
 while (M[l]<G) l++;
 while (M[r]>G) r--;

 if (l>r) goto m4;
 t=M[l]; M[l]=M[r];M[r]=t;
 l++;r--;
 goto m3;
m4:
 if(l<=r) goto m5;
 if(M[r]<=M[l]) goto m5;
 t=M[l]; M[l]=M[r]; M[r]=t;
m5:

 if(l-s <= 1) goto m1;
 st.push(s); st.push(e); st.push(l); st.push(ret_flag);
 ret_flag = 2;
 e = l-1;
 goto func;
ret2:
 ret_flag=st.top();st.pop();l=st.top();st.pop();e=st.top();st.pop();s=st.top();st.pop();

m1:
 if(e-l < 1) goto m2;

 st.push(s); st.push(e); st.push(l); st.push(ret_flag);
 ret_flag = 1;
 s = l;
 goto func;
ret1:
 ret_flag=st.top();st.pop();l=st.top();st.pop();e=st.top();st.pop();s=st.top();st.pop();
m2:

 if(ret_flag==1) goto ret1;
 if(ret_flag==2) goto ret2;

 showM(M, 0, size-1);

 return 0;
}

Поразительно, как раньше люди писали программы, когда языки не поддерживали красивую структурную вложенность? Я сломал себе половину мозга, пока реализовал это несложный алгоритм.
Отдельной проблемой было представить как правильно реализовать рекурсию без такой структуры, как "функция". Пришлось писать "болванку" с переходами для того, чтобы представить себе как рекурсивная функция должна вызываться из двух мест собственного тела.
Естественно, столкнулся с проблемой "кочующей переменной", когда значение переменной приходит из другой части кода, а не должно (забыл положить в стек L).
Опять-таки непонятно как вообще можно написать что-то существенное на языке, который не поддерживает действительноДлинныеИменаПеременных.
Вы спросите, для чего же было терпеть все эти мучения и ужас? Дело в том, что мне нужно реализовать это на ассемблере. Думаю, что такой код теперь не сложно будет перевести.

Визуализаторы базовых алгоритмов

Хотите посмотреть как мне удалось обойти самого графа?
Смотрите подробное описание каждого шага с картинками!

Там ещё много забавного и увлекательного.

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

Конференция "Коктейль для менеджера"

Александр Орлов и Макс Дорофеев в одном флаконе.
Любопытно, что же будет?

Подробности на http://www.dev-labs.ru/

четверг, 15 июля 2010 г.

вторник, 13 июля 2010 г.

github

Все-таки GitHub отстой. Реагирует на комиты как-то странно, путает отображение проектов. Захожу в один проект, а там исходники от другого. А где же теперь исходники от первого?
Ухожу с github.

понедельник, 5 июля 2010 г.

Мифический человеко-месяц

Забавно читать книги по IT написанные 35 лет назад. Многое изменилось на противополженое.

Например, о выпуске релизов:
Леман и Белади дают свидетельства в пользу того, что квант изменений должен быть либо очень большим и редким, либо очень маленьким и частым. (Lehman M., Belady L. Programming system dynamics, oct.1971) Последняя стратегия, согласно их модели, больше подвержена неустойчивости. Мой опыт это подтверждает: я никогда не рискну использовать ее на практике.

Или о диаграммах ПЕРТ:
Подготовка диаграммы ПЕРТ есть самая ценная часть ее применения. ... Первая диаграмма всегда ужасна, и для создания второй приходится проявить много изобретательности.

В последнем удивительно еще и то, что сам Брукс говорит о том, что такие диаграммы полезны. Но читать это можно очень по-разному.

среда, 30 июня 2010 г.

Опять Manufactoria!

Никак не могу пройти один уровень в manufactoria. Грызу, как Рональдо мяч.

Я вернулся!

И вот, после небольшого перерыва я снова с вами!

Поделюсь вкратце тем, что было. Во-первых я до-сих пор под впечатлением от AgileBaseCamp. Один из самых прекрасных докладчиков (из тех, на которых я попал, разумеется) это Александр Орлов, рулевой проекта Happy-PM и вообще мегамоск.

Вот он, в оранжевой футболке:



На доклад Тимофея Евграшина я не пошел специально, потому что предполагал попасть на его замечательный мастер-класс и перекинувшись парой слов "в кулуарах" утвердился в своем решении. Забегая вперед хочу сказать, что этот мастер-класс стал логическим завершением AgileBaseCamp.
Уже есть фотоотчет с мастер-класса, вот некоторые фото:

Мой шеф включается в работу:

Играем в спринт и планирование. Звучат страшные слова velocity и capacity:

Тим получил кружку QAClub:

И общее фото:




И еще одно фото, которого нет в альбоме. Оказалось, что мы возвращаемся с Тимофеем одним поездом.
Вокзал:

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

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

Горы и магометы

Поскольку намерение сменить место работы, с целью получения опыта по работе в команде работающей по Scrum, было признано не оптимальным, Scrum сам придет к нам в организацию.
Руководство воспринимает инициативу благосклонно, подготовка ведется, надеюсь все получится.

P.S.: В любом случае, даже если мы придем к magile это будет существенное упорядочивание процесса.

среда, 2 июня 2010 г.

Серия статей "jQuery для начинающих"

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

вторник, 1 июня 2010 г.

Manufactoria

Отличная игра для тренировки мозга - Manufactoria.
Машина тьюринга 4ever!!!

вторник, 25 мая 2010 г.

Снова статические методы классов в 1С

Я совершенно напрасно переживал по поводу статических методов классов, которых мне (и не только мне) так не хватает. В версии 1С 8.2 у объектов метаданных есть "Модуль менеджера" и функции описанные в нем фактически и являются статическими методами классов. Во всяком случае их можно так использовать.
Те, кто все понял, дальше могут не читать, с остальными давайте разберемся подробнее.

Я сделал небольшой пример. База с тремя справочниками: "Номенклатура", "КатегорииЦен" и "Цены". Номенклатура хранит список товаров, справочник "КатегрииЦен" - просто классификатор категорий, а справочник "Цены" подчинен номенклатуре и имеет два реквизита: "Категория" и "Цена" (Число). Таким образом в нем хранится цена для конкретного товара и конкретной категории. Достаточно стандартная ситуация. (Конечно, это можно организовать и регистром сведений или еще как-нибудь, но для примера я взял справочник. Просто так.)

Скачать базу можно тут: StaticMethods.zip

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

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

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

Однако, всегда хочется лучшего. Например, есть функции, которые относятся исключительно к какому-либо справочнику или документу, но нужны во всей конфигурации. Можно завести общий модуль по имени справочника, но не хотелось бы. Или можно было бы положить такие в модуль объекта. Но без объекта нельзя обратиться к модулю, а не всегда хочется тянуть целый объект из базы, когда достаточно ссылки (или ссылка вообще не нужна). Т.е. с одной стороны функции нужна привязка к "классу" объектов, а с другой, конкретный объект для работы функции не требуется. В ООП такая функция обязательно стала бы статическим методом класса, а в 1С 8.2 ее можно положить в "Модуль менеджера".
Обратите внимание на то, как я вызываю функцию "ПолучитьЦену" в обработке "УстановитьЦены":

НоваяСтрока.Цена = Справочники.Номенклатура.ПолучитьЦену(ТекущийТовар, Выборка.Ссылка);  
Через менеджер справочника. Мне не нужен лишний общий модуль или какие-то другие ухищрения.
Конечно, если говорить конкретно о функции "ПолучитьЦену", то вы могли бы поместить ее и в модуль менеджера справочники "Цены" или даже в "КатегорииЦен" или еще как-нибудь. Все зависит от того как вы строите архитектуру вашего приложения и какие используете соглашения при разработке. Но в любом случае возможность создать "статический метод класса" у вас есть. Что на мой взгляд - прекрасно.

Спасибо за внимание и хорошего вам кода.

Публикация на Infostart.

Статические методы класса

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

Сильнее чем мне их нехватает, наверное, только Гению1С из найденного топика на Мисте.

воскресенье, 23 мая 2010 г.

Школа программиста

По совету Александа зарегистрировался на сайте Школа программиста (ссылка на профиль есть в разделе "Ссылки"). Решать задачи и правда очень увлекательно, и теперь когда выпадает свободная минутка я обязательно захожу туда.

понедельник, 17 мая 2010 г.

ITSea

Оказывается, есть такое событие, как ITSea.
Судя по сайту, еще очень молодое, но как мне кажется, очень  интересное. И где еще можно настолько удачно совмещать приятное с полезным?
Буду следить за обновлениями.

среда, 12 мая 2010 г.

Tron

Фильм Tron (1982) входит в число фильмов, которые обязательны для просмотра настоящим программистом/админом/IT-шником.
В частности, вот что пишет о нем Википедия:
«Трон» — первый в истории кинематографа фильм, основные персонажи которого были полностью (вернее, почти полностью) нарисованы на компьютере. В фильме содержится около 30 минут чистой графики, где живые герои совмещены с нарисованными. Однако некоторые спецэффекты все же создавались по старинке — методом ротоскопирования и ручной раскраски каждого кадра (действие «внутри компьютера» снималось на черно-белую пленку). Кроме того, впервые в истории кинематографа в художественном фильме была продемонстрирована компьютерная анимация лица, хотя и в значительной степени упрощённая.
От себя же могу добавить, что фильм, несмотря на свой наивный сюжет и "устаревшие" эффекты, на самом деле несет в себе частичку прошлого. Взгляд на (it-) жизнь тех времен. И лично я каждый раз поражаюсь насколько великими были наши (it-) предки. Какую нужно было иметь фантазию, какое стремление к новому и неизведанному, чтобы "увидеть" за черно-белыми текстовыми терминалами целый мир. (Фильм-то снимался в 1982-м, тогда даже VGA еще не изобрели, а "графика" была роскошью для пользователей). Все эти "мотоциклы", "танки", "программы"... Все это чудовищно прекрасно.
Культовый фильм.

И, кстати, в декабре 2010-го должно выйти продолжение: TRON Legacy. Конечно, там будут современные спецэффекты. Но будет ли там романтика? Будет ли там Дух?
В любом случае стоит посмотреть.

вторник, 11 мая 2010 г.

gui для git

Недавно я начал пытаться использовать git вместо моего любимого SVN. Поскольку разбираться с командной строкой мне не хотелось, я попытался найти хороший gui. Для централизованной SVN я пользуюсь хорошим клиентом TortoiseSVN, но TortoiseGIT с первого взгляда мне не понравился. Слишком не очевидный интерфейс, который, к тому же, встроен в explorer.
Попытки совладать с gui, который идет в комплекте с самим git (gitk) ни к каким к результатам не привели. Возможно, о того, что мне хотелось чтобы клиент был portable или из-за своей общей "неудобоваримости", стандартный клиент git делал все что угодно, кроме того, что мне нужно и постоянно сообщал об ошибках и неудачах, сбрасывал настройки и вел себя отвратительно.
В какой-то момент мне стало казаться, что все-таки придется курить маны по командной строке git.
Но нашел еще одно интересное gui-решение: SmartGit
Оно бесплатное для некоммерческого использования и на первый взгляд простое и понятное. Для работы требует установленного git, есть portable-версия (жужлите) и какая-то встроенная интеграция с GitHub, правда, пока не совсем понятно в чем ее смысл, если внешние репозитории все-равно нужно руками прописывать в файле .gitconfig
В целом софтина производит впечатление приятное, посмотрим что будет дальше.

понедельник, 10 мая 2010 г.

Рутина

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

воскресенье, 9 мая 2010 г.

Вебинар: "Что такое тестирование?"

Учебный центр Luxoft проведет вебинар на тему "Что такое тестирование?". Поскольку тестирование это важная часть разработки, то всем рекомендую.
Зарегистрироваться можно на сайте учебного центра.

суббота, 8 мая 2010 г.

Как менять типовую конфигурацию 1С без потери совместимости

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

Предположим, что существует некая "типовая конфигурация". Для наглядности я сделал небольшую конфигурацию с двумя справочниками ("Товары" и "Контрагенты"), тремя документами ("Приход", "Расход", "Оплата") и тремя регистрами ("ОстаткиТоваров", "Продажи" и "Взаиморасчеты"). Принцип работы абсолютно прозрачный: фирма (наша) приходует и расходует товары, количество которых фиксируется в регистре "ОстаткиТоваров" (остаточный регистр), при "Расходе" делается движение в регистре "Продажи" на сумму расхода (регистр оборотный, измерения: контрагент, товар), а так же приход и расход двигают остаточный регистр "Взаиморасчеты" ("Приход" в минус, "Расход" в плюс), который так же двигает документ "Оплата" (в минус или в плюс выбирается перечислением "ВидыДвиженияДенег").
Еще в конфигурации есть три отчета (каждый по своему регистру) и все это объединено в подсистему "Основная" (для удобства фильтрации).

Скачать выгрузку демо-базы можно тут: begining.dt

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

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

Какой же выход? Выход есть - подписка на события. Это прекрасная технология, появившаяся в 8-й платформе, очень нам поможет.

Итак, добавим измерение "ргРегион" типа "Справочник.ргРегионы" в регистр "Продажи". Это не сильно нам помешает при обновлении, так как обычно регистры меняются редко и даже если и меняются, то нужно просто следить за тем, чтобы наше измерение не исчезло.

Дальше есть два немного различающихся варианта реализации. Рассмотрим первый, который я назвал "Копирование документа".

Добавим в систему документ "ргРасход". Добавим в него такой же набор реквизитов, как в документе "Расход" и сделаем необходимую форму. Так же добавим в него реквизит "Регион" и разместим его на форме.

А теперь скопируем весь модуль проведения из документа "Расход" в "ргРасход". Шутка! =) Сделай мы так и все потеряло бы смысл. Нам все равно пришлось бы вносить множество изменений в "ргРасход" при обновлении. Мы пойдем другим путем.

Добавим в конфигурацию регистр сведений "ргСвязиДокументов" с двумя измерениями: "ДокументВладелец" и "Документ". Оба измерения - типа "ДокументСсылка". Пусть он у нас будет непериодический и подчиненный регистратору. В качестве регистратора укажите пока документ "ргРасход". Так же добавьте общий модуль с названием "ргРегионы" и сделайте его серверным. Пригодится.

Обработка проведения документа "ргРасход" должна делать вот что:
  1. Создавать новый документ "Расход" и заполнять его так же, как и текущий "ргРасход" (кроме реквизита "Регион" и реквизита "Номер", естественно)
  2. Добавлять запись в регистр "ргСвязиДокументов", где в "ДокументВладелец" записывать ссылку на текущий документ "ргРасход", а в измерение "Документ" ссылку на вновь созданный документ "Расход". Важно, что тут нужно сразу записать движение в регистр, а не ждать конца процедуры обработки проведения.
  3. Проводить вновь созданный документ "Расход".

При отмене проведения документа "ргРасход" пусть происходят следующие действия:
  1. Из регистра "ргСвязиДокументов" выбираются запросом все документы "Расход", которые относятся к нашему документу "ргРасход"
  2. Найденные документы удаляются. (На самом деле тут должно быть не удаление, а пометка на удаление для сохранения ссылочной целостности, но не будем усложнять пример).
Таким образом, мы получили следующую картину: при проведении документа "ргРасход" на самом деле создается документ "Расход", который делает движения в нужных регистрах, а при отмене проведения документа "ргРасход" документ "Расход" удаляется.

Остался последний штрих - добавление нужных нам дополнительных измерений в регистр при проведении документа "Расход".

Добавим подписку на событие с именем "ргПроведение". Объект - документ "Расход", событие - "ОбработкаПроведения" и обработчик из нашего общего модуля "ргРегионы".

Функция-обработчик события должна выглядеть так:

Процедура ргПроведениеОбработкаПроведения(Источник, Отказ, РежимПроведения) Экспорт
 ТекстЗапроса=
 "ВЫБРАТЬ
 | ргСвязиДокументов.ДокументВладелец,
 | ргСвязиДокументов.Документ
 |ИЗ
 | РегистрСведений.ргСвязиДокументов КАК ргСвязиДокументов
 |ГДЕ
 | ргСвязиДокументов.Документ = &ПроводимыйДокумент"
 ;
 Запрос=Новый Запрос(ТекстЗапроса);
 Запрос.УстановитьПараметр("ПроводимыйДокумент",Источник.Ссылка);
 
 Рез=Запрос.Выполнить();
 Если Рез=Неопределено Тогда
  Сообщить("Не выполнен запрос!");
  Отказ=Истина; Возврат;
 КонецЕсли;
 Если не Рез.Пустой() Тогда
  ДокументВладелец=Рез.Выгрузить()[0].ДокументВладелец;
  
  Если ТипЗнч(Источник)=Тип("ДокументОбъект.Расход") Тогда
   Источник.Движения.Продажи[0].ргРегион=ДокументВладелец.Регион;
  КонецЕсли; 
  
 КонецЕсли;  
КонецПроцедуры

В ней мы ищем проводимый документ в регистре "ргСвязиДокументов" и если находим (запрос не пустой и т.д.), то в движения этого документа добавляем "Регион" из документа "владельца", т.е. из того документа, который создал проводящийся сейчас документ "Расход". Так же тут добавлено небольшое условие проверки типа, которое нужно, если это событие будет вызываться для документов разных типов (мало ли куда еще понадобится вставить регион).

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

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

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

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

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

Посмотреть что получилось можно в файле final-1.dt

Есть другой способ, лишенный перечисленных выше недостатков. Я называю его "Документ-обертка".

Его суть заключается в том, что в документе "ргРасход" мы не дублируем документ "Расход". Документ "ргРасход" содержит в себе только реквизит "Регион" и ссылку на документ "Расход". На самой форме документа нужно сделать кнопку "Создать "Расход" по нажатию на которою создавался бы новый документ "Расход" ссылка на который хранилась бы в реквизите документа "ргРасход" и добавлялась бы запись в регистр сведений "ргСвязиДокументов". В остальном логика работы остается прежней, кроме того, что проверка на изменение документа "Расход" не нужна и в модуле проведения документа "ргРасход" не нужны никакие действия.

Итак, вкратце. У нас есть документ-обертка "ргРасход" из которого мы открываем тот документ, который должен быть дополнен нашей аналитикой. Значения наших измерений заполняется в документе-обертке, остальное заполняется в оригинальном документе, который работает как обычно: проводится, редактируется, удаляется и т.д.

Этот способ лишен недостатков способа "Копирование документа", однако у него есть другой недостаток. Пользователю придется выполнять лишнее действие по открытию документа-обертки.

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

Посмотреть что получилось можно в файле final-2.dt

Конечно, все эти ухищрения будут приводить к потере производительности, но как известно за все надо платить.

Спасибо за внимание и хорошего вам кода.


Эта статья на Infostart