Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Методологии программирования. Экстремальное программирование.


Информационный Канал Subscribe.Ru

Профессинальное программирование на .NET


Выпуск 5

Здравствуйте, уважаемые подписчики!

Сначала хочу извиниться за долгое отсутствие. К сожалению, навалилось много дел и небыло времени написать очередной выпуск.

Теперь о приятных вещах. Рассылка по прежнему будет выходить. Надеюсь выдерживать периодичность около 2 раз в месяц. Количество подписчиков превысило 1000 и растет дальше. Это приятно, так как служит индикатором того, что рассылка интересна читателям. Открылся сайт рассылки - DeveloperGuru.NET. На нем будут размещаться материалы рассылки, сопутствующие файлы, форумы для обсуждения вопросов поднимаемых выпусками. Уже сейчас вы можете оставить свои отзывы и комментарии.


Методологии разработки

За последние несколько лет широкую известность получила методология разработки под названием экстремальное программирование (eXtreme Programming - XP). Несмотря на название, скейтбоард, сноубоард и другие "экстримбоарды" при этом не требуются.

Что же скрывается под этим, модным сейчас, словосочетанием? XP - это методология быстрой разработки программного обеспечения, базирующаяся на 12 ключевых принципах. Она была разработана Кентом Беком (Kent Beck) в 1995 году.

Рассмотрим 12 ключевых принципов XP.

Планирование или Игра в Планирование. В процессе планирования заказчик определяет ценность каждой функции (feature) системы с точки зрения своего бизнеса, а программисты стоимость реализации этих функций (в человеко-днях). В первую очередь реализуются наиболее значимые функции, а менее нужные откладываются на следующую итерацию (см. далее).

Небольшие релизы. Процесс разработки разбивается на небольшие итерации (2 - 4 недели), в конце которых выпускается небольшой релиз приложения. Так как в первую очередь реализуются наиболее нужные функции, заказчик получает наиболее необходимую функциональность гораздо раньше окончательного релиза.

Метафора. XP команда использует общее представление, которое помогает понять, как работает программа и где находится определенная функциональность, называемое "метафора".

Простой дизайн. Программа, созданная по XP, должна быть настолько простой, насколько позволяют требования. Ничего не создается "на будущее". Это очень разумный, на мой взгляд, принцип, который я стараюсь применять независимо от методологии. Вспомните, как часто вы пишете код с прицелом на будущее и сколько времени тратите на продумывание функциональности, которая может когда-либо понадобиться. А потом получается, что эта функциональность не нужна или нужна, но в другом виде. Конечно, этот принцип не означает, что приложению не нужен продуманный каркас (framework).

Тестирование. XP разработка базируется на непрерывном тестировании разрабатывемой программы. Программисты сначала пишут автоматизированные юнит тесты (unit tests), а потом создают функциональность, отвечающую этим тестам. Заказчики разрабатывают приемочные тесты, которые позволяют им быть уверенными, что реализована вся необходимая функциональность (причем правильно). Тестирование и, юнит тестирование в частности, не являются прерогативой XP. В настоящее время практически ни одна из методологий разработки не обходится без этого процесса.

Рефактоинг. Рефакторинг представляет собой процесс такого изменения программной системы, при котором не меняется внешнее поведение кода, но улучшается его внутренняя структура. Это достигается путем избавления от дублирующего кода, переименования переменных, методов и других частей кода, чье название не соответствует их сущности, а, также, другими способами.
Практически невозможно проводить рефакторинг, не имея автоматизированных тестов, покрывающих изменяемый код, так как в этом случае нельзя будет гарантировать, что код работает как и раньше.

Парное программирование. В XP программисты работают парами, создавая код на одном компьютере. При этом качество кода значительно повышается по сравнению с тем, когда программисты работают отдельно.

Коллективное владение кодом. Каждый программист в XP команде знает весь код. Благодаря этому не возникает задержек при переключении людей между частями программы. Любой член команды может быть легко заменен. Если какой-то модуль требует больше времени, чем планировалось, к нему можно подключить свободных программистов без потери времени на ознакомление с кодом.
Не стоит думать, что благодаря взаимозаменяемости членов команды, люди становятся менее ценными. Независимо от методологии, в любой компании, создающей ПО, главной ценностью являются специалисты (наряду, конечно, с заказчиками :-) ). XP в этом смысле не исключение. Просто, отсутствие человека на рабочем месте (например, из-за отпуска) не создает проблем с написанием и поддержкой кода, так как нет понятий "мой", "не мой", "его" код.
Один из способов, которым достигается коллективное владение кодом - это парное программирование. Но пары не постоянные, а меняющиеся. Меняясь парами, программисты получают информацию о еще не знакомом им коде от более осведомленного напарника (который создавал этот кусок кода с другим напарником). Также, очень эффективен процесс интеграции новичка в команду, так как он сразу начинает создавать реальный код в паре с опытным коллегой.

