Extensions, Static methods & null

23 окт. 2011 г. | | |

Методы расширения (extension methods), появившиеся ещё в C# 3.0,  - очень полезная штука.
Методы расширения позволяют "добавлять" методы в существующие типы без создания нового производного типа, перекомпиляции или иного изменения исходного типа. Методы расширения являются особым видом статического метода, но они вызываются, как если бы они были методами экземпляра в расширенном типе. (из MSDN)
Т.е. если в классе String нам не хватает какого-нибудь метода, то не нужно создавать еще один класс, наследуясь от String или, чего хуже, делая декоратор, а можно создать метод расширения:

public static class MyExtensions
{
        public static int WordCount(this String str)
        {
            return str.Split(new char[] { ' ', '.', '?' }, 
                             StringSplitOptions.RemoveEmptyEntries).Length;
        }
 }   
(пример тоже из MSDN)
Иногда бывает ситуация, когда нужно вызвать метод расширения в статическом методе класса. Но этого нельзя сделать, несмотря на то, что
Методы расширения являются особым видом статического метода, но они вызываются, как если бы они были методами экземпляра в расширенном типе. (из MSDN)

Но, если всё же очень надо, то есть пара приёмчиков :)

Assert.True()

21 окт. 2011 г. | | |

Рефакторинг

20 окт. 2011 г. | | |

Сегодня наткнулась на такой вот метод:

Ещё чуть-чуть о тестах

18 окт. 2011 г. | | |

И еще одна небольшая заметка о TDD, точнее о том, что такое тест в контексте TDD.
Начинающие тэдэдэшники часто переусердствуют, стараясь тестировать всё и вся, забывая, что тест в TDD - это небольшой метод, проверяющий конкретное бизнес-правило. Акцент тут следует сделать на бизнес-правилах, они специфицируют поведение приложения, именно их нужно тестировать. С помощью TDD мы разрабатываем бизнес-логику. Не следует тестировать работу с БД, с файловой системой, сетевое взаимодействие - это уже совсем другой вид тестирования. Это интеграционные тесты. TDD позволяет нам быстро разрабатывать бизнес-логику, подтверждая работоспособность (или наоборот) кода мгновенным фидбеком. Если приходится специально что-то настраивать, чтобы запустить тест, и настройка занимает больше времени, чем написание самого теста, следует насторожиться. Метод для теста должен быть черным ящиком: известно только, что на входе, нужно удостовериться в правильности того, что на выходе.
В реальной жизни часто бывает так, что нужно взять выборку из БД и подсунуть данные методу для выполнения сложных расчетов. Для тестирования таких методов придумали Mocks, Fackes, Dummies & Stubs. Все эти технологии позволяют абстрагироваться от уровня физического взаимодействия, генерируя методы-заглушки. А методы заглушки возвращают тот набор данных, который им подсовываем. Чтобы было понятнее, вот простенький пример с Mock-библиотекой Moq.

to ORM or not to ORM?

16 окт. 2011 г. | | |

Плюсы и минусы ORM обсуждались не раз. Скорость vs удобство (отсутствие чистого SQL в коде), возможность тонкой настройки запросов для узких мест vs машинная генерация запросов (порой не оптимизированных)... Да и вобще, кому нужны эти лишние прослойки?
Почему стоит отказаться от ORM рассказывает Rob Conery в своём докладе "Kill Your ORM" на NDC 2011 , где, кстати, было очень много интересных докладов.


Максим Цепков. Domain Driven Design - модель вместо требований

11 окт. 2011 г. | | |

Выступление Максима Цепкова на Летнем Аналитическом Фестивале - 2011. Иваново, 25 июня 2011 года.

Запахи TDD

8 окт. 2011 г. | | |

Перевод статьи "TDD Process Smells "

Данный список запаховболее сфокусирован на выполнении принципов самого TDD процесса, чем на  содержимом тестов. Без сомнения, существует множество подобных запахов; я же выбрал наиболее часто встречающиеся по правилу 7 (+/- 2).

Linq DataContext и Dispose

7 окт. 2011 г. | | |

Как известно, любой DataContext объект является IDisposable. При использовании конструкции вида
using (CDataContext db = new CDataContext(ConnectionPool.Connection)) {...}
метод  Dispose() вызывается автоматически, и все занимаемые ресурсы освобождаются.
Насколько критично вызывать метод Dispose() вручную для такого кода?
CDataContext db = new CDataContext(ConnectionPool.Connection);
 return (from tbl in db._addresses
        where tbl.IsCustomer.Equals(true)
        select tbl).ToList();

Перефразируя вопрос: что плохого случится, если не вызвать  Dispose()? Ведь GC всё равно вызовет этот метод, разве что не сразу. DataContext не держит соединение c БД открытым (только, если не открывать его явным способом вроде DataContext.Connection.Open() ) т.е. никаких тяжеловесных ресурсов не занимает, и ничего плохого не происходит. Т.е. совсем не обязательно вручную вызывать Dispose().
Но. Если вы напишите такой код
using(CDataContext db = new CDataContext(ConnectionPool.Connection))
{
    return (from tbl in db._addresses
            where tbl.IsCustomer.Equals(true)
            select tbl);

}
произойдёт исключение "Cannot access a disposed object. Object name: 'DataContext accessed after Dispose.", потому что дерево запроса (возвращаемый тип  IQueryable<_address>) попытается выполнится после того, как DataContext будет уничтожен. Произойдёт это потому, что запрос выполнится тогда, когда будет впервые вызвано перечисление элементов (метод ToList<T>(), например). Если же написать такой код
CDataContext db = new CDataContext(ConnectionPool.Connection)
 return (from tbl in db._addresses
        where tbl.IsCustomer.Equals(true)
        select tbl);

то нужно понимать, что DataContext откроет соединение к базе, извлечет элементы и будет уничтожен только в том месте кода, где произойдет IQueryable<_address>.ToIEnumerable<_address>()

Чего нет в SQL Server Compact 4.0

4 окт. 2011 г. | | |

А нет в 4-ом компакте целой кучи всего:
  1. Репликация данных с SQL Server - ни через Sync Framework, ни через слияние или удаленный доступ к данным. 
  2. Нет поддержки службы SQL Server 2008 Integration Services (SSIS)
  3. SQL Server Management Studio для Sql Server Compact 4 тоже не поддерживается
  4. О мобильных платформах (Windows Mobile, Windows Phone или Windows CE) тоже можно забыть. 
  5. Не поддерживается LINQ to SQL (чего стоило, но не хотелось, ожидать). Все дружно переходим на Entity Framework.

Но всё это поддерживается в SQL Server Compact 3.5 SP2.
Т.е. для того, чтобы перевести существующий проект (SQL CE 3.5 + Linq2Sql) на использование Sql Server CE 4.0, нужно заодно  переехать на Entity Framwork либо другую ORM-прослойку. Стоит ли оно того, вот в чем вопрос.