понедельник, 15 марта 2010 г.

+++

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

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

четверг, 4 марта 2010 г.

+++

Последние недели времени катастрофически ни на что не хватает... но вот вроде бы добрался  до своего блога, так что напишу всего понемножку :)

Бонусы, баллы и скидки
Наверное, все в свое время сталкивались со скидочными карточками. Сейчас же они уже не в моде, балом правят бонусы и баллы :) Быть может, я как нибудь найду время и изложу мысли относительно этой темы в большой пребольшой пост, пока же... Пока же наступило время потратить накопленные баллы, которые обещают в скором времени сгореть, так что в выходные я выбрался в Спортмастер присмотреть себе что нибудь... очень долго ходил по магазину и думал, что же такое купить, что бы и баллы не пропали и полезно было :) В результате, т.к. в ближайшие месяца полтора-два мне так и не светит попасть в тренажерку, я все таки решил прикупить гантели - хоть как то буду поддерживать свою форму ;) Заодно отыграл рублей 500 от стоимости своей куртки.
А вот купив два фильма на DVD и COLIN McRAE DiRT 2 в М.Видео, выяснил, что там большая часть бонусов уже сгорела :( К сожалению система бонусов в М.Видео очень мудреная, так что нормальной выгоды от нее получить очень сложно :)
Так же, накануне сервис Litres.ru снова объявил о дополнительных 40% бонусов при первом платеже между 23 февралем и 8 мартом, а учитывая дополнительные 10% при пополнении с w1.ru   в итоге получается 50%, чем я в общем и воспользовался и Вам советую, сама новость тут, времени осталось не так много ;) Ну а в итоге, я снова запасся художественной литературой, осталось только найти время на ее прочтение... с другой стороны через полторы недели времени на это будет хоть отбавляй.
Ну и напоследок порадовал\разочаровал МТС со своей бонусной программой. Если быть точнее, дело даже не в баллах на бонусном счете, а в купоне на 12% скидку при покупке телефона или ноутбука в салоне связи МТС (насколько я понял, не во всех салонах это работает, но ближайший ко мне есть в списке). Разочарование заключается в том, что покупку надо сделать до 10 марта... а оно мне надо? :) С другой стороны можно что нибудь приглядеть на 8 марта, вот уж эти вымогатели...
COLIN McRAE DiRT 2
Как я уже говорил выше, на выходных купил себе новую игрушку. Сделано было по большей части на радостях от того, что у меня снова работает DVD привод на компьютере (всего то оказывается надо было удалить какой-то волшебный ключ в реестре, ох уж эта виста...).
Впечатления от игрушки позитивные, все таки я давно уже не играл в большие тяжелые игры, так что был приятно удивлен общим уровнем игрушки. COLIN McRAY всегда отличался вроде как лицензированными машинками, которые очень хорошо бьются :) По мере прохождения трассы низ машины начинает пылиться (ну это было уже давно). Режим вида из кабины с места водителя очень понравился. Он конечно не играбелен, в том плане что играть так гораздо сложнее, зато поражает проработанностью. Заезжаешь в лужу - на стекле размазывается грязная вода, из-за которой плохо видно трассу (благо, есть дворники). Опять же пыль очень хорошо ложится на стекло (другое дело, что к середине трассы порой сложно сохранить лобовое стекло в сохранности :). Ну и по мере прохождения дается возможность ставить какую нибудь игрушку на приборную панель (или как она называется?) и подвешивать что-нибудь на лобовое стекло - так прикольно все мотается во время трассы, особенно меня веселят трясущиеся глаза черепа :)
Очень порадовал большой набор музыки, действительно большой набор - сколько трасс я уже прошел, а так и не заметил повторения какой-то композиции, в том же PES в главном меню все время гоняет чуть ли не одна и та же композиция (на самом деле их побольше, но повторение замечаешь очень быстро). К тому же игрушка качественно и полностью переведена на русский язык, даже в итоге на протяжении всей игры все обращаются ко мне по имени (все-таки Артур не настолько распространенное имя).
Покупая игру, я так же очень рассчитывал полноценно поиграть в нее с использованием своего геймпада, но все таки геймпад очень плохо приспособлен к гоночным симуляторам :( По большей части, почему-то плохо срабатывают именно повороты... В итоге играть на клавиатуре гораздо легче, и это при условии, что она беспроводная :)
К минусам игры можно отнести очень долгую загрузку трасс, а так же основного меню - оно выполнено в виде... в виде вашего фургона и некой местности вокруг него. Хочешь выбрать трассу - зайди в фургон - посмотри на карту. Настроить машину - выйди на улицу, подойди к столику... ну и все в таком духе. Мало того, не сразу ясно куда надо поворачиваться (выход из игры оказался в фургоне - надо было повернуться в сторону комнаты с кроватью), так это еще и грузится каждый раз долго :) Загрузку трассы скрашивает музыка, которой, как я говорил, много, а так же показ статистики в виде падающих табличек... но все равно загрузка происходит очень долго :(
Рабочее
На работе все кипит, к сожалению, я сейчас в большей степени отдан xplat`у, так что за w1 слежу своими ушками на макушке :)
Сейчас у w1 очень активно продвигается новая касса, она вкусная и скоро станет еще вкуснее... не могу, к сожалению, в полной мере рассказать про планы, по большей части из-за того, что они могут так и остаться планами. Пока же можно посмотреть Комикс, созданный для кассы ;) Так же активно двигаются дела на Украине, посмотрим, к чему это приведет через несколько месяцев. Еще w1 обзавелся своей сокращалкой ссылок (это сейчас модно ;) так что новости в триттере будет теперь публиковать легче.
В xplat`е не все так радужно, в том плане, что новости у него нацелены не на пользователя. В ближайшее время придется очень много сделать... Это связано и с фискализацией, срок которой 1 апреля (вот пошутим, так пошутим), и с более жестким контролем за точками приема, в частности, придется нам активно дергать наших дилеров для указания актуальных адресов терминалов :) МТС вот хочет на терминалах видеть доступ к своему интернет-помощнику. В связи с наведением всяких порядков мне нравится подход Билайна к делу - он готов платить дополнительный бонус к вознаграждению за соответствие платежки каким-то определенным правилам. Еще он наконец-то задумался поощрять безкомиссионные платежи.
ReSharper NUnit и прочие прелести
Последний раз пробовал ReSharper еще в университете, тогда 2005 студия была еще только в beta. За прошедшее время этот инструмент стал еще более крут, видит даже рекурсию в коде ;)
Еще он помог мне понять одну простую вещь... Все основные проекты у меня до сих пор находятся под .NET 2.0, в следствии чего я не пользовался таким синтаксическим сахаром, как auto property, Object Initializer, var... И только благодаря ReSharper до меня дошло, что это фишки языка C# 3.0, а не .NET 3.0\3.5 :) Нет, часть фишек, конечно, завязана на 3-ий фреймворк, но многие можно использовать и под 2-ым. В конце концов быть может поднакопить и купить лицензию? :)
Еще я в очередной раз решил попробовать использовать Unit тесты, благо надо было написать новую библиотечку. TDD для меня все-таки пока что сложно применим - основная проблема придумать нормальные тесты, а не фиктивные для галочки (терпеть не могу такие тесты, когда вижу). К тому же мне гораздо легче начинать именно с наброска нескольких классов, потом накидывания на них тестов, что бы потом можно было спокойно рефакторить их. Тут, конечно, есть еще проблема в том, что мои бизнес-объекты завязаны практически сразу на БД и не содержат очень много логики.
Те классы, которые содержат много логики, как правило, работают с внешними шлюзами, а значит, работают с использованием WebRequest... делать некий ITransport, чтобы потом можно было обернуть его моками и тестировать, что послал такой-то запрос, в ответ то то... а в конце реализовывать этот ITransport как некий адаптер к WebRequest? Слишком трудоемко, а эффект маленький. По большей части из-за того, что основные проблемы выясняются именно на самом шлюзе в ходе его тестирования. К тому же заранее, даже имея документацию, все равно не сможешь угадать, как именно пришлет ответ внешний шлюз, debug помогает гораздо лучше :) Кстати, как у Вас с этим?
Еще есть, правда, один проект, где есть действительно нормальные такие классы с кучей логики, которые можно покрыть тестами. Они большие, уже как-то работают, нуждаются в рефакторинге - так что тесты там себя очень оправдают, правда все internal или private, так что надо будет сделать еще предварительный вынос всей этой красоты в отдельный проект (ей богу, неужели руки почти добрались до этого? :). Будем считать что на новой библиотеке я вспомнил основы NUnit, хоть и потерял сильно в скорости разработки.
На этом пожалуй все... а то уж и спать пора, а завтра снова в бой ;)

