Wiki

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

Еще из необходимого ПО я считаю надо ставить wiki. К сожалению, предыдущий опыт не был сильно удачен. До этого я пробовал ставить википедии с помощью WebPlatform, насчет самой платформы нареканий нет, но представленные на тот момент википедии удручали. Одна не смогла доставить MySQL, да и сам MySQL не особенно желанный гость на моей машине. Второй движок ScrewWiki – вполне оправдывает свое название. Нифига не работает, редактирование паршивое, оформление тоже. Было решено отказаться от такого счастья. Поиск других движков не выглядел радужной перспективой и на какой-то момент я бросил это дело.

На днях снова заглянул в Web Platform Installer и обнаружил там новый движок для википедии, блогов, рассылок и чего-то в духе твиттера. Называется Incentive. До 10 зарегистрированных пользователей бесплатно.

Подробнее

Правила оформления кода C# v1.0

Волею судеб я попал в «девственные леса» организации, где не было разработок на C# и надо поставить все процессы с нуля. Систему контроля версий, процесс работы, сбор требований и учет работы. Правила оформления кода. Как раз первую версию такого документа я представляю на ваш суд. Я руководствуюсь исключительно своими предпочтениями в оформлении кода, которые позволяют мне быстро и эффективно ориентироваться по коду приложения.

Здесь отражено только форматирование кода, нет указаний на code smell или какие-либо еще недочеты в самом коде.

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

Краткое содержание:

  • Переменные
  • Использование VAR
  • Именование методов
  • Обрамление кода
  • Комментарии
  • Оформление блоков кода
  • Свойства
  • Логические операции
  • Организация класса

Подробнее

Assert DSL 1.1

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

По науке, тесты являются документированием системы. Грамотно написанные тесты дают понять, как работает система, как ведет себя, причем читаться все это должно как готовая спецификация на поведение системы. Т.е. в идеале должен получаться связный и понятный текст. Это идеал, к которому постепенно приближаются методы тестирования, начиная от юнит тестирования и наиболее явно проявляясь в поведенческом/приемочном тестировании, когда сами тесты уже пишутся на языке бизнеса (в этом моменте вспоминаем Fitnesse).

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

В общем, все должно быть направлено на максимальную ясность и четкость тестов, чтобы явно было видно все взаимосвязи. Чтобы можно было восстановить логику программы по одним лишь тестам. В дело читабельности пойдет не только Assert DSL (Domain Specific Language), но и именование файлов, подход Arrange Act Assert. Все это не новые подходы как оказывается, но широкой известности пока не получившие, судя по тому, что я вижу в окружающих меня проектах. Да и сам я натолкнулся на новые темы случайно, изучая исходные коды StructureMap.

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

  • Именовать тестовые файлы по основному методу, который тестируется.
  • Использовать DSL  для создания объектов, чтобы методы делать максимально лаконичными.
  • Стараться писать тесты в стиле «один тестовый метод – один assert».
  • Структурировать внутренности теста.
  • Создать и использовать Assert DSL.

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

Подробнее

Ненавистный INotifyPropertyChanged

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

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

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

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

К сожалению, при разработке пользовательского интерфейса на WPF такая реализация «в лоб» встречается до сих пор сплошь и рядом. Не далее чем неделю назад вычищал такой код из рабочего проекта. Я бы порадовался за трудолюбие и усидчивость разработчиков пишущих такой код, но я склонен думать, что программист должен быть ленивым. В хорошем смысле. Так что лучше потерять немного времени на настройку и потом быстро-быстро все сделать. Далее я опишу 4 более-менее различных подхода к решению данной проблемы.

Подробнее

MS SQL 2011 (Denali) – Автономная база данных

В течение последних лет Microsoft внедрила множество интересных технологий, которые прочно вошли в арсенал разработчиков. Кардинальные изменения были включены в SQL Server 2005, после чего SQL Server 2008 развил и укрепил успех. Denali несет в себе множество новых инструментов, а так же расширений функционала для существующих. В этой статье в деталях рассмотрим один из новых инструментов, который, я уверен, придется по душе разработчикам баз данных. Этот инструмент, фича ­ – автономные базы данных (Contained Database). Рассмотрим что они собой представляют, как с ними работать, к чему можно применить и другие вещи.

