Monthly Archives: Август 2011

Уведомление о встрече

В четверг 18 августа в 14-00 состоится очередное заседание клуба, на котором планируется заслушать выступление Евгения.

Минимальное качество кода

Перед тем, как кому-нибудь показывать последние изменения в проекте (т.е. делать check-in), полезно проверить, что код удовлетворяет минимальным требованиями к качеству.

  1. Необходимо проверить, что код вообще компилируется. Если check-in делается для части файлов, то необходимо убедиться, что новые изменения никак не связаны с файлами, которые остаются незалитыми. Кроме того, полезно проверить, что все необходимые dll залиты на ТФС.
  2. Необходимо исправить предупреждения, которые пишет Resharper, кроме некоторых замечаний, которые можно отключить. Например, требование соответствия структуры папок структуре namespace. Возражения вроде того, что Resharper «тупит» очень часто на поверку оказываются верными с точностью до наоборот.
  3. Новый код должен быть документирован при помощи xml-комментариев. Тэги summary, param и returns обязательны для заполнения. Примеры, как заполняются эти теги, можно смотреть в русской версии msdn. Старый код можно оставлять без комментариев до того момента, как там придется что-то менять.
  4. Необходимо провести проверку нового кода с помощью Code Analysis.

Code Analysis выполняется следующим образом. Сначала в свойствах нужного проекта выбирается набор применяемых правил. Для простоты можно выбрать стандартный набор правил Microsoft Minimum Recommended Rules.

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

Все найденные замечания отобразятся в стандартной панели.

Если какое-то замечание было определено неправильно (а такое бывает не так уж и часто), то его можно убрать, нажав пункт Supress warning в контекстном меню.

О пользе подписывания чекинов

В случае когда команда Check-in используется как команда Save (т.е. check-in происходит без написания комментариев раз в день или «когда накопились изменения»), возникают следующие проблемы:

  • при желании откатить одни изменения вероятно придется откатывать и другие изменения, залитые в том же check-in;
  • непонятно, в каком из check-in находится то изменение, которое требуется откатить;
  • для стороннего наблюдателя непонятно, что изменилось в проекте после последнего изменения.

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

Заливка dll на тфс

Очень часто проект использует какие-то компоненты, не входящие в состав .NET Framework. Если таковые были добавлены в ссылки проекта (через Add reference), то при открытии такие ссылки отобразятся примерно вот так.

Это происходит потому, что Visual Studio не может найти требующиеся dll на локальном компьютере.

Чтобы не заставлять каждого, кто хотел бы взглянуть на проект, судорожно искать необходимые компоненты, правильнее заливать эти компоненты в ТФС наравне с файлами с кодом.

Так можно создавать папку Lib в корневом каталоге в ТФС, туда добавлять нужные dll — а потом добавлять ссылки через окно Browse, отыскивая там dll в этой папке. Однако, чтобы при открытии проекта Visual Studio скачала данные dll из папки Lib, необходимо сделать данные файлы файлами проекта. Проще всего это можно сделать путем добавления этих dll через Add existing item (+ Add as link) в нужный проект.

Процедура добавления «as link» гарантирует обновления dll в проекте при обновлении их в папке Lib. После добавления нужно сделать Build action равным None у всех добавленных файлов.

Метод Merge в паттерне Команда

Чаще всего в паттерне Команда реализуют методы Do и Undo, которые выполняют и отменяют выполнение команды соответственно. Однако возникают ситуации, когда действия пользователя соответствуют целому ряду однотипных команд, которые пользователь ожидает отменять за один раз. Например, если печатание одной буквы в текстовом редакторе соответствует одной команде, то пользователь ожидает от программы отмены ввода больше, чем по одной букве за раз. В этом случае можно применить технику слияния нескольких команд при помощи метода Merge. Merge входит в базовый интерфейс, но реализуется только для тех команд, которые поддерживают слияние. Результатом Merge является новая команда, результатом выполнения которой будет совокупное действие слитых команд и которая может быть отменена за один раз.

Автогенерация документации

Правильно написанные xml комментарии в коде позволяют в последующем автоматически генерировать документацию к этому коду (так называемый class reference в стиле документации msdn). Официальной утилитой от Microsoft в этом деле является SandCastle, а также набор графических утилит к ней.
Полезными атрибутами документирования кода являются

  • summary — общее описание класса или метода;
  • remarks — более подробное описание особенностей использования кода;
  • see — ссылка на класс;
  • seealso — ссылка на связанный класс;
  • example — пример использования;
  • code — блок кода;
  • exception — описание условий возникновения тех или иных исключений;
  • param — описание параметра;
  • paramref — ссылка на параметр;
  • returns — возвращаемое значение;
  • value — описание значения свойства.

Кроме того, подобный метод позволяет проверять полноту документирования при помощи различных утилит наподобие Resharper, а также иметь документацию, никогда не отрывающуюся от кода, который она описывает.
Ниже приведен xml комментарий к методу AddTable, который добавляет новую таблицу в бд в библиотеке LoBDb.Net.

