Екстремальне програмування, Комерція, Різне, статті

Теорія

Екстремальне програмування – методологія швидкої розробки програмного забезпечення. Складається з набору методик і принципів, що дозволяють як окремо, так і в комплексі, оптимізувати процес розробки. Цей підхід також регламентує права розробників і замовників.

Права і ролі

В екстремальному програмуванні чітко описані всі ролі. Кожна роль передбачає характерний набір прав і обов’язків. Тут існують дві ключові ролі: замовник і розробник.


Замовник

Людина або група людей, зацікавлених у створенні конкретного програмного продукту. Він має следуещие права та обов’язки:


Для успішного використання своїх прав замовник повинен покладатися на дані, надані розробниками.


Розробник

Один або група від двох до десяти чоловік, які займаються безпосередньо програмуванням і супутніми інженерними питаннями. Розробник наділений такими правами і обов’язками:



Ролі всередині ролі

Кожна з базових ролей екстремального програмування може бути уточнена більш дрібними ролями. В XP дозволено суміщення ролей в рамках однієї людини.


Сторона замовника

Упорядник історій – Спеціаліст предметної області, що володіє здібностями доступно викласти і описати вимоги до розроблюваної системі. Ця людина або група людей відповідальні за написання історій користувача і прояснення непорозуміння з боку програмістів.

Приймальник – Людина, що контролює правильність функціонування системи. Добре володіє предметною областю. В обов’язки входить написання приймальних тестів.

Великий бос – Стежить за роботою всіх ланок, від розробників до кінцевих користувачів. Він контролює впровадження системи та супутні організаційні моменти. Може бути також інвестором проекту.


Сторона розробника

Програміст – Людина, що займається кодуванням і проектуванням на низькому рівні. Він досить компетентний для вирішення поточних задач розробки та надання правдивих оцінок запланованим завданням.

Інструктор – Досвідчений розробник, що добре володіє всім процесом розробки та його методиками. Несе відповідальність за навчання команди аспектам процесу розробки. Впроваджує і контролює правильність виконання методик використовуваного процесу. Звертає увагу команди на важливі, але з якихось причин упущені моменти розробки. Разом з тим інструктор, як і будь-яка інша людина, не всезнаючий і з увагою відноситься до ідей інших членів команди.

Спостерігач – Член команди розробників, що користується довірою всієї групи, який стежить за прогресом розробки. Він порівнює попередні оцінки трудозатрат і реально витрачені, виводячи кількісні показники роботи команди. Це такі як середня швидкість і процентне співвідношення виконаних і запланованих завдань. Дана інформація надається замовнику для своєчасного контролю над ситуацією. Частина цієї інформації ненав’язливо надається і розробникам, для знання стану проекту, місць виникнення труднощів і що ще можна встигнути зробити.

Дипломат – Комунікабельна особистість, яка ініціює спілкування між членами команди. Так як документообіг мінімізований, важливо постійне спілкування і передача досвіду всередині команди, краще розуміння вимог до системи. Дипломат регулює і спрощує спілкування між замовниками та розробниками. Є важливою ланкою на зборах. Він перешкоджає недомовкам, розпалу пристрастей і непотрібним сварок. Дипломат не може нав’язувати своєї думки обговорюються.


Зовнішні ролі

Консультант – Фахівець, що володіє конкретними технічними навичками, для допомоги розробникам у важко вирішуваних завданнях. Зазвичай залучається зі сторони.


Правила Екстремального Програмування


Угода про кодування

Ви в команді, яка працює над даним проектом тривалий час. Люди приходять і йдуть. Ніхто не кодує поодинці і код належить всім. Завжди будуть моменти, коли необхідно буде зрозуміти і скоригувати чужий код. Розробники будуть видаляти або змінювати дублюючий код, аналізувати і покращувати чужі класи і т.п. З часом можна буде сказати хто автор конкретного класу.

Отже, всі повинні підкорятися загальним стандартам кодування – форматування коду, іменування класів, змінних, констант, стиль коментарів. Таким чином, ми будемо впевнені, що вносячи зміни в чужий код (що необхідно для агресивного і екстремального просування вперед) ми не перетворимо його в Вавілонське Стовпотворіння.

