Это один раз из десяти переписать?

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

Текущая ситуация:

  • Я взял на себя обслуживание приложения VB6/SQL.
  • Общее количество строк кода составляет 75-100 тысяч (код программной части, модули и классы).
  • Первоначальный разработчик ушел, так что остался только я, и нет возможности расширить команду, по крайней мере, на несколько лет.
  • В программе не было никакой архитектуры (только прямые вызовы SQL в виде простого текста в виде кода программной части).
  • Не пытается следовать принципам DRY или OAOO.
  • В базе данных было несколько первичных ключей, но не было внешних ключей.
  • До того, как эта система была внедрена, все управлялось в больших электронных таблицах, поэтому эта система действительно является огромным улучшением по сравнению с тем, что у них было, но она не делает то, что они предполагают.
  • Мне удалось написать несколько инструментов для замены всех буквальных экземпляров имен таблиц и имен столбцов константами и поисковыми запросами, а также я написал скрипт для быстрого создания кода для создания этих констант и поисковых запросов из базы данных, так что теперь я могу безопасно вносить изменения в базу данных и везде видеть, что сломалось. Я начал нормализовать базу данных «по краям», но это около 3% пути.
  • Модульных тестов нет, поэтому каждый раз, когда я меняю базу данных, мне в основном приходится переписывать любую логику, лежащую поверх нее, и я использую две версии, чтобы сравнить функциональность и убедиться, что они одинаковы. Все идет нормально.
  • Я начал с того, что просто попытался исправить критические ошибки, чтобы остановить кровотечение, и я могу с уверенностью сказать, что в основном это сделано, поэтому теперь я на мгновение отступлю, чтобы взглянуть на общую картину.
  • Руководство благосклонно и разумно в своих ожиданиях.
  • Долгосрочная цель - все равно преобразовать его в .NET...

Итак, я взвешиваю следующие варианты:

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

Я думаю, что если я выберу вариант 1, то в конце концов у меня будет только приложение VB6, которое они все еще хотят обновить до .NET, и я изучил это, и это дорого и требует много времени, и даже с инструментами, которые вы все равно получится что-то вроде Франкенштейна. Если я выберу вариант 2, я думаю, что смогу закончить быстрее и перейду сразу к целевой технологии.

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

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

Итак, можно ли считать это одним из случаев «один из десяти» или нет?


person RewriteOrRefactor    schedule 24.08.2010    source источник
comment
По моему опыту, 1 из 10 безнадежно оптимистичен. Скорее, 1 из 3 должен быть, но 1 из 100.   -  person annakata    schedule 24.08.2010
comment
@annakata Ваш опыт успешных переписываний или опыт поддержки приложений, которые не были переписаны? По моему опыту, попытки переписать не редкость, когда вообще ничего полезного не получается.   -  person MarkJ    schedule 24.08.2010
comment
@MarkJ: И то, и другое, к сожалению, и я также видел проблему сбоя перезаписи, о которой вы тоже упоминаете. По сути, вы не должны пытаться переписать, если вы не достаточно хороши, чтобы понять, почему вам это действительно нужно, И у вас есть поддержка руководства.   -  person annakata    schedule 24.08.2010
comment
Есть разница между переносом кода на новый язык и полным переписыванием. Вы можете использовать методологию «сначала тестирование», чтобы разумно продвигать код вперед, сохраняя при этом всю накопленную мудрость существующей кодовой базы.   -  person Alex Feinman    schedule 24.08.2010


Ответы (11)


У меня был проект, изначально написанный на VB6, и меня наняли, чтобы преобразовать его в .NET. Недавно я ушел с этой работы. Я вполне убежден, что программу, вероятно, не стоило переписывать.

Вот некоторые факторы, которые следует учитывать, если вы выберете метод перезаписи (на основе моего проекта)

  • Прямой перезаписи не будет. Как только станет известно, что он будет переписан, появятся новые запросы функций, и будет изрядное количество редизайна / реархитектуры.
  • Люди не примут режим «только обслуживание» без большого сопротивления. Какое-то время каждая ошибка будет критически важной.
  • Перенос приложения VB6 в .Net НЕ следует рассматривать как более легкий, чем перенос приложения C++ в .Net или проекта Haskell в .Net. Есть некоторая общность, но в итоге кодовая база отличается на 99 % (возможно, 1 % для существующих уравнений).
  • Предполагая, что эта программа находится в производстве (даже внутри компании), ваша новая программа, скорее всего, не будет соответствовать требованиям, по крайней мере, на начальном этапе. Вы услышите "Но по-старому..." или "Раньше..."
  • Assuming your customers are not other IT people, they WILL NOT understand:
    • What is taking so long
    • Почему это не похоже на программу (по внешнему виду) старой
  • Хотя текущее приложение разрабатывалось с течением времени, скорее всего, ожидается, что ваше приложение будет иметь 100% функциональности при вводе в эксплуатацию и за меньшее время.

