<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Andrei Marukovich&#039;s blog</title>
	<atom:link href="http://lunarfrog.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://lunarfrog.com/blog</link>
	<description>Willing to learn and share</description>
	<lastBuildDate>Tue, 01 Dec 2009 04:32:24 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Паттерн Dependency Injection и введение в Ninject &#8211; DI фреймворк для .NET</title>
		<link>http://lunarfrog.com/blog/2009/11/30/%d0%bf%d0%b0%d1%82%d1%82%d0%b5%d1%80%d0%bd-dependency-injection-%d0%b8-%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2-ninject-di-%d1%84%d1%80%d0%b5%d0%b9%d0%bc%d0%b2%d0%be%d1%80%d0%ba/</link>
		<comments>http://lunarfrog.com/blog/2009/11/30/%d0%bf%d0%b0%d1%82%d1%82%d0%b5%d1%80%d0%bd-dependency-injection-%d0%b8-%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2-ninject-di-%d1%84%d1%80%d0%b5%d0%b9%d0%bc%d0%b2%d0%be%d1%80%d0%ba/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 02:53:25 +0000</pubDate>
		<dc:creator>Andrei Marukovich</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://lunarfrog.com/blogs/?p=17</guid>
		<description><![CDATA[В статье показывается пример тесно связанных классов, проводиться их рефакторинг с реализацией паттерна Dependency Injection (внедрение зависимости) и демонстрируется применение фреймворка Ninject, облегчающего внедрение зависимостей.
public class Engine
{
public double GetSize()
{
return 2.5; // in liters
}
}
public class Car
{
private readonly Engine _engine;
public Car()
{
_engine = new Engine();
}
public void GetDescription()
{
Console.WriteLine(&#8220;Engine size: {0}&#8221;, _engine.GetSize());
}
}
class Program
{
static void Main()
{
Car car = new Car();
car.GetDescription();
}
}
Каждый из [...]]]></description>
			<content:encoded><![CDATA[<p>В статье показывается пример тесно связанных классов, проводиться их рефакторинг с реализацией паттерна Dependency Injection (внедрение зависимости) и демонстрируется применение фреймворка Ninject, облегчающего внедрение зависимостей.</p>
<blockquote><p><code><span style="font-family: Courier New; color: black; font-size: small;"><span style="color: #0600ff;">public</span> <span style="color: #0600FF;">class</span> Engine<br />
<span style="color: #000000;">{</span><br />
<span style="color: #0600ff;">public</span> <span style="color: #0600FF;">double</span> GetSize<span style="color: #000000;">(</span><span style="color: #000000;">)</span><br />
<span style="color: #000000;">{</span><br />
<span style="color: #0600ff;">return</span> <span style="color: #0600FF;">2.5</span><span style="color: #008000;">;</span> <span style="color: #008080;"><em>// in liters</em></span><br />
<span style="color: #000000;">}</span><br />
<span style="color: #000000;">}</span></span></code></p>
<p><span style="color: #0600ff;">public</span> <span style="color: #0600FF;">class</span> Car<br />
<span style="color: #000000;">{</span><br />
<span style="color: #0600ff;">private</span> <span style="color: #0600ff;">readonly</span> Engine _engine<span style="color: #008000;">;</span></p>
<p><span style="color: #0600ff;">public</span> Car<span style="color: #000000;">(</span><span style="color: #000000;">)</span><br />
<span style="color: #000000;">{</span><br />
_engine <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> Engine<span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span><br />
<span style="color: #000000;">}</span></p>
<p><span style="color: #0600ff;">public</span> <span style="color: #0600ff;">void</span> GetDescription<span style="color: #000000;">(</span><span style="color: #000000;">)</span><br />
<span style="color: #000000;">{</span><br />
Console.<span style="color: #0000ff;">WriteLine</span><span style="color: #000000;">(</span><span style="color: #666666;">&#8220;Engine size: {0}&#8221;</span>, _engine.<span style="color: #0000ff;">GetSize</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span><br />
<span style="color: #000000;">}</span><br />
<span style="color: #000000;">}</span></p>
<p><span style="color: #0600FF;">class</span> Program<br />
<span style="color: #000000;">{</span><br />
<span style="color: #0600ff;">static</span> <span style="color: #0600ff;">void</span> Main<span style="color: #000000;">(</span><span style="color: #000000;">)</span><br />
<span style="color: #000000;">{</span><br />
Car car <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> Car<span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span><br />
car.<span style="color: #0000ff;">GetDescription</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span><br />
<span style="color: #000000;">}</span><br />
<span style="color: #000000;">}</span></p></blockquote>
<p>Каждый из нас писал подобный код хотя бы раз в жизни. А те, в чьи обязанности входит проверка кода начинающих программистов, могут видеть это достаточно часто. С синтаксической и логической точек зрения в нем нет ничего криминального. Код отлично отработает, выполнив все от него ожидаемое, и в нем абсолютно ничего не надо трогать, если это часть программы состоящей из пяти классов. Вопросы возникают, когда такой код появляется в реальном проекте, насчитывающем десятки классов, имеющем длинный жизненный цикл и большую вероятность изменения пользовательских требований, способа хранения данных или поддерживаемого оборудования.</p>
<p>Чем же он плох? Если кратко, то зависимостью конкретного класса Car от конкретного класса Engine. Представим, что конструктор класса Engine измениться – в этом случае придется менять и Car. Или, к примеру, появиться еще один двигатель. И что бы машина смогла его использовать, опять-таки, понадобиться изменить класс Car. Кроме того, подобная жестко запрограммированная  зависимость снижает тестируемость классов – класс Car невозможно протестировать отдельно от Engine или заменить Engine на ложный объект, для симуляции непредвиденных обстоятельств.</p>
<p>Что же можно сделать для улучшения кода? Первое – ввести интерфейс IEngine, который будет реализовываться классом Engine.</p>
<blockquote><p><code><span style="font-family: Courier New; color: black; font-size: small;"><span style="color: #0600ff;">public</span> <span style="color: #0600ff;">interface</span> IEngine<br />
<span style="color: #000000;">{</span><br />
<span style="color: #0600ff;">double</span> GetSize<span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span><br />
<span style="color: #000000;">}</span></span></code></p>
<p><span style="color: #0600ff;">public</span> <span style="color: #0600ff;">class</span> Engine <span style="color: #008000;">:</span> IEngine<br />
<span style="color: #000000;">{</span><br />
<span style="color: #0600ff;">public</span> <span style="color: #0600ff;">double</span> GetSize<span style="color: #000000;">(</span><span style="color: #000000;">)</span><br />
<span style="color: #000000;">{</span><br />
<span style="color: #0600ff;">return</span> <span style="color: #0600ff;">2.5</span><span style="color: #008000;">;</span> <span style="color: #008080;"><em>// in liters</em></span><br />
<span style="color: #000000;">}</span><br />
<span style="color: #000000;">}</span></p></blockquote>
<p>Далее, изменить класс Car, что бы вместо класса Engine в нем использовался интерфейс IEngine. И второе, не менее важное изменение – класс Car не должен создавать двигатель сам, теперь конструктор получает ссылку на объект, реализующий интерфейс IEngine.</p>
<blockquote><p><code><span style="font-family: Courier New; color: black; font-size: small;"><span style="color: #0600ff;">public</span> <span style="color: #0600ff;">class</span> Car<br />
<span style="color: #000000;">{</span><br />
<span style="color: #0600ff;">private</span> <span style="color: #0600ff;">readonly</span> IEngine _engine<span style="color: #008000;">;</span></span></code></p>
<p><span style="color: #0600ff;">public</span> Car<span style="color: #000000;">(</span>IEngine engine<span style="color: #000000;">)</span><br />
<span style="color: #000000;">{</span><br />
_engine <span style="color: #008000;">=</span> engine<span style="color: #008000;">;</span><br />
<span style="color: #000000;">}</span></p>
<p><span style="color: #0600ff;">public</span> <span style="color: #0600ff;">void</span> GetDescription<span style="color: #000000;">(</span><span style="color: #000000;">)</span><br />
<span style="color: #000000;">{</span><br />
Console.<span style="color: #0000ff;">WriteLine</span><span style="color: #000000;">(</span><span style="color: #666666;">&#8220;Engine size: {0}L&#8221;</span>, _engine.<span style="color: #0000ff;">GetSize</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span><br />
<span style="color: #000000;">}</span><br />
<span style="color: #000000;">}</span></p></blockquote>
<p>И последнее, что необходимо сделать – это изменить функцию Main.</p>
<blockquote><p><code><span style="font-family: Courier New; color: black; font-size: small;"><span style="color: #0600ff;">class</span> Program<br />
<span style="color: #000000;">{</span><br />
<span style="color: #0600ff;">static</span> <span style="color: #0600ff;">void</span> Main<span style="color: #000000;">(</span><span style="color: #000000;">)</span><br />
<span style="color: #000000;">{</span><br />
IEngine engine <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> Engine<span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span><br />
Car car <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> Car<span style="color: #000000;">(</span>engine<span style="color: #000000;">)</span><span style="color: #008000;">;</span></span></code></p>
<p>car.<span style="color: #0000ff;">GetDescription</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span><br />
<span style="color: #000000;">}</span><br />
<span style="color: #000000;">}</span></p></blockquote>
<p>Получившееся в результате решение легче расширяемо, более тестируемо и является примером реализации паттерна Dependency Injection (внедрение зависимости) – зависимость машина-двигатель конфигурируется не внутри класса, а двигатель, созданный вне класса, внедряется в него.</p>
<p>Минус такого решения – потерялась простота создания нового экземпляра класса Car. Представьте, если в программе достаточно много подобных зависимостей, их все придется создавать вручную снова и снова. Поэтому, мы пойдем дальше и посмотрим, как можно облегчить жизнь используя Ninject, фреймворк для автоматического внедрения зависимостей.</p>
<h3>Ninject</h3>
<p>Основную идею использования DI фреймворков для создания объектов можно описать так: &#8220;Мне нужен объект класса A, создай его, и меня не интересует, что и как ты для этого будешь делать&#8221;. И вот как будет выглядеть создание машины с использованием Ninject:</p>
<blockquote><p><code><span style="font-family: Courier New; color: black; font-size: small;"><span style="color: #0600ff;">class</span> Program<br />
<span style="color: #000000;">{</span><br />
<span style="color: #0600ff;">static</span> <span style="color: #0600ff;">void</span> Main<span style="color: #000000;">(</span><span style="color: #000000;">)</span><br />
<span style="color: #000000;">{</span><br />
<span style="color: #008080;"><em>// Ninject Initialization</em></span><br />
IKernel ninjectKernel <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> StandardKernel<span style="color: #000000;">(</span> <span style="color: #008000;">new</span> MyConfigModule<span style="color: #000000;">(</span><span style="color: #000000;">)</span> <span style="color: #000000;">)</span><span style="color: #008000;">;</span></span></code></p>
<p><span style="color: #008080;"><em>// Using Car</em></span><br />
Car car <span style="color: #008000;">=</span> ninjectKernel.<span style="color: #0000ff;">Get</span><span style="color: #008000;">&lt;</span>Car<span style="color: #008000;">&gt;</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span><br />
car.<span style="color: #0000ff;">GetDescription</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span><br />
<span style="color: #000000;">}</span><br />
<span style="color: #000000;">}</span></p></blockquote>
<p>Что такое ninjectKernel станет понятно чуть позже, а сейчас стоит обратить внимание на отсутствие любого упоминания IEngine или Engine. Благодаря предварительной конфигурации Ninject знает, что машине требуется двигатель и когда его просят создать новый экземпляр класса Car, он самостоятельно создает Engine и передает его в конструктор Car. Таким образом, все что требуется – это запросить класс. Все зависимости, необходимые для его создания или работы, DI фреймворк разрешит самостоятельно. Если, конечно, он был предварительно правильно сконфигурирован.</p>
<p>Ninject можно или загрузить с сайта <a rel="nofollow" href="http://ninject.org">Ninject.org</a> в виде стабильной версии, или взять в виде актуальных исходных файлов из репозитория. Я рекомендую воспользоваться вторым способом, так как версия, находящаяся в репозитории, поддерживает несколько новых возможностей, в том числе код для интеграции с ASP.NET MVC.</p>
<p>Для начала работы с Ninject, в проект необходимо добавить ссылку на сборку <em>Ninject.Core.dll</em>, реализующую базовые возможности фреймворка. Второй шаг – конфигурирование. К сожалению, Dependency Injection – это не магия и что бы Ninject знал, каким образом разрешать зависимости, он должен быть проинструктирован. Для нашей программы необходимы только две инструкции:</p>
<blockquote><p><code><span style="font-family: Courier New; color: black; font-size: small;">Bind<span style="color: #008000;">&lt;</span>IEngine<span style="color: #008000;">&gt;</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span>.To<span style="color: #008000;">&lt;</span>Engine<span style="color: #008000;">&gt;</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span><br />
Bind<span style="color: #008000;">&lt;</span>Car<span style="color: #008000;">&gt;</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span>.ToSelf<span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span></span></code></p></blockquote>
<p>В то время как многие DI фреймворки полагаются на конфигурационные XML файлы, Ninject имеет простой, интуитивно понятный API для задания зависимостей, использующий привычный синтаксис языка и позволяющий задействовать все возможности IDE.</p>
<p>Первая инструкция связывает интерфейс IEngine с классом Engine таким образом, что всякий раз, когда Ninject обнаружит необходимость в объекте типа IEngine, то будет создан объект Engine. Вторая инструкция описывает желаемое поведение при запросе на создание экземпляра класса Car – необходимо создать этот экземпляр, все просто. На самом деле, вторая инструкция не обязательна – такое поведение реализуется фреймворком по умолчанию. При необходимости автосвязывание классов можно и отключить, и настраивать все самому.</p>
<p>Теперь возникает вопрос – а где выполнять конфигурирование? Конфигурирование выполняется в виртуальном методе Load класса, реализующего интерфейс IModule. Проще всего будет наследовать такой класс от класса StandardModule.</p>
<blockquote><p><code><span style="font-family: Courier New; color: black; font-size: small;"><span style="color: #0600ff;">public</span> <span style="color: #0600ff;">class</span> MyConfigModule <span style="color: #008000;">:</span> StandardModule<br />
<span style="color: #000000;">{</span><br />
<span style="color: #0600ff;">public</span> <span style="color: #0600ff;">override</span> <span style="color: #0600ff;">void</span> Load<span style="color: #000000;">(</span><span style="color: #000000;">)</span><br />
<span style="color: #000000;">{</span><br />
Bind<span style="color: #008000;">&lt;</span>Car<span style="color: #008000;">&gt;</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span>.ToSelf<span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span><br />
Bind<span style="color: #008000;">&lt;</span>IEngine<span style="color: #008000;">&gt;</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span>.To<span style="color: #008000;">&lt;</span>Engine<span style="color: #008000;">&gt;</span><span style="color: #000000;">(</span><span style="color: #000000;">)</span><span style="color: #008000;">;</span><br />
<span style="color: #000000;">}</span><br />
<span style="color: #000000;">}</span></span></code></p></blockquote>
<p>При желании, может быть создано несколько таких модулей, например для разделения конфигураций для различных частей программы. Далее эти модули используются для создания контейнера, который и будет выполнять для нас всю грязную работу.</p>
<blockquote><p><code><span style="font-family: Courier New; color: black; font-size: small;">IKernel kernel <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> StandardKernel<span style="color: #000000;">(</span>cfg1, cfg2, …<span style="color: #000000;">)</span><span style="color: #008000;">;</span></span></code></p></blockquote>
<p>Информации, приведенной выше, достаточно для начала работы с Ninject, но недостаточно для реализации более сложных сценариев. Такие возможности как контекстно-зависимое связывание, связывание, основанное на соглашениях, контроль времени жизни, существенно расширяют возможности применения Ninject и будут описаны в следующей статье.</p>
]]></content:encoded>
			<wfw:commentRss>http://lunarfrog.com/blog/2009/11/30/%d0%bf%d0%b0%d1%82%d1%82%d0%b5%d1%80%d0%bd-dependency-injection-%d0%b8-%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2-ninject-di-%d1%84%d1%80%d0%b5%d0%b9%d0%bc%d0%b2%d0%be%d1%80%d0%ba/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Библиотека Code Contracts: контрактное программирование под .NET</title>
		<link>http://lunarfrog.com/blog/2009/11/30/%d0%b1%d0%b8%d0%b1%d0%bb%d0%b8%d0%be%d1%82%d0%b5%d0%ba%d0%b0-code-contracts-%d0%ba%d0%be%d0%bd%d1%82%d1%80%d0%b0%d0%ba%d1%82%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8/</link>
		<comments>http://lunarfrog.com/blog/2009/11/30/%d0%b1%d0%b8%d0%b1%d0%bb%d0%b8%d0%be%d1%82%d0%b5%d0%ba%d0%b0-code-contracts-%d0%ba%d0%be%d0%bd%d1%82%d1%80%d0%b0%d0%ba%d1%82%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 02:50:18 +0000</pubDate>
		<dc:creator>Andrei Marukovich</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://lunarfrog.com/blogs/?p=11</guid>
		<description><![CDATA[Code Contracts library for .NET 3.5: introduction in Russian. Code Contracts provide a language-agnostic way to express coding assumptions in .NET programs. The contracts take the form of pre-conditions, post-conditions, and object invariants and act as checked documentation of your external and internal APIs.
Контрактное программирование &#8211; это метод проектирования программ, предполагающий четкое специфицирование интерфейсов и [...]]]></description>
			<content:encoded><![CDATA[<p>Code Contracts library for .NET 3.5: introduction in Russian. Code Contracts provide a language-agnostic way to express coding assumptions in .NET programs. The contracts take the form of pre-conditions, post-conditions, and object invariants and act as checked documentation of your external and internal APIs.</p>
<p>Контрактное программирование &#8211; это метод проектирования программ, предполагающий четкое специфицирование интерфейсов и описание обязанностей компонентов системы при взаимодействии друг с другом.</p>
<p>Обычно, контракт включает три основные группы элементов:</p>
<ul class="arrows">
<li>предусловия &#8211; обязательства, которые должны быть выполнены вызывающей стороной перед вызовом метода</li>
<li>постусловия &#8211; обязательства, гарантирующиеся вызываемым методом</li>
<li>инварианты класса &#8211; обязательства, что свойства класса будут удовлетворять определенным требованиям. Например, инвариантом для класса PositiveNumber, может быть утверждение, что хранимое число всегда больше или равно 0.</li>
</ul>
<p>Таким образом, этот метод обеспечивает уверенность вызываемого компонента, что он получит только надлежащие входные данные, а результат, возвращенный вызывающему компоненту, будет корректным.</p>
<p>На PDC2008 было анонсировано появление в .NET 4.0 набора функций реализующих поддержку контрактного программирования и входящих в новое пространство имен <em>System.Diagnostics.Contracts</em>. На практике это будет выглядеть так:</p>
<pre class="code"><span class="op">class</span> Account
{
   <span class="op">public double</span> Balance { <span class="op">get</span>; <span class="op">set</span>; }

   <span class="op">public void</span> Deposit(<span class="op">double</span> amount)
   {
      Contract.Requires(amount &gt;=0);

      Balance += amount;
   }

   <span class="op">public void</span> Withdraw(<span class="op">double</span> amount)
   {
      Contract.Requires(amount &gt; 0);
      Contract.Requires(amount &lt;= Balance);

      Balance -= amount;
   }

   <span class="op">public</span> Account Transfer()
   {
      Contract.Ensures(Balance == 0);
      Contract.Ensures(Contract.Result&lt;Account&gt;() != <span class="op">null</span>);

      Account newAccount = <span class="op">new</span> Account() {Balance = <span class="op">this</span>.Balance};
      Balance = 0;
      <span class="op">return</span> newAccount;
   }

   [ContractInvariantMethod]
   <span class="op">protected void</span> ValidAccount()
   {
      Contract.Invariant(Balance &gt;=0);
   }
}</pre>
<p>Как можно увидеть, контракт реализуется при помощи функций, что сразу вызывает вопрос, почему? Гораздо красивее была бы объявление контракта отдельно от кода, например с помощью  атрибутов. К сожалению, атрибуты, по утверждению разработчиков, не позволяют описать все сценарии использования контрактов. Была возможность передавать в атрибуты сложные выражения, но они не захотели дублировать функциональность синтаксического анализатора. Так же они не захотели добавлять эту функциональность напрямую в язык, так как при этом другие .NET-языки не смогли бы ею воспользоваться. Так что мы имеем набор из десятка функций и нескольких атрибутов, которые войдут в <em>mscorlib</em>.</p>
<h3>Code Contracts library</h3>
<p>.NET 4 пока что не вышел, но попробовать контрактное программирование можно уже сейчас, загрузив библиотеку Code Contracts для .NET 3.5 с сайта <a rel="nofollow" href="http://msdn.microsoft.com/en-ca/devlabs/dd491992.aspx">Dev Labs</a>. Библиотека доступна в двух вариантах: VSTS Edition для владельцев Visual Studio Team System, в которой доступны все возможности и ее применение разрешено в коммерческих целях, и Standard Edition для всех версий Visual Studio, за исключением Express Edition. Эта версия лицензируется для академических целей и не включает проверки контрактов во время компиляции.</p>
<p style="text-align: center;"><img src="http://lunarfrog.com/images/blog/ccoptions.png" alt="" /></p>
<p>При инсталляции, в систему добавляется библиотека Microsoft.Contracts, примеры и документация. Также, в Visual Studio инсталлятор добавляет в свойства проекта дополнительную страницу Code Contracts, на которой можно управлять поведением библиотеки. Для того, что бы начать работу с контрактами, в проект необходимо добавить ссылку на библиотеку <em>Microsoft.Contracts.dll</em>, расположенную в папке <em>%PROGRAMFILES%/Microsoft/Contracts/PublicAssemblies</em>.</p>
<p>Код, приведенный выше для примера, демонстрирует использование трех основных частей контракта: предусловий Contract.Requires в функциях Deposit и Withdraw, декларирующих, что они работают только с положительными суммами денег; постусловий Contract.Ensures в функции Transfer, которые заявляют, что в качестве результата функция должна вернуть новый счет и обнулить текущий; инварианта класса ValidAccount, утверждающего, что счет находиться в правильном состоянии, если его баланс больше или равен нулю.</p>
<p>Итак, контракт объявлен. Но что это нам дает? Что произойдет, если контракт будет нарушен, например, в случае такого вызова account.Deposit(-1000.0)? Это зависит от используемых настроек. Если включена статическая проверка контрактов, то уже на этапе компиляции будет выдано предупреждение о нарушении контракта. Если же включена только проверка контрактов во время выполнения, то, в простейшем случае, в момент вызова функции будет сгенерировано исключение ContractException. Если проверка отключена полностью, то никакой реакции не последует, так как в скомпилированном коде будут отсутствовать любые проверки.</p>
<ul class="arrows">
<li>На самом деле код не просто скомпилирован, но и пропущен через модуль ccrewrite.exe, который подвергает полученный в результате компиляции IL-код постобработке, в результате чего декларация контракта превращается в конкретные вызовы методов проверки.</li>
</ul>
<p>Дополнительно, библиотека позволяет достаточно гибко менять параметры runtime-проверки контрактов. Во-первых, можно задать какие именно части контракта необходимо проверять, например, только предусловия. И, во-вторых, можно перехватить событие Contract.ContractFailed  или задать свой класс, методы которого будут вызываться вместо генерации исключения. Таким образом, к примеру, можно автоматически протоколировать нарушения контракта перед завершением программы.</p>
<p>Далее коротко пройдемся по всем основным элементам контракта.</p>
<h3>Предусловия</h3>
<p>Декларируют условия, необходимые для работы метода, выражаются с помощью Contract.Requires() и обычно используются для проверки входящих параметров. Функция Requires()принимает в качестве параметра логическое выражение выражающее условие контракта.  Так же существует перегруженная функция, принимающая в качестве второго параметра строку – сообщение, используемое при нарушении условия.</p>
<pre class="code">Contract.Requires(amount &gt; 0, <span class="str">"Invalid amount"</span>);</pre>
<p>Как уже упоминалось выше, в зависимости от настроек текущей конфигурации в скомпилированном коде проверок контракта может и не быть. Однако, если вы хотите, что бы проверка предусловия осуществлялась всегда, вне зависимости от настроек, то можно использовать функцию Contract.RequiresAlways(), которая будет работать даже при отключеннии проверок в настройках проекта.</p>
<pre class="code">Contract.RequiresAlways(x != 0);</pre>
<p>Если вы добавляете поддержку контрактов в существующее приложение, то, возможно, у вас уже есть проверка входящих параметров функций. Если она выполнена в виде</p>
<pre class="code"><span class="op">if</span> (условие) <span class="op">throw new</span>...</pre>
<p>то, добавив вызов Contract.EndContractBlock() после этих проверок, вы превратите их в предусловия. Аналогичное действие окажет и вызов Contract.Requires(). На выражения накладываются следующие ограничения – они не должны выполнять ничего кроме генерации исключения, оператор else не поддерживается.</p>
<h3>Постусловия</h3>
<p>Постусловия декларируют состояние, достигнутое после завершения работы метода. Простой пример постусловия:</p>
<pre class="code">Contract.Ensures(Balance == 0);</pre>
<p>Постусловия, как и предусловия, объявляются в начале метода, однако в результате постобработки проверка условия будет осуществлена после выполнения всех инструкций метода. Это легко увидеть, запустив отладку метода содержащего постусловия – сначала отладчик пройдет по всем инструкциям, включая return и лишь затем перейдет к выполнению проверок.</p>
<p>Приведенный выше синтаксис работает в простейших случаях, для реализации более сложных сценариев используются дополнительные методы.</p>
<p>Так, для верификации возвращаемого функцией значения используется специальный метод Contract.Result&lt;T&gt;(), где T &#8211; это тип возвращаемого функцией значения.</p>
<pre class="code">Contract.Ensures( Contract.Result&lt;<span class="op">int</span>&gt;() &gt; 0 );</pre>
<p>Метод Contract.OldValue(e) позволяет получить значение переменной e до начала работы метода. Существует несколько ограничений на применение OldValue, главное из которых – переменная должна существовать перед началом выполнения инструкций метода и ее значение должно быть вычисляемым. В качестве таких переменных, например, могут выступать свойства класса или входящие переменные метода.</p>
<pre class="code">Contract.Ensures(Contract.OldValue(i) &lt; n);</pre>
<p>Для проверки в постусловиях значений out-переменных используется метод Contract.ValueAtReturn(out T t)</p>
<pre class="code"><span class="op">public void</span> TestOut (<span class="op">out int</span> a)
{
   Contract.Ensures(Contract.ValueAtReturn(<span class="op">out</span> a) == 8);
   a = 8;
}</pre>
<h3>Инварианты класса</h3>
<p>Инварианты класса относятся ко всему экземпляру класса и декларируют условия, при которых объект находиться в “хорошем” состоянии.</p>
<pre class="code">[ContractInvariantMethod]
<span class="op">protected void</span> ValidAccount()
{
   Contract.Invariant(Balance &gt;= 0);
}</pre>
<p>Объявления всех инвариантов помещаются в один метод класса, помеченный атрибутом ContractInvariantMethod. Этот метод не должен содержать никакого кода, кроме объявлений инвариантов и не может возвращать значения. Каждый инвариант задается вызовом метода Contract.Invariant(). Проверка инвариантов класса происходит в конце каждого public метода класса &#8211; если посмотреть IL-код программы, то можно увидеть, что в процессе постобработки в конец каждого такого метода добавляется вызов нашей функции, помеченной атрибутом ContractInvariantMethod.</p>
<p>Дополнительно, в любом месте программы можно использовать Contract.Assert() для проверки условия в этой точке.</p>
<pre class="code">Contract.Assert( _number &gt; 0 );</pre>
<p>В процессе выполнения программы, если выражение ложно, то  произойдет вызов Debug.Assert, в противном случае не последует никаких действий.</p>
<h3>Контракты для интерфейсов</h3>
<p>Описанные выше методы декларации контракта отлично работают в случае с конкретным классом. Однако что нам делать, если возникнет необходимость задать контракт для интерфейса? Ведь компилятор C# не позволит добавить для интерфейса тело функции с  вызовом методов Contract.Requires() или Contract.Ensures(). На помощь приходит вспомогательный класс и пара атрибутов – ContractClass и ContractClassFor.</p>
<pre class="code">[ContractClass(<span class="op">typeof</span>(SavingAccount))]
<span class="op">interface</span> IAccount
{
   <span class="op">int</span> Balance { <span class="op">get</span>; }
   <span class="op">void</span> Deposit(<span class="op">int</span> amount);
}

[ContractClassFor(<span class="op">typeof</span>(IAccount))]
<span class="op">class</span> SavingAccount : IAccount
{
   <span class="op">int</span> IAccount.Balance
   {
      <span class="op">get</span>
      {
         Contract.Ensures(Contract.Result&lt;<span class="op">int</span>&gt;() &gt;=0 );
         <span class="op">return default</span>(<span class="op">int</span>);
      }
   }
   <span class="op">void</span> IAccount.Deposit(<span class="op">int</span> amount)
   {
      Contract.Requires(amount &gt; 0);
   }
}</pre>
<p>Для интерфейса создается вспомогательный класс, реализующий его и декларирующий контракт. Для установления связи между классом и интерфейсом используются атрибуты. Точно таким же способом можно объявить контракт для абстрактного метода, создав вспомогательного наследника и реализовав метод.</p>
<p>Поскольку статья задумывалась как введение в библиотеку Code Contracts, то я не стал описывать некоторые нюансы ее использования и методы, используемые в специальных случаях – с ними вы можете познакомиться в достаточно подробном документе, идущем вместе с библиотекой. Так же, для начала, может быть интересным видео с одним из разработчиков библиотеки, доступное на сайте <a rel="nofollow" href="http://msdn.microsoft.com/en-ca/devlabs/dd491992.aspx">Dev Labs</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://lunarfrog.com/blog/2009/11/30/%d0%b1%d0%b8%d0%b1%d0%bb%d0%b8%d0%be%d1%82%d0%b5%d0%ba%d0%b0-code-contracts-%d0%ba%d0%be%d0%bd%d1%82%d1%80%d0%b0%d0%ba%d1%82%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