Вищесказане означає, що всі члени команди повинні домовитися про загальні стандарти кодування. Неважливо яких. Правило полягає в тому, що все їм підпорядковуються. Ті, хто не бажає їх дотримуватися залишає команду.

Колективне володіння кодом

Колективне володіння кодом стимулює розробників подавати ідеї для всіх частин проекту, а не тільки для своїх модулів. Будь розробник може змінювати будь-який код для розширення функціональності, виправлення помилок або рефакторинга.

З першого погляду це виглядає як хаос. Однак беручи до уваги що як мінімум будь код створений парою розробників, Що Unit тести дозволяють перевірити коректність внесених змін і що в реальному житті все одно так чи інакше доводиться розбиратися в чужому коді, стає ясно що колективне володіння кодом значно спрощує внесення змін та знижує ризик пов’язаний з високою спеціалізацією того чи іншого члена команди.

CRC Сесія

Використовуйте Class, Responsibilities, Collaboration (CRC – Клас, Обов’язки, Взаємодія) картки для дизайну системи командою. Використання карток дозволяє легше привчитися мислити об’єктами а не функціями і процедурами. Також картки дозволяють більшій кількості людей брати участь в процесі дизайну (в ідеалі – всій команді), а чим більше людей робить дизайн, тим більше цікавих ідей буде привнесено.

Кожна CRC картка являє собою екземпляр об’єкта. Клас об’єкта може бути написаний зверху, обов’язки ліворуч, взаємодії справа. Ми говоримо “можуть бути написані”, оскільки коли CRC сесія в розпалі, учасникам зазвичай потрібно невелике число карток з іменами класів і не обов’язково вони повинні бути повністю заповнені.

CRC сесія відбувається так: кожен з учасників відтворює систему кажучи які повідомлення він шле яким обьектам. Проходить по всьому процесу повідомлення за повідомленням. Слабкі місця і проблеми відразу виявляються. Альтернативи дизайну також добре видно при симуляції процесу.

Для наведення порядку часто використовується обмеження числа одночасно взаємодіючих двома.

Замовник

Одна з вимог XP – замовник завжди доступний. Він повинен не просто допомагати команді розробників, а бути її членом. Всі фази XP проекту вимагають комунікації з замовником, найкраще лицем до лиця – на місці. Краще за все, просто призначити одного або декількох замовників в команду розробників. Остерігайтеся, замовник буде потрібно на тривалий час, і контора замовника може постаратися віддати вам якогось стажера в якості експерта. Вам потрібен експерт.

User Stories пишуться замовником за допомогою розробників. Замовник допомагає впевнитися що більшість бажаних функцій системи покрито User Story.

Під час планування релізу замовникові необхідно обговорити вибір User Stories які будуть включені в планований реліз. Також, можливо, буде потрібно узгоджувати період самого релізу. Замовник приймає рішення стосуються цілей бізнесу.

Вибирайте найпростіше рішення

Простий дизайн завжди легше реалізувати, ніж складний. Тому завжди робіть найпростіше рішення, яке може працювати. Якщо знаходите щось складне – замініть це чимось простим. Завжди виявляється швидше і дешевше замінити складний код простим до того як почнеш розбиратися в складному коді.

Рефакторіте чужий код якщо він здається вам складним. Якщо щось виглядає складним – це вірна ознака проблеми в коді.

Зберігайте рішення наскільки можливо простими якомога довше. Ніколи не додавайте функціональність на майбутнє – до того як з’являється в ній необхідність. Однак майте на увазі: зберігати дизайн простим – Важка робота.

Функціональні тести

Приймальні тести (раніше їх також називали Функціональні) пишуться на основі User Story. Вони розглядають систему як чорний ящик. Замовник відповідальний за перевірку коректності функціональних тестів. Ці тести використовуються для перевірки працездатності системи перед випуском її у виробництво. Функціональні тести автоматизуються так, щоб була можливість їх часто запускати. Результат повідомляється команді і команда відповідає за планування виправлень функціональних тестів.

Часта інтеграція

Розробники, по-можливості, повинні інтегрувати і випускати свій код кожні кілька годин. У будь-якому випадку ніколи не можна тримати зміни довше одного дня. Часта інтеграція дозволяє уникнути відчуження і фрагментирования в розробці, коли розробники не можуть спілкуватися в сенсі обміну ідеями або повторного використання коду. Кожен має працювати з самою останньою версією.