Все это опыт реальной миграции с VB6 на .Net. Я был единственным разработчиком .Net. Не было ресурсов, чтобы нанять дополнительную помощь. Основные различия между моей ситуацией и вашей: 1. первоначальный разработчик все еще был там - просто в новой роли (иногда это усложняло задачу) и 2. оригинальное приложение не нуждалось в большом количестве исправлений ошибок.

Я думаю, что если бы мне пришлось делать это снова, я бы попытался создать несколько .NET dll и включить их в приложение VB6. По частям переходим на .net. Так что, возможно, вы переместите данные и бизнес-логику для расчетов с клиентами в .NET. Все остальные аспекты остаются прежними. Графический интерфейс, другие функции и т. Д. Затем, после того, как это будет развернуто и помечено как завершенное, перейдите в раздел «Доставка» и сделайте то же самое. Последним шагом является создание нового графического интерфейса .NET, использующего ваши библиотеки DLL.

Это дает вам пару преимуществ

  • В итоге приложение написано на .NET
  • Позволяет медленно внедрять изменения. Вы не будете отлаживать отгрузку и дебиторскую задолженность, HR и т. Д. Все в одно и то же время недели «ввода в эксплуатацию»
  • Позволяет использовать более современные инструменты, не нарушая работу всей программы. Хотите использовать NHibernate, PLINQ или MEF? Делайте это по одному модулю за раз. Изучите инструмент и делайте маленькие шаги
  • Обеспечивает гибкость графического интерфейса. В конце концов, вы можете сделать WinForms, WPF или веб-проект, используя ваши основные библиотеки DLL.
  • Не бросает тонну изменений пользователю сразу. Вы переписали эту часть дебиторской задолженности, и пользователь понятия не имеет, потому что графический интерфейс тот же. Затем, когда вы развертываете графический интерфейс, вы ЗНАЕТЕ, что ваш сервер работает.
  • Упростит будущий рефакторинг. Вы уже разбили свой проект на небольшие куски. Вы можете продолжить работу над ними, зная, на что они влияют и т. д.

Я был бы ОЧЕНЬ утомлен, решая, как один разработчик, переписать это приложение и предоставить им работающий продукт. Я думаю, что по консервативной оценке (при условии отсутствия расширения масштабов и т. д.) это будет 24 месяца. Скорее всего 3-4 года.

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

person taylonr    schedule 24.08.2010
comment
+1, хорошо, это длинно, но хорошо сказано, и вы уловили то, что я видел в других проектах VB6-›.NET. Несколько отличных моментов. - person FrustratedWithFormsDesigner; 24.08.2010
comment
Просто чтобы внести ясность, я не выступаю за 100% переписывание за один раз. Я бы взял один модуль за раз, как вы предлагаете, вырезал его из приложения VB6, перенес данные в новую нормализованную структуру базы данных и написал новый многоуровневый модуль в .NET, который просто выполняет эту часть. Они запустят новый модуль из старого приложения VB6 в том же месте, куда они перешли бы для использования существующей функциональности. Кроме того, я обнаружил, что наилучшие результаты заключаются в том, чтобы убедиться, что я затрагиваю множество болевых точек пользователей одновременно с небольшим переписыванием, чтобы они видели, что они тоже что-то получают. - person RewriteOrRefactor; 24.08.2010
comment
Честно говоря, вы узнаете ТОННУ о разработке программного обеспечения в этом проекте. Большинство не будет иметь ничего общего с кодом :) Как сказал кто-то еще, убедитесь, что вы закрепили БД перед запуском кода и т. д. Минимизируйте свои переменные (БД, графический интерфейс, формат экспортных данных, кодовая база и т. д.) - person taylonr; 24.08.2010
comment
+1. Официальный рекомендация Microsoft UK заключается в том, что они рекомендуют полностью переписать с нуля кода VB6 в VB.Net для небольшого количества ситуаций. Есть лучшие варианты, такие как автоматическая миграция с помощью коммерческих инструментов или частичная замена модуля за модулем. - person MarkJ; 24.08.2010

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

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

