суббота, 20 декабря 2008 г.

Знаю ли я русский язык?

Недавно наткнулся на нехитрый тест по проверке знаний русского языка.

Я проверил свои знания русского языка и получил четверку.



Сходи, проверься?

Кроме информации выше, на странице был еще вот такое резюме по поводу моего результата:

Вы ответили на 6 из 8 простых вопросов. Не самый плохой результат на общем фоне. Скорее всего, вы неплохо знали русский язык в школе, просто было это давно, и теперь учебник Розенталя для вас заменяет грамматическая автопроверка в "Ворде". Гордиться вам особенно нечем, но для выживания в среде носителей русского языка этого вполне хватит. Таких, как вы, в стране, согласно опросу ВЦИОМа, - 21%.*


Какие мои личные выводы?

1. Мои учителя действительно были правы, когда ставили мне 4 на протяжении многих лет школы.
2. Спустя много лет мой мозг еще не успел засохнуть :)
3. Как гражданин Украины, который родился и вырос в этой стране, вполне могу себе позволить иметь оценку четыре по языку, который не является государственным.
4. По украинскому языку у меня тоже было четыре. Но это связано с тем что я говорю и думаю на русском языке, а мое любимое, [censored], государство считает что я (и еще 1/2 - 1/3 граждан) должен знать государственный язык.

воскресенье, 9 ноября 2008 г.

XML в качестве DataSource для юнит тестов

Что-то в последнее время я вижу просто невообразимое обилие постов на тему TDD, что не может не радовать :)

Регулярно читая посты одного моего уважаемого коллеги по имени Mike Chaliy обнаружил заметку CSV у якості DataSource.

Вначале хотел оставить комментарий, но потом решил сделать это в виде отдельного поста.

Итак, Mike предпочитает CSV. Он достаточно подробно описал причины его решения, поэтому я решил немного пропиарить формат XML :)

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

На мой взгляд, у CSV формата в качестве источника данных для юнит тестов так же есть несколько недостатков, которые я привожу ниже:

1. Изменение структур данных. Добавляется новое либо удаляется старое поле. Приходится менять CSV документ. Причем придется чуть-чуть поколдовать над загрузкой документа в тот же Excel для того чтобы представить его в табличном виде. После чего нужно отредактировать эту таблицу и опять сохранить в CSV.

В случае с XML можно обойтись банальным Find/Replace в текстовом редакторе. Хотя это конечно дело вкуса. В любом случае нужно помнить об этом, поскольку для кого-то это может быть проблемой.

2. Обработка ошибок чтения. В .NET достаточно бедные средства для того чтобы работать с CSV форматом. С другой стороны, связка XML-файл + XSD-схема + класс-контейнер полученный от XSD.exe + чтение файла с валидацией по схеме выглядит очень привлекательно.

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

Если бы он обновлял XML документ он бы получил довольно внятное объяснение почему документ не может быть загружен.

3. Строгая типизация. Если использовать класс-контейнер, то сериализатор сам будет делать все приведения типов. В случае с CSV тебе придется этот код писать самому.

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


Таким образом, для меня выбор между CSV и XML практически эквивалентен с очень небольшим перевесом в пользу XML ;)

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

Начинающим на заметку. Два поста об оформлении исходного кода.

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

http://blogs.gotdotnet.ru/personal/ezakhareyev/CommentView.aspx?guid=77a8ef9b-19cb-401a-b832-ffac0ad7b3ad


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



Точки выхода или немного о структурном программировании:

http://blogs.gotdotnet.ru/personal/XaocCPS/PermaLink.aspx?guid=72b2322a-6782-4ee6-b4e9-66df9678b56a

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


UPDATE:
Поправил вторую ссылку в которой текст и целевой url не совпадали.

Пожалуй отвечу на коментарии прямо в этот пост.

[mormat] Не знаю, почему в компании DevExpress другие гайдлайны (открывающая скобка на старой" строчке), неужели им удобно читать собственный код.. Сила привычки?

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


[mormat] Что касается множественных return-ов в теле метода, то помоему односторонняя совершенно статья. Где обоснование, где рассмотрение альтернативных точек зрения? Где плюсы, минусы? Я, например, знаю обратную точку зрения, что ряд валидирующих проверок в начале метода (с return-ами) сильно упрощает поддержку кода.

Честно говоря тут я более категорично настроен :) Если речь идет имено о валидации переданных данных, то тут стоит бросать исключения, а не использовать return. Хотя, уверен что ты имел ввиду скорее не валидацию параметров, а проверку на применимость метода.

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

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

  1. public ResultType DoSomething(SomeType value)  
  2. {  
  3.     // Если параметр невалидный, то этот метод прокинет исключение.  
  4.     ValidateSomeType(value);  
  5.   
  6.     // В некоторых случаях бывает удобно инициализировать объект значением по-умолчанию сразу с его объявлением.  
  7.     ResultType result;  
  8.   
  9.     // Если нам не нужно выполнять никаких действий над объектом, то мы просто выйдем из метода.  
  10.     if (IsAcceptable(value))  
  11.     {  
  12.         ...  
  13.     }  
  14.   
  15.     return result;  
  16. }  