Кожна пара розробників повинна віддавати свій код як тільки для цього з’являється розумна можливість. Це може бути коли все UnitTest-и проходять на 100%. Віддаючи зміни кілька разів на день, Ви зводите проблеми інтеграції практично до нуля. Інтеграція – це діяльність виду “заплати зараз або заплати більше пізніше”. Тому інтегруючи зміни щодня маленькими порціями ви не опинитеся перед необхідністю витрачати тиждень щоб зв’язати систему в одне ціле безпосередньо перед здачею проекту. Завжди працюйте над останньою версією системи.

Для менеджера. Якщо розробник не віддає змін довше одного дня – це ясний індикатор серйозної проблеми. Ви повинні негайно розібратися в чому справа. Весь досвід XP команд каже що завжди причиною затримки є поганою дизайн і його завжди потім доводиться переробляти.

Планування Ітерації

Iteration Planning Meeting скликається перед початком кожної ітерації для планування завдань які будуть зроблені в цій ітерації. Для ітерації вибираються User Stories, які вибрав замовник в плані релізу починаючи з самих важливих для замовника і найгірших (пов’язаних з ризиком) для розробників. Також в ітерацію включаються непрацюючі Функціональні тести.

User Stories і невиконані Функціональні тести розбиваються на завдання. Завдання записуються на картках. Ці картки і є детальний план на ітерацію. Кожне завдання має бути тривалістю від 1 до 3 ідеальних днів.

Розробники розбирають завдання і оцінюють тривалість часу, необхідного для їх виконання. Таким чином, кожен розробник оцінює скільки часу задача займе саме у нього. Це важливо, щоб кінцеву оцінку обсягу робіт робив сам розробник.

Швидкість проекту визначає поміщаються ваші завдання в ітерацію чи ні. Загальна тривалість завдань запланованих на ітерацію не повинна перевищувати швидкості, досягнутої в попередній ітерації. Якщо ви набрали занадто багато, то замовник повинен вирішити які User Stories, відкласти на наступну ітерацію. Якщо набрали занадто мало, то треба додати наступну User Story. В деяких випадках можна попросити замовника розділити одну з User Story, на дві, щоб включити частину в поточну ітерацію.

Відкладання User Story на наступну ітерацію може виглядати страшно, але не дозволяйте собі жертвувати рефакторингом і Unit Test-ами щоб зробити більше. Заборгованість за цими категоріями швидко сповільнить вашу швидкість. Не робіть того, що по-вашому знадобиться в наступних ітераціях – робіть тільки те що необхідно для виконання поточних User Stories.

Слідкуйте за швидкістю проекту і відкладеними User Stories. Цілком можливо, що план релізу доведеться переробляти кожні три-п’ять ітерацій. Це нормально. Адже план релізу – це погляд у майбутнє і природно очікувати що ваші передбачення доведеться коригувати.

Ітерації

Ітеративна розробка збільшує гнучкість процесу. Розділіть ваш план на ітерації тривалістю від 2 до 3 тижнів. Зберігайте постійну тривалість ітерації на час проекту. Нехай ітерації будуть пульсом вашого проекту. Це той ритм який дозволить зробити вимір прогресу і планування простим і надійним.

Не плануйте завдань заздалегідь. Замість цього збирайте Планування Ітерації на початку кожної ітерації щоб запланувати що буде зроблено. Також порушенням правил вважається забігати вперед і робити те, що не заплановано у цій ітерації. Таким чином, стає можливим тримати під контролем змінюються вимоги Замовника.

Приймайте всьерьез терміни завершення ітерації. Вимірюйте прогрес в процесі роботи. Якщо видно, що ви не зможете зробити всі заплановані завдання до терміну, то знову збирайте Планування Ітерації і оцініть завдання заново і відкладіть частину завдань.

Сконцентруйте зусилля на завершенні найважливіших завдань, обраних Замовником, замість того щоб мати кілька незакінчених завдань, обраних розробником.

Міняйтеся завданнями

Необхідно періодично змінювати завдання у розробників для зменшення ризику концентрації знань і вузьких місць в коді. Якщо тільки одна людина у вашій команді може працювати в цій галузі і ця людина йде або вам просто треба багато всього зробити в даному сегменті програми, ви виявите що ваш проект ледве-ледве просувається вперед.