среда, 24 февраля 2010 г.

Старая фотография пешеходного моста через Урал

Разбирал тут старые фотографии и откопал один раритет. Даже не знаю какой это год, но это то место, где сейчас находится пешеходный мост в Зауралку, фото сделано чуть правее от текущего спуска с Беловки, судя по тому, что мне удалось выяснить. К сожалению сканера у меня нет, так что пришлось сфоткать фото ;) результат какой получился:
Как видно на фотографии, через реку проходит "сезонный" деревянный мост. Насколько мне известно - раньше мост менялся каждый сезон, т.е. зимой можно было ходить по льду, весной все таяло, Урал выходил из берегов, а когда успокаивался - строили вот такой сезонный деревянный пешеходный мост. Весной, пока мост еще не поставили, перебирались на пароме. Зауральная роща, кстати, всегда была очень популярным местом отдыха в Оренбурге, начиная где то с конца XIX века :)
Что-то прямоугольное на том берегу - это, скорее всего, начало возведения чего-то вроде лодочной станции. Её можно увидеть еще на более старых дореволюционных фотографиях, которые я откопал в сети.
Вообще, фотография скорее всего сделана еще до того, как сделали этот наш нынешний знаменитый спуск с Беловки, на вершине которого стоит памятник Чкалову (с того времени мост строили тоже деревянный, но более солидный - фото тут и тут). Так и не смог найти когда его сделали, но в 60-70 он уже, вроде, был. Мост построили позже, где то в 70-75 (тоже так и не удалось найти точную дату). С другой стороны, судя  по зданию на фото, детская железная дорога построена (это, скорее всего, начальная станция, хотя не факт...), а железка построена в 1953. В итоге на фото время где то между 50-60, ну или того раньше, если это все таки не железка.
Напоследок, если охота посмотреть, старые фото Оренбурга:
P.S. Пошел изобретать машину времени...

суббота, 20 февраля 2010 г.

Wakoopa

Практически всю эту неделю проболел и провел дома (тут скорее неделя от пятницы считается), в результате статистика использования программ за последнюю неделю оказалась интересной: 
Больше времени нашлось на Habrahabr и Google Reader, по Skype я общался меньше (еще бы, ведь я скрывался :), да и почту читал реже. Что характерно - судя по статистике Visual Studio и SQL Server Managment вообще не попали в 10ку, хотя конечно все это скрывается под Remote Desktop, т.к. немного по работе все таки пришлось что то делать :) Еще я видимо часто что то искал, т.к. не помню еще случая, что бы Google Search попадал в 10ку. Ах, ну и еще видно, что я воспользовался "случаем" и поигрался в эмуляторы ;)
P.S. Статистика хранится в сервисе Wakoopa, а для сбора используется специальный треккер этого сервиса. Скриншот из еженедельного отчета от этого сервиса. Рекомендую ;)

+++