Непрерывная интеграция. XP команда интегрирует код и "билдит" его несколько раз в день. Это избавляет от проблем, которые возникают в тех случаях, когда билд создается редко. Программисты постоянно работают с последней версией системы.

Сорокачасовая рабочая неделя. Уставшие программисты делают больше ошибок. Поэтому, в XP не принято перерабатывать и работать по выходным. В конце итерации, в случае необходимости, допускается некоторый overtime. В этом случае усталость компенсируется небольшим праздником, который принято устраивать после каждой итерации.

Присутствие заказчика. Заказчик или его представитель должны присутствовать в команде разработчиков. С ним решаются вопросы связанные с бизнес процессами, уточняются требования. Присутствие заказчика позволяет избежать простоев.

Стандарты кодирования. Поскольку в XP код принадлежит всем разработчикам, стандарты кодирования имеют еще большее значение, чем в других методологиях.

Одним из существенных преимуществ XP является низкая стоимость и время внедрения. Вместе с тем, чтобы методология работала, необходимо следовать всем принципам, что часто является непросто реализовать. Многих программистов сложно убедить работать парами. Еще сложнее создать эффективно работающие пары, в которых программисты работают слаженно, дополняя друг друга.
Ограничения XP - небольшие проекты до 6 месяцев с командой разработчиков от 2-х до 10-ти человек.

Я уже говорил, что некоторые принципы XP имеют смысл и сами по себе и в составе других методологий. Если какой-то принцип может оказаться полезным в вашей разработке, попробуйте его применить. Только прошу, внедрив несколько принципов XP, не говорите, что работаете по XP :-). Это будет некоторая другая методология. В дальнейшем, я попытаюсь показать, что каждый проект требует своей собственной методологии (которая, конечно, может базироваться на одной из широкоизвестных).

Для тех, кто хочет узнать про XP больше.
На русском языке выпущена серия книг по экстремальному программированию, написанных основоположниками этой методологии.
В интернете можете начать с этих ресурсов:
www.xprogramming.ru - ресурс на русском языке, есть форум
www.extremeprogramming.org
www.xprogramming.com

Инструменты разработчика

Для юнит-тестирования (unit-testing), используемого во многих методологиях, применяются специальные утилиты, позволяющие сразу запустить все тесты и увидеть результат. Одна из наиболее популярных на сегодня утилит для юнит-тестирования - NUnit. С ее помощью можно создавать юнит-тесты на любом .NET языке.


.NET для профессионалов

Практическое введение в юнит-тестирование

Давайте рассмотрим процесс создания юнит-теста с использованием NUnit. Для этого скачайте и установите себе NUnit.
В прошлом выпуске мы говорили про округление. Давайте напишем метод арифметического округления и юнит-тест для него. Для этого создадим с помощью Visual Studio новый solution и 2 проекта типа class library, один из которых назовем RoundLibrary, а второй RoundLibraryTest. При разработке программ с использованием юнит-тестов (test-driven development) принято сначала создавать юнит-тест, а потом, собственно, код, который должен тестироваться. Давайте так и сделаем, хотя должен признать, что не всегда удается следовать этому правилу.
В проекте RoundLibraryTest добавим ссылку на NUnit.Framework и RoundLibrary (через Add Reference). Затем, добавим новый класс с именем RoundTest. При помощи директивы using подключим пространства имен NUnit.Framework и RoundLibrary:

using NUnit.Framework;
using RoundLibrary;

Затем, перед именем класса добавим атрибут TestFixture:

[TestFixture]

Теперь добавим метод MathRoundTest():

[Test]
public void MathRoundTest()
{
}

Атрибуты TestFixture и Test указывают, что класс и метод содержат код юнит-теста.

Осталось добавить код:

Assert.AreEqual(3, Round.MathRound(3.1, 0));
Assert.AreEqual(3, Round.MathRound(3.2, 0));
Assert.AreEqual(3, Round.MathRound(3.3, 0));
Assert.AreEqual(3, Round.MathRound(3.4, 0));
Assert.AreEqual(4, Round.MathRound(3.5, 0));
Assert.AreEqual(4, Round.MathRound(3.6, 0));
Assert.AreEqual(4, Round.MathRound(3.7, 0));
Assert.AreEqual(4, Round.MathRound(3.8, 0));
Assert.AreEqual(4, Round.MathRound(3.9, 0));
Assert.AreEqual(4, Round.MathRound(4.0, 0));
Assert.AreEqual(4, Round.MathRound(4.1, 0));
Assert.AreEqual(4, Round.MathRound(4.2, 0));
Assert.AreEqual(4, Round.MathRound(4.3, 0));
Assert.AreEqual(4, Round.MathRound(4.4, 0));
Assert.AreEqual(5, Round.MathRound(4.5, 0));
Assert.AreEqual(5, Round.MathRound(4.6, 0));
Assert.AreEqual(5, Round.MathRound(4.7, 0));
Assert.AreEqual(5, Round.MathRound(4.8, 0));
Assert.AreEqual(5, Round.MathRound(4.9, 0));

Но пока он даже не скомпилируется. Добавим в проект RoundLibrary новый класс Round, в котором добавим следующий метод:

public static double Round(double value, int digits)
{
 return 0;
}

Теперь можем "сбилдить" солюшен. После билда, убедившись, что нет ошибок, запустите утилиту NUnit-Gui и откройте сборку RoundLibraryTest.dll. NUnit отобразит в виде дерева все тестовые классы и методы выбранной сборки. Нажав кнопку Run, запустите наш единственный метод. Он окрасится красным цветом и появится сообщение:

RoundLibraryTest.RoundTest.MathRoundTest :
expected:<3>
but was:<0>

Все верно, наш метод MathRound() пока ничего не делает, всегда возвращая ноль. Исправим это, написав реальный код:

  double scale = Math.Pow(10.0, digits);
  double round = Math.Floor(Math.Abs(value) * scale + 0.5);
  return (Math.Sign(value) * round / scale);

"Сбилдим" solution и снова запустим тест (перезапускать оболочку NUnit не надо). На этот раз тест должен окраситься в зеленый цвет.

На этом, краткое введение в юнит-тестирование закончено. Исходный код примера можно скачать с сайта рассылки

P.S. Visual Studio 2005, релиз которой должен появиться в конце осени, позволяет создавать юнит-тесты без помощи сторонних утилит. При этом механизм остается таким же.


Логическая задача

Сначала, ответы на задачи из предыдущего выпуска. Т.к. их текст немного длинноват, я не буду повторять их условия здесь. Те, кто не читал предыдущий выпуск, могут ознакомиться с условием задачи, прочитав его в архиве рассылки. Напомню лишь, что речь идет о задачах из книги головоломок "Принцесса или тигр?".

Ответы:

4. Поскольку обе таблички утверждают одно и то же, значит, они одновременно либо говорят правду, либо лгут. Допустим, что обе надписи утверждают правду, -  тогда в обеих комнатах должны находиться принцессы. В частности, это будет означать, что и в комнате II принцесса. Но нам сообщили, что если в комнате II находится принцесса, то утверждение на соответству-ющей табличке должно быть ложным. В результате мы приходим к противоречию, и, следовательно, надписи на обеих табличках не могут являться истинными; они будут ложными. Итак, мы получаем, что в комнате I сидит тигр, а в комнате II находится принцесса.

5. Если предположить, что в первой комнате сидит тигр, то мы приходим к противоречию. Действительно, в этом случае утверждение на первой табличке оказывается ложным, что сразу приводит нас к выводу, что ни в одной из комнат нет принцессы, то есть что в обеих комнатах должно сидеть по тигру. В то же время из условия задачи мы знаем - наличие тигра во второй комнате означает, что вторая надпись является верной, то есть в другой комнате должна находиться принцесса. Это противоречит исходному предположению о том, что в первой комнате сидит тигр. Значит, тигр в первой комнате оказаться не может, и, следовательно, там должна находиться принцесса. Таким образом, вторая табличка не лжет - во второй комнате действительно обретается тигр. Итак, принцесса находится в первой комнате, а тигр сидит во второй.

6. Первая надпись утверждает, что в обеих комнатах либо находятся принцессы, либо сидят тигры  ведь только в такой ситуации все равно, какую из комнат выбрать.
   Пусть, например, принцесса находится в первой комнате. Тогда фраза, приведенная на первой табличке, истинна; отсюда следует, что во второй комнате также находится принцесса. С другой стороны, предположим, что в первой комнате сидит тигр. Тогда первая надпись будет ложной и, значит, в обеих комнатах должны находиться различные обитатели, откуда опять следует, что во второй комнате должна оказаться принцесса. Тем самым доказано, что принцесса должна находиться в комнате II независимо от того, кто занимает комнату I. Наконец, поскольку принцесса находится в комнате II, то надпись II является ложной и, следовательно, в комнате I должен сидеть тигр.