Что не так с текущими базами?

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

Вот некоторые из ключевых проблем:

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

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

Подробнее

MS SQL 2011 (Denali) – With Result Set

Модификация возвращаемого набора данных (NEW)

В оригинальном звучании и в жизни эта возможность звучит как With Result Set. Эта штука позволяет менять имена и типы данных в возвращаемом хранимой процедурой наборе данных.

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

Для демонстрации работы будем использовать в качестве примера таблицу tbl_Test состоящую из 3 колонок.

Подробнее

MS SQL 2011 (Denali) — Throw

Служебное слово Throw (NEW)

Новое полезное дополнение для SQL Server 2011 (Denali) ­– выражение Throw. Разработчики на .Net уже догадались наверно, где и как оно будет использоваться.

Это слово может использоваться в сочетании с управляющей конструкцией Try…Catch и позволяет послать уведомление о возникновении ошибки времени исполнения. Когда возникает исключение, программа ищет ближайший по иерархии вверх блок Catch который может обработать исключение. Используя это выражение внутри блока Catch можно изменить вывод ошибки. Более того, теперь вызывать исключение можно произвольно в любом месте скрипта.

Далее рассмотрим различные способы поимки исключении, которые предоставляет SQL Server начиная с версии 2000.

Подробнее

MS SQL 2011 (Denali) – Offset

Offset и Fetch First\Next выражения – расширения команды Order By (NEW)

В новом SQL Server 2011 (Denali) расширяются возможности команды Order By с помощью двух долгожданных дополнительных команд:

  • Offset (смещение)
  • Fetch First или Fetch Next (взять первые… или взять следующие…)

Offset

Использование данной команды позволяет пропустить указанное количество строк перед тем как выводить результаты запроса. Что под этим подразумевается: Допустим, у нас есть 100 записей в таблице и нужно пропустить первые 10 строк и вывести строки с 11 по 100. Теперь это легко решается следующим запросом:

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

Подробнее

MS SQL 2011 (Denali) – Sequence

Sequence (NEW) — последовательность

Возможность которой не удивишь нынче пользователей Oracle, DB2, PostgreSQL и множества других реляционных баз данных, наконец-то появилась и в SQL Server. На арене Sequence!

Sequence – генерирует последовательность чисел так же как и identity. Однако основным плюсом sequence является то, что последовательность не зависит от какой-либо конкретной таблицы и является объектом базы данных.

Рассмотрим пример скрипта написанного на SQL Server 2008. Создание простой таблицы с двумя колонками, одна из которых будет авто инкрементальной.

Похожим образом создадим еще одну таблицу.

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

Общий синтаксис для команды выглядит так:

Создадим последовательность чисел:

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

После того как объект создан, можно его использовать в создании и заполнении таблиц как показано ниже:

Если создать вторую таблицу в таком же духе, то можно снова использовать GenerateNumberSequence и получать сквозную нумерацию объектов.

Последовательность (Sequence) которую мы создали, можно посмотреть в системном каталоге sys.sequences.

Это не вся доступная информация по sequence, просто эти колонки нам понадобятся далее. Чтобы получить всю информацию замените имена колонок на звездочку. =) Про Is_Exhausted будет упомянуто позднее.

Sequence может быть следующих типов:

  • Int
  • Smallint
  • Tinyint
  • Bigint
  • Decimal
  • Numeric

Не обязательно начинать последовательность с единицы. Можно начинать с любого числа в пределах возможных значений объявленного типа. Например, для целочисленных значений это может быть от -2147483648 до 2147483647.

Проверим на практике, что скажет SQL Server при задании начального числа вне допустимого диапазона. Начнем с левой границы.

An invalid value was specified for argument ‘START WITH’ for the given data type.

Что и ожидалось. Теперь нарушим правую границу.

 

Сервер сообщит нам об ошибке так:

The sequence object ‘GenerateNumberSequence’ cache size is greater than the number of available values; the cache size has been automatically set to accommodate the remaining sequence values.

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

При попытке создать таблицу с использованием такой последовательности, сервер выдаст ошибку:

The sequence object ‘GenerateNumberSequence’ has reached its minimum or maximum value. Restart the sequence object to allow new values to be generated.

