новое    архив    фото    Харьковские сети    login   


дата   27-11-2009 13:43:48



Последнее изменение: 11 июня 2008г. Экстремальное программирование – реальность и мифы Написать эту статью меня побудило большое количество дискуссий вокруг XP как методологии разработки. Мнение о ней в основном негативное. По разным причинам. Проанализировав все, что я слышал, я пришел к выводу, что многие просто не представляют себе, что такое XP, и делают выводы либо в отсутствие опыта вообще, либо при его наличии, но в очень малом объеме. В этой статье я хочу коснуться следующих вопросов – теории и практики XP, распространенных мифов об XP и предназначения XP. Я пройдусь по всем практикам, поясняя, что есть что и, самое главное, зачем это надо. Итак, краткое оглавление. * Теория и практика XP * Практики XP 1. Планирование 2. Тестирование 3. Парное программирование 4. Рефакторинги 5. Простой дизайн 6. Коллективное владение кодом 7. Постоянные (непрерывные) интеграции кода 8. Заказчик в команде 9. Частые выпуски версий 10. 40-часовая рабочая неделя 11. Стандарты кодирования 12. Метафора системы * Мифы об XP * Предназначение XP * Проведение грани – тут XP, тут не XP. Пожалуй, начнем. Теория и практика XP Теория XP в своей основе проста. Существует некий набор практик, применение которых способно дать лучший результат, нежели стандартные жесткие методики. Причем эти практики в XP применяются в превосходной, экстремальной форме, откуда, собственно, и название. Происходит XP из простой посылки. Программное обеспечение – чрезвычайно непостоянная вещь. И эта непостоянность вызывает закономерные проблемы при стандартных способах разработки. Хуже всего то, что требования могут меняться непосредственно в то время, когда разрабатывается продукт. Т.е. к моменту выхода он уже несколько устаревает. Именно эту проблему – жесткости стандартных методик разработки – и призвана решить методология XP. Здесь, однако, есть небольшой нюанс. Все книги, которые я читал, – они несколько популяризаторского толка. И именно в таком шоу-стиле они и написаны. "Йо, вау, аплодисменты, XP это круто" – такие ощущения просвечивают тут и там. И уже одно это зачастую вызывает неприятие. Кроме того, некоторые высказывания народ почему-то склонен понимать буквально, что приводит опять-таки к неприятию идей еще до того момента, как их успевают осознать. Есть еще один момент, которого не учитывают многие. Дело в том, что между теорией и практикой – пропасть. Вы можете прекрасно знать теорию, но не быть способным применить ее на практике. Приведу пример. Он, правда, не из области программирования, а из области вождения машины. Мне как-то эта область весьма близка. Допустим, некто (пусть это будет девушка) учится водить машину. Для определенности – трогаться с места. Она прекрасно знает, что надо плавно отпустить сцепление. И тем не менее – машина глохнет. Раз, другой, третий, десятый. Почему? Потому что это практика. Создатели педального узла не предусмотрели вождение на "шпильках". В нужный момент каблук теряет опору и проскальзывает, в результате сцепление отпускается рывком. Ладно, обувь сменили. Машина продолжает глохнуть. Почему? Потому что отпускать сцепление плавно нужно не на всей длине хода, а только на рабочей – 2 см от силы. И если отпускать сцепление с той скоростью, которая нужна именно на рабочей части хода – до этой рабочей части нога будет подниматься минуту. Затечет, заболит, этот процесс в конце концов просто надоест. В результате – сцепление брошено, машина заглохла. Что же нужно на самом деле? Практика и ничего более. БЫСТРО поднять ногу до рабочей зоны, плавно и существенно медленнее отпустить педаль в рабочей зоне, после схватывания отпустить вообще. Практика, практика и еще раз практика. И очень желательно – вместе с инструктором. Который точно знает, где начинается рабочая зона, и даст это почувствовать обучаемому. Точно так же, как надо учиться вождению с инструктором – XP надо изучать рядом с тем, кто уже знает практические тонкости, сильно меняющие всю картину. А чаще всего бывает вот как: человек "XP изучал с пристрастием (хотелось понять, что же это за фигня такая на мою голову), так что понял всё правильно", потом "пережил два внедрения XP в разных проектах и дважды задавил эту ересь", и на этом основании делает далеко идущие выводы – "XP полностью ... исключает возможность получения качественного результата". Это все равно, что девушка из примера выше после трех попыток, закончившихся заглохшим двигателем, безапелляционно заявила бы, что на коробке с ручным переключением водить невозможно. Ересь это. Автогонщиков бы такое заявление весьма позабавило, я думаю. У меня опыт работы по классической методологи XP больше года. Причем я начинал в команде, которая уже давно работала с использованием XP, так что у меня была возможность обойти те грабли, на которые наступают теоретики. На текущем же месте работы мы применяем некоторые из практик и постепенно движемся в сторону введения остальных. Постепенно – ввиду сильной сопротивляемости менеджмента. В следующей части я хочу дать описание практик XP прежде всего с точки зрения их реального применения, а не с позиций голой теории. Еще один момент. XP – это не набор правил из серии "шаг вправо, шаг влево, прыжки на месте – расценивается как попытка к бегству и карается расстрелом". Это всего лишь рекомендации. Каждая из них имеет свой смысл и способна дать свой эффект. В какой степени применять каждую из этих рекомендаций – нужно решать по обстоятельствам. И это один из моментов, который понимаешь только при работе с методикой. Применение практик "в максимальной степени" на деле означает "в максимальной степени, возможной в каждом конкретном случае". Ибо, как и в любой работе, приходится иметь дело с людьми. Другой вопрос, что вместе практики дают эффект, зачастую сильно превосходящий сумму. Это можно сравнить с резонансом. Полк, проходящий по мосту, способен разрушить его, если не собьет шаг (существует специальная команда, и обусловлена она именно этим, были прецеденты!) И это при том, что то же самое, но вразбивку (фактически, сумма воздействий) он выдерживает "на ура". Итак, перейдем к рассмотрению непосредственно практик XP. Практики XP По сути, тут нет ничего нового. Все эти вещи известны. Некоторые, правда, сильно пугают заказчика, не привыкшего к подобному подходу. Тут "в лоб" не стоит давить, не получится. Только испугается. Практика показывает, что когда заказчик начинает ощущать преимущество даже от частичного применения практик, его скептицизм изрядно ослабевает. Ну, вот мы и добрались до самих практик. Пойдем по порядку. Планирование Это та стадия, на которой вы обсуждаете с заказчиком, чего он хочет. Как правило, заказчик знает это весьма смутно. Ваша задача – вытащить из него необходимую вам информацию. Прежде всего, человек, с которым вы общаетесь, должен быть профессионалом, знающим область, для которой вы пишете продукт, равно как и всю операционную деятельность, для которой этот продукт предназначен. Попытки обсуждать с генеральным директором программу для бухгалтерии обречены на провал. Разве что он и сам бухгалтер. Человек должен разбираться в проблемах, стоящих перед ними, и в том, как они хотели бы их решить с помощью обсуждаемого ПО. Обсуждение идет по принципу "от крупного к мелкому". Сначала обсуждается задача в общих чертах, потом она разбивается на подзадачи. И так далее. До какого уровня? Я считаю, что можно остановиться, когда каждая задача займет где-то день. В этом случае ее можно обсудить досконально. Пример Допустим, разрабатывается система документооборота. Заказчик хочет в нее добавить выставляемые счета и платежи по ним. Что нужно сделать: 1. Добавить в систему такие понятия как invoice и payment. Т.е. определить их в базе, сделать бизнес-объекты, сделать UI под каждый из них. Итого – по дню работы на каждый элемент. 2. Добавить в систему возможность сопоставлять счета и платежи. Бизнес-логика, таблица сопоставления в базе, UI. В зависимости от сложности логики – это 1-3 дня. 3. Добавить в систему возможность связывать счета с уже имеющейся в системе информацией по сделкам, издержкам и т.п. Это опять-таки бизнес-логика, изменения в базе, UI. Для начала хватит. Что нужно выяснить у заказчика: 1. Какая информация должна содержаться в объектах типа счет и платеж. Поля, названия их, которые должны фигурировать в UI, форматы вводимых данных, возможная их валидация. Должны ли вводимые данные соответствовать чему-то имеющемуся в системе, например, выставляемый счет может относиться к определенному контрагенту, соответственно, нужна возможность поиска контрагента вместо его ввода в UI, и т.д. и т.п. Вам нужна ВСЯ информация, которая потребуется вам для реализации этого требования заказчика. 2. Может ли один платеж быть соотнесен с несколькими счетами? Может ли один счет быть оплачен несколькими платежами? Что должно быть видно пользователю, какие действия он должен предпринять, чтобы поставить в соответствие счет и платеж? Должен ли пользователь видеть полностью оплаченные счета? Полностью расписанные по счетам платежи? 3. Должен ли пользователь иметь возможность создавать счет прямо из UI, относящегося, скажем, к сделке, или он всего лишь может выбрать уже существующий счет? Должен ли пользователь иметь возможность выставлять несколько счетов на сделку? Один счет на несколько сделок? И т.д. и т.п. Вопросов может быть существенно больше. Когда все требования таким образом сформированы – они фиксируются где-нибудь в письменном виде. Дабы не было разногласий. Затем заказчик определяет приоритеты. Допустим, ему очень нужна возможность выставлять счета, причем из UI сделок. А соотношение с платежами пока не очень актуально. Тогда именно в этом порядке и сортируются данные задачи. Причем обратите внимание – в примере заказчику нужна часть пункта 1, часть пункта 3. Т.е. эти пункты должны быть разбиты на подзадачи. После того, как приоритеты расставлены – производится временная оценка. Тут есть тонкость. Даже несколько. Первое – оценивать задачу может лишь тот, кто будет ею непосредственно заниматься. По той простой причине, что разработчики не идентичны. Один может сделать задачу быстрее, другой – медленнее. Следовательно, точная оценка при обсуждении задач с заказчиком сделана быть не может. Впрочем, она не может быть сделана по определению. :) Второе. Разработчики работают в разных ситуациях. Они могут целый день не отрываться от задачи, а могут полдня потратить на консультации других разработчиков, исследования и т.п. Это непредсказуемо. Возможно лишь статистическое накопление информации. Так вот, как правило, на разработку из-за таких отвлекающих факторов тратится больше времени, нежели изначальная оценка. Потому в XP принят такой подход. Оценка работы при условии, что разработчик будет сконцентрирован исключительно на задаче, что его ничто не будет отвлекать, что он будет работать с максимальной продуктивностью – эта оценка называется идеальное время. Время, потраченное на разработку в действительности, называется реальным. Отношение этих времен, усредненное за определенный промежуток времени (например, за 8 циклов разработки, см. Частые выпуски версий), называется коэффициентом загрузки (load factor). Таким образом, разработчики оценивают идеальное время выполнения задачи, после чего, умножив его на коэффициент загрузки, можно получить реальную оценку выполнения задачи. И именно эта оценка должны фигурировать в описании задачи. Принято считать, что коэффициент загрузки в начале работы команды равен 3. После того, как команда уже втянулась в проект, скорость разработки начинает повышаться. Для профессиональной команды, хорошо сработавшейся друг с другом и с заказчиком, коэффициент загрузки по опыту находится где-то в районе 1.7-1.8. Пойдем дальше. Описание задачи получено, временная оценка тоже, приоритеты расставлены. При работе с заказчиком удобно иметь систему общего доступа, в которой будут отражаться все детали, касающиеся разработки. Что-нибудь типа TWiki (http://www.twiki.org/). Это позволяет оперативно вносить изменения в работу. Итак, в TWiki создается т.н. история (user story), в которой описывается все, что относится к конкретной задаче. Все, что сообщил заказчик, временные оценки, приоритет. Возможно, комментарии в процессе реализации. После того, как история создана, заказчик еще раз просматривает ее и подтверждает, что все верно и он с такой постановкой задачи согласен. Всё, можно работать. Такой подход может показаться весьма муторным. Однако он служит одной очень важной цели. Такое обсуждение заставляет заказчика продумать до мелочей его требования к системе. Следовательно, сильно уменьшается вероятность того, "через неделю заказчик меняет требования на противоположные", как упоминал кто-то из форума. Да и вообще, часто оказывается, что часть изначальных требований заказчику и не нужна, а нужно ему что-то совсем другое. Если бы он просто написал ТЗ, а потом бы его реализовали, – пришлось бы переделывать очень много. И заказчик был бы явно недоволен. В случае же XP-планирования – он с гораздо большей вероятностью получает именно то, что хочет. Стоит еще упомянуть вот какой момент, связанный с планированием. Если какая-то функциональность вызвала затруднения в реализации и все, что запланировано, не укладывается в рамки очередного релиза – объем реализуемой функциональности необходимо снизить. Именно так – не отодвинуть выпуск продукта, а уменьшить функциональность. Почему – см. в разделе Частые выпуски версий. Т.е. убрать из запланированной функциональности то, что наименее критично. Решить это должен заказчик, и никто кроме него не может это сделать. Парадоксально, но факт, – часть функциональности таким образом вообще отсеивается. Что означает, что она изначально не была нужна. В результате процесса планирования/перепланирования мы получаем четкий план работы на ближайшую версию-две. Таким образом, планирование нужно производить по меньшей мере раз в версию. А лучше – раз в неделю, для того, чтобы скорректировать оценки, основываясь на текущем положении вещей. О планировании пока всё. Переходим к следующей практике XP – Тестирование А точнее – написание тестов ПЕРЕД написанием кода. Тестирование вообще процесс, нелюбимый разработчиками. Написание тестов – тем более. А уж написание тестов ДО кода – вообще смертоубийство. Между тем, тесты приносят реальную пользу. В каждый момент времени, выполнив все тесты, мы можем сказать, что система работает так, как от нее ожидают. Очень часто это помогает при каких-то внутренних изменениях, которые не должны затрагивать функциональность, например, при рефакторингах. Да, команда тестировщиков в конечном итоге скорее всего выловит ошибку. Но сколько пройдет времени? Собрать версию, выложить ее на тестовый сервер, запуск нагрузочных тестов, запуск приемочных тестов. День. Если не больше. А могут вообще и не найти ошибку. И вылезет она только уже в рабочей системе, найдут ее пользователи. При том, что для выявления ошибки с помощью тестов нужно 20-30 минут. Столько, как правило, выполняются тесты в системах среднего размера. Далее. Зачем писать тесты ДО функциональности. Во-первых, неукоснительное соблюдение этого правила гарантирует, что любая часть функциональности системы покрывается тестами. Если оставить тесты на потом – в силу природной лени (нелюбви к тестам, нехватки ресурсов – нужное подчеркнуть) есть большая вероятность того, что они так и не будут написаны. Во-вторых, есть гораздо более интересная тонкость. При написании тестов ДО функциональности мы расцениваем эту самую функциональность как черный ящик. У нас есть набор требований – на входе А, на выходе В. Тест состоит в том, чтобы подать на вход А и сравнить результат с В. И именно так мы его и будем писать. Конечно, тесты бывают существенно более сложными, с проверкой множества правил бизнес-логики. Так вот, если оставить тест на потом, то мы уже будем знать, как работает этот черный ящик. И вольно или невольно, но мы можем заложиться на собственную реализацию. Т.е. для теста блок функциональности будет уже не черным ящиком, а механизмом, принцип работы которого известен. Таким образом, если этот блок изменится, но продолжит работать корректно – тест может не пройти. Это еще полбеды. Хуже, если в тесте мы будем проверять не конечный результат, а именно работу механизма. И тогда, с точки зрения теста механизм может работать верно, но на выходе даст не В, а С. Я видел и такое. Польза от подобного теста сомнительна. Чтобы избежать такого эффекта, и нужно писать тесты ДО функциональности. Я знаю, что писать тесты не любит никто, но все же хочу призвать ими заниматься. Польза от этого может быть существенно больше, чем представляется. Двигаемся дальше. На очереди практика, вызывающая очень много вопросов, критики и т.п., а именно – Парное программирование В прямом смысле этого слова. Парное – два разработчика за одним компьютером. Критики обычно утверждают, что в таком раскладе общая производительность пары разработчиков ниже, чем по отдельности. Хочу поделиться опытом. Собственный опыт Декабрь 2000 года. Мы с коллегой сидим в длительной коммандировке в Голландии. Днем работа, вечером делать нечего. Пиво пить мы не любим. В карты играть – вдвоем неинтересно. Пойти тоже особо некуда. Есть один компьютер на двоих. В итоге родилась идея написать компоненту для Delphi, которая нам обоим была нужна. Надо сказать, что и он и я до этого предпринимали попытки ее написать, однако безрезультатные. Работали мы с ним как и положено в XP – вдвоем за одним компьютером. Один вечер он сидит и пишет, я рядом. Другой вечер – наоборот. Результат меня поражает до сих пор. Мы написали то, что надо, за 4 вечера. При том что до этого каждый из нас потратил на эту задачу как минимум пару недель, и с гораздо худшим результатом. Написаную компоненту мы активно использовали в дальнейшем и не выявили ни одной ошибки. Она работала как часы, при этом ее код был простым, оптимальным, а интерфейс – интуитивным. Я хорошо помню процесс разработки. Ошибки вылавливались еще до того, как код компилировался впервые. Существенный плюс второй пары глаз. В процессе написания кода постоянное обсуждение, в результате чего код получался чистым, ибо оптимизировался на лету. Очень большое количество интересных идей – результат мышления в одном направлении, один был катализатором для другого. Учитывая, сколько времени было потрачено ДО этого, и каков был результат – я этот опыт парного программирования расцениваю как сугубо положительный. Итак, написание кода вдвоем. Что это дает? Прежде всего – мышление у людей не совпадает. В результате в каждой точке ветвления есть большая вероятность, что я и кто-то другой изберем разные направления движения. Т.е. родятся две идеи вместо одной. Соответственно, появляется возможность выбрать более оптимальную из них. Если такое происходит в каждый момент, как это бывает при парном программировании – оптимальность и ясность кода резко возрастает. Соответственно, падает количество ошибок, что немаловажно для стоимости дальнейшей поддержки кода. Критики этого, как правило, не учитывают. Далее. Написание кода вдвоем означает, что код досконально знает не один человек, а два. Таким образом, знания о работе кода сложнее потерять. При традиционном подходе – каждый сам за себя – это зачастую очень острая проблема. Третье. При работе в паре разработчики, фактически, подстегивают друг друга. В результате этого повышается скорость работы каждого из них. Это же, кстати, является и минусом парной работы. Работать вдвоем в таком режиме 8 часов в день – ОЧЕНЬ тяжело. Средний выход сильно выше, соответственно, выше и усталость. Но общий эффект, даже при отдыхе, перекурах, питье кофе, чая и т.п. все равно лучше, нежели при программировании порознь. Довольно часто парное программирования настолько пугает заказчика (как вариант – руководство компании), что от XP отказываются только поэтому. В таком случае можно применять т.н. параллельное программирование. Отличается от парного оно исключительно тем, что у разработчиков не один компьютер, а два. И внешне ситуация гораздо приятнее для руководящего ока. В случае применения такой практики есть два "но". Первое – разработчики должны сидеть за соседними столами, так, чтобы быть максимально близко друг к другу. Это даст им возможность обсуждения задачи. Опять-таки можно подвинуться на полметра в сторону – и оказаться за одним компьютером. Правда, при этом несколько упадет эффективность написания кода, ибо уже не будет одновременного мышления в одном направлении при работе на двух компьютерах. Но даже это способно дать лучший эффект, чем программирование порознь. Должен сказать, что опыт параллельного программирования у меня тоже есть. Собственно, он основной, именно так и работала команда, в которой я начинал изучение XP на практике. Как я уже говорил, эффективность у такой работы ниже, чем при парном программировании, однако свои плюсы там тоже несомненно были. В этом месте очень многие критики заявляют – это уже не XP. Потому еще раз хочу подчеркнуть – XP не есть набор наручников и железных клеток. Это всего лишь рекомендации. И степень применения каждой из них надо выбирать в каждом случае. Да, модификации могут повлиять на общую производительность, но общий эффект все равно будет. Называйте то, что получилось как хотите. Я лично это называю XP. В противном случае можно договориться до того, что из двух автомобилей один является автомобилем, а другой нет, на том основании, что какой-то гуру двадцать лет назад описал автомобиль как имеющий механическую коробку передач, а у второго из них она автоматическая. Не стоит относится к чьим-то словам фанатично, пусть даже они и стояли у истоков. В 1977-м году Кен Олсон, основатель Digital Equipment Corp. (DEC), сказал, что "нет никаких причин кому-либо желать иметь дома компьютер". Что вы ответите тому, кто будет отговаривать вас купить домой компьютер только на основании этого утверждения? Подводя итог. Парное программирование имеет несомненные плюсы. Я это знаю на личном опыте. Если по каким-то причинам не получается ввести именно парное программирование – используйте хотя бы параллельное. С течением времени, когда доверие со стороны заказчика (руководства) к методике в общем возрастет (ибо они будут видеть результат!), можно будет перейти и на парное программирование. Переходим к одной из наиболее обсуждаемых практик – Рефакторинги Как правило, само слово "рефакторинг" – словно красная тряпка для быка. Причем как для критиков XP, так и для руководства. Меня однажды уволили после произнесения этого слова. Руководство просто не смогло понять, что можно сделать в течение двух месяцев, если не разрабатывать новую функциональность. Происходит это по большей части ввиду глубокого непонимания сути рефакторинга как явления. Потому я хочу дать объяснение, зачем это нужно. Я уже говорил, но повторю еще раз. Программное обеспечение – вещь непостоянная, подверженная изменениям. Требуется новая функциональность. Расширяется старая. Вот тут и зарыта собака размером с доброго слона. Дело в том, что, каким бы тщательным ни было проектирования приложения – невозможно предугадать, что понадобится через полгода-год. Более того, попытки предугадать приведут лишь к пустой трате времени. Ибо будет реализовано очень много того, что не понадобится с большой вероятностью. А потому – логичное решение: реализовывать то, что нужно прямо сейчас. Возможно, с небольшим заделом на будущее, можно оставить немного места для маневров, если таковые понадобятся, но только если это не займет много времени. Подробнее про такой подход – в следующем разделе: Простой дизайн. Через некоторое время (иногда немалое!) появились новые требования к продукту. И теперь старое решение уже не очень хорошо. Единственным возможным вариантом является переработка старого решения так, чтобы оно отвечало новым требованиям, но при этом вся старая функциональность сохранилась. Пример Пусть у нас есть система, скажем, что-то типа webmail administration. Создание почтовых ящиков, управление квотами и т.д. и т.п. При некоторых действиях администратора происходят изменения не только в базе данных, но и в LDAP и на диске. И изменения эти должны быть выполняться целиком и в определенной последовательности, чтобы избежать несоответствий. Т.е. при изменениязх, скажем, А и В, проводимых из двух потоков одновременно, состояние после завершения изменений должно быть либо (А1,В1), либо (А2,В2), но никак не (А1,В2) или (А2,В1). Т.е. – нужна синхронизация. Какое решение можно предложить? Использовать механизм синхронизации Java – synchronized- методы и блоки. Просто и красиво. Сделали. Работает. Через год в систему введены фоновые процессы. Которые тоже надо синхронизировать, причем как между собой, так и со старым кодом. И если со старым кодом еще как-то можно использовать ту же модель синхронизации, то при синхронизации процессов между собой это уже проблематично. Дело в том, что процесс может длиться достаточно долго. И если ждать, пока завершится первый процесс, чтобы затем запустить второй (а именно так и будет при использовании synchronized) – запрос к системе будет висеть. Администратор может решить, что где-то сбой, нажать Stop в браузере, потом запустить процесс еще раз. В общем, ничего хорошего не получится. Нужно иметь возможность не ждать, если ресурс уже блокирован. В случае с synchronized-кодом это невозможно. Решение – использовать, скажем, библиотеку синхронизации Дуга Ли. Причем не напрямую, а с созданием некого интерфейсного слоя. Дело в том, что эта библиотека введена в Java 1.5 (пакет java.util.concurrent), но интерфейс ее сильно при этом изменен. В свете планирующегося перехода на версию 1.5 лучше полностью повторить именно этот интерфейс, чтобы впоследствии миграция состояла бы только в замене имени пакета – с собственного на java.util.concurrent. Cделали. Работает. Замечательно! Еще через год от бизнеса приходит требование – обеспечить устойчивость системы. Т.е. – поднять ее на не менее чем двух серверах. А это значит – обеспечить синхронизацию при наличии нескольких JVM. Все методы, используемые до этого времени, не годятся. Решение – используя уже существующий интерфейс, написать реализацию системы распределенной блокировки. Т.е. на поверхности – ровно те же интерфейсы, что и в Java 1.5, а под ним что-то принципиально другое. На основе, например, транзакционного кластерного кеша. JBossCache, Tangosol Coherence и иже с ними. Сделали. Работает. Причем основной код вообще не пришлось трогать! Подменили реализацию библиотеки синхронизации. С библиотеки Дуга Ли на собственную. Разумеется, при всех переделках система внешне осталось той же. Не изменились ни поведение, ни бизнес-логика. Приведенный пример является типичным описанием рефакторинга. По своему определению, рефакторинг – это переработка системы для приведения в соответствие с текущими требованиями. При этом внешне система остается той же. Критики часто утверждают, что рефакторинг есть следствие некачественного кода, дизайна, и т.п. Дескать, если система написана хорошо, никакие рефакторинги ей не нужны. Это в корне неверно. Рефакторинг МОЖЕТ быть следствием неправильного дизайна. Но я за 3 года ни разу не встречался с подобными случаями, хотя рефакторингами занимаюсь постоянно. В основном рефакторинг есть следствие эволюции системы, ее естественного развития. Сравните его с ремонтом квартиры. В комнате переклеивают обои. Почему? Обязательно ли потому, что старые были плохо наклеены? Совсем нет. Обои можно переклеивать потому, что хочется новых. Другого цвета. Другой фактуры. Изменились требования к комнате – и ее обновляют. Но это ни в коем случае не является следствием изначальных ошибок. У пятилетней девочки в комнате розовые обои с зайчиками и мишками – норма. У пятнадцатилетней – вряд ли. И это – изменившиеся требования – есть повод к ремонту. В XP приняты т.н. постоянные рефакторинги. Зачем это делается? Сравним с тем же ремонтом. На кухне стала качаться плитка. Можно подклеить, а можно и оставить на потом. Подклейка займет час. Дует из окон, пыль проникает. Можно поменять рамы на современные, пластиковые, шумоизолирующие и т.п., а можно оставить на потом. Замена займет полдня. Ну и т.д. и т.п. А теперь представьте себе, что ВСЁ, что каким-то образом не устраивало в кухне, оставляют на потом. Что будет в итоге? В итоге из кухни вынесут мебель, плиту, мойку, собьют ВСЮ плитку, т.к. она уже наполовину осыпалась, снимут рамы, ..., ... В общем, разнесут кухню вдребезги напополам. Ремонт будет продолжаться неделю, в течение которой в квартире жить будет невозможно. А после ремонта еще и убрать надо будет. Что в итоге? В итоге мы имеем капитальный ремонт, который во-первых, дольше, во-вторых, дороже текущего. И весь промежуток времени до капитального ремонта мы будем жить в состоянии, которое нас каким-то образом не устраивает. Жить, конечно, можно, но... При том, что в случае текущего ремонта – это было бы и быстрее, и дешевле, и комфортнее в конечном итоге. Параллель с постоянным (текущим) рефакторингом проводить или уже не стоит? Рефакторинги жизненно необходимы в любой эволюционирующей системе. И тем более – при использовании XP, которая изначально ориентирована именно на гибкую разработку. Единственный вопрос. "За чей счет этот банкет? Кто оплачивать будет?" – как говорил незабвенный Иван Васильевич. Это решать вам. У нас было принято, что раз уж рефакторинги наша инициатива, то и делаются они за наш счет. Часть из них мы иногда предлагали оплачивать заказчику, если эта часть была связана с реализацией новой функциональности, которую он запрашивал. Но делали мы это не всегда. Надеюсь, что теперь суть рефакторинга как процесса вы уловили. Перейдем к следующей, не менее обсуждаемой практике – Простой дизайн Я не знаю, откуда что берется, но у подавляющего большинства противников XP прочно укоренилось утверждение: простой == плохой (некачественный, безграмотный). Может, из-за того, что кто-то где-то сказал про минимально возможное количество классов. Может, еще из-за чего. Но их этого правила делается совершенно фантастический вывод – XP ориентирована на безграмотный дизайн и, следовательно, на безграмотный код. Господа! Если вам кто-то сказал, что "просто" значит "безграмотно" – вас этот кто-то обманул. Можно писать просто, но при этом грамотно. А можна – как слышыца. И эта какрас и будит бизграматна. А можна писать са страшна сложными граматичискими канструкцыями упатрибляя диипричасные абароты и все равно эта будит бизграматна. Грамотность – она не зависит от сложности кода. Это правило означает всего лишь одно – изобретать паровоз надо только тогда, когда лошадь уже не справляется. А пока она бодро топает, причем вас устраивает и скорость и грузоподъемность – паровоз вам не нужен. Если бы в примере, упомянутом выше, с самого начала разрабатывали распределенную синхронизацию – добром бы это не кончилось. Во-первых, с самого начала намаялись бы страшно, ибо библиотеки, пригодные для использования, появились существенно позднее. Во-вторых, систему все равно пришлось бы неоднократно переделывать. Потому как два года назад предугадать требования, выдвигаемые сегодня – НЕ-ВОЗ-МОЖ-НО! А следовательно – время, силы и средства потрачены впустую. Наконец, третье. Где гарантии, что то, на что вы хотите заложиться сегодня, ВООБЩЕ понадобится? На мой взгляд система вообще не требовала дублирования. Были проблемы с устойчивостью, но обусловлены они были исключительно системными проблемами. И решать их надо было на системном уровне – операционной системы и железа. Решение же этих проблем на уровне ПО было продиктовано исключительно политикой. Итак, что же все-таки означает "простой дизайн"? Делайте то, что нужно именно сейчас. Никто не мешает делать это грамотно. Но не закладывайтесь на то, что может произойти далее чем через два месяца! Потому что два месяца – это уже достаточный срок для пересмотра направления движения. Правило "простого дизайна" неразрывно связано с правилом "непрерывных рефакторингов". Это как раз тот случай, когда результат больше чем простая сумма. Если писать просто, но не корректировать систему под текущие требования – хорошо не будет. Если корректировать, но писать при этом очень сложно – тоже ничего хорошего. Ибо коррекция как раз будет направлена на то, чтобы разгрести изобретенную кучу незнам-чего. Если же писать просто, и постоянно при этом корректировать код – результат будет гораздо лучше. Вернемся к аналогии с ремонтом. Вариант "сделать просто, но не поддерживать постоянно" мы уже рассматривали. Рассмотрим теперь другой вариант – "сделать сложно и поддерживать". Представьте, что вместо аккуратно крашеного потолка, обоев и кафеля мы сделаем на потолке штукатурные фрески, а пол покроем деревом. Как то было сделано, скажем, в 17 веке во дворцах саксонских королей. И все это – на кухне. К чему это приведет? Во-первых, из-за влажности и тепла фрески будут разрушаться катастрофическими темпами. Мы ежедневно будем что-то подправлять. Во-вторых, дерево на полу не лучшим образом отнесется к воде, которая на него будет попадать. Плюс дерево – материал более капризный, нежели кафель, оно будет "гулять" под воздействием температуры. В результате мы будем на поддержку всего этого хозяйства в нормальном состоянии тратить куда больше времени, нежели могли бы. Но самое печальное, что сделано все это было для того, чтобы блеснуть перед гостями из далеких краев. А гости не приехали. Это – классический пример того, зачем нужен простой дизайн. Я сталкивался с таким много раз, еще до того, как познакомился с XP. Функциональность сначала создавалась сложная, запутанная, потом она использовалась дай Бог на 10%, потом ее упрощали, а половину вообще уничтожали на корню. И оставался вопрос – а зачем так было делать с самого начала? Что в итоге? В итоге мы приходим к тому, что ПРОСТО не тождественно ПЛОХО И это надо осознать любому. Простой дизайн не означает, что можно писать как попало. В этом случае не спасет никакая методология. Очень надеюсь, что эту мысль мне удалось донести. Идем дальше. Следующая практика – Коллективное владение кодом Что это означает? Означает это вот что: у кода нет автора, его может менять любой разработчик. Что это НЕ означает? Это НЕ означает, что за код не отвечает никто. Существует четкое правило: сломал – чини. Если изменения, внесенные кем-то, сделали код неработоспособным – именно автор изменений ответственнен за приведение кода в рабочее состояние. Причем не когда-нибудь потом, а ПРЯМО СЕЙЧАС! Разработчик не имеет права заниматься чем-либо другим до того, как исправит внесенные им ошибки. Потому, когда говорят, что если у кода нет автора, то это анархия – не верьте. Автор кода – вся команда. И всегда есть тот, кто за код отвечает. Это тот, кто менял его последним. Больше по этому поводу сказать нечего. Следующая практика – Постоянные (непрерывные) интеграции кода Зачем это надо. Чтобы быть уверенным, что продукт не сломан последними изменениями. Это дает возможность быстро отреагировать на возможные проблемы. Кроме того, "интеграция" вовсе не означает "компиляция". Это еще и всевозможные проверки целостности кода, включая запуск тестов. Собственный опыт В текущем проекте у нас сборки происходят раз в полчаса, если за это время были изменения в коде, лежащем в репозитории. Сделано это на основе CruiseControl. Кроме unit-тестов (см. JUnit) у нас запускается проверка кода с помощью FindBugs, которая находит весьма нетривиальные ошибки, и проверка с помощью JCSC – на соответствие нашим стандартам кодирования. Все это вместе минимизирует возможность того, что в продукт попадет неработающий или даже просто не соответствующий стандартам код. Таким образом, при постоянной интеграции кода есть уверенность в том, что в любое время можно взять код – и он будет работать. Или же есть информация о том, что код сломан. Причем поступает она в самом худшем случае через час после того, как это случилось. Следующая практика – Заказчик в команде Идея проста. Чем длиннее цепочка, тем больше она напоминает испорченный телефон. Каким бы тщательным ни было планирование – некоторые вопросы все р

добавить отзыв

0.0013411045074463