/// <summary>
/// Adds a new user-defined table with the specified name.
/// </summary>
/// <remarks>
/// The current user has to have the permission to change the schema in order to execute this function.
/// </remarks>
/// <param name = "tableName">The name of the new table.</param>
/// <returns>Returns the newly created user-defined table.</returns>
/// <exception cref = "System.ArgumentNullException">Thrown when the value of <paramref name = "tableName" /> is null.</exception>
/// <exception cref = "System.ArgumentException">Thrown when the value of <paramref name = "tableName" /> is an empty string.</exception>
/// <exception cref = "System.ArgumentException">Thrown when the value of <paramref name = "tableName" /> is too long.</exception>
/// <exception cref = "System.ArgumentException">Thrown when the value of <paramref name = "tableName" /> doesn't start with a letter.</exception>
/// <exception cref = "System.ArgumentException">Thrown when the value of <paramref name = "tableName" /> contains a forbidden symbol.</exception>
/// <exception cref = "System.ArgumentException">Thrown when the value of <paramref name = "tableName" /> is a keyword in one of the supported dbms.</exception>
/// <exception cref = "System.Data.Common.DbException">Thrown when a table with the same name already exists.</exception>
/// <exception cref = "System.Data.Common.DbException">Thrown when the current user has no permission to execute this function.</exception>
/// <example>
/// The following code shows how to create a new user-defined table with the specified name.
/// <code>
/// using System;
/// using Centido.Core;
///
/// class DomainSample
/// {
/// static void Main()
/// {
/// var domainConfig = new DomainConfiguration()
/// {
/// DbConnectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=MyDb;User Id=admin;Password=P@assw0rd;",
/// DbProviderName = "System.Data.SqlClient"
/// };
///
/// var domain = Domain.Build(domainConfig);
///
/// domain.DeleteAll();
///
/// //Creating a new table
/// var studentTable = domain.AddTable("students");
///
/// //Creating a table column
/// var nameColumn = studentTable.AddColumn("name", ColumnType.String)
/// as StringColumn;
/// nameColumn.DisplayName = "The student name";
///
/// //Enumerating the table columns
/// foreach(var column in studentTable.Columns)
/// {
/// Console.WriteLine("Column: name = {0}, display name = {1}",
/// column.Name, column.DisplayName);
/// }
/// }
/// }
/// </code>
/// </example>
public Table AddTable(string tableName)

Уведомление о встрече

В четверг 11 августа в 14-00 состоится очередная встреча. Подобные встречи будут посвящены design-review и design-preview у тех участников, которые будут к тому моменту проектировать новую функциональность в своих проектах или соответственно заканчивать подобные работы. Судя по всему, к следующей встрече можно будет сделать design-review у Данила, который закончит проектирование своего компонента, и у Евгения, который может рассказать про проектирование и тестирование фабрик классов. Во время проведения design-review участникам следует обеспечить доступ к обсуждаемому коду.

Методы тестирования ПО

Презентация c выступления.
Книга, по которой была сделана презентация.

Уведомление о встрече

Очередная встреча клуба состоится в понедельник 8 августа в 14-00. Темой встречи будет автоматическое тестирование кода посредством написания юнит-тестов.

Впечатления от использования ORM от Microsoft

В ходе использования таких ORM от Microsoft, как LinqToSql и Entity Framework 4.0, были обнаружены следующие подводные камни.

Microsoft Entity Framework 4.
1) Неудобство работы с дизайнером модели:
a. невозможность редактирования физической модели (через дизайнер) приводит к необходимости каждый раз вызывать команду ”Update model from database”, которая обновляет не только физическую модель, но и удаляет все изменения в концептуальной модели в случае, если они не согласуются с принципами построения «по умолчанию»;
b. все сущности модели нужно помещать на единственную диаграмму, что бывает затруднительно для восприятия, если число таких сущностей превышает определенный порог;
c. стратегию наследования Table-Per-Concrete type (TPC) и автогенерирующиеся ключи GUID нельзя настроить, используя исключительно дизайнер;
d. невозможность менять порядок полей сущностей при отображении их в дизайнере.
2) Плохая совместимость со сторонними СУБД:
a. Хотя и существуют бесплатные ADO.Net провайдеры для разных СУБД, однако для их полноценной работы с Entity Framework требуется специальная поддержка (вследствие этого после выхода каждой новой версии Entity Framework соответствующие провайдеры для сторонних СУБД появляются со значительным опозданием);
b. Бесплатные провайдеры есть не для всех сторонних СУБД;
3) Отсутствие возможности отмены всех несохраненных изменений (можно отменять изменения только в отдельных сущностях);
4) Неудобство редактирования модели в XML:
a. концептуальная и физическая модели, отображение одной в другую, а также служебная информация, используемая дизайнером, хранится в одном файле, что делает поиск нужной информации проблематичным;
5) Невозможность указания стратегии замещения объектов при выполнении запросов (т.е. нельзя указать LoadBehavior=Replace);
6) Отсутствие возможности асинхронного выполнения запросов.

Microsoft Linq to Sql.
1) Поддержка исключительно СУБД от Microsoft;
2) Невозможность указания стратегии замещения объектов при выполнении запросов (т.е. нельзя указать LoadBehavior=Replace).
3) Отсутствие поддержки работы в Disconnected mode.
4) Отсутствие оператора Include на уровне запросов (есть только LoadWith на уровне контекста).
5) Опции LoadWith работают, только если совсем отключить EagerLoading.
6) Глубина подгрузки при EagerLoading ограничена одним уровнем вниз.

Итоговый вывод — воздержаться от использования ORM от Microsoft до тех пор, пока эти технологии не будут наконец доделаны.