вторник, 20 апреля 2010 г.

Кремниевая долина

Занятная картинка.


Хорошо нашему брату там небось живеться. Скучно работать в Oracle? Иди в Google:)
PS. Не знал, что Aricent в кремниевой долине есть.

суббота, 3 апреля 2010 г.

Code Contracts

Есть такое понятие, как самотестируемый код(не путать с тестами). Общая суть в том, что в дебажную сборку программы добавляются проверки необходимых для успешной работы условий, и если условие не выполняется - значит что-то пошло не так.
К примеру, в неком методе необходимо проверить входные параметры, а не null ли передался вместо полноценного объекта? Затем проверить результат работы метода.

static void SomeMethod(object param)
{
    // проверяем входные параметры
    Debug.Assert(param != null);
    
    // делаем что-то важное...
    DoSomethingImportant();    

    // проверяем результат работы
    Debug.Assert(somethingImportant != somethingUnimportant); 
}

Хорошо. Но не слишком удобно, так как предусловия и постусловия проверяются в разных 
местах. 

Ну а теперь перейдем к самому интересному. С относительно недавних пор (начало 2009 
года) у Microsoft есть такой продукт как Code Contracts (в Java как мне сказали 
аналог есть давно). Данная библиотека пока не является ни частью .NET, ни частью 
Visual Studio. По крайней мере с VS2010 Beta 2, она не ставилась. А так у меня 
поставилась на VS2008 и интегрируется с msbuild.

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;

namespace CodeContractsTest
{
    class Program
    {

        static void Main(string[] args)
        {
            List listEven = new List() { 2, 4, 6, 8};
            AddItem(listEven, 10);

            // последующий вызов вызовет исключение
            //AddItem(listEven, 11);


            foreach (var item in listEven)
            {
                Console.WriteLine(item);
            }

            Console.ReadKey();
        }

        static void AddItem(List list, int item)
        {
            Contract.Requires(item % 2 == 0);
            Contract.Ensures(list.Count <= 6);
            Contract.Ensures(list.Count == Contract.OldValue(list.Count) + 1);

            list.Add(item);
            //последующий вызов вызовет исключение
            //list.Add(item);
        }

    }
}

Как видим в нашем распоряжении есть два наглядных метода для проверки пре- (Requires)
и постусловий Ensures. Это гораздо нагляднее чем использовать Debug.Assert, хотя
Contract.Assert тоже есть:) Есть еще атрибуты [ContractClass] и [ContractClassFor].
Можно объявить интерфейс, обозначить его [ContractClass], затем создать класс,
реализующий этот интерфейс, обозначить его как [ContractClassFor] и реализовать в
нем контракт. И все классы, которые будут реализовывать наш интерфейс по умолчанию
будут проверяться на соответствие контракту.

Ссылка на Code Contracts: http://research.microsoft.com/en-us/projects/contracts/

PS. Точнее в VS210 Beta 2. По умолчанию можно подключить сборку
System.Diagnostics.Contracts, и даже писать ее методы (компилироваться будет, но
работать нет). И только после того, как библиотеку установить, в свойствах проекта
появиться Code Contracts и с ними можно будет работать.