Я просто всегда чувствую, что если у вас есть база данных и вы можете положиться на нее, вы должны быть в состоянии переписать с помощью интеграционных тестов, а затем модульных тестов намного надежнее.

После того, как у вас будет твердая база данных, я думаю, что лучшим сценарием было бы попытаться разбить код на отдельные и многократно используемые сборки (которые вы должны иметь возможность использовать в .NET), а затем постепенно преобразовать их в .NET из VB. Это может быть невозможно, если код ужасно пахнет спагетти!

person ArtificialGold    schedule 24.08.2010
comment
Процесс переноса кода из отделенного кода в модули сам по себе будет масштабным. Не в последнюю очередь потому, что во многих случаях он загружает коллекции данных из SQL в MSFlexGrid, а затем манипулирует данными в MSFlexGrid на основе номеров столбцов, а не каких-то констант, поэтому выясняя значение If Trim(MyGrid.Matrix(MyGrid. row, 15)) = 1 Тогда... это действительно сложно, и выполнение любых автоматических исправлений также сложно, тем более, что на Grid, скорее всего, ссылаются непосредственно из других форм и модулей. Да, и использование конструкции With...End With делает ее более увлекательной. :) - person RewriteOrRefactor; 24.08.2010
comment
Возможно, лучше сначала поработать над самыми простыми и легкими вещами. Сразу вводите константы. Также перенесите любой встроенный sql в базу данных в хранимых процедурах (или используйте шаблон репозитория для ускорения разработки). Также не бойтесь писать множество методов, которые можно протестировать и назвать, чтобы помочь вашему здравомыслию. Похоже, вам нужно прочитать: amazon.co.uk/Working-Effectively-Legacy-Robert-Martin/dp/ Может потребоваться полная переработка, но это отличная дорожная карта для рефакторинга, если вы можете сделать это... - person ArtificialGold; 24.08.2010

Начните преобразовывать различные модули по одному, выводя их из приложения VB6.

Расставьте приоритеты в соответствии с тем, что является критически важным/стратегическим, чтобы вы также могли добавлять ценность по мере продвижения.

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

В краткосрочной перспективе у вас будет больше работы (и код VB6, и .NET, которые нужно поддерживать), но с более чистой архитектурой вы сможете начать отходить от устаревшего приложения все быстрее и быстрее.

Таким образом, обе системы некоторое время будут работать одновременно, так что у вас будет запасной вариант, и вы сможете добавить правильную структуру (архитектуру, целостность базы данных и т. д.).

person Oded    schedule 24.08.2010
comment
.NET имеет богатую поддержку COM-взаимодействия, поэтому нет никаких причин, по которым переписанные модули VB6 нельзя было бы напрямую заменить .NET, поэтому вы не поддерживаете оба параллельно. В какой-то момент вы заменяете оболочку приложения, и компоненты .NET в VB6 заменяются компонентами VB6 в приложении .NET. - person Richard; 24.08.2010
comment
@ Ричард - это было бы похоже на построение карточного домика, судя по тому, что описывает ОП. - person Oded; 24.08.2010
comment
@Oded: в какой-то степени верно, за исключением того, что текущий карточный домик работает. Лучше меняться постепенно, добавляя модульные тесты, ... во что-то архитектурно лучшее, чем начинать с нуля, когда у вас не будет ничего работать (функционально) целую вечность. - person Richard; 24.08.2010
comment
@Richard: Просто неправда. а) это работает лишь незначительно, и б) я могу переписать небольшие фрагменты и развернуть их за 2-4 недели, включая новые функции. - person RewriteOrRefactor; 24.08.2010
comment
@RewriteOrRefactor В таком случае зачем задавать вопрос? (Кроме того, большое значение имеет тот факт, что это несколько независимых частей, которые могут быть переписаны независимо друг от друга, я предполагал одно монолитное приложение.) - person Richard; 24.08.2010
comment
@Richard: Практически любое приложение можно разобрать и переписать по частям с использованием другой технологии, если оно работает на той же платформе. Я думал, что это данность. Вопрос в том, нужно ли сначала провести рефакторинг (переместить код из формы в BLL, затем написать модульные тесты, затем провести еще один рефакторинг, затем нормализовать БД, затем исправить и провести рефакторинг и т. д.). Переписать означает выбросить существующий код VB6 (кроме использования его в качестве функционального справочника). Оба варианта выполняются поштучно. - person RewriteOrRefactor; 25.08.2010

Это было здорово написать. Однако, ИМХО, в нем отсутствует важная часть. Какова ценность рерайта с точки зрения заказчика и каковы затраты и риски. Я предполагаю здесь, но это может быть следующее

