Alexey's profileLife vs. ProgrammingPhotosBlogListsMore Tools Help

Blog


    June 05

    Остановка

    Уважаемые (судя по статистике кто-то тут еще остался), данный блог больше поддерживаться не будет. Совсем. Даже в режиме зеркала.
    Приглашаю всех по адресу http://alexey.raga.name
    Спасибо за внимание :)
    May 31

    Команда, просто команда.

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

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

    Задача стара как мир, но каких только способов решения ее не увидишь... Сегодня, например, я даже столкнулся с таким совершенно экзотическим способом: разработчик наследовался от кнопки для того, чтобы определить ее поведение. То есть у него были такие наследники, как, скажем, SettingsButton, DeleteButton и т.д. Экземпляры этих кнопок создавались и передавались контролу, который их внутри себя размещал.

    Сначала я не знал, смеяться мне или плакать, но потом решил, что, поскольку создавшего это я не знаю, то все же посмеюсь. Заодно и напишу о том, как эту задачу правильно решать. Ничего нового я не скажу и те, кто при слове "Команда" уже все поняли, дальше могут не читать.

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

    public abstract class CommandBase
    {
       
    public abstract string Title { get; set; }
       
    public abstract void Execute();
    }


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

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

    private void RegisterButton(CommandBase command)
    {
       
    //Создадим пользовательский элемент, в данном случае - кнопку
       
    Button btn = new Button();
        btn.Text = command.Title;

        //при нажатии на кнопку запускается команда
       
    btn.Click += delegate(object sender, EventArgs e) { command.Execute(); };

        //добавим кнопку на панель кнопок
       
    _buttonsPanel.Controls.Add(btn);
    }

    А потом просто использовать этот метод там, где мы "наполняем" пользовательский интерфейс:

    MyProfileCommand

    profileCmd = new MyProfileCommand(currentUser);
    Navigator.RegisterButton(profileCmd);
    MainMenu.RegisterMenu(profileCmd);

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

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

    May 26

    Новый ноутбук: выбор сделан.

    Dell Inspiron 9400  Несколько месяцев я размышлял о том, когда и какой ноутбук покупать.

    Дело в том, что после того, как у меня потрескались корпуса у КПК Acer N30 и ноутбука Acer 5021, связываться с Acer'ом больше не хотелось.

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

    В конце концов выбор пал на Dell Inspiron 9400 со следующими параметрами:

    CPU: Core2 Duo 2.00GHz
    Display: 17" широкоформатный, 1920х1200
    HDD: 160GB
    RAM: 2GB (667)
    Video: ATI Mob. Radeon x1400 256MB
    WiFi: версия спецификации "n", на будущее, не люблю провода
    BlueTooth: встроенный

    Все драйверы ко всем устройствам уже были установлены с дистрибутивом Висты и работают прекрасно.

    Из полезного софта было установлено Windows Vista Home Premium, Roxio DVD Studio, Dell MediaDirect.
    Из бесполезного софта было снесено: Corel PhotoPaint Trial, McCafe AntiVirus, Google Desktop, Google Toolbar.

    Весь софт, который был нужен, установился и работает без проблем: Nikon Capture NX, Ulead VideoStudio 11, Abby Lingvo 12 и т.д.

    В общем, покупкой я доволен.

    Вот еще, меня спрашивают, насколько это удобно - такое разрешение на 17-дюймовой матрице. На мой взгляд - очень даже удобно. По своим характеристикам (чекткость, яркость) эта матрица превосходит матрицы ноутов HP и Acer'а, которые у нас есть. И, хотя на том же Acer'е матрица очень даже неплохая, разница ощутима, когда ставишь ноуты рядом.
    Кроме того, фотографии, обработанные на том же Acer'е, выглядят на Dell'e как-то насыщенней и, что хочется отметить, четче. Иногда даже создается впечатление несколько излишнеей четкости, быть может с непривычки.

    Что же касается работы.. Час назад установил на ноут Visual Studio "Orcas" Beta1. Просто супер - я могу открыть все нужные мне панели и при этом остается еще полно места для написания кода. Очень здорово.

    Остается только поблагодарить Dell за их работу: заказ делали по телефону, просили изменить конфигурацию (матрица, процессор, память и т.д) а так же, самое главное, англоязычный софт и QWERTY-клавиатуру (местные используют AZERTY).
    Заказ был принят за 10 минут, оплачен банковским переводом и за 4 дня доставлен UPSом прямо домой.

    За все это с меня содрали 1564 евро, цена для ноута такой конфигурации очень даже ничего.

    Счастливого ему "плавания" ;)

    May 20

    Smart Client Software Factory - May Release

    Буду краток.

    Майский релиз SCSF. Поддержка WPF, CAB, улучшенный гайдлайн и т.д.

    Брать можно здесь: http://www.codeplex.com/smartclient

     

    May 07

    Электронные платежи: российская действительность.

    Я вот решил проапгрейдить Лингво до 12-й версии. А еще есть такой магазин - СофтКей.
    Вообще, они, вроде, хорошие ребята. Хотя бы потому, что другого способа не заказывать коробку почтой, а просто скачать интересующий меня продукт я не нашел. А нашел СофтКей.

    Поэтому пошел в этот СофтКей, сказал ему, что хочу Лингво, а платить буду карточкой Visa.
    Все прошло хорошо, платеж прошел мгновенно, я получил СМС о том, что деньги с меня сняли и два письма от СофтКея.

    К сожалению, ключа внутри не оказалось, равно как и ссылки, откуда можно скачать купленное.
    Подождал. Ссылки нет. Почитал письма, залогинился, смотрю статус заказа. Смотрю, значит, а там написано, что заказ не оплачен.
    Странно, думаю. Деньги-то сняли. Обычно после этого сразу прилетает "спасибо, дорогой клиент" и ссылки, и ключи, и бонус-паки.. Чай не в первый раз.
    А тут - тишина.

    Полез читать про оплату. Вроде все должно быть ОК.
    Полез читать FAQ. А там и написано:

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

    Ужас какой. Вообще-то я с ними разговаривать не хотел. Я ввел свой номер карты, я ввел CCV. Я хотел продукт, а говорить по телефону, да еще и в международном роуминге не хотел совершенно.

    И как быть, если я немой?! Что, немым, получается, никак нельзя купить продукт?

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

    Вот такая она, российская действительность. У кого только тут покупал - не видел такого...

    May 06

    День рождения Королевы Беатрикс

    Оранжевые мамы
    Оранжевым ребятам
    Оранжевые песни
    Оранжево поют 

    День рождения Королевы отмечается в Нидерландах 30-го апреля не смотря на то, что родилась королева Беатрикс где-то в середине лета. Объясняется это тем, что день рождения предыдущей королевы, матери нынешней, был именно 30-го апреля. В этот же день она отреклась от престола и ее место заняла Беатрикс. Вот так, королевы меняются, а праздник решили не переносить. Какая разница, на самом деле, что праздновать - коронацию или день рождения? Да и вообще, совместить можно.

    В этот день по всем крупным городам Нидерландов с утра устраиваются народные гуляния, ярмарки и распродажи. Любой человек может выйти на улицу и что-нибудь продать, при этом он не обязан платить налогов. Магазины тоже могут торговать в "безналоговом" режиме, правда, практически все они в праздник закрыты. Но на тех немногих, что все же работают, можно обнаружить объявления: "Сегодня в течение всего дня скидка 25%".

    Мы приехали в Амстердам утром, часов около 11, и город был уже полон. Нам сразу же выдали какие-то (оранжевые) рюкзачки, кстати, идея очень полезная - кто-то складывал туда мусор, кто-то - приобретенные на ярмарке вещи..

    Нет спроса... Еще раз доказал всем, что похож на немца Гуляем тут все...

    Народ стекался в столицу до самого вечера - по улице от вокзала в центр шел сплошной (оранжевый) поток в течение всего дня.

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

    На канале Посторонись!

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

    1. После того, как вы с друзьями "уговорили" бутылочку чего-нибудь, положите ее на пол и попробуйте поднять с помощью нехитрого приспособления: палка, к ней привязана веревка, на конце которой пластмассовое кольцо диаметром 10-15 сантиметров. Идея в том, чтобы держась за палку "зацепить" горлышко кольцом и привести лежащую бутылку в вертикальное положение.
    2. Ваши друзья никогда не хотели забросать Вас яйцами в прямом смысле этого слова? Предоставьте им эту возможность! Чтобы мне долго не описывать, а вам - не вникать, приведу фото:

      Где-то шагах в 10 от обстреливаемого находится "огневой рубеж", который представляет из себя стол с коробками яиц. Попадают редко. Но попадают.

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

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

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

    Но это будет уже другая поездка, в другое время и с другими целями...

     Ночь и половину следующего дня до отъезда мы провели в Гааге - в городе, где находится королевский дворец и где живет сама виновница торжества - Королева Беатрикс.

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

    Королевский дворец. Штандард поднят - королева дома.Пляж Гааги. 
    Я вверх по лестнице пошел - и человека там нашел. Его там не было вчера, как я хочу, чтоб он ушел...Скульптура Гааги: Посадили монстра на кол, оторвали монстру все, что смогли...
    May 04

    Первомайские выходные: Франция.

    На прошлые выходные выпало покататься по близлежащим странам. Соответственно, два дня мы катались по Франции, поставив себе целью посетить столько замков, сколько успеем (успели три) и оставшиеся два дня провели в Нидерландах, празднуя день рождения королевы Беатрикс и гуляя по Гааге.

    Для начала расскажу поездке во французские замках, коих мы, как я уже сказал, посетили три: Фонтенбло, Блуа и Амбуаз. Замки эти оказались настолько разными, что я даже подумал, что вот бы объединить достоинства трех в одном.

    Фонтенбло, огромный старый замок времен Филипа Первого, удивил заброшенностью и пустынностью своей территории. Но при этом его "содержимое" оказалось просто сплошным произведением искусства. Несколько снимков:

    Коридор в замке Фонтенбло Комната в замке Фонтенбло
    Потолки и стены - они такие Залы Фонтенбло Комната в замке Фонтенбло

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

    Внутренний двор замка Блуа Обновленный замок Блуа
    Убийство герцога Гиза Спальня, в которой умерла Екатерина Медичи

    Амбуаз тоже отличился в истории. Здесь была поставлена точка в первой войне между гугенотами и католиками - заключен амбуазский мир. Здесь же прятался король Франсиск Второй во времена заговора гугенотов, которым надоело преследование. Гугеноты хотели избавиться от фанатичных Гизов и, если удастся, убрать Франсиска Второго от власти и передать эту самую власть Бурбонам. Но замок там крепкий, высокий, так что нападение было отбито, а головы нападающих украсили ворота и стены замка...
    А еще над этим замком трудился Леонардо ДаВинчи, который завещал похоронить себя там, что и было выполнено.
    Нам же этот замок понравился своей опрятной и красивой территорией :)

    "Парадный вход" в замок Амбуаз. Индус. Я сначала думал, что он медитирует под деревом. А он играл с PocketPC...
    Памятник Леонардо ДаВинчи.

    Кроме замков в те дни мы успели погулять по Орлеану (Жанну д'Арк помните?) и поразмышлять о тех скудных клочках огромной и, как теперь начинаем понимать, очень интересной истории, которые остались в наших головах..

    Лично я пришел к выводу, что вся путанница в истории тех веков - из-за Генрихов. Уж очень много их было и в Англии и во Франции, и королей и герцогов :)
    Да и наша "российская действительность" путаницы добавляет. Мы-то их всех знаем как Генрихов, поди разберись где кто. Почему было не называть французских Генрихов так, как называют их французы (Анри), а английских так, как называют их англичане (Генри)?!
    Было бы все понятно. Анри Третий. Генри Четвертый. Сразу ясно, кто откуда и из какого периода. А то... :)

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

    April 25

    Люксембург

    Нужно будет вернуться. Интересный город в плане выйти-погулять.

    К тому же я так и не узнал доподлинно, как же звучит люксембургский язык :)

    Несколько фотографий здесь: http://picasaweb.google.be/alexey.raga/Luxembourg

    April 20

    Identification

    19626561.d1fa5f484d857eb8134c36667de3fad7.1177098222.79bd302d9b18628104b38b515dbba682
    April 18

    Keukenhof - тюльпановый рай

    В прошлые выходные съездили в Keukenhof, это городок в Нидерландах, в 45 километрах от Амстердама.

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

    Фоторезультаты этого гуляния можно пронаблюдать здесь: http://picasaweb.google.be/alexey.raga/Keukenhof

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

    April 16

    О "Начальниках Камчатки" или в продолжение разговора...

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

    Руководитель проекта - это не "начальник программистов". 
    На самом деле существуют три независимые "ветки одного дерева" - ПиЭмы, Разработчики и Тестеры. Независимые. Точно так же, как тестеры не подчиняются программерам и программеры не подчиняются тестерам, точно так же ПиЭмы не находятся в подчинении программеров\тестеров и программеры\тестеры не находятся в подчинении ПиЭмов. Вместо подчинения они все друг с другом сотрудничают.

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

    На самом деле ситуация становится гораздо продуктивнее, когда все три "ветви власти" работают в штатном режиме, каждый в своей зоне ответственности:

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

    То, насколько именно тестировщиком (и всей командой) понята концепция этой самой "реальной работы" - вот одна из задач ПиЭма.

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

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

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

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

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

    void OnCustomerFeedback(Requirement req)
    {
        int daysToComplete = AskDevelopersForTimeline(req);
        daysToComplete = daysToComplete * 2;
        SendToCustomer(String.Format("We need {0} days", daysToComplete));
        bool finished = false;
        while (!finished)
        {
            Delay(Random());
            finished = KickDevelopers("How is it going?");
        }
    .....
    }

    делать неправильно ;) К сожалению, это очень часто встречается...

    April 14

    Редактирование видео: Выбор сделан.

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

    Некоторое время я "ковырялся" в бесплатном софте типа VirtualDub, MediaCoder и т.д, но понял, что это не для меня.

    Ни один из встреченных мною бесплатных продуктов не умел делать работу полностью - от захвата видеоизображения и до получения результата. Так, например, VDub умеет делать захват, кое-какой процессинг, но в нем совершенно невозможно делать даже самый простенький (многого мне не нужно) монтаж... Кроме того, мне не удалось заставить его, например, кодировать результат с помощью кодеков из Windows Media SDK 11.

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

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

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

    Выбирал из трех вариантов бюджетных продуктов:

    1. Pinnacle Studio
    2. Ulead VideoStudio Plus
    3. Sony Vegas Studio

    Первым "отпал" Пинакл по причине своей капризности, нестабильности и требовательности. Ну и интерфейс там странный, но это уже придирки :)

    В борьбе Юлида и Сони Вегаса победил Юлид. Он продемонстрировал бОльшее количество "фич", кроме того, к нему есть патч, созданный специально для "понимания" моей камеры.
    К тому же очень понравилась технология SmartProxy, при которой для работы в редакторе (предпросмотра и т.д.) в фоновом режиме создается "уменьшенная" копия видеопотока (разрешение можно задать самому). Благодаря этому редактор работает быстрее, так как для предпросмотра в окошечке и на таймлайне ему не приходится обрабатывать для меня весь HDV-поток.

    После оплаты (благодаря PayPal это заняло пару минут) я получил не только сам VideoStusio Plus но и еще всякие пакеты с бонусами и дополнительными возможностями (типа Cool3D). То есть, вместо 2-х инсталляционных файлов мне предоставили аж 9 оных, приятно :)

    Пойду сносить триалы, устанавливать все это дело и, наконец, обрабатывать видео с того же Мон-Сан-Мишеля и Парижа :)

    April 12

    DSL & Software Factofies: V3

    Я уже писал о том, что такое DSL и Software Factories, как выражается второе через первое и т.д.

    Теперь вы можете увидеть это своими глазами на примере Services Software Factory V3.
    Причем, именно увидеть: здесь разработчики выложили видео (рекомендую скачать, всего 11 мегабайт, но виднее) о том, как будет работать следующая версия их фабрики.

    Отличия в частности в том, что в данном случае мы будем иметь "классический" DSL вместо обычного для фабрик набора указаний "сделай то-то".

    Лично мне этот вариант кажется более логичным, гибким и удобным.

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

    April 10

    Поездка в Нормандию - Mont Saint Michel

    Как я уже писал, в прошлые выходные съездили во Францию, в Нормандию, в совершенно замечательное место - Mont Saint Michel.

    Что это такое лучше всего видно на фотографии:
    Mont Saint Michel Не перевелись еще поломники-пешеходы...

    Это монастырь, построенный на острове, на скале высотой около 80 метров. Примечательно то, что монастырь этот был построен потому, что этого настоятельно требовал архангел Михаил. Именно настоятельно, так как ему пришлось при этом трижды сниться епископу Альберту и убеждать его в необходимости сей постройки. Сам же епископ вовсе не горел желанием что-либо строить в такой "дыре" и полагал, что его сны есть не более, чем ночные видения. И тогда Архангелу Михаилу пришлось действовать более радикально: приснившись епископу в очередной раз он нажал пальцем на лоб спящему, да не просто нажал, а сделал там нехилую вмятину размером с монету. Череп епископа с этой самой вмятиной, кстати, хранится в музее и его можно увидеть.
    Естественно, после этого бедному Альберту пришлось идти и строить.. А то кто знает, на что он там в следующий раз нажмет...
    Словом, строили много лет и построили. Сегодня высота башни, с которой смотрит архангел Михаил, около 150 метров.

    Представьте, как это было: практическии полная изоляция, два раза в сутки прилив-отлив, вода прибывает и убывает со скоростью около 20 км/ч, во время отлива море уходит километров на 15-20 от стен монастыря. Самая большая в Европе высота прилива - 9 метров - именно здесь.

    Ну и где?! Где море, я вас спрашиваю?!   Ушло море. Далеко. (Вид со среднего уровня монастыря) 

    Значительно позже строится дорога, соединяющая Mont Saint Michel с "большой землей", а до того поломники (а это одно из мест поломничества) добираются (те, которым везет) до цели во время отливов прямо по пескам.
    Примерно вот так:
    Вид на соседний остров с Mont Saint Michel Пересекая море...

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

    Интересен и тот факт, что Mont Saint Michel никогда не был захвачен силой, ибо на лодках подойти к нему невозможно по причине отливов, а держать осаду невозможно по причине приливов.

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

    Еще пара фотографий:
    Одна из башен (вид снизу) Внутренний дворик на самом верху. Здесь монахи предавались размышлениям о вечном...

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

    P.S. Напоследок показавшийся забавным факт, рассказанный гидом: в окресностях Mont Saint Michel жители держат много барашков специальной породы - с серыми туловищем, черными ногами и черной головой. Так вот, поскольку эти самые барашки пасутся в такой вот местности, куда постоянно приходит море, мясо их имеет солоноватый вкус, оно мягкое и лишено характерного привкуса баранины.
    Это мясо является одним из "фирменных" блюд этой местности, которое, при возможности, обязательно нужно попробовать.
    К сожалению, у меня такой возможности тоже не было :(

    April 09

    Релиз Enterprise Library 3.0

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

    Итак, релиз. Из основных улучшений и новшеств:

    - Новые Application Blocks: Validation Application Block и Policy Injection Application Block (немного расскажу ниже)
    - Поддержка .NET 3.0 (WPF, WCF)
    - Data Access Application Block "научился" поддерживать транзакции и работать с SQL Server Compact Edition
    - Некоторые изменения в Exception Handling Application Block и в Logging Application Block.

    Коротко о новых блоках.

    Valication Application Block позволит разработчику в декларативной форме (с помощью атрибутов или непосредственно в конфигурационном файле) задавать правила валидации свойств объектов. Работает это и в WinForms, и в ASP.NET и в WCF
    Блок содержит набор уже готовых правил, таких, как валидация с использованием регулярных выражений, валидация даты (можно, например, задать правило при вводе даты рождения для проверки совершеннолетия пользователя), валидация по значению перечислений, длинны строки, null и т.д. Кроме этого можно создавать свои собственные правила.
    Более того, правила можно комбинировать (OR и AND), а так же задавать различные наборы правил для различных контекстов. Так, например, правила валидации для интерфейса пользователя могут быть отличны от правил валидации при сохранении в БД.
    Повторюсь, что наборы правил можно задавать с помощью атрибутов, а можно прямо в конфигурационном файле, то есть, без изменения существующего кода.

    Policy Injection Application Block - позволяет разработчику контроллировать операции, осуществляемые над объектом. Например, можно задать правило, чтобы при вызове метода Hello класса World происходила запись в лог. Или, перед вызовом проверить какие-то условия (разрешен ли доступ, находимся ли в режиме онлайн и т.д), а после завершения вызова совершить какие-то действия (записать аудит, сбросить кеш и т.д.).
    С помощью таких pre- и post- полиси мы можем управлять некоторыми аспектами поведения системы без модификации кода кучи методов (например, без вставки кода записи в лог в начало каждого метода).
    В "наборе" блока имеется ряд полезных "хандлеров" (обработчиков):
    Exception Handling Handler, Caching Handler, Performance Counter Handler, Validation Handler, Logging Handler, Authorization Handler. Используя эти обработчики можно в декларативной форме задавать правила, которые будут обрабатываться блоком.

    В общем об инфраструктуре EL3 можно сказать еще и то, что "конфигуратор" теперь интегрирован в Visual Studio 2005. Не скажу, что это такое уж большое и важное изменение, но все же приятно :)

    Осталось добавить только, что EL3 на 100% совместима с EL2, то есть, разработчикам не придется переделывать код при переходе (во всяком случае такое обещано).
    Пора начинать использовать :) В дальнейшем я, быть может, напишу еще пару постингов о EL3 в плане конкретного использования в коде.

    А пока буду думать о Нормандии :)

    March 24

    Российская обувь в Бельгии

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

    Помимо самого факта удивило две вещи:

    1) Цена. Пара ботинок стоила 20 евро.
    2) Качество. Какими-то топорными они мне показались. Особенно внутри.

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

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

    Но цена в 20 евро все равно удивляет.

    March 14

    О кочевниках

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

    Однако это все ерунда. Когда мы заспорили с женой и полезли искать факты в интернете, то оказалось, что то, что я всю жизнь знал под названием "кызыл-орда", оказывается, называется в России "золотая орда" и преподается в российских (по крайней мере в подмосковных) школах под этим названием :)

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

    WebServices: что может быть проще?

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

    Писать этот постинг меня сподвигло то, что сразу с двумя человеками из разных компаний и разных городов недавно разговаривал о том, как (и почему именно так) нужно строить архитектуру при работе с веб-сервисами.
    Поскольку сейчас я как раз занят тем, что пишу одновременно и слой веб-сервисов и клиента  к нему (с использованием того самого WPF), то об этом я и расскажу. Заодно прерву "затяжное молчание".

    Итак, начнем есть трехслойный пирог (серверная логика, веб-сервисы, клиентская логика) с середины, то есть, со слоя веб-сервисов.

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

    Отсюда вытекает простая рекомендация: не нужно передавать клиентскому приложению объекты бизнес-модели серверной логики. С точки зрения развития и поддержки приложения, я бы даже сказал "никогда не нужно".

    Создавайте отдельные объекты для передачи посредством веб-сервисов. Такие объекты называются "контрактами данных" (Data Contracts).
    Ваш слой веб-сервисов будет оперировать объектами бизнес-логики серверной части, но для передачи клиенту будет "транслировать" их и их данные в объекты-контракты данных и лишь затем передавать.

    Зачем это нужно? Очень просто. Как я уже сказал, клиентское приложение, пользуясь веб-сервисом Reports, совершенно не заинтересовано "знать" бизнес-модель серверной части. И для него бизнес-сущность "User" вовсе не является набором "запись в таблицу Users + ссылка в таблицу Occupations + ссылка в таблицу Departments + 2 ссылки в таблицу Addresses по их IDшникам". Ему и надо-то воспользоваться сервисом Reports всего лишь для того, чтобы этот самый репорт отобразить, и для него User - это "монолитный" объект со всеми необходимыми адресами, должностями и т.д. А вот информация о паролях, логинах, ролях и т.д. ему совершенно не нужна, поэтому и передавать ее в сервисе Reports не за чем.
    Поэтому слой веб-сервисов "берет" все эти серверные бизнес-объекты (адреса, должности), трансформирует эти данные в отдельный объект, определенный контрактом, и уже его передает клиенту.
    Кроме этого, контракты данных получаются достаточно простыми и четкими, что позволяет легко использовать сервисы даже из не-.net приложений, если придется. Да и в любом случае удобнее, чем передавать сложные объекты бизнес-модели, часто имеющие свою иерархию, избыточную с т.з. веб-метода информацию и т.д.
    Все счастливы.

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

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

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

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

    Второй: Вы сами контролируете объекты, с которыми вы работаете.
    После получения данных от веб-сервиса и трансформации их в собственные объекты клиентской бизнес-модели, программисты оной могут творить с/из этих объектов свободно что угодно.
    Нужно сделать Undo? Пожалуйста, добавили необходимые методы. Нужно, чтобы объект оповещал об изменении его свойств? Пожалуйста, реализовали INotifyPropertyChanged и получили беспроблемный двусторонний байндинг в UI. Нужна собственная иерархия? Опять пожалуйста, хозяин-барин.

    Итак, коротко обобщим основные рекомендации:

    1. Создавайте на стороне серверной логики полноценные объекты бизнес-модели и работайте с ними (а не с именованными наборами данных, за поведение которых отвечают сторонние классы, которые хрен найдешь, если не знаешь).
    2. Создавайте контракты сервисов (API, наборы операций, веб-методы), которые передают и принимают контракты данных (простые типы-носители необходимых для операции данных). Никогда не используйте бизнес-объекты серверной логики в качестве контрактов данных.
    3. Не работайте напрямую с объектами-контрактами данных в клиентском приложении. Создайте полноценные объекты бизнес-модели клиентской части, и заполняйте их данными, полученными от веб-сервисов. Так вы одновременно получите возможность развивать и управлять этой моделью и избавитесь от необходимости реализовывать странные сторонние классы, отвечающие за манипуляцию данными (те самые, которые потом хрен найдешь и проконтроллируешь).

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

    Пример (упрощенный) веб-метода, возвращающего данные о производителе товара:

    public DataTypes.Brand GetByID(int id)
    {
        BusinessLogic.ManufacturerGetById action = new BusinessLogic.ManufacturerGetById();
        BusinessEntities.Manufacturer m = action.Execute(id);
        return Translators.BrandToManufacturerTranslator.Translate(m);
    }

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

    Клиент же, получив эти данные, таким же способом заполняет ими свой объект
    Brand : Company, INotifyPropertyChanged, ISearcheable
    с которым и продолжает работать дальше.

    February 28

    Visual Studio "Orcas" - мартовский CTP

    Еще не настал март, как уже вышел обещанный CTP новой Visual Studio, о которой я рассказывал здесь.

    Скачать можно как образ для Virtual PC (сам Virtual PC бесплатен, если кто не помнит), так и "обычный" инсталляционный пакет.

    Изменений ОЧЕНЬ много, да я уже давал ссылку  на видео с некоторыми из них...

    February 26

    CAB + WPF

    23-го февраля, видимо в качестве праздничного подарка, был выпущен релиз Composite Application Block, который поддерживает WPF. Ура!

    Пока создатели SmartClient Software Factory грозятся выпустить в конце апреля новую версию их продукта, которая будет содержать инструменты для добавления View, использующих WPF (и еще нескольких новых фич), CAB с поддержкой WPF можно скачать здесь: http://www.codeplex.com/wpfcab

    Для работы с ним нужно:

    1. Создать "пустой" WPF-проект.
    2. Удалить Window1.xaml и выкинуть из файла App.xaml упоминания о нем.
    3. Добавить в заголовок App.xml следующее указание неймспейса:

      xmlns:cab="clr-namespace:Microsoft.Practices.CompositeUI.Windows.Workspaces;assembly=Microsoft.Practices.CompositeUI.Windows"

    4. Создать в нем класс-аппликейшн, например ShellApplication, который унаследовать от ApplicationShellApplication<MainWorkItem, App>. Здесь MainWorkItem - это "главный" воркайтем приложения, а App - это класс, который уже есть в Вашем проекте и описывается файлами App.xaml и App.xaml.cs
    5. Создать класс Program (имя может быть любым), в котором определить статический метод Main так, как это делается в "обычном" WinForms-приложении. Запустить в нем созданный в п.2 класс-аппликейшн:
      new ShellApplication().Run();
    6. Установить класс Program как стартовый класс в свойствах приложения.

    Все, проект WPF CAB готов. Дальше все как обычно, кроме того, что вместо WinForms можно использовать WPF для создания View.

    Кстати, если сейчас запустить приложение, то у него даже не будет окна. Для того, чтобы исправить этот "недостаток", нужно создать новую WPF-форму с именем, скажем, ShellWinfow.xaml и переопределить известный метод в ShellApplication:

    protected override void AfterShellCreated()
    {
       
    base.AfterShellCreated();
       
    ShellWindow mainWindow = RootWorkItem.Items.AddNew<ShellWindow>();
       
    Shell.MainWindow = mainWindow;
        mainWindow.Show();
    }

    Ну и еще одна "фича". В тех элементах, где планируется использование воркспейсов (DeckWorkspace, TabWorkspace, etc), в заголовок можно добавить следующий атрибут: xmlns:cab="http://schemas.microsoft.com/cab/wpf
    Это позволит потом определять воркспейсы в XAML-файле следующим образом:

    <cab:DeckWorkspace x:Name="headerWorkspace"/>

    В остальном работа с CAB не изменилась.

    Более подробно можно посмотреть в примере (BankShell), который теперь тоже "переведен" на CAB WPF.