5й подкаст Петербургской группы ALT.NET
Опубликовано: Февраль 28, 2010 Filed under: Podcast | Tags: Podcast, S.O.L.I.D., scrum, tdd, xp Оставить комментарий →
SOLID & TDD и прочие показатели качества кода
Наши гости: Alexander Byndyu и Vitaly Stakhov
SCRUM & XP
- http://ru.wikipedia.org/wiki/Scrum
- http://ru.wikipedia.org/wiki/Экстремальное_программирование
- http://www.infoq.com/minibooks/scrum-xp-from-the-trenches
OOD: Best practicies
- Single Responsibility Principle
- Open/Closed Principles
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
TDD: Best Practicies
- Mocks aren’t stubs
- xUnit.NET, NUnit, MbUnit, и та утилита, от Microsoft, которую не смог вспомнить Александр
Ещё говорили о
Подкасты Петерубргской Группы Alt.Net Подкасты о разработке в среде .Net. Ключевые слова: C#, F#, Boo, Visual Studio, .Net, PostSharp, Asp.Net личная подкаст-лента |
4й подкаст Петербургской группы ALT.NET
Опубликовано: Февраль 20, 2010 Filed under: ALT.NET, Podcast | Tags: .net, ALT.NET, asp.net mvc, css3, Разработка, FubuMVC, html5, javafx, mvc, Podcast, RIA, RoR, silverlight, spbalt.net, visual studio 1 Comment »
Всё, что вы хотели узнать о ASP.NET
Что нового в ASP.NET MVC2.
- Асинхронные контроллеры
- Зоны (areas)
- Валидация через data annotation
- Строго-типизированные хелперы
- Хелпер-темплейты, параметры по-умолчанию
Альтернативные view engines
Удобен ли Visual Studio для веб-разработки
- Новое понимание MVC. Другой контроллер. Конвенции.
Почему я уйду на Ruby on Rails / Django
Как хорошо работать с Asp.Net AJAX и jQuery
HTML5 + CSS3 (@font-face)
- font-face на js – cufon http://wiki.github.com/sorccu/cufon/about
RIA
- Олимпиада 2010, Silverlight, Windows 7 Phone, JavaFX
Создавать ли View для iPhone
Подкасты Петерубргской Группы Alt.NetПодкасты о разработке в среде .Net. Ключевые слова: C#, F#, Boo, Visual Studio, .Net, PostSharp, Asp.Net |
Альтернативный MVC Framework на ASP.NET: FubuMVC
Опубликовано: Февраль 16, 2010 Filed under: ALT.NET, asp.net, asp.net mvc | Tags: ALT.NET, asp.net, FubuMVC, IoC, mvc, SoC, Spark, StructureMap, ViewEngine 9 Comments »Введение
Почему же альтернативный? Всё просто, данный framework пишется силами выдающихся участников ALT.NET community, а именно:
Jeremy Miller, Chad Myers, Mark Nijhof, Ryan Kelley, и Joshua Flanagan.
FubuMVC не имеет никакого отношения к ASP.NET MVC Framework, кроме того, что так же построен поверх ASP.NET и реализует паттерн Front-Controller. Название FubuMVC строится из акронима “For us by us” и аббривеатуры MVC (кто ещё не знает, что это значит Model-View-Controller ?). Проект был инициирован по причине недовольства вышеперечисленных личностей архитектурными решениями, принятыми в ASP.NET MVC. Сказать, по правде, по прошествии года, после старта проекта, он не утратил своей элегантности и простоты в подходах.
FubuMVC вносит несколько непривычное понимание Controller’а. Теперь это не просто некоторый класс, теперь это больше логическая связность некоторых методов. Это раскрывает более широкие возможности для настройки специфичного поведения Controller’а, к примеру, обработки ошибок, реализации правил кэширования, определения типа возвращаемых значений. К тому же возможность динамического объединения вызовов Action’ов уже является удобным механизмом к расширению. Далее мы более подробно поговорим об особенностях этой реализации в FubuMVC.
В качестве View Engine (в данном случае является лишь определением и не имеет отношения к ASP.NET MVC View Engine) используется механизм рендринга WebForms (проще говоря FubuPage, которая является View в FubuMVC, наследует от System.Web.UI.Page), но имеется возможность в подключении всех существующих в ASP.NET MVC ViewEngine’ов, примером тому может быть реализация SparkViewEngine.
Конечно же уместным будет вопрос, а зачем же нужен “другой” MVC Framework, с меньшим количеством участников проекта, с меньшим вниманием со стороны разработчиков, с меньшим количеством тестеров и прочими атрибутами mainstream проектов.
В основу проекта FubuMVC его создатели заложили больше возможностей для кастомизации проекта под прикладные нужды, а так же конвенциям (соглашениям) относительно настройки и расширяемости. Причём конвенции должны покрывать основные и типичные нужды приложения, коих в разработки решений достаточно большое количество. Какие-либо дополнительные разработки будут инициировать собой появление дополнительных модулей.
Аналогичные конвенции (соглашения) существую в известном всем MVC Framework на Ruby: Ruby On Rails. На своей практике разработки под Ruby On Rails я неоднократно убеждался, что данные конвенции действительно позволяют снизить сложность и количество написанного кода. Примером тому может служить ORM Active Record с его соглашениями касательно преобразования объектов в таблицы реляционной базы данных, а так же соглашение, относительно хранения конфигурации в формате YAML.
Официальный сайт проекта: http://fubumvc.com/
FubuMVC на GitHub: http://github.com/darthfubumvc/fubumvc
Первое погружение
Начнём с конвенций именования и структуры проекта. Вся работа с настройкой приложения FubuMVC ведётся через некоторый DSL, стиль конфигурирования очень близок к работе с FluentNhibernate.
public class HelloWorldFubuRegistry : FubuRegistry
{
public HelloWorldFubuRegistry()
{
IncludeDiagnostics(true);
Applies.ToThisAssembly();
Actions
.IncludeTypesNamed(x => x.EndsWith("Controller"));
Routes
.IgnoreControllerNamespaceEntirely()
.ConstrainToHttpMethod(action => action.Method.Name.EndsWith("Command"), "POST")
.ConstrainToHttpMethod(action => action.Method.Name.StartsWith("Query"), "GET");
Views
.TryToAttach(x=>
{
x.to_spark_view_by_action_namespace_and_name(GetType().Namespace);
x.by_ViewModel_and_Namespace_and_MethodName();
x.by_ViewModel_and_Namespace();
x.by_ViewModel();
});
Output.ToJson.WhenCallMatches(action => action.Returns<AjaxResponse>());
HomeIs<HomeInputModel>();
}
}
Исходя из данной конфигурации IoC-container’а нетрудно догадаться о следующем:
- Все классы, оканчивающиеся на “Controller” будут зарегистрированны в качестве Controller
- Все запросы, оканчивающиеся на “Command” должны будут приниматься POST’ом, а начинающиеся на “Query” GET’ом
- Все View будут заполняться соответствующими по именованию ViewModel
- Весь вывод, возвращающий тип AjaxResponse будет серилизоваться в JSON
В качестве IoC-container’а в FubuMVC выбран StructureMap. Выбор не случаен, т.к. фактически StructureMap является старейшим IoC/DI-container’ом. Начало разработки датировано июнем 2004ого года и велось Jeremy D. Miller, так же и участником проекта FubuMVC.
Второе погружение
Давайте рассмотрим несколько примеров приложений на FubuMVC
Первое из них http://github.com/DarthFubuMVC/fubumvc-examples/tree/master/src/Actions/ControllerActionStyle/
Начнём, с того, что проверим его работоспособность:
В namespace’е SimpleWebsite.Core определена наша модель предметной области, а именно Movies, работе с которыми и просвещенно приложение.
В SimpleWebsite.Controllers определен единственный Controller и View, работу которых мы и видим на рисунке выше.
Давайте разберемся с MoviesController. Судя по его конструктору нетрудно догадаться, что DependencyInjection мы получаем out-of-box без каких-либо переопределений Controller Factory:
private readonly IRepository _repository;
public MoviesController(IRepository repository)
{
_repository = repository;
}
Метод List() является “списочным” и предоставляет нам доступ к ViewModel
public ListMoviesViewModel List()
{
return new ListMoviesViewModel {Movies = _repository.Query<Movie>()};
}
Стоит обратить внимание на конвенцию именования в данном случае. Под ViewModel (читается так же как PresentationModel) понимается адаптированная для представления модель, что подчеркивает SoC в реализации FubuMVC. View в данном случае будет строго типизировано на этот тип:
public class List : FubuPage<ListMoviesViewModel> <br />{}
Метод Add() попадает под правило обработки AjaxResponse, следовательно вернется на страницу в виде JSON, где будет радужно встречен jQuery обработчиком.
Аналогичная ситуация с методом Remove().
Стоит обратить внимание на конвенцию именования принимаемых данными методами типов:
AddMovieInput, RemoveMovieInput
Наименования данных классов указывают на направление данных, т.е. их ввод с запросом. С помощью этих типов на View мы определяем Url для обработки соответствующих Action’ов Controller’а:
<%= Get<IUrlRegistry>().UrlFor(new AddMovieInput()) %>
FubuMVC реализует 3 модели обработки запросов:
- Controller / Action Привычный для ASP.NET MVC Framework способ. Определяется некоторый тип – Controller, который содержит в себе соответствующие методы – Action’ы. Данный пример был рассмотрен выше.
- Controller-less Actions (HandlerStyle) Данный способ подразумевает под собой “обезличенные” Action’ы. т.е. без привязки к какому-либо Controller’у. Правила нахождения Action’ов описываются Policy, которые можно описывать и добавлять в коде.
- REST-like (EndPointStyle) Этот способ близок к предыдущему, однако, в отличии от него реализует не только метод Execute, а все методы, необходимые для REST взаимодействия, каждый метод Get(), Post(), Put(), Head() в дальнейшем будет соответствовать типу HTTP запроса:
var httpVerbs = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase) {"GET", "POST", "PUT", "HEAD"};
Погружаемся далее
Как вы уже догадались, FubuMVC славится своими возможностями для расширения. Предлагаю ознакомиться с ещё одним примером: http://github.com/DarthFubuMVC/fubumvc-examples/tree/7c4b2165aedb6754a01538aee956e29d4060654c/src/Outputs/VaryByAcceptHeader
В данном примере рассматривается вариативность формата возвращаемых данных от параметра запроса, причём вы можете с легкостью добавить новый формат данных.
Этот пример практически ни чем не отличается от рассматриваемого, раннее, за тем лишь исключением, что в классе
VariableOutputConvention : IConfigurationAction
мы регистрируем интересующие нас возвращаемые типы, а так же указываем дополнительный Behavior для рендринга страницы:
RenderVariableOutput : BasicBehavior
После чего достаточно только заполнить интересные вам Movies http://localhost:59187/movies/list и попросить вернуть их в JSON http://localhost:59187/movies/list?renderformat=json или в XML http://localhost:59187/movies/list?renderformat=xml
Данный пример наглядно иллюстрирует точки расширения FubuMVC для любых нужд.
Диагностика
По адресу http://localhost:59187/_fubu вас будет ждать небольшой сюрприз, а именно – диагностическая утилита для FubuMVC.![]()
C её помощью вы сможете просматривать все зарегистрированные в вашем приложении
- Chains – цепочки поведения, так называются логические связи между маршрутами и Action’ами. О цепочках можно посмотреть все обертки и возвращаемые значения.
- Routes – показывает все зарегистрированные маршруты, и связанные с ними Action’ы, тип выводимых данных и цепочки поведения.
- Actions – зарегестрированные в приложении Action’ы, их маршруты и возвращаемые значения
- Inputs – возможные типы и способы ввода в вашем приложении со стороны запросов
Заключение
При первом и поверхностном знакомстве проект FubuMVC не показался мне чем-то выдающимся. Однако в последнее время мой интерес к нему постоянно растёт. Я считаю, что FubuMVC является более удобным и гибким инструментом, по сравнению с ASP.NET MVC. Однако это ещё не значит, что я уже готов доверить данному проекту свои коммерческие проекты. Тот факт, что сообщество всё же поддерживает многообразие качественных решений для создания приложений на ASP.NET, может только радовать.
Материалы
FubuMVC Contrib http://code.google.com/p/fubumvc-contrib/
Front Controller http://msdn.microsoft.com/en-us/library/ms978723.aspx
FubuMVC – Front Controller style framework http://blog.fohjin.com/blog/2009/2/21/FubuMVC_Front_Controller_style_framework
FubuMVC Google Group http://groups.google.com/group/fubumvc-devel?pli=1
Ещё один MVC Framework на ASP.NET OpenRasta http://trac.caffeine-it.com/openrasta
Соглашение относительно настройки http://msdn.microsoft.com/ru-ru/magazine/dd419655.aspx
3й подкаст Петербургской группы Alt.Net
Опубликовано: Февраль 10, 2010 Filed under: Книги, Podcast | Tags: Книги, Подкаст, Podcast Оставить комментарий →Литература для .Net-разработчика
- CLR via C# (Richter, 3rd edition coming up), C# in a nutshell, C# in Depth (skeet)
- Design Patterns (GoF), Design Patterns in C#, Refactoring to Patterns,DP in Java
- Martin Fowler Signature Series: PoEAA, xUnit Test Patterns,Integration Patterns, Test-Driven Development, Implementation Patterns
- Agile Software Development on C++ and C# (both 1st and 2nd versions) by Robert C Martin
- DDD, Applying DDD by Nilsson, DDD with C#/.NET: Problem – Design – Solution
- Generative Programming
- Expert F# – the book of rulership, also Foundations of F# and F# for scientists
- Building DSLs in Boo
Non-.Net
- The C++ programming language, Essential STL
(hey, some of us do interop) - Learn Ruby, Python Cookbook
- CodeComplete, Code Craft
Domain-specific books:
- 4 books ASP.NET by Dino Esposito
- Applications = Code + Markup
- Asp.Net MVC in Action, Asp.Net MVC Quickly
- Inside WSS 3.0
Подкасты Петерубргской Группы Alt.NetПодкасты о разработке в среде .Net. Ключевые слова: C#, F#, Boo, Visual Studio, .Net, PostSharp, Asp.Net |
Каких возможностей мне не хватает в SharePoint 2010 BCS
Опубликовано: Февраль 8, 2010 Filed under: BCS, sharepoint, SharePoint 2010, Uncategorized | Tags: BCS, sharepoint 2 Comments »В данной заметке я решил немного поразмышлять о том, чего же мне не хватает в BCS при планировании основных сервисов приложений, руководствуясь стандартными для SharePoint практиками. Большинство из этих ограничений связаны с природой сервисов BCS, а именно тем, что данные не находятся в локальном хранилище, соответственно не могут полностью контролироваться с помощью сервисов SharePoint.
Итак, начнём:
- Нельзя давать разрешения на отдельные записи во внешнем списке (external list). Наконец-то SharePoint в исполнении 2010ой версии научили корректно использовать Access Control Lists (ACL), однако, по вполне понятным причинам данные возможности не доступны при работе с внешними данными
- Возможности рабочих процессов не доступны полностью для внешних списков. Казалось бы, всё замечательно и готово для интеграции, однако внешние данные остаются внешними данными, и многие события, необходимые для работы с рабочими процессами недоступны для SharePoint, однако это не исключает использование внешних данных в рабочих процессах, работающих на обычных списках. Об этой проблеме и способах её разрешения довольно-таки подробно описано в статье Using SharePoint workflows with Business Connectivity Services (BCS).
- Отсутствие версионности и истории изменений во внешних списках. Вполне логично, что внешние списки остаются лишь “обёрткой” для внешних данных и хранить изменения, а следовательно и обеспечивать версионность, довольно-таки неординарная задача, которую команда BCS решила не касаться, по той же причине “элементы социального взаимодействия”, такие как рейтинги и тегирование, так же будут недоступными при работе с внешними данными (BCS).
- Экспорт в Excel. Очень странно почему данный функционал не доступен, т.к. не накладывает никаких ограничений на используемые данные, а просто меняет их представление. Как альтернативу данному подходу могу предложить что-нибудь наподобие Print List (http://www.sharepoint-tips.com/2007/01/how-to-add-print-list-option-to-list.html), т.е. решения по экспорту внешних данных из SharePoint будут подразумевать кастомизацию.
- RSS каналы. С одной стороны причины схожи с экспортом в Excel, однако здесь, как мне кажется, противоречие даже со здравым смыслом, т.е. RSS-канал как правило должен отслеживать изменения в данных и оповещать об этом подписчика, в случае с внешними данными, они могут и не меняться, а будет меняться лишь выборка, что будет генерировать многочисленное количество неконтролируемых обновлений.
- Просмотр в виде таблицы. Очень удобная функция, не понятно, что именно сподвигло на её отсутствие команду разработчиков, скорее всего возможности пакетной обработки в новом интерфейсе SharePoint, которыми она была так удобна.
- Внешние данные не доступны для доступа через REST сервисы. Как мне кажется причина так же в возможности непрогнозируемого изменения данных произвольным образом, что не даёт никакой гарантии для потребителя данных сервисов.
В заключение
BCS – остаются лишь внешними данными, относительно SharePoint-среды, в связи с этим не следует воспринимать их более чем данные. Все функциональные возможности должны быть реализованы либо во внешнем приложении, либо в приложении на SharePoint. В последнем случае внешние данные перестают быть интеграционными, а обеспечивают лишь альтернативный способ хранения для приложений на SharePoint.
Полноценный Behavior Driven Development на .NET
Опубликовано: Февраль 4, 2010 Filed under: .net, BDD | Tags: .net, AAA, BDD, Cucumber, DDD, Domain-Driven Design, RSPec, Ruby, tdd, Tests 4 Comments »Введение
Меня переполняют эмоции. Это связанно с тем, что сегодня мой товарищ сообщил о следующем: есть полноценная реализация BDD движка для .NET.
Называется проект SpecFlow
Исходный код ныне базируется на GitHub http://github.com/techtalk/SpecFlow
Немного теории
Вопрос о том, что же такое Behavior Driven Development неоднозначен. Особенно противоречивы его отношения с Test Driven Development. Однако предлагаю абстрагироваться от сравнения двух подходов и договорится, что суть этого есть одно и тоже, т.к. особенных различий нет. Основной чертой выделяющей BDD от TDD по-моему усмотрению является ориентация на различных участников процесса производства программного обеспечения, будь то менеджер, разработчик, тестер, заказчик. Вы вместе пишете тесты, и вместе можете развивать проект в нужном направлении и вполне понятных терминах. Так же на ум в данном случае приходит такой термин, как Ubiquitous Language из Domain Driven Design. А ведь и в самом деле, обобщение терминологии описания вашей предметной области вполне может ложится на практику BDD.
Меня в BDD больше всего прельщает возможность описания функциональности на разговорном языке, что гарантирует актуальность документации (т.к. ваши behavior тесты и будут фактически вашей документацией). Так же при написании тестов на подобном уровне вы четко сконцентрированы на поставленной задаче, а не способах её разрешения и применяемых инструментах, что так же весьма полезно для качества как вашего дизайна, так и соответствии программного продукта назначению.
Все известные инструменты (к примеру mock-объекты) и практики (такие как шаблоны тестирования), используемые вами при разработке в стиле TDD, изменятся незначительно при переходе на BDD стиль, в связи с чем можно начать применять BDD уже сегодня. Так же вполне возможно, что вам необходимо будет произвести более низкоуровневое тестирование некоторых компонентов, что несомненно приведёт к смешиванию двух практик, что несомненно должно происходить осознано и с должен вниманием.
Снаружи вовнутрь. Процесс при разработке в стиле BDD так же немного смещается. Так как тестами двигают в равной мере все участники, то ориентация в первую очередь будет на интерфейсе пользователя. т.е. для описания необходимых фич, заинтересованным лицам (скорее всего заказчику) необходимо будет держать перед глазами эскизы эрканов для взаимодействия. Этот подход снижает риски неоправданных ожиданий, т.к. в большинстве случаев программный продукт для потребителя – всего лишь пользовательский интерфейс.
Инструменты
На данный момент существует множество BDD framework’ов, однако “наиболее верным” с точки зрения родоначальников данного термина (Dan North, David Chelimsky, Aslak Hellesøy) является такой проект как: Cucumber (ранее известный как RSpec). Этот проект написан для Ruby. Большинство RubyOnRails разработчиков (как основные представители ruby сообщества) пользуются именно этим фреймворком для тестирования своих продуктов.
Известны некоторые способы запуска данного проекта под .NET с помощью IronRuby, однако должной поддержки со стороны как сред разработки в .NET, так и внимания сообщества такое решение не получило.
Инструменты для .NET в основном копируют формат и принципы, заложенные в Cucumber, их существует несколько:
- SpecFlow – предмет сегодняшнего разговора (из плюсов – аналогия с Cucumber и интеграция в Visual Studio 2008 и 2010)
- NBehave – работа с данным фреймворком близка к возможностям Cucumber в настоящее время (до этого он так же был в разряде “многословных” и это, наверное, наиболее распространенный BDD фреймворк среди .NET разработчиков)
- NSpecify, NSpec – довольно-таки “многословные” фреймворки для BDD
- Specter – аналогично, примечателен тем, что написан на Boo
Теперь практика
Для того, чтобы проиграться с этим замечательным инструментом нам понадобятся:
- NUnit, последнюю версию можно скачать здесь http://www.nunit.org/index.php?p=download
- SpecFlow http://www.specflow.org/downloads/installer.aspx, я использовал версию 1.2.0
- Visual Studio 2008 (надеюсь у вас она установлена)
- Test Runner (я буду использовать R#)
Итак, давайте приступим. Если хочется открыть сразу всё это и посматривать в блог, а разбираться там, то вполне можно скачать пример, ссылка на него будет внизу текста.
Создавать мы с вами будет стандартный пример для подобного рода фреймвороков, а именно Калькулятор.
Создадим новый solution в студии, в котором будет два проекта.
- Calculator
- Calculator.Tests
Для того, чтобы его описать в решении + подготовить реализацию нам понадобится немного инфраструктурных заморочек в проекте Calculator.Tests (ниже работа пока будет только с ним):
- добавить reference на TechTalk.SpecFlow.dll (которая скорее всего окажется в папке с установленным SpecFlow)
- добавить reference на nunit.framework.dll (его следует искать в GAC’е)
Теперь всё готово для того, чтобы погрузиться в мир BDD. Откиньтесь на спинки кресел и расстегните ремни.
В пункте Add New Item у вас наверняка появились новые пункты, начинающиеся на SpecFlow![]()
Далее задайте имя нашей фиче addition.feature и щелкните Add.
Как вы догадались мы добавим описание первой фичи, для этого тот текст, который будет содержаться в файле по-умолчанию следует заменить на следующий:
http://github.com/aslakhellesoy/cucumber/blob/master/examples/i18n/en/features/addition.feature# language: en Feature: Addition In order to avoid silly mistakes As a math idiot I want to be told the sum of two numbers Scenario Outline: Add two numbers Given I have entered <input_1> into the calculator And I have entered <input_2> into the calculator When I press <button> Then the result should be <output> on the screen Examples: | input_1 | input_2 | button | output | | 20 | 30 | add | 50 | | 2 | 5 | add | 7 | | 0 | 40 | add | 40 |
Жмём ctrl+s и большая часть работы по описанию выполнена.
Теперь нам надо сделать описание steps, для того, чтобы связать сценарий с тестируемым модулем. Для этого добавьте новый элемент SpecFlow Step Definition, назовём мы его calculator_steps.cs.
Данный файл уже содержит в себе некоторые записи по-умолчанию, в принципе они вполне подходят для нашего примера. (Кстати, обратите внимание как строго упорядочены все методы по шаблону AAA: Arrange, Act, Assert, в данной интерпретации Given, When, Then)
Однако немного их всё же придется изменить.
Внутри данного метода:
[Given("I have entered (.*) into the calculator")]
public void GivenIHaveEnteredSomethingIntoTheCalculator(int number)
{
//TODO: implement arrange (recondition) logic
// For storing and retrieving scenario-specific data,
// the instance fields of the class or the
// ScenarioContext.Current
// collection can be used.
// To use the multiline text or the table argument of the scenario,
// additional string/Table parameters can be defined on the step definition
// method.
ScenarioContext.Current.Pending();
}
Мы видим, что на нашем калькуляторе печатают некоторые числа, ок, подтвердим это:
[Given("I have entered (.*) into the calculator")]
public void GivenIHaveEnteredSomethingIntoTheCalculator(int number)
{
Calculator.Input(number);
}
И не стесняйтесь того, что пока Visual Studio не совсем понимает, что такое Calculator
Отлично, смотрим на следующий метод, его мы тоже немного поправим:
[When("I press add")]
public void WhenIPressAdd()
{
Calculator.Add();
}
И, вслед за ним, удостоверимся, что получаем именно то, чего желаем:
[Then("the result should be (.*) on the screen")]
public void ThenTheResultShouldBe(int result)
{
Assert.IsEqual(result, Calculator.Result);
}
Теперь самое время разобраться с нашим калькулятором.
Создадим следующее поле:
protected Calculator Calculator = new Calculator();
Теперь пора бы разобраться и с типом Calculator, его мы создадим в проекте Calculator. Так же добавим reference из проекта Calculator.Tests на проект Calculator. С типом так же всё в порядке, однако не хватает некоторых методов, их тоже следует создать.
Теперь, когда ваш проект скомпилируется, можете запустить ваш testrunner, чтобы убедится, что вы на красной полосе.
Теперь можно заняться имплементацией нашего калькулятора. На данный момент я предлагаю следующее:
public class Calculator
{
private IList<int> _buffer = new List<int>();
public int Result { get; private set; }
public void Input(int number)
{
_buffer.Add(number);
}
public void Add()
{
Result = _buffer.Sum();
_buffer.Clear();
}
}
Запускаем наши тесты и видим, что они проходят, супер!

Вроде бы с первой фичей мы успешно разобрались, почему бы не взяться за вторую?
Второй возможностью будет деление:
http://github.com/aslakhellesoy/cucumber/blob/master/examples/i18n/en/features/division.feature
# language: en Feature: Division In order to avoid silly mistakes Cashiers must be able to calculate a fraction Scenario: Regular numbers Given I have entered 3 into the calculator And I have entered 2 into the calculator When I press divide Then the result should be 1.5 on the screen *в оригинале для cucumber у aslakhellesoy несколько иной синтаксис, но он на данный момент не поддерживается в SpecFlow
данную фичу мы добавим в наш тестовый проект под названием devision.feature. как не трудно заметить, что основные шаги мы с вами уже описали в предыдущем примере, сейчас осталось только добавить 1 метод:
[When("I press divide")]
public void WhenIPressDevide()
{
Calculator.Devide();
}
Добавить так же метод в класс Calculator.
Скомпилировать наш проект. И запустить тесты. Конечно же они не пройдут, т.к. деление мы с вами ещё не реализовали:
public void Devide()
{
Result = _buffer[0] / _buffer[1];
_buffer.Clear();
}
После этого мы запускаем тесты с надеждой на зеленную полосу, однако этого не происходит, т.к. мы указали тип int во всех методах, однако же в описании последней фичи мы ожидаем дробное число. Необходимо отрефакторить проект в связи с новыми потребностями. После всех изменений тесты проходят на ура и мы получаем калькулятор с возможностью деления и сложения, описанных строго в бизнесс-требованиях.
Материалы
Исходный код рассматриваемого проекта http://dl.dropbox.com/u/4070949/Calculator.zip
Скринкаст от создателей SpecFlow http://www.specflow.org/specflow/screencast.aspx
Моя статья Пример практики BDD при работе со Specter Framework
Книга The RSpec Book: Behaviour Driven Development with RSpec, Cucumber, and Friends
Википедия http://en.wikipedia.org/wiki/Behavior_Driven_Development
Spb ALT.NET Podcast #2: Persistence in .NET
Опубликовано: Февраль 2, 2010 Filed under: Podcast | Tags: ALT.NET, CouchDB, NHibernate, Oracle, ORM, Persistance, Podcast, SQL Server 1 Comment »Persistence в .Net-приложениях
- Роль persistence layer в приложении
- Реляционные базы данных: SQL Server/Compact Edition, Oracle, MySQL, SQLite
- Объектные базы данных: db4o, CouchDb (+ Divan), MongoDB
- Объектно-реляционные мэпперы (ORMы): NHibernate, Entity Framework, Linq2SQL, LLBLGen, Subsonic,Telerik OpenAccess; сравнение разных ORM-фреймворков (warning: сайт написан авторамиDataObjects.net)
- LINQ провайдеры и LINQ-like запросы в RoR
- Должен ли разработчик быть еще и DBA?
Подкасты Петерубргской Группы Alt.NetПодкасты о разработке в среде .Net. Ключевые слова: C#, F#, Boo, Visual Studio, .Net, PostSharp, Asp.Net личная подкаст-лента |
Аналогичные конвенции (соглашения) существую в известном всем MVC Framework на Ruby:
Участники: 