пятница, 15 августа 2008 г.

Миграция данных из одной таблицы в другую. Гибкое решение.

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

  1. string nsvid="";
  2. string nsit="";
  3. string type="";
  4. string nzav="";
  5. string ninv="";
  6. string lim="";
  7. string tochnost="";
  8. string where="";
  9. System.DateTime dtp = System.DateTime.Today;
  10. Int64 pov=0;
  11. System.DateTime dtn = System.DateTime.Today;
  12. string texsos="";
  13. for (Int64 i = 0; i <>
  14. {
  15. if (!bdt[int.Parse(i.ToString())].Is___п_пNull())
  16. pp = long.Parse(bdt[int.Parse(i.ToString())].___п_п.ToString());
  17. if (!bdt[int.Parse(i.ToString())].Is___свид_Null())
  18. nsvid = bdt[int.Parse(i.ToString())].___свид_;
  19. if (!bdt[int.Parse(i.ToString())].IsНаименование_СИТNull())
  20. nsit = bdt[int.Parse(i.ToString())].Наименование_СИТ;
  21. if (!bdt[int.Parse(i.ToString())].IsТипNull())
  22. type = bdt[int.Parse(i.ToString())].Тип;
  23. if (!bdt[int.Parse(i.ToString())].Is_Заводской__Null())
  24. nzav = bdt[int.Parse(i.ToString())]._Заводской__;
  25. if (!bdt[int.Parse(i.ToString())].Is_Инвентарный___Null())
  26. ninv = bdt[int.Parse(i.ToString())]._Инвентарный___;
  27. if (!bdt[int.Parse(i.ToString())].IsПредел_измеренийNull())
  28. lim = bdt[int.Parse(i.ToString())].Предел_измерений;
  29. if (!bdt[int.Parse(i.ToString())].Is_Класс__разряд__ц_д___погрешностьNull())
  30. tochnost = bdt[int.Parse(i.ToString())]._Класс__разряд__ц_д___погрешность;
  31. if (!bdt[int.Parse(i.ToString())].IsВладелецNull())
  32. where = bdt[int.Parse(i.ToString())].Владелец;
  33. if (!bdt[int.Parse(i.ToString())].IsДата_поверкиNull())
  34. dtp = bdt[int.Parse(i.ToString())].Дата_поверки;
  35. if (!bdt[int.Parse(i.ToString())].IsПериодичность_поверкиNull())
  36. pov = long.Parse(bdt[int.Parse(i.ToString())].Периодичность_поверки.ToString());
  37. if (!bdt[int.Parse(i.ToString())].IsДата_следующей_поверкиNull())
  38. dtn = bdt[int.Parse(i.ToString())].Дата_следующей_поверки;
  39. if (!bdt[int.Parse(i.ToString())].Is_Тех_состояниеNull())
  40. texsos = bdt[int.Parse(i.ToString())]._Тех_состояние;
  41. pdt.AddPriborRow(i+1, nsvid, nsit, type, nzav, ninv, lim, tochnost, where, dtp, pov, dtn, tochnost);
  42. }
  43. priborTableAdapter.Update(pdt);
  44. pdt.AcceptChanges();


Достаточно беглого взгляда на этот код чтобы понять - реализация метода неоптимальна.

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

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

1. Делаем универсальный конвертер данных:

  1. public static class ConvertUtils
  2. {
  3. public static object ToType(object originalValue, Type targetType)
  4. {
  5. if (targetType == typeof(string))
  6. {
  7. return originalValue.ToString();
  8. }
  9. if (targetType == typeof(int))
  10. {
  11. return int.Parse(originalValue.ToString());
  12. }
  13. throw new Exception(
  14. string.Format(
  15. "Type {0} is not expected.",
  16. originalValue.GetType().FullName));
  17. }
  18. }


Если есть необходимость можно расширить метод до ToType(object originalValue, Type originalType, Type targetType)

2. Заводим "словарик" для преобразования данных:

  1. var migrateDictionary = new SortedDictionary<string, type="">()
  2. {
  3. { "___п_п", typeof(long) },
  4. { "___свид_", typeof(string) },
  5. { "Наименование_СИТ", typeof(string) },
  6. };



Можно расширить словарик до такого вида:

Ключ = Имя исходного поля + его тип
Значение = Имя целевого поля + его тип

3. И непосредственно реализация метода по переносу данных. Ни зависит ни от чего, разве что от ADO.NET, а именно типов DataRow, DataTable, DataSet :)

  1. // Объекты DataRow естественно реально существуют :)
  2. DataRow sourceDataRow = null;
  3. DataRow targetDataRow = null;
  4. foreach (var migrateInfo in migrateDictionary)
  5. {
  6. var columnName = migrateInfo.Key;
  7. var targetType = migrateInfo.Value;
  8. var sourceValue = sourceDataRow[columnName];
  9. targetDataRow[columnName] = ConvertUtils.ToType(sourceValue, targetType);
  10. }



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

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