Cross Training зазвичай є важливим аспектом в компаніях які намагаються уникнути концентрації знань в одній людині. Переміщення людей за кодом в комбінації з парним програмуванням непомітно робить Cross Training для вас. Замість однієї людини, яка знає все про даний шматку коду, кожен в вашій команді знає багато про код в кожному модулі.

Команда стає набагато більш гнучкою якщо всі знають достатньо про кожну частини системи щоб почати працювати над нею. Замість того щоб чекати поки “гуру” закінчить роботу над критичним шматком коду, кілька програмістів можуть працювати над ним одночасно.

При початку нової ітерації кожен розробник повинен перейти на нову задачу. Парне програмування допомагає подолати проблему адаптації (це означає що новий розробник може почати працювати в парі з досвідченим в даній області розробником).

Така практика також стимулює появу нових ідей і поліпшення коду.

Залишайте оптимізацію на потім

Ніколи не оптимізуйте нічого до закінчення кодування. Ніколи не намагайтеся вгадати де будуть вузькі місця по продуктивності. Вимірюйте!

Зробіть щоб це працювало, потім щоб працювало правильно, потім щоб працювало швидко.

Парне програмування

Весь код для виробничої системи (а це значить за винятком пробних рішень) пишеться парами. Два розробника сидять поруч. Один набирає, інший дивиться. Час від часу вони змінюються. Не дозволяється працювати в поодинці. Якщо з якоїсь причини другий з пари пропустив щось (хворів, відходив і т.п.) він зобов’язаний переглянути всі зміни зроблені першим.

Звучить незвично, але XP стверджує що після невеликого періоду адаптації більшість людей прекрасно працюють в парах. Їм навіть подобається, оскільки робота робиться помітно швидше. Діє принцип “Одна голова добре, а дві краще “. Пари зазвичай знаходять більш оптимальні рішення. Крім того істотно збільшується якість коду, знижується число помилок і прискорюється обмін знаннями між розробниками.

Безжально Рефакторіть!

Ми, програмісти, схильні триматися за дизайн довго після того як він стає незграбним. Ми продовжуємо повторно використовувати незручний в супроводі код оскільки він все ще якось працює і ми боїмося зіпсувати його. Але чи дійсно це вигідно? XP приймає точку зору що це невигідно. Коли ми прибираємо надмірність, покращуємо застарілий дизайн прибираємо невикористовувані шматки – ми робимо рефакторинг. Рефакторинг в кінцевому підсумку заощаджує час і покращує якість продукту.

Безжально переглядайте будь-який код для того, щоб зберігати дизайн простим у міру розробки. Зберігайте код ясним і зрозумілим щоб його було легко зрозуміти, модифікувати і розширювати. Переконайтеся що все написано один і тільки один раз. В кінцевому підсумку, це займає менше часу ніж доводити до розуму заплутану систему.

План Релізу

План Релізу розробляється на зборах з планування Релізу. Реліз Плани описують погляд на весь проект і використовуються в подальшому для планування ітерацій.

Важливо, щоб технічні люди робили технічні рішення і люди бізнесу – бізнес рішення. Планування Релізу визначає набір правил, які дозволяють всім приймати свої рішення. Ці правила визначають метод вироблення задовольняє всіх плану робіт.

Сутність зборів з планування релізу для команди розробників в тому, щоб оцінити кожну User Story в ідеальних тижнях. Ідеальна тиждень – це скільки по-вашому забере час виконання завдання якщо ніщо більше вас не буде відволікати. Ні залежностей, ні додаткових завдань, але включаючи тести. Замовник потім вирішує які завдання найбільш важливі або мають вищий пріоритет.

User Stories записуються на картках. Розробники та Замовник разом тасують картки на столі поки не вийде набір User Stories які разом будуть складати перший (або наступний) Реліз. Усім хочеться випустити якомога раніше корисну систему яку можна протестувати.

Реліз можна планувати за часом або за об’ємом. Для того щоб визначити скільки User Stories можуть бути реалізовані до конкретної дати або скільки реального часу займе даний набір завдань використовують швидкість проекту. Якщо плануєте за часом, помножте кількість ітерацій на швидкість проекту для того щоб дізнатися скільки User Story може бути реалізовано. При плануванні за об’ємом, розділіть загальне кількість ідеальних тижнів необхідних для всіх User Stories на швидкість проекту і ви отримаєте кількість ітерацій необхідних для закінчення релізу.