Клиенты могут получить следующее

  1. более быстрое устранение дефектов/улучшений.
  2. Меньшая вероятность появления новых дефектов во время развертывания
  3. Большой пул разработчиков для найма
  4. Может быть в состоянии реализовать функции, которые были невозможны в прошлом

Затраты/Риски

  1. Почти полная потеря текущих инвестиций
  2. Может внести дефекты, которые были устранены в прошлом.

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

person Conrad Frix    schedule 24.08.2010
comment
Хорошая точка зрения. Выполнение перезаписи может легко добавить кучу функций, которые они действительно хотят, и в то же время эта новая функциональность сократит трудозатраты. Я думаю, что (написать модульные тесты)->(переписать в .NET) намного быстрее, чем (рефакторить исходный код)->(написать модульные тесты)->(перенормировать и исправить)->(добавить новые функции). - person RewriteOrRefactor; 24.08.2010
comment
+1 Еще одним преимуществом является то, что разработчики остаются довольными, что упрощает удержание хороших разработчиков. Это действительное преимущество для клиента - person MarkJ; 24.08.2010
comment
И не забывайте о самых больших затратах и ​​рисках: почти никаких новых функций, пока идет переписывание, а также риск сильно недооценить задачу переписывания. - person MarkJ; 24.08.2010
comment
@MarkJ: помните, я говорю о переписывании модуля за модулем в .NET с одновременным добавлением функций, поэтому ждать новых функций не придется долго. - person RewriteOrRefactor; 24.08.2010
comment
Да, что сказал MarkJ: я бы предположил, что это один из самых больших рисков (при условии, что управление проектами и развертыванием достаточно хорошо, чтобы избежать самого большого риска, который может заключаться в том, что новая реализация хуже старой). - person ChrisW; 24.08.2010

Я думаю, вам может потребоваться довольно много времени (слишком много времени), чтобы переписать приложение 100KLOC (включая обратный инжиниринг спецификаций и тестирование) без посторонней помощи.

person ChrisW    schedule 24.08.2010
comment
У меня нет с собой моего экземпляра Software Estimation, но я думаю, что 100KLOC может составлять в среднем примерно 5 человеко-лет или что-то в этом роде. Так что вы должны спросить себя: чувствую ли я себя удачливым: выше среднего, способным превзойти все шансы? Ну, а ты? - person ChrisW; 24.08.2010
comment
Ха, другому разработчику понадобилось всего 3 года, чтобы написать столько! - person RewriteOrRefactor; 24.08.2010
comment
+1 У меня здесь Быстрая разработка. Бизнес-продукт 70-100kLOC потребует в среднем 61-93 человеко-месяцев. Конечно, это для готового продукта, отлаженного и работающего :) - person MarkJ; 24.08.2010
comment
На самом деле, если вы удалили избыточность, это, вероятно, всего лишь приложение из 30 тыс. строк в VB6 и короче в .NET. - person RewriteOrRefactor; 24.08.2010

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

person AndersK    schedule 24.08.2010

1). Это VB6, разработка которого MS прекратила два года назад (ref) . Они его не поддерживают, поэтому и вы не должны его поддерживать, и именно поэтому программное обеспечение никогда не заканчивается.

2). Объем кода не имеет значения — сложность рефакторинга или переписывания приложения зависит от его размера.

3). Отсутствие оригинального архитектора означает, что вы всегда будете угадывать намерения и спотыкаться о вещи, о которых вы даже не подозревали. Я бы охарактеризовал это как серьезный риск, если бы вы решили не переписывать.

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

5). Отсутствие модульных тестов — еще один серьезный риск, поскольку вы не сможете доверять никаким изменениям, которые вносите. Это первое, что вам нужно изменить, какой бы подход вы ни выбрали.

6). Если у вас есть одобрение руководства и стратегическое желание перейти на .NET, тогда у вас действительно нет причин не переписывать.

Так что это несколько серьезных рисков, связанных с отказом от переписывания и отсутствием причин избегать этого. Я бы попытался разбить приложение на логические сервисы и разделить ответственность там, где это возможно. Удалите и замените фрагменты бизнес-логики, прижигающие старое приложение, на уровни защиты от коррупции, чтобы попытаться свести к минимуму оборот время, а также для демонстрации обоснованности перезаписи.

Удачи солдат.