Сегодня меня вытащили на лыжный забег в зауралку. Как показала практика, скорость моя оставляет желать лучшего, практически весь путь я был первый, правда с конца :)
Кроме всего прочего решил заодно опробовать сервис Endomondo - это сервис, который позволяет сохранять путь вашей лыжной пробежки\прогулки\заплыва и т.д. и т.п. В связи с этим заранее в нем зарегистрировался и установил программку на свой телефон (кроме Symbian версии есть версии и под другие платформы - Android, iPhone, и на сколько я понимаю WM, вполне возможно есть Java, но я не уверен). В общем об этом сервисе я и хотел сегодня поговорить, а именно в сравнении с Buddy way (это аналог, который я уже попробовал - пример тут).
Первое впечатление от программы - она показалась мне поинтереснее чем Buddy way. Отличительной особенностью является то, что пройденный путь не отсылается сразу на сервис, как это сделано в Buddy way, а делает это автоматически при обнаружении заданной заранее Wi-Fi точки доступа (я настроил на домашнюю точку доступа). Так же, в Endomondo можно выбрать тип "прогулки", чего нельзя делать в Buddy way.
К сожалению в полевых испытаниях не выдержал мой телефон :) В итоге программа вылетела в самом конце пути. По приходу домой я снова запустил программу и нашел в истории пройденный путь, который тут же автоматически отправился в сервис, но... как выяснилось, путь сохранился не весь (а вот и он), обрыв происходит где то на половине :(. На этом примере сразу же видно, что в случае Budyy way путь загружается сразу, что немного спасает от вылета программы, зато не так экономно с точки зрения трафика. Стоит сказать, что GPRS\3G может легко потеряться и досылать придется опять же дома, но Buddy way сохраняет не отправленный путь явно лучше - проверил на своем примере:)
Если говорить про конечное отображение на сервисах и их сравнениях: Buddy way отображает максимальную скорость и остановки, в Endomondo этого к сожалению нету, вместо этого только отметки по километру, что явно огорчает - и это не смотря на то, что данные о скорости Endomondo сохраняет.
Зато Endomondo более точно строит маршрут по точкам, на сколько я понял Buddy way использует для построения ломаной стандартные средства google maps, которые "оптимизируют" отображение, в результате чего иногда съедается часть пути - по сути просто используются не все точки для отображения. Стоит отметить, что если в Endomondo Workout превратить в Route то эффект будет тот же самый - часть точек пропадет из пути и он будет не такой точный... честно говоря мне пока не до конца ясно различие между ними, ну разве что Routes сохраняются на будущее и могут использоваться другими участниками как некая рекомендованная трасса...
Так же в Buddy way есть возможность "проиграть" путь, чего к сожалению я не нашел в Endomondo. Кроме всего прочего в Buddy way можно связать с прогулкой фотографии, но только в виде альбома из сервиса picasa (причем довольно криво, так что не будет записывать это в плюсы Buddy way ;).
К плюсам Endomondo можно отнести возможность указывать тип прогулки, в дальнейшем эта информация используется для сбора статистики. А так же есть возможность импортировать Workouts в сервис в формате Garmin. К сожалению я не работал с такими отдельными устройствами (именно гпсники), так что сказать ничего не могу.
В общем и целом, по субъективным ощущениям Endomondo выглядит более... красяво что ли, но Buddy way более функциональный будет... На очереди еще несколько подобных сервисов для исследований (Nokia sport tracker пока не удалось завести на моем телефоне) - если у вас есть на примете подобные сервисы, сообщите - буду благодарен :)
P.S. Специально для тех, кто ждет фотки с прогулки - их практически нету, а если быть точнее есть только общие, сделанные в самом конце, так что не ждите ;)

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

Начинаем все сначала?

Блог в своем первом варианте не пошел :)
Одна из основных причин это отсутствие четкой направленности его тематики. Думая пол года назад об этом я хотел его реанимировать и начать писать что нибудь по околорабочей области (платежные системы, сервисы и прочее), но ничего не получилось, скажем так - из черновиков не вышел ни один пост :) Кроме всего прочего последнее время мной в большей степени охватил микроблогинг twitter (если кто не знает @tagirovarthur это я ;)
Быть может когда то, я открою отдельный тематический блог... но он явно будет иметь другое название (если внезапно есть предложения - пишите, я рассмотрю :)
Ну а пока решил писать тут просто некоторые веселые и не очень моменты из своей жизни, все таки блог имени меня ;)
P.S. В целях исследования открою "зеркало" на spaces от live.

Гребени 2010-01-31

Сегодня меня таки вытащили покататься на сноуборде! Всего в жизни катался на нем 2 раза, сегодня был как раз второй :)
Погода сегодня была хорошая, не то что весь последний месяц, всего то -10 и практически никакого ветра. Как выяснилось по прибытии, кататься я разучился, пришлось учиться заново... теперь через год снова поеду учиться кататься на сноуборде ;)
Из полезностей от меня - заснял нашу главную лыжницу на видео, ну хоть какая то польза человеку. После катания с трудом доковылял до дома, теперь отлеживаюсь вот... надеюсь ходить завтра я смогу и дойду таки до работы :)
Ниже маленький фото отчет с места:
P.S. И напоследок, спасибо тем, кто меня вытащил, снабдил сноубордом и даже не угробил :)

суббота, 19 апреля 2008 г.

+++


IMG_0452
Originally uploaded by arthurtagirov
Ну вот, наконец то, и я открыл сезон катания на велосипеде :) После небольшой игры в футбол, подцепился на хвост к другу и затем мы немного покатались по зауралке и не только... Естественно, теперь у меня все болит, но я доволен :)
P.S. По-моему, это первая фотография с моего фотоаппарата со мной за этот год :)

пятница, 21 марта 2008 г.

Blog.ru

Сегодня наткнулся на блог - blog.ru. Первым делом меня очень развеселила надпись на главной странице - "Твой блог на blog.ru. Логично?". А что, и вправду логично :) В общем, я решил его попробовать, к тому же там была обещана некая интеграция с lastfm.
Честно признаюсь, как дело обстоит с lastfm я еще не посмотрел, но вот что мне понравилось, так это возможность импорта записей из других систем, в частности с blogger. Все мои записи спокойно перенеслись в blog.ru, что самое главное вместе с тегами. Конечно для этого надо было указать логин и пароль, но если кто то не доверяет системе (я то наивный чукотский парень), то может воспользоваться импортом сообщений из RSS (Atom так же поддерживается, на сколько я понял) ленты (не знаю как там с тегами, но по моему их в таком случае просто неоткуда брать). В импорте есть настройки, какие имено посты необходимо импортировать - это могут быть все посты (которые уже есть и которые будут поялвяться в блоге), только вновь появляющиеся и только те, которые уже есть.
Вообще, настроить можно несколько источников в ваш блог, и в данном случае поддержка RSS - это очень хорошо ;) Правда вот относительно лент появляется вопрос - как проверить что это ваша лента, но оставим этот вопрос на потом.
Так же можно настроить постинг постов через email, что может быть очень удобно для микроблогинга.
Возможностей по настройке интерфейса и прочему наблюдается не так много, но я пока не настолько сильно во всем разбирался. Честно признаться - этот пост является неким тестовым постом, который по идеи должен со временем автоматически появиться и в blog.ru. Так что - скоро напишу более подробный экскурс по этому новому для меня блогу.
P.S. Кстати говоря, есть еще и экспорт блога, который я быть может тоже скоро попробую ;)

воскресенье, 9 декабря 2007 г.

Отмучался с Emit...