Якщо менеджмент не влаштовують терміни завершення, може з’явитися спокуса зменшити оцінки обсягу робіт. Ви ніколи не повинні цього робити. Занижені оцінки обов’язково створять безліч проблем пізніше. Замість цього ведіть переговори з менеджерами, розробниками і замовниками поки не виробите прийнятний для всіх план релізу.

Часті Релізи

Розробники повинні випускати версії системи користувачам (або бета-тестерам) якомога частіше.

Планування Релізу використовується для пошуку невеликих функціональних фрагментів мають значимий бізнес-сенс і які можуть бути випущені в реальне оточення на ранніх стадіях розробки. Це критично для своєчасного отримання корисних відгуків, щоб мати можливість впливати на процес розробки. Чим більше ви затримуєте випуск важливої ​​частини системи тим менше у вас буде часу виправити її.

Пробне рішення

Створюйте пробні рішення для відповіді на складні технічні питання, для обгрунтування тих чи інших технологічних рішень. При прийнятті будь-якого технологічного рішення існує ризик і пробні рішення покликані зменшити його.

Зробіть програму яка відтворює досліджувану проблему і ігнорує все інше. Більшість пробних рішень не призначені для подальшого використання так що чекайте що вони будуть викинуті. Мета їх створення – зменшити ризик прийняття неправильного технічного рішення або більш точна оцінка часу на реалізацію User Story.

Збори стоячи

Щоранку проводяться збори для обговорення проблем, їх рішень і для посилення концентрації команди. Збори проводиться стоячи для уникнення тривалих дискусій не цікавих всім членам команди.

У типовому зборах більшість учасників нічого не вносять, просто беруть участь щоб послухати що скажуть інші. Велика кількість часу людей витрачається щоб отримати невелику кількість комунікації. Тому участь усіх людей у ​​зборах веде ресурси з проекту і створює хаос в плануванні.

Для такого роду комунікацій і потрібно збори стоячи. Набагато краще мати одне коротке обов’язкове збори, ніж безліч довгих на яких більшість розробників має все одно присутній.

Якщо у вас проводяться щоденні збори стоячи, то всі інші збори повинні відвідувати тільки ті люди, які необхідні і будуть щось привносити. Більше того, є можливість навіть уникнути деяких зборів. З обмеженням учасників, більшість зборів може бути проведено спонтанно перед монітором, де обмін ідеями набагато більш інтенсивний.

Щоденне ранкове зібрання це не ще одна трата часу. Воно дозволить вам уникнути багатьох інших зборів і заощадить більше часу, ніж на нього витрачено.

Метафора Системи

Завжди вибирайте System Metaphor – просту і зрозумілу концепцію щоб члени команди називали всі речі однаковими іменами. Для розуміння системи і виключення дублюючого коду надзвичайно важливо як ви називаєте об’єкти. Якщо ви можете припустити як називається небудь об’єкт в системі (якщо ви знаєте що він робить) і він правда так називається – ви збережете купу часу і сил. Створіть систему імен для своїх обьектов так, щоб кожен член команди міг користуватися нею без спеціальних знань про систему.

Unit Test-и

Unit тести грають ключову роль в XP. Вони дозволяють швидко змінювати код не боячись наробити нових помилок. Unit тест пишеться для кожного класу, тест повинен перевіряти всі аспекти роботи класу – тестувати все що може не працювати.

Хитрістю тут є те, що тест для класу повинен бути написаний раніше самого класу. Це значить, що як тільки ви випустите перший працюючий результат, він буде підтримуватися системою тестування. Для проведення тестів пишеться спеціальна система тестування зі своїм інтерфейсом.

Unit тест для класу зберігається в загальному репозиторії разом з кодом класу. Ніякої код не може бути випущений без Unit тесту. Перед віддачею коду розробник повинен упевнитися що всі тести проходять без помилок. Ніхто не може віддати код, якщо все не пройшли 100%. Іншими словами оскільки до ваших змін всі тести проходили, то якщо ви маєте помилки, то це результат ваших змін. Вам і виправляти. Іноді буває неправильним або неповним код тесту. В такому випадку треба виправляти його.