среда, 30 июля 2008 г.

Ubuntu Linux и менеджер пакетов от Debian.

Провел небольшой эксперимент на тему "насколько хороша ОС Ubuntu Linux (и менеджер пакетов от Debian в частности)".

Лично я просто обажаю систему управления пакетами в Linux, она насколько логичная, мощная и гибкая, что я в нее просто влюблен :)

Неоднократно испытавал на прочность различными способами менеджер пакетов в Ubuntu.

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

Я сделал следующее:
1. Запустил Krusader 2.0 SVN trunk (KDE4/Qt4)
2. Запустил из под него Konsole (KDE3/Qt3)
3. Запустил менеждер пакетов Synaptic и отметил для удаления библиотеку Qt3 и все от нее зависящие
4. Применил изменения, после чего менеджер пакетов удалил мне весь KDE3 и все Qt3 приложения, однако я с нетерпением ждал что же будет с приложением Konsole которое было запущено. Причем это приложение не бездействовало, в нем происходила компиляция Krusader 2.0, ветки trunk.
5. Закрыл Krusader 2.0 SVN trunk
6. Дождался окончания компиляции и обновления Krusader 2.0 в окне Konsole
7. Закрыл окно Konsole, попытался повторно запустить это приложение, но мне сообщили что оно было удалено.
8. Вуаля, это просто великолепно!

Остается надеятся что никаких "хвостов" из-за таких финтов на моем жестком не осталось, а вы как считаете?

четверг, 19 июня 2008 г.

Динамические языки в .NET проектах не за горами

Думаю что многие из .NET разработчиков уже неоднократно слышали о IronPython.

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

IronPython начинал разрабатываться вначале независимым разработчиком, который в последствии перешел под крыло Microsoft.

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

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

Около полугода назад я ознакомился с IronPython Studio, средой разработки на языке IronPyton, которая была выполнена на базе Visual Studio 2008 Shell (isolated mode). Если проще, то это отдельная среда, как две капли воды похожая на Visual Studio 2008, однако исключительно для этого языка.

Сегодня я узнал о существовании IronPython Studio на базе Integrated Shell, что дает возможность сопровождать проекты на IronPython в одном решении вместе с проектами на других языках. А это уже совсем другая история... Очень надеюсь, что я не ошибаюсь на этот счет :)

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

пятница, 6 июня 2008 г.

Метод Path.Combine, который собирает путь из многочисленного набора аргументов.

Набрел на статью, которая открыла мне глаза :)

Почему-то я постоянно использовал неудобный Path.Combine(string, string) и ничего с этим не делал.

Настало время перемен :)

воскресенье, 18 мая 2008 г.

Очень креативный скрин с LORа

Друзья, эта картинка просто выносит мозг.


Я думаю что после этого скриншота вопросов о пределах креативности сообщества пользователей Linux вообще не будет...

...после того как пройдет истерика, традиционно прочесть все комментарии...

среда, 2 апреля 2008 г.

Правила внятной обработки ошибок на .NET

Я довольно неравнодушно отношусь к организации обработки ошибок.

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

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

От себя добавлю, что даже я не соблюдаю все из перечисленных автором моментов.
Естественно, что это очень плохо...

четверг, 6 марта 2008 г.

Фильм "Семь"

На днях еще раз посмотрел фильм "Семь".

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

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


Джон
: Ничего плохого если человек любит свое дело,
Не буду отрицать, что хочу повернуть грех против грешников

Милз: Подожди, но ты же убиваешь невинных

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

Милз: Убийцы...

Джон: А женщина...

Милз: Убийцы как ты сам, Джон

Джон: Женщина! Такая гадкая внутри, что не смогла бы жить, если только не ее красота снаружи
Торговец наркотиками, педераст и торговец наркотиками
Не забудем про шлюху, разносчицу заразы
Только в этом гавеном мире можно сказать что эти люди невинны
И сказать это не смеясь, вот в чем проблема


Вывод.

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

среда, 20 февраля 2008 г.

Очень полезный Add-in для VS 2003

Кому как, а мне иногда в дебагере очень хочется посмотреть содержимое DataSet :)

Причем хочется посмотреть содержимое целиком. А еще хочется скопировать содержимое, вставить в Exel и поиграться с автофильтрами...

В общем много чего разного хочется, и я вот узнал что все это оказывается очень даже возможно :)

Special QuickWatch for a DataSet