В предыдущем посте я описывал свой механизм проектирования по контракту. Никто ничего не откомментировал по его поводу, ну да ладно, не будем сейчас про это. Сегодня я закончил еще один этап своей работы, а именно генерирование прокси класса по определенному интерфейсу, который внутри себя использует класс ContractsManager, который в свое время внутри себя использует класс, который реализует необходимый интерфейс - ужас одним словом ;)
Попутно с этим, мне пришлось немного разобраться с таким пространством имен как System.Reflection.Emit. Страшное, надо сказать пространство имен ;)
С генерированием конструктора, который принимает параметр и запихивает его в специальное поле, проблем не возникло - примеров этого было много :) Ну попутно еще разобрался с тем, как сгенерировать поле.
Дальше началась проблема - необходимо было сделать метод, который реализует метод интерфейса следующим образом: внутри себя вызывает специальный метод у поля. Этому методу надо было передать имя метода и параметры метода. Ну так приблизительно я и сделал... Но прокси класс никак не хотел работать, со словами, что у него там какая то фигня сгенерирована, а не метод интерфейса :) Через некоторое время до меня наконец дошло, что это в C# ключевое слово params позволяет перечислять параметры через запятую... но потом они упаковываются в массив, а следовательно надо передавать не параметры, а массив параметров... И тут встала проблема - как создать локальную переменную в виде массива объектов, заполнить этот массив из параметров и передать куда нибудь... К счастью google помог и в этом :)
В итоге могу сказать - даже если плохо разбираешься в системном программировании .NET (имеется ввиду Emit, да и вообще программирование на чистом MSIL), то google лучший помошник. Хотя информацию приходиться агрегировать из примеров по маленьким кусочкам... Кстати говоря, ни нашел ни одного нормального источника на русском (да и английском), где можно было бы подробно почитать про Emit. Есть что то на intuit, но там на очень конкретном примере, в котором многое опускается...
P.S. А еще наконец то заменил себе старый монитор на новый ;)

воскресенье, 2 декабря 2007 г.

Проектирование по контракту - первые попытки

