C#

Рекламный модуль
Самый клевый ламинат с изображениями на портале - Http://nl.ua. | имплантиране на зъби, имплантология.

Осуществление верификации

Для запуска проверки класса TestCurrencyTrader используем следующий код: TestCurrencyTrader els = new TestCurrencyTrader(); :1s.InitializeExchangeRate() ; Измененный проверочный код подразумевает создание экземпляра класса -eszCurrencyTrader и последующий вызов метода InitializeExchangeRate О . Но про¬верка ли это? В конце концов, метод InitializeExchangeRate () не имеет ни параме¬тров, ни возвращаемого значения. Считайте это посылкой письма по обычной почте. Зы не знаете наверняка, придет ли письмо, но вероятно, придет. Проверка "вероятно, ггр идет" — это действительно плохая идея. Необходимо переместить код верификации из проверочной функции в класс TrstCurrencyTrader следующим образом: ;lass TestCurrencyTrader : CurrencyTrader public void InitializeExchangeRate() I ExchangeRate = 10 0.0; if (ExchangeRate != 100.0) { throw new Exception("100 . 0 verification failed") ; } } Код, выделенный полужирным шрифтом, — это код верификации, используемый ИЯ проверки наличия у ExchangeRate того же значения, которое ему было присвоило. На заметку. Проверки, которые мы используем, становятся все более сложными, и у вас возника¬ет вопрос: "Почему все делается так?" В этой книге мы создаем собственную инфраструктуру проверки. Но вы не обязаны поступать именно так. Для создания проверок вы могли бы ис¬пользовать инфраструктуру проверки типа NUNIT (http://www.nunit.org) или профессио¬нальные инструменты Microsoft Visual Studio Professional. Но здесь я хочу продемонстрировать, <ак использовать язык С# без инструментов проверки. Изучив, как записывать проверки само¬му и с самого начала, надеюсь, вы поймете, чего ожидать от инфраструктур проверки. Использование условных операторов Наличие кода верификации внутри класса приемлемо в контексте проверочного пасса TestCurrencyTrader. Однако проблема контролируемости все еще присутствует I тех классах, которые не предоставляют свое состояние. Чтобы понять проблему, давайте вернемся к коду разогрева духовки. Давайте пере-~::;лем класс Oven так, чтобы включить верификацию, как здесь. :lass Oven private int _temperature; public void SetTemperature( int temperature) temperature = temperature; if ( _temperature != 100.0) { throw new Exception( "100.0 verification failed"); } } public bool AreYouPreHeated () { // Проверить, соответствует ли температура духовки необходимой return false; } ) Код, выделенный полужирным шрифтом, иллюстрирует верификацию, очень пох: -жую на ту, что мы использовали в классе CurrencyTrader, который в данном случае проверяет параметр температуры на определенное значение. В то время как верифика¬ция полезна при проверке специфического значения, она не очень подходит для обще:: случая. Тот способ, которым написан код, допускает единственное значение для темпе¬ратуры — это 100, 0; все остальное приведет к исключению. Чтобы обойти эту проблему, используем условные операторы (conditional statemerc языка С#, представляющие собой специальные ключевые слова, позволяющие раз¬работчику определить, откомпилирован ли фрагмент исходного кода. Следующее — это пример исходного кода, который включает условные операторы: class TestCurrencyTrader : CurrencyTrader { public void InitializeExchangeRate () { ExchangeRate = 100.0; #if INTEGRATEJTESTS if (ExchangeRate != 100.0) { throw new Exception("100.0 verification failed"); } #endif } Условный оператор всегда начинается с символа #. за которым следует ключевое слово, например if. Между ключевыми словами #if и #endif находится код, компи¬лируемый условно. Это называется директивой препроцессора (preprocessor directive В этом примере происходит условная компиляция кода, содержащегося внутри блока #if и #endif, если значение INTEGRATEJTESTS истинно. Вы можете определить идентификатор компиляции, такой как INTEGRATE__TEST: в исходном коде или в IDE. В среде Visual C# Express можно определить идентификатс - INTEGRATE__TESTS следующим образом. 1. Щелкните правой кнопкой мыши на своем проекте и в появившемся контекст¬ном меню выберите пункт Properties (Свойства). 2. Перейдите на вкладку Build (Построение). 3. Введите в поле Conditional Compilation Symbols (Символы условной компиляции значение INTEGRATE_TESTS. Использование для верификации частичных классов Условная компиляция полезна, когда вы хотите включать или удалять код, в зави¬симости от конфигурации. Однако некоторым программистам категорически не пс-нравится наличие кода условной компиляции внутри функции, поскольку это стало бь: кошмаром поддержки. Другое решение заключается в том, чтобы использовать ключе¬вое слово partial class вместе с операторами условной компиляции. До сих пор во всех примерах, когда мы определяли класс, все его методы и код объ- являлись внутри фигурных скобок класса. Используя частичные (partial) классы, мож- но объявить класс в нескольких местах. Когда компилятор С# компилирует исходный код, отдельные части класса будут собраны в единое определение класса. Для нашего проверочного кода мы можем создать реализацию частичного класса и условно ком- пилировать проверочную часть реализации класса. Ниже приведен измененный класс Test CurrencyTrader, применяемый для проверки состояния, без предоставления к нему доступа извне. :;r~ial class TestCurrencyTrader : CurrencyTrader public void InitializeExchangeRate() TxchangeRate = 100.0; *if !INTEGRATE_TESTS partial class TestCurrencyTrader : CurrencyTrader public void VerifyExchangeRate(double value) if (ExchangeRate != value) { throw new Exception("ExchangeRate verification failed"); } } #endif Мтючевое слово partial предшествует ключевому слову class. Первая реализация т;-::а TestCurrencyTrader — это пример непредоставления доступа к состоянию. ' рая реализация класса TestCurrencyTrader, которая объявлена в контексте опера- словной компиляции, содержит метод VerifyExchangeRate (). Этот метод верифи- _ ::: проверяет свойство ExchangeRate на специфическое значение. *з заметку. Вы можете использовать частичные классы только в контексте одной сборки —«клю¬чевое слово partial нельзя использовать для нескольких сборок. Когда я говорю "одиночная : ::эка", я имею в виду откомпилированные части исходного кода .NET, представленного в та¬ге ". "На старт, внимание, марш!" Другими словами, если вы определяете частичный класс i :.'5лиотеке, то все части частичного класса должны быть определены в этой библиотеке. Частичные классы существенно упрощают разделение функциональных возможно- К : ~о разным файлам исходного кода, чтобы изменение одного файла исходного кода ■ мияло на другие файлы исходного кода. Этот пример демонстрирует использование ганых классов для манипулирования внутренним состоянием класса без наруше- ~ правила: "Не предоставлять внутреннее состояние". Частичные классы можно так- : пользовать в контексте генераторов объектного кода, где один файл исходного кода 1 гржит специальный код, а другой файл исходного кода содержит код генератора.