Величезним спокусою є заощадити на Unit тестах коли мало часу. Але цим Ви тільки обманюєте себе. Чим складніше написати тест, тим більше часу він потім заощадить. Це доведено практикою.

Unit тести дозволяють здійснити колективне володіння кодом. Вони дозволяють відносно легко переглядати поганий код. Також Unit тести дозволяють в будь-який момент мати стабільно працюючу систему.

User Story

User Story (щось типу розповіді користувача) – це опис того як система повинна працювати. Кожна User Story написана на картці і представляє якийсь шматок функціональності системи, що має логічний сенс з точки зору Замовника. Форма – один-два абзаци тексту зрозумілого користувачеві (не сильно технічного).

User Story пишеться Замовником. Вони схожі на сценарії використання системи, але не обмежуються користувача інтерфейсом. По кожній історії пишуться функціональні тести, які підтверджують що дана історія коректно реалізована – їх ще називають приймальними (Acceptance tests).

Кожній User Story дається пріоритет з боку бізнесу (користувач, замовник, відділ маркетингу) і оцінка часу виконання з боку розробників. Кожна історія розбивається на завдання і їй призначається час коли її почнуть реалізовувати.

User Stories використовуються в XP замість традиційних вимог. Головна відмінність User Story від вимог (requirements) – рівень деталізації. User Story містить мінімум інформації, необхідної для обгрунтованої оцінки того, скільки часу треба на її реалізацію.

Типова User Story займає 1-3 тижні ідеального часу. Історія вимагає менше 1 тижня занадто деталізована. Історія вимагає більше 3 тижнів може бути розбита на частини – окремі історії.

Швидкість проекту

Швидкість Проекту (або просто швидкість) це міра того, як швидко виконується робота у вашому проекті.

Щоб виміряти швидкість проекту, ви просто повинні порахувати об’єм User Stories, або як багато (за часом) завдань було виконано за ітерацію. Просто порахуйте сумарний час оцінки обсягу роботи (ідеальне час).

Під час планування релізу швидкість проекту використовується для оцінки того скільки User Stories може бути зроблено.

Під час планування ітерації, швидкість проекту у попередній ітерації використовується для визначення того скільки User Stories треба планувати в поточну ітерацію.

Цей простий механізм дозволяє розробникам відновитися після важкої ітерації. Якщо у вас після відновлення залишається вільний час – йдете до замовника і просите ще User Story. У результаті швидкість знову зросте.

Не треба використовувати цей параметр як абсолютний. Він не підходить для порівняння продуктивності двох проектів, оскільки кожна команда має свої особливості. Цей параметр важливий тільки для команди щоб тримати її на “рівному кілі”.

Ви повинні чекати невеликі зміни швидкості проекту під час роботи. Але якщо швидкість змінюється сильно, необхідно провести перепланування релізу. Як тільки нова система йде до користувачів, чекайте зміни швидкості проекту, так як у вас з’являться завдання з підтримки.

Коли виявлена ​​помилка

Якщо виявляється помилка, то створюється тест, щоб запобігти її повторне появу. Помилка, що відбулася в робочій системі (вже встановленої), вимагає написання функціонального тесту. Створення функціонального тесту безпосередньо перед діагностикою помилки дозволяє замовникам чітко описати проблему і довести цю проблему до розробників.

Нездійсненний функціональний тест вимагає створення Unit Test. Це допомагає сфокусувати зусилля з налагодження і чітко показує коли помилка виправлена.

Вам це не знадобиться

Утримайтеся від заповнення системи речами, які знадобляться вам в майбутньому. Тільки 10% від очікуваного дійсно знадобиться вам в первісному вигляді, тобто 90% вашого часу буде витрачено даремно.

Завжди є спокуса додати функціональність зараз а не потім, тому що ми бачимо як зараз додати її і відчуваємо що система буде набагато краще. Але ми завжди повинні нагадувати собі що це нам ніколи не знадобиться. Додаткова функціональність тільки сповільнює прогрес і з’їдає ресурси. Забудьте про майбутні вимоги і додаткову гнучкість. Сконцентруйтеся на тому, що необхідно зробити зараз.

Використано матеріали сайту xprogramming.ru/.


Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*