Сегодня я предложу вам один способ использования проектирования по контракту в .NET, точнее очередную библиотеку, автором которой и являюсь ;) Надеюсь, что вы напишите свои впечатления, замечания, пожелания и т.д. и т.п.
На сегодня, наверное, будет только один пример использования. Пример, который используется во многих статьях про проектирование по контракту - класс стек ;)
Сначала приведу код интерфейса - он довольно простой ;)
public interface IStack<T>
{
int Count { get; }

bool Empty { get; }

void Put(T item);

T
Remove();

T
GetItem();
}
Теперь можно сказать, какие предусловия, постусловия и инварианты можно придумать для данного интерфейса. Инвариантом может послужить условие о том, что количество элементов всегда больше или равно нулю. Предусловием для методов Remove и GetItem будет то, что количество элементов в стеке больше нуля. Постусловием для метода Put будет то, что свойство Count увеличивается на единицу, для Remove - уменьшается на единицу, для GetItem - свойство Count не изменяется.
По схеме, которую хочу предложить вам я, все утверждения записываются в отдельном классе (хотя их может быть и больше). Для каждого метода этого отдельного класса можно указать чем именно он является - предусловием, постусловием или инвариантом. Так же, необходимо произвести что то вроде mapping`а или биндинга параметров этих методов к параметрам проверяемого метода, а так же свойствам и полям. Все это делается через атрибуты.
Приведу пример проверяющего класса:
internal class StackCheck
{
[Invariant("Количество элементов больше или равно 0")]
public bool CheckCount(int Count)
{
return Count >= 0;
}

[Ensure("Количество элементов увеличивается на единицу", "Put")]
public bool EnsurePut(
[Old][PropName("Count")] int oldCount,
[PropName("Count")] int count)
{
return count == oldCount + 1;
}

[Ensure("Количество элементов уменьшается на единицу", "Remove")]
public bool EnsureRemove(
[Old][PropName("Count")] int oldCount,
[PropName("Count")] int count)
{
return count == oldCount - 1;
}

[Ensure("Количество элементов не изменяется", "GetItem")]
public bool EnsureItem(
[Old][PropName("Count")] int oldCount,
[PropName("Count")] int count)
{
return count == oldCount;
}

[Require("Стек не должен быть пустым", "GetItem")]
[Require("Стек не должен быть пустым", "Remove")]
public bool RequireNotEmpty([PropName("Count")] int count)
{
return count > 0;
}
}
Несложно заметить, что все проверочные методы должны возвращать bool, в противном случае этот метод будет опущен при проверке.
Атрибут Invariant задает, что метод является инвариантом класса, в данном случае такой метод один - CheckCount. В параметр конструктора атрибута можно передать описание инварианта. В случае, если инвариант не выполнится, то это сообщение будет использоваться в качестве сообщения ошибки, так же этот текст может быть использован для документации (подумываю позже написать что нибудь и для этого ;).
Перед параметром Count этого проверочного метода нет никакого атрибута, в таком случае для метода инварианта этот параметр будет пытаться биндиться к свойству проверяемого класса с соответствующим именем (регистр в данном случае важен), если такого свойства не будет, то к полю с таким названием, если не будет и поля, то сгенерируется исключение. В общем случае перед параметром проверочного метода инварианта можно указать один из двух атрибутов - PropName (биндится к свойству с указанным именем) или FieldName (биндится к полю с указанным именем).
Следующий метод помечен атрибутом Ensure. Этот атрибут принимает два параметра: описание (использование аналогично инварианту), а так же название метода, к которому относится постусловие. Кроме уже имеющихся возможных атрибутов параметров, в постусловиях можно использовать атрибут Old. Он говорит о том, что значение свойства (или чего то другого, в зависимости от второго параметра) должно браться до того, как был вызван проверяемый метод. Так же, кроме атрибутов биндинга к свойству и полю можно использовать атрибут биндинга к параметру метода - PropName. Если никакого атрибута не проставлено, то считается, что стоит атрибут PropName с названием аналогичному названию параметра. Сам метод EnsurePut проверяет, что количество элементов после вызова метода Put в проверочном классе будет увеличено ровно на единицу. Следующий метод - EnsureRemove, практически идентичен предыдущему, только он проверяет, что количество элементов уменьшилось на единицу после вызова метода Remove. Далее идет метод EnsureItem - он проверяет, что после вызова метода GetItem количество элементов не изменится.
Следующий метод помечен атрибутом Require (даже двумя ;) Параметры атрибута Require аналогичны атрибуту Ensure, только он говорит о том, что помеченый им метод является предусловием, а не постусловием. К параметрам метода предусловия могут применены все те же атрибуты, что и к методам Ensure, за исключением Old (он просто опускается и не учитывается). Как видно из кода, здесь проверяется, что перед вызовом методов Remove и GetItem количество элементов больше нуля.
В принципе, логичнее проверять не свойство Count, а свойство Empty. В таком случае код можно переписать так:
[Require("Стек не должен быть пустым", "GetItem")]
[Require("Стек не должен быть пустым", "Remove")]
public bool RequireNotEmpty([PropName("Empty")] bool empty)
{
return !empty;
}
Как можно заметить, сам класс помечен как internal. По крайней мере для рефлексии это имеет не такое большое значение ;)
Теперь, имея такой класс, мы можем сказать интерфейсу стека, что он должен использовать его в качестве проверочного - для этого служит атрибут ContractsType, которому необходимо передать тип проверяемого класса. Еще одно немаловажное свойство, в связи с этим, проверочный класс (в нашем случае StackCheck) должен иметь пустой публичный конструктор (хотя по поводу публичного - кто знает эту рефлексию ;)
[ContractsType(typeof(StackCheck))]
public interface IStack;
{
//Описание интерфейса...
}
Наверное теперь у вас возникает вопрос - как все это использовать? А использовать все это можно через специальный класс, который называется ContractsManager - он создается для экземпляра определенного класса. Например можно использовать вот так:
Stack<int> stack = new Stack();
ContractsManager contractsManager = new ContractsManager(stack);
int res = contractsManager.RunMethod<int>("Remove");
В данном примере мы создаем класс "обертку", которая может вызвать метод вместе с проверками. Заметьте, что используется generic метод - для того, что бы указать, результат какого типа вернет метод. Так же, обратите внимание на то, что здесь используется класс Stack - наследник интерфейса IStack - т.е. все проверки наследуются по иерархии.
Т.к. стек создается по умолчанию пустой, то в данном случае сгенерируется исключение - RequireException с текстом сообщения - "Стек не должен быть пустым".
Если необходимо вызвать метод без каких либо проверок, то можно просто вызвать метод у экземпляра класса. Но это еще не все. На самом деле у каждого из атрибутов (Invariant, Require и Ensure) имеется еще один параметр, который можно задать - это приоритет (по умолчанию он равен 0). У класса ContractsManager в свое время так же есть 3 свойства которые задают максимальные приоритеты для инвариантов, предусловий и постусловий (по умолчанию тоже равны 0). Соотвественно эти свойства можно менять во время исполнения программы тем самым "балансируя" производительностью.
Естественно, что все это пока только... бета ;) Уже сейчас есть некоторые проблемы, например с generic - скажем так, пока что я особо не обращаю на них внимание. Так же, есть еще несколько идей относительно того, что можно было бы еще добавить. В общем, жду так же и ваших комментариев ;)
P.S. Да, я очень не хороший мальчик, но библиотеку с кодом всего этого я пока никуда не выложил ;)

Pipes

Наткнулся сегодня на один интересный сервис. Служит он для построения лент новостей из уже имеющихся, причем имеется очень много интересных возможностей.
Например можно взять обычную ленту новостей и отфильтровать все ее записи по категориям или еще чему нибудь. Так же можно переименовать часть полей, можно сделать join нескольких лент, ну и всякого рода другие интересные возможности. В общем, советую попробовать хотя бы ради интереса ;)
Из недостатков пока нашел только то, что иногда русский язык отображается неправильно (но скорее всего это связано с неправильным указанием кодировки в самой ленте новостей).
Сам сервис предоставляет yahoo, но самое интересное, что при этом сервис использует некоторые API от google. В общем, идея, конечно интересная, посмотрим что будет дальше.

пятница, 30 ноября 2007 г.

+++

Помните, как в ночном дозоре Завулон играет в приставку с помощью сотового телефона? Ну точнее махает мечом путем махания сотовым телефоном... Так вот кто, оказывается, придумал Wii :)

Still Alive

Наверное многие уже слышали эту песенку... Если, конечно играли в Portal :) В данном случае можно посмотреть на живое исполнение ;)
Еще хотелось бы сказать, что в Valve всегда делали довольно хорошие игры. Меня конечно немного тошнило во время игры в Portal, но сама история меня зацепила - особенно песенка в конце. Ну и конечно же, интересно было в свое время почитать про то, как создавалась эта игрушка, как внедрялись некоторые забавные элементы игры...
P.S. Хочу пирог... :)

понедельник, 19 ноября 2007 г.

Проектирование по контракту (бинарный поиск)

В свое время много вопросов вызвала дискуссия: надо ли проверять массив на упорядоченность (предусловие) при бинарном поиске. Надо? :)

Поразмышляю на эту тему ;)
Начну с того, что еще раз обращу внимание на то, что в теории никто не говорит о том, что в действительности надо делать с предусловием, постусловием и инвариантами. Они есть и все ;)
Теперь обратимся к разуму :) На сколько мне известно, бинарный поиск имеет сложность Q(log(n)) (по умолчанию у программистов логарифм двоичный ;), а вот проверка массива на упорядоченность, по всей видимости, Q(n) (по крайней мере я не знаю способа сделать это быстрее ;) Т.е. получается, что сама по себе проверка сводит на нет все преимущества бинарного поиска... К тому же, стоит сказать, что выигрыш в бинарном поиске обычно происходит при неоднократном обращении (имеется в виду, что если нам надо найти элемент в не упорядоченном массиве один раз, то лучше просто пройтись по нему, чем отсортировать его, а потом искать в нем бинарным поиском). При рассмотрении проблемы с этого ракурса, кажется логичным не включать проверку массива на упорядоченность в бинарный поиск ;)
Теперь стоит ответить на вопрос - что же тогда делать с наши предусловием? Оно же имеет место быть (по логике вещей). На самом деле, скорее всего это тот класс (имеется в виду не класс в программировании, а... социальный класс ;) предусловий, который может использовать в своей работе разработчик. Т.е. другими словами, у программиста есть метод бинарного поиска, который ему необходимо реализовать, причем при этом ему сказано - "не заморачивайся по поводу не упорядоченности элементов в массиве". Такие предусловия не должны попадать в код в виде непосредственных проверок. В принципе, можно сделать их автоматическое добавление в xml документацию ;)
Ну и напоследок, рассмотрим несколько примеров предусловий для бинарного поиска, которые можно было бы и включить в код.
Итак, начнем с упорядоченности элементов в массиве. Вроде мы можем быть абсолютно уверены в том, что элементы в массиве упорядочены, но не совсем ;) Ведь нам еще важно - в каком направлении они упорядочены :) Так что проверяем, что, первый элемент <= последнему. В принципе, от данной проверки можно отказаться, если написать такой бинарный поиск, который просто анализирует, в каком направлении отсортирован массив. Вторая проверка больше подойдет для Generic коллекций. Если я ничего не путаю, то, скорее всего, в алгоритме бинарного поиска придется что то сравнивать ;) А это означает, что элементы массива должны реализовывать интерфейс IComparable (ну если мы говорим про .NET ;).
Кстати говоря, наверное еще желательно, что бы все элементы были одного типа (точнее говоря приводились к типу, который мы ищем). Но это уже попахивает очередной проверкой всех элементов ;)
Ну вот на этом я, пожалуй, и закончу ;)

воскресенье, 18 ноября 2007 г.

Dot Net Books

Наткнулся тут на один сайт посвященный книжкам по .NET. Наполнение этого сайта меня просто поразило ;)
P.S. Особой внимание обратите на комментарий к первому посту :)

Проектирование по контракту - идеальный случай

Попробую написать коротенький такой пост про то, как бы по моему мнению идеально выглядело бы внедрение DBC в язык программирования, так сказать - мечты ;)
Допустим что у нас есть некий проект в котором есть классы с описанными инвариантами, пред и пост условиями. Ну и представим, что их описание довольно легкое, скажем так, нас в первую очередь сейчас должен волновать не способ их описания ;) Что теперь с этим описанием необходимо делать?
Ну можно делать, например, разного рода ворнинги. Например, есть метод у которого в предусловии у первого параметра стоит, что он должен быть больше нуля, а мы передаем туда переменную просто типа int. В таком случае необходимо добавить warning о том, что переменная может быть и меньше нуля. Ну или есть у нас еще некий класс у которого есть свойство для которого задано, что оно больше нуля и именно это свойство мы передаем в метод - в таком случае ворнинга быть не должно быть.
Под категорию таких же проверок может подойти так же, например, вызов метода из другого метода. Есть метод1, который внутри себя где то в середине вызывает метод2, передавая ему расчитанные в методе1 параметры. В зависимости от входных данных метода1 зависит передаваемый параметр в метод2, т.е. в зависимости от ограничений на входные данные метода1 зависит то, какой параметр мы можем передать в метод2. Анализируем ограничения на параметр в методе2 и, быть может, выдаем замечание о том, что ограничение на параметр в методе1 можно и усилить, т.к. при некоторых его значениях вызов метода2 будет некорректен.
Пусть у всех пред пост условий и инвариантов есть приоритет - в таком случае при компиляции можно указывать, какие проверки в итоге можно включать результирующий код, а какие нет. Это так сказать - игра с балансом производительности и безопасности.
Возможность автоматического тестирования на основе все тех же пред пост условий и инвариантах.
В общем говоря, DBC должен открыть возможность дополнительного анализа кода (ведь появилась некая дополнительная мета информация о нем), а не просто добавлять проверки в код ;)

Проектирование по контракту (часть 2ая)

В предыдущем посте я начал рассказывать про проектирование по контракту (DBC). А закончил я рассказ на том, что сделал некий небольшой обзор уже существующих попыток внедрить проектирование по контракту в .NET. Теперь же наступило время продолжить ;)
Стоит сказать, что изначально, идею проектирования по контракту я хотел использовать с целью тестирования кода. Идея была приблизительно следующая: описываются предусловия, постусловия и инварианты с помощью атрибутов, затем запускается некая среда, которая подгружает созданную сборку, на основе атрибутов генерирует некий набор случайных тестов, и запускает их. Тут может возникнуть вопрос - какой именно набор тестов, что значит случайный и что эти тесты проверяют? Да и, вообще, зачем все это нужно? Отвечу на вопросы по порядку.
Начну, наверное издалека, а именно с вопроса - чем меня не удовлетворяют стандартные автоматизированные тесты на основе NUnit? А не удовлетворяют они меня тем, что все тесты приходится придумывать самому. Согласен, что в ряде случаев это правильно, но не всегда. Например, есть у нас метод принимающий целочисленный параметр. Для этого метода известно, что в зависимости от того, в какой диапазон попадет этот параметр, метод может повести себя по разному. Предположим что таких диапазонов 3. В таком случае мы пишем 3 теста, в каждом из которых проверяем метод при подаче в него параметра из соответствующего диапазона (1го, 2го и 3го), ну или пишем один большой тест (что, лично я, делать не советую ;). Вроде все правильно, только вот из каждого диапазона мы проверим только несколько значений. А вдруг, на самом деле существует некий 4ый диапазон для чисел из которого наш метод будет выполняться неправильно? В таком случае наши тесты не найдут этот самый диапазон. И это при том, что проверяемый нами метод полностью покрыт тестами. Естественно, что сейчас найдутся люди, которые скажут, что оттестировать все варианты невозможно, но тем не менее...
Лично мне в данной ситуации более логичным кажется в каждом их трех тестов брать не конкретный параметр из заданного диапазона, а случайно сгенерированный. Естественно, что тогда нельзя будет точно определить выходной параметр метода, но, скорее всего некие ограничения на него наложить будет можно (сумма двух положительных - положительна). При таком методе тестирования, теоретически, может сгенерироваться параметр из нашего 4го диапазона и в таком случае тест может и не пройти (а может и пройти, выходные параметры мы же проверяем не на точное соответствие). Конечно для верности в тесте надо будет сгенерировать несколько входных параметров. В итоге мы получаем некое стохастическое тестирование. А вдруг да и грохнется наш тест на каких то непредвиденными нами входными данными? Причем, в первую очередь, имеется виду не то, что сам метод не выполнится (это уже фуззи тестирование), а то, что выходные параметры не пройдут проверку.
Конечно нельзя сказать, что данный метод тестирования лучше традиционного. Лучше сказать так - они бы прекрасно дополняют друг друга.
Ну вот мое "издалека" и кончилось. Я думаю, что смышленные уже догадались, что три описанных выше теста с легкостью могут быть превращены в три различных контракта для метода. Осталось только автоматизировать процесс автоматической генерации данных, ну а еще придумать удобный способ описания этих самых контрактов (а иначе толку от идеи мало, т.к. легче будет писать такие тесты ручками). В итоге получаем ответы на наши вопросы. Генерируется набор тестов, который проверяет определенный контракт метода генерируя случайным образом входные данные для этого метода.
Теперь, наверное, стоит ответить на вопрос, какое отношение все это имеет к первому моему посту, где я рассказывал про Spec# и eXtensible C#? А отношение следующее - лично по моему сугубо личному мнению, велосипеды получились неудобные, т.к. использоваться проектирование по контракту должно не как велосипед. Поясню. Теория проектирования по контракту вообще говоря, не подразумевает использования пред пост условий и инвариантов для более простой записи проверяющих условий в коде. В первую очередь она служит для того, что бы описать некие логические ограничения классов во время проектирования (именно проектирования, а не кодирования), которые нельзя описать с помощью обычных конструкций языка. Ну, например, нельзя компилятору объяснить, что количество элементов в коллекции должно быть больше нуля, т.к. с точки зрения компилятора int может применять и отрицательное значение. Нет, конечно можно сделать свойство в котором метод set будет все это проверять, но проблема не в этом. Проблема в том, что само по себе условие о том, что свойство Count должно быть больше нуля никак не отражается в описании класса (в описании интерфейса этого класса, так будет лучше) - программист сам понимает, что он должен сделать такое ограничение, ну или проектировщик интерфейсов описывает это дополнительно где нибудь (например в тех. задании на реализацию этого интерфейса, или в remarks к свойству). Существующие же решения просто предлагают краткую форму написания проверок.
Еще пару слов об автоматизированном тестировании, а точнее о TDD. Это очень хорошая методология, правда ;) На самом деле TDD позволяет как раз частично описать те самые ограничения (и не только их). Соотвественно, потом появляется возможность спокойно реализовать код и проверить его с помощью тестов на соответствие этих самых ограничений (а не написать код, а потом писать тесты, которые "подтверждают" что это самый код работает). На самом деле всвязи с этим у TDD прослеживается хорошая связь с DBC. Только вот DBC содержит более "абстрактные" проверки (TDD проверяет конкретный пример - частный случай, а DBC говорит, как должно быть в общем). Но не смотря на связь нельзя сказать, что TDD это частный случай DBC или наоборот... просто здесь есть некие пересечения, есть что то общее, но только в некоторых частях обоих методологий.
Немного отступлю от темы, что бы еще раз разрекламировать TDD. Недавно у меня была следующая проблема: я уезжал из города на неделю, но необходимо было придумать задание, которое бы выполнили в мое отсутствие. Задание заключалось в том, что бы создать DataSet определенной структуры. Можно конечно было просто сказать - сделайте DataSet соответствующий структуре такой то БД, но боюсь, что "реализаторы" не могли в полной мере понять, как же надо соответствовать структуре БД, да и проверять потом сделанную работу просмотром кода не очень то удобно. Соответственно были сделаны тесты, которые просто проверяли, что DataSet содержит внутри себя такое то кол-во таблиц, что таблицы имеют такие то названия, что в таблицах есть такие то столбцы такого то типа, что заданы определенные ключи и определенные связи между таблицами. Другими словами я описал то, что хотел увидеть в результате, но в форме тестов. В итоге люди, особо не понимающие, что, например, столбец должен иметь такой тип данных и именно такое название, зачем нужны связи между таблицами и т.д. смогли реализовать код (хотя конечно не за неделю, но тут уже проблема в другом). Задание же для них было приблизительно следующее: все кружочки должны быть зеленого цвета. Самое главное, что и я был спокоен относительно того, что код был реализован правильно.
Но вернемся к нашей теме. А начну я с того, что брошу еще один камень в парк велосипедов. Камень этот имеет название "постусловия". Что такое постусловия? Это утверждения, которые говорят о корректности выполненого метода. Что же происходит с ними, например, в eXtensible C#? Постусловия превращаются в подобие Assert, которые вызываются перед return метода... Т.е. получается, каждый раз, когда вызывается метод, он проверяет себя - а правильно ли я вообще выполнился? С одной стороны это, может быть и правильно - метод поймет, что сделал какую то глупость во время выполнения приложения... т.е. приложение более устойчиво к своим же ошибкам? Ну это зависит от того, что в такой ситуации сделает метод. Наверное логичнее всего отправить отчет microsoft - пусть разбираются ;) А если честно, то получается, что тесты перетекли в уже готовое приложение и выполняются каждый раз во время выполнения метода (что естественно сказывается на производительности, причем, по моему, это нельзя оправдать большей надежностью).
С предусловиями все таки все не так плохо. Часть из них действительно необходимо включать в результирующий код, например предусловие о том, что какой то параметр метода не должен быть равен null. С другой стороны возникает вопрос, что делать если предусловие не выполняется? Генерировать исключение, просто выходить из метода?
Ну или еще милый пример (это если я, конечно, все таки понимаю проектирование по контракту)... Допустим у нас есть несколько контрактов на метод сложения двух чисел: "если оба числа положительные, то результат положителен", "если оба числа отрицательные, то результат отрицателен". Ведь у обоих контрактов есть предусловие и постусловие.... причем если для конкретного предусловия не выполняется его постусловие, то метод реализован неправильно, но вод вставлять эти пред и пост условия в конечный исполняемый код... извините, но по моему это неправильно. К тому же тут наблюдается следующая ситуация: несоответствие одному из предусловий еще не говорит о том, что входные параметры неверны, ведь они вполне подходят для другого предусловия. В данном примере входные параметры даже могут не удовлетворять обоим предусловиям. В общем случае тут получается ситуация, когда по одному из контрактов метод с данными входными параметрами выполняться не должен, а по другому должен. Что делать? Это зависит от самих контрактов. Например контракт должен быть обязателен к исполнению, или нет. Тут мне, наверное, стоит оговориться - на сколько я помню, в самой теории DBC нет вывода нескольких типов контрактов (а жаль). Кстати, что думаете об этом? Путаю ли я тестирование и проектирование по контракту? :)
Следующий пункт в моем не структурированном высказывании будет посвящен связи проектирования по контракту и аспектному программированию. Связь может быть натянутой, ну или немного искуственной, сейчас объясню почему. Для начала скажу, что связь проектирования по контракту с аспектным программированием появилось только из-за того, как это проектирование по контракту реализовываться. Ведь самым логичным подходом считается следующий: ловим момент вызова метода, проверяем все наши предусловия, если они прошли проверку, то вызываем метод, получаем выходные параметры, проверяем на их основе постусловия, если все хорошо, то возвращает результат дальше. Вот и получается, что у нас что то делается в начале вызова метода и в его конце. Лично мое мнение - это все неправильно. По крайней мере про постусловия я уже говорил выше, да и с предусловиями все не так ясно. Могу лишь согласится, что аспектное программирование логично применять при верификации кода в тестах по контрактам и инвариантам.
Кстати об инвариантах. Как не жаль, но инварианты это единственное, что на данный момент до сих пор осталось только в теории... По хорошему, инварианты нужно проверять и в предусловиях и в постусловиях, в реальности же, необходимость в этом наблюдается не всегда (в принципе отчасти это и логично). Из-за этого, скорее всего, было принято единственное решение - вообще их не использовать, а жаль... Лично я вижу следующее решение данной проблемы: для каждого контракта указывать, какие именно инварианты имеет смысл проверять в данном контракте. Так же, по хорошему, необходимо проверять часть инвариантов, когда происходит изменение свойств и полей. Хотя, учитывая, что свойство - это просто два метода (а на метод можно навесить контракт), то проблема остается актуальной только для обычных полей.
Подводя промежуточные итоги я могу лишь сказать, что или идеи DBC написаны не очень четко (т.е. иногда возникают спорные вопросы относительно того, что же это такое... ну вот как у меня с несколькими контрактами), или везде, где утверждается использование DBC - оно используется только отчасти (а точнее - используется название "проектирование по контракту" для каких либо целей, но никакое это не проектирование по контракту)...
P.S. Честно говоря, уже забыл с чего я начал этот пост, и что именно хотел сказать в его начале... Наверное это пока что только начало рассуждений о том, что же на самом деле такое "проектирование по контракту". И, надеюсь, что вы поможете ответить мне на этот вопрос ;)

суббота, 17 ноября 2007 г.

Проектирование по контракту (часть 1ая)

Now playing on iTunes: Fleur - Сегодня
В настоящее время я занимаюсь попыткой "внедрить" проектирование по контракту в .NET (на примере языка C#). Внедрить я взял в кавычки неспроста, дело в том, что под внедрить понимается не как непосредственное внедрение проектирования по контракту в синтаксис языка (ну или в саму среду .NET), больше имеется в виду внедрение идеи проектирования по контракту в сам процесс написания приложений на .NET. В связи с этим, хотел бы поделится некоторыми идеями и наблюдениями, но о всем по порядку...
Наверное сначала стоит уточнить, что вообще такое проектирование по контракту (знающие могут пропустить абзац ;). Если совсем кратко, то это описание некоторых утверждений, которые должны выполняться в определенный момент работы программы. Например есть некоторые ограничения на входные параметры метода (предусловия), если они будут выполнены при вызове метода, то гарантируется что и сам метод выполнится успешно, кроме того будут выполнены ограничения наложенные на выходные параметры метода (постусловия), если они конечно есть. Ну например для метода деления одного числа на другого: "второе число не должно быть равно нулю, в таком случае деление произойдет". Или для того же метода деления чисел: "если оба числа положительные, то деление произойдет и результат будет положительным". Ну и т.д. Все это называется контрактом (контракт на метод). Кроме контрактов есть так называемые инварианты класса (вообще говоря, это может быть и интерфейс) - это некие утверждения (как правило затрагивающие поля и свойства), которые должны удовлетворятся на протяжении всей жизни экземпляра этого класса (в теории их проверка обычно происходит перед вызовом метода и после его выполнения, т.е. в пред и пост условиях). Примером инварианта для какой нибудь коллекции может служить такое вот утверждение: "количество элементов в коллекции больше нуля". Ну я, надеюсь, что вкратце ясненько, хотя, быть может и не по научному ;)
Для чего вообще используется идея проектирования по контракту? В первую очередь для повышения надежности разрабатываемого продукта (приложения, кода, "черти что и с боку бантик" - для кого что ;). Естественно, что идея проектирования по контракту не на столько нова, а значит и для C# (а он тоже уже не так нов) уже что то придумано (стоит заметить, что в наше время вообще сложно быть в чем то первым, как правило получается только снова изобрести уже существующий велосипед, но это так - лирическое отступление). Существующими и , в принципе, работоспособными примерами чего то придуманного служат, например, Spec# и eXtensible C#. Расскажу про них совсем немного ;)
Spec# представляет собой некое расширение синтаксиса языка C#. При таком подходе можно написать предусловия, постусловия и инварианты (далее будем называть все это прелестями для краткости ;) прямо в коде - прямо как в теории проектирования по контракту. При этом компилятор дополнительно "что то там" проверяет на этапе компиляции на основе этих самых прелестей, что, естественно позволяет выявить ошибки еще на этапе разработки. Так же компилятор на основе все тех же прелестей добавляет ряд проверок в код, которые будут работать во время исполнения. Ну и, естественно для всего этого есть некая среда разработки в виде расширения Visual Studio, что бы жизнь казалась медом :) Не смотря на все, вроде как, имеющиеся плюсы, есть один минус (который может все перевесить) - Spec# всетаки не C#, т.е. другой язык программирования. Ну так же, по моему, не имеется уже привычного нам всем IntelliSense ;).
Проблему "другого" языка может решить eXtensible C#, который представляет собой немного другой подход к проблеме внедрения проектирования по контракту. Во-первых, это набор атрибутов, с помощью которых (вроде как) можно описать наши прелести. Во-вторых, это некое расширение компилятора, которое на основе соответствующих атрибутов вставляет в код дополнительные проверки. Тут может возникнуть вопрос - в чем же отличие, если eXtensible C# это тоже расширение компилятора? На самом деле в том, что код написанный с применением eXtensible C# можно скомпилировать и обычным компилятором, в таком случае просто атрибуты eXtensible никак не повлияют на скомпилированный код (просто останутся в метаданных).
Тут я сделаю некое лирическое отступление про то, как все это работает. На самом деле с eXtensible C# компиляция проходит в два прохода: сначала проект собирается обычным компилятором, а затем компилятор eXtensible C# загружает созданную сборку, через рефлексию анализирует свои атрибуты, на их основе "подправляет" код (вставляя проверки) и снова все компилирует (ну в случаи неудачи выводит стандартные ошибки компиляции). Соотвественно, за счет этого eXtensible C# легко отключается, ну а за счет атрибутов достигается обратная совместимость со стандартным компилятором (если это можно назвать совместимостью, лучше сказать так - eXtensible C# использует то, что никак не мешает обычному компилятору ;).
Стоит сразу сказать, что в eXtensible C# так же не обошлось без минусов. Во-первых, из-за применения атрибутов нет никаких проверок во время разработки (ошибки вскрываются во время компиляции, ну или после ;). Во-вторых, из-за применения атрибутов, писать утверждения довольно проблематично, точнее сказать - в атрибут они передаются как самая обычная строчка ("count > 0") - наверное, отсюда, кстати и берется первый минус , т.к. во время передачи строчки никак нельзя узнать, правильно ли она написана, только во время компиляции (другими словами забудьте про Intellisense ;). В третьих, никак не используются инварианты классов (кстати, может быть их нет и в Spec#...). В четвертых, eXtensible C# применим (как видно из названия, кстати) только для C# - другими словами, для других языков программирования данные атрибуты являются просто пустышкой.
Есть и немного другие подходы (например кто то советует просто использовать класс System.Diagnostic.Debug с его методом Assert). Подведя итог можно сказать следующее: велосипеды уже есть, но ездить на них не так уж и удобно (еще лучше сказать - ездить конечно можно, но только при явном желании). Вопрос в другом - можно ли изобрести что то лучше? В общем, если кто то найдет ответ - скажите мне ;) А я по старинке буду пока что просто пробовать изобрести очередной велосипед. Кстати, наконец то настало время рассказать про свои замечания... Но уже, наверное, не сегодня ;)
P.S. А пока можете комментировать - ваше мнение мне очень интересно ;)

воскресенье, 11 ноября 2007 г.

На кого из героев „Футурамы“ ты похож?

Прошел от тут один милый тест - любителям Футурамы посвящается;) Что то в моем результате есть противоречивое... но мое, наверное)))))

Результат теста «На кого из героев „Футурамы“ ты похож»:


Проф.

Лила

Гермес

Бендер

Зойдберг

Фрай

Эми

Киф

Зепп
64-1537964

Если Вы желаете узнать больше о своем характере и о характере героев «Футурамы», то прочитайте статью «Псих-о-рама».

Пройти тест.