Это можно трактовать как просьбу движка рестартовать указанную последовательность. Для этого необходимо воспользоваться конструкцией RESTART WITH.

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

Т.е. если задать

 

А потом выполнить скрипт:

То результат будет таким:

Последовательность началась с заданного значения.

Получить минимальные и максимальные значения можно из каталога sys.sequences.

MIN и MAX значения

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

Минимальное значение равняется 10, максимальное – 20, но мы пытаемся задать начальное значение равное единице. Это за пределами допустимого диапазона и поэтому нас порадуют сообщением:

The start value for sequence object ‘GenerateNumberSequence’ must be between the minimum and maximum value of the sequence object.

Далее можем представить, что следующее значение в последовательности нарушает границу. В таком случае получим ошибку:

The sequence object ‘GenerateNumberSequence’ has reached its minimum or maximum value. Restart the sequence object to allow new values to be generated.

Для решения проблемы есть два пути:

  • Использовать служебные слова Restart или Restart With.
  • Использовать опцию CYCLE

Опция CYCLE

Данная опция зацикливает последовательность и, достигнув максимального значения, последовательность продолжается с минимального. Например:

 

После того как максимальное значение было достигнуто, результаты станут такими:

Для выборки использовался запрос:

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

Но из-за того, что вторая запись пересекла диапазон допустим значений, номер был сброшен на минимальное значение, заданное для последовательности (10). Если сейчас посмотреть в каталог sys.sequences, то будет видно, что текущее значение равняется 10.

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

В этот момент Sequence проверит порядок в котором записи будут вставлены и так как “Violet” идет раньше “Tape” и текущий номер равен 10, записи будут вставлены как:

Следующее_занчение =Текущее_значение +Сдвиг т.е. 10 +1 будет присвоено для  “Violet”. Теперь значение Sequence = 11 и для второй записи значение будет 12 следуя то же самой формуле.

Опция NO CYCLE

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

Sequence в сочетании с Over()

Можно использовать последовательность вместе с выражением Over для генерирования порядковых номеров как показано ниже:

Результат:

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

Ограничения использования Next Value для функций.

Sequence ни в каких случаях нельзя использовать в сочетании с:

  • Проверкой ограничений (constraints)
  • Значениями по умолчанию
  • Вычисляемыми колонками
  • Представлениями (views)
  • Пользовательскими функциями
  • Пользовательскими функциями агрегации
  • Подзапросами
  • СТЕ (Common Table Expression)
  • Подтаблицами
  • Выражением TOP
  • Выражением Over
  • Выражением  Output
  • Выражением On
  • Выражением Where
  • Выражением Group By
  • Выражением Having
  • Выражением Order By
  • Выражением Compute
  • Выражением Compute By

Функция sp_sequence_get_range

Если рассмотреть все использованные выше подходы к добавлению строк в таблицы используя NEXT VALUE FOR, то становится заметно, что это выражение присутствует в каждом уровне VALUES, что выглядит несколько утомительно. Вместо этого можно использовать функцию sp_sequence_get_range для получения необходимого диапазона значений, которые можно использовать впоследствии. Сейчас продемонстрирую как это можно осуществить.

Вот что будет в результате выполнения:

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

Сравнение между Sequence и Identity

Не стоит ставить между ними глобальный знак равенства из-за следующих факторов:

  • Identity относится к таблице и является ее частью неотделимой, Sequence – независимый объект базы данных.
  • Можно получить набор последовательности с помощью sp_sequence_get_range, что в принципе невозможно с Identity.
  • Для Sequence можно определять границы значений, что так же невозможно для Identity.
  • Цикличность значений можно задать так же только для Sequence.

И еще несколько слов про Sequence.

  • Sequence дает больший прирост производительности по сравнению с Identity. Сравнение и результаты в статье Аарона Бертарнда (Aaron Bertrand)
  • Можно задавать права доступа к Sequence, так же как и к другим объектам базы.

Почитать дополнительно о Sequence можно на MSDN:

  1. CREATE SEQUENCE
  2. Creating and Using Sequence Numbers
  3. sp_sequence_get_range

 

Дальше будет так же интересно, так что оставайтесь на связи. Перевод.

Hard’n’heavy!