7. Первая табличка фактически утверждает, что в обеих комнатах находятся разные обитатели (в одной -  принцесса, в другой - тигр), но ничего не говорит нам о том, кто же именно в какой комнате.
   Если комнату I занимает принцесса, то утверждение таблички I истинно; следовательно, в комнате II должен сидеть тигр. С другой стороны, если в комнате I посажен тигр, то первая надпись оказывается ложной, откуда следует, что на самом деле обитатели обеих комнат должны быть одинаковы, и поэтому в комнате II также должен находиться тигр. Итак, в комнате II действительно сидит тигр. Это значит, что вторая надпись является истинной и, следовательно, принцесса должна находиться в первой комнате.

8. Предположим, что верхняя табличка «В этой комнате сидит тигр» прикреплена у дверей комнаты I. Если принцесса находится в этой комнате, то утверждение на табличке будет ложным - однако при этом нарушаются объявленные королем условия. Если же в левой комнате сидит тигр, то надпись на табличке будет истинной - условия, объявленные королем, оказываются нарушенными вновь. Поэтому ясно, что верхняя табличка не  может висеть на дверях комнаты I. Значит, она должна находиться на дверях комнаты II; в свою очередь нижняя табличка должна располагаться на первой двери.
   Итак, табличка, которая должна висеть на первой двери, гласит: «В обеих комнатах сидят тигры». При этом принцесса не может находиться в комнате I; ведь в противном случае левая табличка оказывается правдивой, что приводит нас к очевидному противоречию - будто бы в обеих комнатах сидят тигры. Следователь но, в комнате I сидит тигр. Отсюда сразу становится ясно, что табличка на дверях этой комнаты ложна, и поэтому в комнате II должна находиться принцесса.

Далее, продолжение мучений узников. Внимание! Задачи становятся сложнее!


Третий день

- Проклятье! - воскликнул король. - Опять все наши узники ускользнули. Я думаю, завтра надо занять
три комнаты вместо двух. В одну поместим принцессу, а в две другие - по тигру. Поглядим, каково придется нашим умникам!
- Блестящая идея, ваше величество! - сказал министр.
- Ваши оценки, мой друг, крайне лестны для меня, хотя и несколько однообразны, - поморщился король.
- Блестяще сказано, ваше величество! - воскликнул министр.

9. Испытание девятое.

   Итак, на третий день король сделал все так, как задумал. Узнику были предложены на выбор три комнаты, в одной из которых, как объяснил король, находилась принцесса, а в двух других сидели тигры.
   На дверях комнат были повешены следующие таблички:

I
В этой комнате сидит тигр
II
В этой комнате находится принцесса
III
Тигр сидит в комнате II

  При этом король добавил, что не более одного из этих утверждений является истинным. Где принцесса?

10. Испытание десятое.

   И снова в комнаты поместили лишь одну принцессу и двух тигров. Король объяснил узнику, что на этот раз табличка на двери, за которой находится принцесса, говорит правду, а из двух других надписей по меньшей мере одна является ошибочной. Сами же таблички имели такой вид:

I
Тигр сидит в комнате II
II
Тигр сидит в этой комнате
III
Тигр сидит в комнате I

   Что делать узнику?

11. Три возможности.

   Это испытание было еще каверзнее. Король объяснил узнику, что в одной из комнат сидит принцесса, в другой - тигр, а третья комната пуста. При этом надпись на двери комнаты, в которой находится принцесса, - истинна, надпись на двери, за которой сидит тигр, - ложна, а то, что написано на табличке у пустой комнаты, может оказаться как истинным, так и ложным. Вот эти таблички:

I
Комната III пуста
II
Тигр сидит в комнате I
III
Эта комната пуста

   А узник раньше видел эту самую принцессу и совсем не прочь был жениться на ней. Поэтому, хотя пустая комната, конечно, получше комнаты с тигром, узнику все же хотелось угадать, где принцесса.
   Так где же принцесса, а где тигр? Если вы сумеете ответить на эти вопросы, то без труда поймете, какая комната пуста.


Технологический партнер рассылки:
PARKING.RU.
Качественный ВИРТУАЛЬНЫЙ ХОСТИНГ на платформе Windows (r): поддержка .NET-приложений, управление сайтом, аренда бизнес-приложений, сертифицированные специалисты.


На этом все. Желаю приятного программирования.


Вопросы? Пожелания? Пишите: author@developerguru.net

Subscribe.Ru
Поддержка подписчиков
Другие рассылки этой тематики
Другие рассылки этого автора
Подписан адрес:
Код этой рассылки: comp.soft.prog.gurudotnet
Отписаться
Вспомнить пароль

В избранное