person annakata    schedule 24.08.2010
comment
К счастью, большая часть почему все еще существует. Команда менеджеров, участвовавшая в запросе системы, все еще здесь, и я могу просто сказать, почему она это делает? и они всегда дают мне довольно четкий ответ, а также достаточно хорошие отзывы о том, что они на самом деле хотели бы сделать. Интересная ссылка об уровнях защиты от коррупции, но на самом деле из-за отсутствия нормализации и отсутствия обобщения не так много связей между различными частями существующей базы данных (например, для каждого типа контракта есть отдельная таблица). Так что прижигание не слишком болезненно. - person RewriteOrRefactor; 24.08.2010
comment
Борьба с коррупцией может работать в обоих направлениях — вы можете создавать свои доменные службы, ориентируясь на идеалы, а не на реальность. - person annakata; 24.08.2010

Может быть. Для начала вы говорите: «Не пытается следовать принципам DRY или OAOO», так что сразу же появляется много избыточности, которую можно было бы реорганизовать, но если бы вы переписали на .NET, вам не пришлось бы рефакторить . Кроме того, количество LOC, вероятно, раздуто из-за этой проблемы.

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

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

person FrustratedWithFormsDesigner    schedule 24.08.2010
comment
Ваша точка зрения о раздутом счете LOC очень верна. Я оцениваю, вероятно, сокращение примерно в 3 раза, по крайней мере, даже если вы избавитесь от избыточности, оставаясь в VB6. В .NET у вас есть лучшие инструменты благодаря некоторым новым функциональным элементам, и вы можете получить более высокий коэффициент. Моя цель - получить что-то менее 20 тысяч строк. - person RewriteOrRefactor; 24.08.2010

Во-первых, ты бедный s*d. никогда не хорошее место, чтобы быть брошенным на.

Тем не менее, это действительно звучит так, как будто вы схватили быка за рога и следуете устойчивому курсу. У меня возникло бы искушение добавить, что VB6 больше не будет поддерживаться в следующем году (насколько я помню), что будет означать, что если приложение выйдет из строя в результате изменений ОС, то вы в основном застрянете. Кроме того, я бы попытался увидеть, сколько параллельных разработок вы можете провести с этим в .net, поскольку взаимодействие не должно (знаменитые последние слова) быть слишком сложным для работы.

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

Я добавлю больше деталей, когда смогу вернуться к теме.

person jim tollan    schedule 24.08.2010
comment
Твоя память тебя подводит. Среда выполнения VB6 является частью Windows 7, поэтому основная поддержка будет продолжена. как минимум до конца января 2015 г.. - person MarkJ; 24.08.2010
comment
Ха, спасибо за сочувствие, но на самом деле все не так уж и плохо. Как я уже сказал, руководство здесь очень разумное и продуманное. У нас хорошее общение. Кроме того, я думаю, что MS пообещала, что VBRUN-whatever.dll будет продолжать работать на протяжении всего срока службы Win7, и прямо сейчас я запускаю приложение на Win7, так что все должно быть в порядке. - person RewriteOrRefactor; 24.08.2010
comment
извините, я имел в виду фактическую поддержку через m$. но, возможно, это тоже было расширено, учитывая сценарий среды выполнения win7. - person jim tollan; 24.08.2010

Я бы выбрал маршрут «заморозить и написать новое приложение».

  • Используйте столько кода/методов VB6, сколько сможете или сочтете нужным, из приложения VB6. Похоже, вы можете перейти на VB.NET, и некоторый код может пережить обновление. В любом случае, есть преобразователи кода, которые могут помочь.

  • Начните редизайн базы данных. Напишите сценарии для преобразования данных в нормализованную форму, которая имеет для вас смысл.

  • Затем запустите помодульную миграцию в новое приложение. Если вы можете помочь, не вносите больше изменений/исправлений/улучшений в новое приложение.

person p.campbell    schedule 24.08.2010
comment
VB.NET или C# не имеет большого значения. Я написал достаточно большие приложения в обоих. У меня есть новая целевая схема. Это так сильно отличается от того, что у меня есть сейчас, это то, что на самом деле побудило меня пойти по этому пути принятия решений. Написание сценариев для переноса данных не является серьезной проблемой. - person RewriteOrRefactor; 24.08.2010

Долгосрочная цель - все равно преобразовать его в .NET...

Похоже, вы просто будете поддерживать старый код, пока не придет время перенести его на .NET. Так что сохраните некоторые работы и начните сегодня, переписать. Мои 2 цента.

Убедитесь, что существующее приложение все еще можно использовать, пока вы переписываете, поскольку звучит так, будто это невозможно сделать за день или два. Состояние «только для обслуживания» кажется мне хорошей идеей.

person Select0r    schedule 24.08.2010