Продолжение перевода статьи «Big ball of Mud».
он же
QUICK HACK (быстрый хак)
KLEENEX CODE (код на салфетке)
DISPOSABLE CODE (утилизируемый код)
SCRIPTING (скрипт)
KILLER DEMO (демо-убийца)
PERMANENT PROTOTYPE (постоянный прототип)
BOOMTOWN (быстро выросший город)
Владелец дома может возвести временный ангар или навес для автомобиля с твердым намерением разобрать эту конструкцию и заменить ее на что-то более постоянное. Как показывает время, такие структуры могут прожить гораздо дольше, чем планировалось изначально. Может у него не осталось средств, чтобы заменить эти временные решения. Или, когда появляется такая новая постройка, то сразу возникает соблазн попользоваться ей «еще какое-то» время.
То же самое происходит и с прототипированием системы — вы не сильно переживаете о том, насколько красив и эффективен ваш код. Вы знаете, что код нужен вам только для того, чтобы показать работающий прототип. Как только он готов, код будет выброшен и прописан заново уже более тщательно. Когда подходит время демонстрации, возникает непреодолимое желание нагрузить его крутыми, но, по сути, бесполезными функциями. Иногда такая стратегия бывает “принести успешной”. Клиент, вместо того чтобы спонсировать разработку следующего этапа проекта, остается доволен прототипом.
Вам нужно немедленно исправить незначительную проблему, или быстро сделать прототип, или доказать концепцию.
Время или его отсутствие — это зачастую решающая сила, которая заставляет программистов писать одноразовый код (THROWAWAY CODE). Хорошая, продуманная, обоснованная программа требует больше времени для решения проблемы, чем мы располагаем или проблема не стоит того, чтобы затрачивать на нее много времени. Очень часто программисты стремительно создают программу с минимальной функциональностью, обещая себе, что в ближайшем времени они сделают более доработанную, элегантную версию. При этом, они прекрасно понимают, что создание переиспользуемых компонент позволяет им намного проще решать возникающие в будущем проблемы и что хорошо проработанная архитектура позволяет разработать систему, которую можно будет легко поддерживать и расширять.
Быстрое создание «грязного» кода часто рассматривают как временную меру. Но, пожалуй, еще чаще никогда не находится времени, чтобы продолжить эту работу. В коде появляются слабые места, а программа, наоборот, бурно растет.
Следовательно, очень часто любыми доступными средствами, создается простой, удобный, одноразовый код, который поможет решить возникшую проблему.
Одноразовый код часто пишется, как альтернатива повторному использованию чьего-то более сложного кода. Когда на горизонте маячит крайний срок сдачи проекта, вероятность того, что вы создадите сырую и неаккуратную программу, которая будет работать сама по себе, перевешивает неизвестные расходы на изучение и овладение чьей-то библиотекой или средой разработки.
Обычно программисты не являются экспертами в конкретной области знаний, особенно в самом начале своей карьеры. Диаграммы сценариев использования или CRC-карты [Beck и Cunningham, 1989] могут помочь им в освоении этих знаний. Однако нет ничего лучше создания прототипа, чтобы помочь команде разобраться в домене.
Когда вы создаете прототип, обязательно найдется человек, который скажет «и так хорошо, можно отправлять». Для того чтобы не дать прототипу попасть в производство, можно написать прототип на таком языке или с использованием такого инструмента, чтобы сделать версию для производства не представлялось возможным.
Сторонники экстремального программирования [Beck, 2000] часто создают быстрые, одноразовые прототипы на скорую руку (spike solutions). Прототипы помогают нам понять, как обойти проблемы, но прототипы никогда нельзя путать с хорошим дизайном [Johnson и Foote, 1988].
Не все программы должны быть дворцом. Простая одноразовая программа — это как палаточный городок или город, разросшийся в результате открытия месторождений, и такому городу не нужны решения проблем с перспективой на 50 лет, потому что через пять лет он все равно превратится в город-призрак.
Настоящая проблема с одноразовым кодом появляется того, когда этот код становится многоразовым.
Создание одноразового кода (THROWAWAY CODE) — это практически универсальная практика. Все разработчики ПО с любым уровнем опыта и навыков, хотя бы один раз применяли такой подход к разработке программного обеспечения. Например, в сообществе паттернов есть два примера «быстрого и грязного кода», которые сохранились надолго. Это код онлайн регистрации PloP и страницы Wiki-Wiki Web.
На самом деле, изначальный код онлайн регистрации EuroPLoP/PloP/UP представлял собой распределенное приложение на базе веб, которое запускалось на четырех разных машинах на двух континентах. Информацией о конференции управляла машина в городе Сент-Луис, а информация о регистрации хранилась на машинах в Иллинойсе и Германии. Система могла генерировать отчеты об регистрации и даже мгновенно обновлять онлайн список посетителей. Все началось в 1995 году, когда была создана «быстрая и грязная» HTML коллекция, демонстрационный код Cи и скрипты csh. По большому счету, ожидалось, что это будет эксперимент, но как это бывает, проект вышел за рамки ожиданий его создателей. Сегодня это все та же HTML коллекция, тот же демонстрационный код Cи и скрипты csh. Это наглядный пример того, как «быстрый и грязный» код может начать жить своей собственной жизнью.
Оригинальный Си код и скрипты содержали, пожалуй, меньше тридцати оригинальных строк кода. Многие строки были просто скопированы и вставлены и отличались только текстом, который они генерировали или полями, которые они проверяли.
Вот пример одного из скриптов, который генерировал отчет о посещаемости:
Этот скрипт был медленный и неэффективный, особенно, когда возрастает количество регистраций, но его достоинство в том, что он работает. Если количество посетителей превышало сотню, то скрипт работал очень плохо и нестабильно. Однако, так как место проведения конференции не могло вместить сто посетителей, то мы знали, что регистрация будет еще долго ограничена и не ждали проблем с работой скрипта. Хотя в целом это был некомпетентный подход к проблеме, он удовлетворял многих и выполнял функции, для выполнения которых и был написан. Такие практические ограничения типичны для быстрого кода и чаще всего их не документируют. По большому счету, в быстром коде практически ничего не документируют. Если документация и существует, то она, как правило неактуальная и не точная.
Код Wiki-Web на www.c2.com также начинался, как CGI эксперимент под руководством Уорда Каннингема (Ward Cunningham) и также вышел за пределы ожиданий. Название «wiki» — это одна из личных шуток Каннингема. Он позаимствовал это слово из гавайского языка, когда заметил его на перронном автобусе в аэропорту, отправляясь в отпуск на Гавайи. В переводе это слово означает «быстрый». Уорд впоследствии так и стал использовать это слово для любых «быстрых и грязных проектов». Wiki Web уникален тем, что любой посетитель может изменять все, что написал кто-то до него. На первый взгляд, это какой-то вандализм, но на практике все оказалось неплохо. В свете успеха этой системы, автор предпринял дополнительные попытки доработать проект, однако быстрый и грязный код на языке Perl по-прежнему остался основанием всей системы.
Можно подумать, что обе системы находятся на краю и вот-вот превратятся из маленьких комков грязи в большой комок грязи. Код Си регистрационной системы распространился из одного сервера NCSA HTTPD и по-прежнему содержит в себе зомби-код. Стратегия «пусть работает» (KEEPING IT WORKING) — это первое, что приходит в голову, когда нужно принимать решение о расширении или улучшении системы. Обе системы неплохие кандидаты для реконструкции (RECONSTRUCTION), при условии, если будут ресурсы, интерес и аудитория. А пока эти системы, которые по-прежнему вполне удовлетворительно выполняют свои задачи, для решения которых они и разрабатывались, остаются такими, какими есть. На их поддержание уходит намного меньше сил и энергии, чем потребовалось бы для того, чтобы полность переписать их. Они продолжают развиваться поэтапно (PIECEMEAL), не спеша.
Вы можете попытаться исправить распад архитектуры, вызванное «быстрым и грязным» кодом, изолировав ее от других частей системы, сохранив ее собственные объекты, пакеты и модули. Пока такой код будет находиться в условиях карантина, то его способность повлиять на целостность здоровых частей системы будет сведена к минимуму. Этот подход обсуждается в рамках паттерна «замести под половик» (SWEPING IT UNDER THE RUG ). Как только станет очевидно, что якобы одноразовый артефакт еще будет присутствовать какое-то время, то можно обратить свое внимание на улучшение структуры, либо посредством итеративного процесса поэтапного роста (PIECEMEAL GROWTH), либо через новый черновой проект, что обсуждается в паттерне «реконструкция» (RECONSTRUCTION).
Он же
СТИХИЙНЫЙ РОСТ
ИТЕРАТИВНАЯ ИНКРЕМЕНТАЛЬНАЯ РАЗРАБОТКА
Российский космический комплекс «Мир» был создан для изменения конфигурации и наращивания модулей. Базовый модуль был запущен в 1986 году, модули «Квант» и «Квант-2» присоединились к комплексу в 1987 и 1989, соответственно. Модуль «Кристалл» был добавлен в 1990. В 1995 году были присоединены модули «Спектр» и стыковочный отсек (в 1986 году даже не думали об этом отсеке). Наконец, последний модуль «Природа» был запущен в 1996. Подобное маневрирование несколькими модулями позволило реконструировать комплекс несколько раз по мере его роста.
Градостроительство не может похвастаться стабильной историей успеха. Например, столица США город Вашингтон строился по генеральному плану французского архитектора Пьера Ланфана. Столицы Бразилии (Бразилия) и Нигерии (Абуджа) также сначала были городами на бумаге. Другие города, например Хьюстон, росли без какого-либо опорного плана. У каждого подхода есть свои недостатки. Например, радиальная система улиц плана Ланфана дала сбой, как только улицы стали уходить все дальше от центра. С другой стороны, отсутствие какого-либо плана, привело к появлению лоскутного одеяла, состоящего из жилых, торговых и промышленных районов, расположенных в случайном порядке.
Большинство городов похожи больше на Хьюстон, чем на Абуджу. Города могли начинаться как поселения, земельные участки, доки или железнодорожные станции. Возможно, в эти места людей тянуло золото или лес, доступ к транспортной сети или никому не принадлежащая земля. По прошествии времени, в некоторых поселениях количество людей достигало критического уровня, и тогда запускался цикл с положительной обратной связью. Успех города привлекал в него ремесленников, торговцев, врачей и священников. Растущее население способно поддерживать инфраструктуру, государственные институты и полицейскую охрану. А это, в свою очередь, привлекает еще больше людей. За немногими исключениями (сразу вспоминается город Солт-Лейк-Сити), основатели таких поселений никогда не задумывались о том, что они закладывают основы для большого города. Их амбиции были довольно скромными и сиюминутными.
За последние несколько лет вошло в моду критиковать «традиционную» каскадную модель процесса разработки ПО. Читателю может показаться, что такие нападки сродни тому, чтобы стегать дохлую лошадь. Однако, если это так, то лошадь слишком живучая для дохлого животного. Хотя многие считают, что этот подход уже давно себя дискредитировал, он породил такое наследие процессов и методологий, что они до наших дней сохранились под разными масками.
В период до появления каскадной модели, пионеры программирования применяли простой, небрежный и относительно неорганизованный подход к разработке ПО «компилируй и исправляй» (code-and-fix). Учитывая, что проблемы в те дни были на грани примитивности, такой подход чаще всего оправдывал себя. Однако результатом отсутствия организации почти всегда становился большой комок грязи.
Каскадная модель появилась в ответ на это болото. И если модель «компилируй и исправляй» подходила для небольших проектов, с более масштабными задачами она уже не справлялась. По мере того, как ПО становилось все сложнее, уже было недостаточно собрать в кабинете группу программистов и дать им указание написать код. Крупные проекты требовали хорошего планирования и координации действий всей команды. Почему, задавался вопрос, программное обеспечение нельзя разрабатывать так же, как разрабатываются автомобили и мосты, с тщательным анализом проблем и подробным и предварительно продуманным дизайном? Действительно, изучение расходов на разработку ПО показало, что почти всегда решение проблемы во время поддержки программы обходилось дороже, чем во время разработки дизайна. Конечно, было лучше мобилизовать все ресурсы и всех специалистов, чтобы избежать расходов во время поддержки ПО. Несомненно, разумней сначала проложить всю систему канализации, прежде чем возводить стены и потом делать в них дыры. Семь раз отмерь, один раз отрежь.
Одна из причин, почему каскадная модель смогла добиться процветания еще поколение назад заключается в том, что требования к компьютерам и бизнесу менялись в довольно медленном темпе. Аппаратное обеспечение было очень дорогим, поэтому зарплаты программистам, которых нанимали для работы с этим обеспечением приходилось очень сильно сокращать. Пользовательские интерфейсы, по сегодняшним стандартам, были примитивными. Можно было получить любой пользовательский интерфейс, какой вам только хотелось, при условии, что это был буквенно-числовой «зеленый экран». Еще одна причина популярности каскадной модели заключалась в её сходстве с практиками, применяемыми в более развитых инженерных и производственных областях, что было очень удобно.
Современным дизайнерам приходится иметь дело с натиском постоянно меняющихся требований. Частично, это объясняется стремительным ростом самой технологии; частично, это связано с быстрыми изменениями делового климата (некоторые изменения вызваны технологией). Клиенты привыкли к более продвинутому ПО и хотят получать более широкий выбор и большую гибкость. Продукты, которые когда-то были разработаны «с нуля» программистами-одиночками, теперь должны быть интегрированы со сторонним кодом и приложениями. Пользовательские интерфейсы стали сложными как изнутри, так и снаружи. Действительно, иногда приходится выделять целый уровень системы, чтобы обслуживать пользовательский интерфейс. Есть угроза, что изменения будут опережать наши возможности угнаться за ними.
Генеральные планы часто строгие, некорректные и устаревшие. Пользователям со временем будут нужны изменения.
Изменение: фундаментальная проблема с проектирование сверху вниз заключается в том, что требования реального мира — это неизбежно движущиеся мишени. Нельзя просто надеяться на решение проблемы раз и навсегда, потому что к тому времени как вы с ней закончите, проблема уже изменится. Нельзя просто делать то, что просят клиенты, так как часто они сами не знают, чего они хотят. Вы не можете просто планировать, так как планирование должно обеспечивать вам возможность адаптироваться. Если нельзя полностью предугадать, что происходит, то нужно быть готовым к гибкости и быстрому реагированию.
Эстетика: цель проектирования сверху вниз заключается в том, чтобы иметь возможность заранее распознавать и определять значимые архитектурные элементы системы. С точки зрения такого понимания, качественный дизайн элегантно и в полной мере определяет структуру системы, до того как будет написана даже одна строка кода. Расхождения между этими черновыми планами и реальностью считаются отклонениями от нормы и рассматриваются как ошибки со стороны дизайнера. Если дизайн качественный, то в нем заранее будут предусмотрены подобные упущения. При наличии непостоянных требований, надежды на такой безупречный дизайн так же тщетны, как и желание всегда попадать мячом в лунку с первого раза.
Для того чтобы избежать этой неловкости, дизайнер может попытаться прикрыть себя, предложив более сложное, более обобщенное решение некоторых проблем, зная, что другим придется брать на себя задачу по созданию этих артефактов. Когда такие предположения о сложности оказываются верны, они могут быть источником силы и удовлетворения. Это и есть та красота (Venustas), о которой говорил Витрувий. Однако, иногда ожидаемые обстоятельства так никогда и не наступают и получается, что дизайнер и разработчики напрасно потратили время на решение проблемы, с которой никто не столкнулся. В другой ситуации, не только не возникло ожидаемой проблемы, но и само решение должно было развиваться в другом направлении. В таких случаях, теоретическая сложность может стать ненужным препятствием для последующей адаптации. Парадоксально, но стремление к элегантности может оказаться непреднамеренным источником сложности и беспорядка.
В своей самой неприглядной форме, желание предугадать и предотвратить изменение может привести к «аналитическому параличу», так как уплотняющая сеть предполагаемых расхождений разрастается до такой отметки, когда возможности дизайна окажутся слишком ограниченными.
Таким образом надо постоянно обращать внимание на те силы, которые способствуют изменению и росту. Пусть возможности роста будут сначала использованы локально. Постоянно проводите рефакторинг.
Хорошее ПО привлекает более широкую аудиторию, которая, в свою очередь, может предъявлять больше требований к программе. Эти новые требования часто могут быть удовлетворены, но ценой разработки решений полностью противоречащих исходной архитектуре. [Foote, 1988] назвал это архитектурное разрушение «потерей общности среднего возраста».
Когда дизайнеры сталкиваются с выбором между созданием с нуля чего-то элегантного или разрушением архитектуры существующей системы, чтобы быстро решить проблему, то архитектура проигрывает. Это естественная фаза в эволюции системы [Foote и Opdyke, 1995]. Эту фазу можно назвать «неубранной кухней», во время которой части системы разбросаны по всему столу и ждут, когда же их, наконец, уберут. Опасность в том, что уборки можно и не дождаться. Что касается настоящих кухонь в заведениях общественного питания, то в ситуацию вмешается санитарно-эпидемическая станция. В случае с ПО, увы, редко где можно найти специальное агентство, которое контролировало бы подобную запущенность. Бесконтрольный рост может, в конечном итоге, стать вредоносной силой. А результатом пренебрежения станет большой комок грязи.
В своей книге «Как здания учатся» Стюарт Брэнд [Brand, 1994] заметил, что то, что он называет архитектурой «большой дороги» (high road architecture) часто приводит к появлению дорогих зданий, которые трудно изменить; в то время как здания народной архитектуры, такие как бунгало и склады были более адаптируемы. Брэнд также отметил, что функция постепенно переходит в форму и что народные здания более приспособлены к изменениям. Аналогично и с программным обеспечением, вам вряд ли захочется осквернять святое место другого программиста.
В свое книге «Эксперимент Орегона» [Brand, 1994] [Alexander, 1988], Кристофер Александер написал:
Александер также отметил, что наша политика ипотечных залогов и капитальных затрат делает доступными крупные суммы денег, но эта политика не предоставляет никаких ресурсов для поддержки, улучшения и развития [Brand, 1994] [Alexander, 1988]. В мире программного обеспечения, мы с самого начала жизненного цикла задействуем наших самых талантливых и опытных людей. Позже, поддержка ПО осуществляется уже младшим звеном сотрудников, а ресурсы могут быть очень скудными. Так называемый этап поддержки — это часть жизненного цикла, в котором приходится на самом деле платить цену за фиктивный генеральный план. Приглашают программистов технической поддержки, чтобы они справились с все растущими расхождениями между уже установленным дизайном и постоянно меняющимся миром. Если гипотеза о том, что детальное понимание архитектуры приходит на позднем этапе жизненного цикла, тогда эту практику следует пересмотреть.
Брэнд заметил, что поддержка — это учение. Он выделяет три уровня учения в контексте систем. Первый уровень — это привычка, когда система должным образом выполняет свои функции в рамках тех параметров, для которых она была разработана. Второй уровень вступает в игру, когда система должна адаптироваться к изменению. Здесь систему обычно приходиться менять, а ее способность выдержать такие изменения определяет степень ее адаптируемости. Третий уровень самый интересный: учиться, чтобы научиться. В случае со зданиями, в качестве примера можно привести возведение дополнительного этажа. Так как система вынуждена перенести серьезные изменения структуры, то она адаптируется, и последующие адаптации будут менее болезненными.
Поэтапный рост можно применять, как альтернативное решение в зависимости от сложившихся обстоятельств, начиная с существующей, живой, дышащей системы и работая снаружи, шаг за шагом, чтобы не повредить жизнеспособность системы. Вы укрепляете программу, по мере того как используете ее. Масштабные продвижения по всем фронтам отсутствуют. Вместо этого, изменение разбивается на небольшие, посильные задачи.
Что удивляет в поэтапном росте — это роль, которую играет обратная свазь(Feedback). Герберт Саймон [Simon, 1969] заметил, что лишь немного системы, которые были созданы в результате эволюции или созданы человеком, зависели от прогноза( который является нашим основным средством справляться с будущим). Он также отметил, что вспомогательные механизмы, такие как гомеостаз (саморегуляция) и ретроспективная ответная реакция являются намного более эффективными средствами. Гомеостаз ограждает систему от кратковременных колебаний в среде, а механизмы ответной реакции реагируют на долгосрочные расхождения между фактическим и желаемым поведением системы и осуществляют соответствующие корректировки. Александер [Alexander 1964] очень подробно изложил роли, которые играют гомеостаз и ответная реакция в адаптации.
Если вы умеете быстро адаптироваться к изменениям, то прогнозирование изменений становится менее важным. Брэнд отмечает, что ретроспективный взгляд лучше предвидения [Brand, 1994]. Такая быстрая адаптация лежит в основе одной из мантр экстремального программирования [Beck, 2000]: тебе это не понадобится.
Сторонники экстремального программирования говорят, что нужно притвориться, что ты не такой умный, как думаешь и подождать, пока твоя умная идея не потребуется, не нужно поспешно озвучивать эту идею. В тех случаях, когда вы окажетесь правы, вы скажете, что так и думали, что так будет, поэтому знаете, что делать. В тех случаях, когда вы ошибетесь, вам не придется прилагать усилия, чтобы решить проблему, которой нет.
Экстремальное программирование очень сильно зависит от обратной связи, чтобы все требования были синхронизированы с кодом, делая акцент на краткосрочных (три недели) итерациях и обширных, длительных консультациях с пользователями, касательно приоритетов в области дизайна и разработки в ходе всего процесса разработки. Экстремальные программисты не занимаются масштабным заблаговременным планированием. Вместо этого, они как можно быстрее пишут код и направляют эти прототипы в нужное русло, в зависимости от того, что хотят пользователи на основании обратной связи.
Обратная связь также играет свою роль в определении владельца кода. Если разработчики не укладываются в сроки, то во время следующей итерации им дают другое задание, независимо от того, насколько они близки к завершению предыдущей задачи.
В экстремальном программировании, тестирование — это неотъемлемая часть процесса разработки. В идеале, тесты разрабатываются до написания самого кода. Код тестируют постоянно в процессе его разработки. В экстремальном программировании есть что-то от «возврата к будущему». Во многих отношениях, такой подход напоминает метод «компилируй и исправляй». Единственное, что отличает экстремальное программирование — это центральная роль обратной связи, которая способствует развитию системы. Развитию системы также способствует современные объектно-ориентированные языки программирования и мощные инструменты рефакторинга.
Сторонники экстремального программирования называют это минимальным вниманием к планированию и предварительному дизайну. Вместо этого, они полагаются на обратную связь и постоянную интеграцию. Мы уверены, что предварительное планирование и дизайн в некоторой степени — это не только важно, но и неизбежно. Никто не будет заниматься проектом вслепую. Необходимо заложить фундамент, принять решение об инфраструктуре, выбрать инструменты и задать общее направление. На ранних этапах необходимо сконцентрироваться на общем архитектурном видении и стратегии.
Если оставить изменения без контроля, то они подорвут жизнеспособность системы. А запланированные изменения укрепят систему. Изменения могут породить вредоносное распространение или здоровый и надлежащий рост.
В объектно-ориентированной среде за последние десять лет пришли к общему согласию, что объекты появляются из итеративного и инкрементального эволюционного процесса. См. например [Booch, 1994]. Модель тектоника программного обеспечения (SOFTWARE TECTONICS) [Foote и Yoder, 1996] изучает, как системы могут инкрементально справляться с изменением.
Самый большой риск, связанный с поэтапным ростом заключается в том, что этот рост постепенно разрушит всю структуру системы и неизбежно превратить ее в большой комок грязи. Стратегия «замести под половик» идет рука об руку с поэтапным ростом. Оба паттерна придают особое значение острым, локальным проблемам и не обращают внимание на большие проблемы с архитектурой.
Для того, чтобы противостоять этим силам, необходимо постоянно заниматься консолидацией (CONSOLIDATION) и проводить рефакторинг. Именно такими процессами со временем урегулируются локальные и глобальные силы. Такая перспектива жизненного цикла дублирует фрактальную модель [Foote и Opdyke, 1995]. Процитируем Александера [Brand, 1994] [Alexander, 1988]:
Другие части статьи
1 часть
ОДНОРАЗОВЫЙ КОД
он же
QUICK HACK (быстрый хак)
KLEENEX CODE (код на салфетке)
DISPOSABLE CODE (утилизируемый код)
SCRIPTING (скрипт)
KILLER DEMO (демо-убийца)
PERMANENT PROTOTYPE (постоянный прототип)
BOOMTOWN (быстро выросший город)
Владелец дома может возвести временный ангар или навес для автомобиля с твердым намерением разобрать эту конструкцию и заменить ее на что-то более постоянное. Как показывает время, такие структуры могут прожить гораздо дольше, чем планировалось изначально. Может у него не осталось средств, чтобы заменить эти временные решения. Или, когда появляется такая новая постройка, то сразу возникает соблазн попользоваться ей «еще какое-то» время.
То же самое происходит и с прототипированием системы — вы не сильно переживаете о том, насколько красив и эффективен ваш код. Вы знаете, что код нужен вам только для того, чтобы показать работающий прототип. Как только он готов, код будет выброшен и прописан заново уже более тщательно. Когда подходит время демонстрации, возникает непреодолимое желание нагрузить его крутыми, но, по сути, бесполезными функциями. Иногда такая стратегия бывает “принести успешной”. Клиент, вместо того чтобы спонсировать разработку следующего этапа проекта, остается доволен прототипом.
Вам нужно немедленно исправить незначительную проблему, или быстро сделать прототип, или доказать концепцию.
Время или его отсутствие — это зачастую решающая сила, которая заставляет программистов писать одноразовый код (THROWAWAY CODE). Хорошая, продуманная, обоснованная программа требует больше времени для решения проблемы, чем мы располагаем или проблема не стоит того, чтобы затрачивать на нее много времени. Очень часто программисты стремительно создают программу с минимальной функциональностью, обещая себе, что в ближайшем времени они сделают более доработанную, элегантную версию. При этом, они прекрасно понимают, что создание переиспользуемых компонент позволяет им намного проще решать возникающие в будущем проблемы и что хорошо проработанная архитектура позволяет разработать систему, которую можно будет легко поддерживать и расширять.
Быстрое создание «грязного» кода часто рассматривают как временную меру. Но, пожалуй, еще чаще никогда не находится времени, чтобы продолжить эту работу. В коде появляются слабые места, а программа, наоборот, бурно растет.
Следовательно, очень часто любыми доступными средствами, создается простой, удобный, одноразовый код, который поможет решить возникшую проблему.
Одноразовый код часто пишется, как альтернатива повторному использованию чьего-то более сложного кода. Когда на горизонте маячит крайний срок сдачи проекта, вероятность того, что вы создадите сырую и неаккуратную программу, которая будет работать сама по себе, перевешивает неизвестные расходы на изучение и овладение чьей-то библиотекой или средой разработки.
Обычно программисты не являются экспертами в конкретной области знаний, особенно в самом начале своей карьеры. Диаграммы сценариев использования или CRC-карты [Beck и Cunningham, 1989] могут помочь им в освоении этих знаний. Однако нет ничего лучше создания прототипа, чтобы помочь команде разобраться в домене.
Когда вы создаете прототип, обязательно найдется человек, который скажет «и так хорошо, можно отправлять». Для того чтобы не дать прототипу попасть в производство, можно написать прототип на таком языке или с использованием такого инструмента, чтобы сделать версию для производства не представлялось возможным.
Сторонники экстремального программирования [Beck, 2000] часто создают быстрые, одноразовые прототипы на скорую руку (spike solutions). Прототипы помогают нам понять, как обойти проблемы, но прототипы никогда нельзя путать с хорошим дизайном [Johnson и Foote, 1988].
Не все программы должны быть дворцом. Простая одноразовая программа — это как палаточный городок или город, разросшийся в результате открытия месторождений, и такому городу не нужны решения проблем с перспективой на 50 лет, потому что через пять лет он все равно превратится в город-призрак.
Настоящая проблема с одноразовым кодом появляется того, когда этот код становится многоразовым.
Создание одноразового кода (THROWAWAY CODE) — это практически универсальная практика. Все разработчики ПО с любым уровнем опыта и навыков, хотя бы один раз применяли такой подход к разработке программного обеспечения. Например, в сообществе паттернов есть два примера «быстрого и грязного кода», которые сохранились надолго. Это код онлайн регистрации PloP и страницы Wiki-Wiki Web.
На самом деле, изначальный код онлайн регистрации EuroPLoP/PloP/UP представлял собой распределенное приложение на базе веб, которое запускалось на четырех разных машинах на двух континентах. Информацией о конференции управляла машина в городе Сент-Луис, а информация о регистрации хранилась на машинах в Иллинойсе и Германии. Система могла генерировать отчеты об регистрации и даже мгновенно обновлять онлайн список посетителей. Все началось в 1995 году, когда была создана «быстрая и грязная» HTML коллекция, демонстрационный код Cи и скрипты csh. По большому счету, ожидалось, что это будет эксперимент, но как это бывает, проект вышел за рамки ожиданий его создателей. Сегодня это все та же HTML коллекция, тот же демонстрационный код Cи и скрипты csh. Это наглядный пример того, как «быстрый и грязный» код может начать жить своей собственной жизнью.
Оригинальный Си код и скрипты содержали, пожалуй, меньше тридцати оригинальных строк кода. Многие строки были просто скопированы и вставлены и отличались только текстом, который они генерировали или полями, которые они проверяли.
Вот пример одного из скриптов, который генерировал отчет о посещаемости:
echo "<H2>Registrations: <B>" `ls | wc -l` "</B></H2>"
echo "<CODE>"
echo "Authors: <B>" `grep 'Author = Yes' * | wc -l` "</B>"
echo "
"
echo "Non-Authors: <B>" `grep 'Author = No' * | wc -l` "</B>"
echo "
"
Этот скрипт был медленный и неэффективный, особенно, когда возрастает количество регистраций, но его достоинство в том, что он работает. Если количество посетителей превышало сотню, то скрипт работал очень плохо и нестабильно. Однако, так как место проведения конференции не могло вместить сто посетителей, то мы знали, что регистрация будет еще долго ограничена и не ждали проблем с работой скрипта. Хотя в целом это был некомпетентный подход к проблеме, он удовлетворял многих и выполнял функции, для выполнения которых и был написан. Такие практические ограничения типичны для быстрого кода и чаще всего их не документируют. По большому счету, в быстром коде практически ничего не документируют. Если документация и существует, то она, как правило неактуальная и не точная.
Код Wiki-Web на www.c2.com также начинался, как CGI эксперимент под руководством Уорда Каннингема (Ward Cunningham) и также вышел за пределы ожиданий. Название «wiki» — это одна из личных шуток Каннингема. Он позаимствовал это слово из гавайского языка, когда заметил его на перронном автобусе в аэропорту, отправляясь в отпуск на Гавайи. В переводе это слово означает «быстрый». Уорд впоследствии так и стал использовать это слово для любых «быстрых и грязных проектов». Wiki Web уникален тем, что любой посетитель может изменять все, что написал кто-то до него. На первый взгляд, это какой-то вандализм, но на практике все оказалось неплохо. В свете успеха этой системы, автор предпринял дополнительные попытки доработать проект, однако быстрый и грязный код на языке Perl по-прежнему остался основанием всей системы.
Можно подумать, что обе системы находятся на краю и вот-вот превратятся из маленьких комков грязи в большой комок грязи. Код Си регистрационной системы распространился из одного сервера NCSA HTTPD и по-прежнему содержит в себе зомби-код. Стратегия «пусть работает» (KEEPING IT WORKING) — это первое, что приходит в голову, когда нужно принимать решение о расширении или улучшении системы. Обе системы неплохие кандидаты для реконструкции (RECONSTRUCTION), при условии, если будут ресурсы, интерес и аудитория. А пока эти системы, которые по-прежнему вполне удовлетворительно выполняют свои задачи, для решения которых они и разрабатывались, остаются такими, какими есть. На их поддержание уходит намного меньше сил и энергии, чем потребовалось бы для того, чтобы полность переписать их. Они продолжают развиваться поэтапно (PIECEMEAL), не спеша.
Вы можете попытаться исправить распад архитектуры, вызванное «быстрым и грязным» кодом, изолировав ее от других частей системы, сохранив ее собственные объекты, пакеты и модули. Пока такой код будет находиться в условиях карантина, то его способность повлиять на целостность здоровых частей системы будет сведена к минимуму. Этот подход обсуждается в рамках паттерна «замести под половик» (SWEPING IT UNDER THE RUG ). Как только станет очевидно, что якобы одноразовый артефакт еще будет присутствовать какое-то время, то можно обратить свое внимание на улучшение структуры, либо посредством итеративного процесса поэтапного роста (PIECEMEAL GROWTH), либо через новый черновой проект, что обсуждается в паттерне «реконструкция» (RECONSTRUCTION).
ПОЭТАПНЫЙ РОСТ
Он же
СТИХИЙНЫЙ РОСТ
ИТЕРАТИВНАЯ ИНКРЕМЕНТАЛЬНАЯ РАЗРАБОТКА
Российский космический комплекс «Мир» был создан для изменения конфигурации и наращивания модулей. Базовый модуль был запущен в 1986 году, модули «Квант» и «Квант-2» присоединились к комплексу в 1987 и 1989, соответственно. Модуль «Кристалл» был добавлен в 1990. В 1995 году были присоединены модули «Спектр» и стыковочный отсек (в 1986 году даже не думали об этом отсеке). Наконец, последний модуль «Природа» был запущен в 1996. Подобное маневрирование несколькими модулями позволило реконструировать комплекс несколько раз по мере его роста.
Градостроительство не может похвастаться стабильной историей успеха. Например, столица США город Вашингтон строился по генеральному плану французского архитектора Пьера Ланфана. Столицы Бразилии (Бразилия) и Нигерии (Абуджа) также сначала были городами на бумаге. Другие города, например Хьюстон, росли без какого-либо опорного плана. У каждого подхода есть свои недостатки. Например, радиальная система улиц плана Ланфана дала сбой, как только улицы стали уходить все дальше от центра. С другой стороны, отсутствие какого-либо плана, привело к появлению лоскутного одеяла, состоящего из жилых, торговых и промышленных районов, расположенных в случайном порядке.
Большинство городов похожи больше на Хьюстон, чем на Абуджу. Города могли начинаться как поселения, земельные участки, доки или железнодорожные станции. Возможно, в эти места людей тянуло золото или лес, доступ к транспортной сети или никому не принадлежащая земля. По прошествии времени, в некоторых поселениях количество людей достигало критического уровня, и тогда запускался цикл с положительной обратной связью. Успех города привлекал в него ремесленников, торговцев, врачей и священников. Растущее население способно поддерживать инфраструктуру, государственные институты и полицейскую охрану. А это, в свою очередь, привлекает еще больше людей. За немногими исключениями (сразу вспоминается город Солт-Лейк-Сити), основатели таких поселений никогда не задумывались о том, что они закладывают основы для большого города. Их амбиции были довольно скромными и сиюминутными.
За последние несколько лет вошло в моду критиковать «традиционную» каскадную модель процесса разработки ПО. Читателю может показаться, что такие нападки сродни тому, чтобы стегать дохлую лошадь. Однако, если это так, то лошадь слишком живучая для дохлого животного. Хотя многие считают, что этот подход уже давно себя дискредитировал, он породил такое наследие процессов и методологий, что они до наших дней сохранились под разными масками.
В период до появления каскадной модели, пионеры программирования применяли простой, небрежный и относительно неорганизованный подход к разработке ПО «компилируй и исправляй» (code-and-fix). Учитывая, что проблемы в те дни были на грани примитивности, такой подход чаще всего оправдывал себя. Однако результатом отсутствия организации почти всегда становился большой комок грязи.
Каскадная модель появилась в ответ на это болото. И если модель «компилируй и исправляй» подходила для небольших проектов, с более масштабными задачами она уже не справлялась. По мере того, как ПО становилось все сложнее, уже было недостаточно собрать в кабинете группу программистов и дать им указание написать код. Крупные проекты требовали хорошего планирования и координации действий всей команды. Почему, задавался вопрос, программное обеспечение нельзя разрабатывать так же, как разрабатываются автомобили и мосты, с тщательным анализом проблем и подробным и предварительно продуманным дизайном? Действительно, изучение расходов на разработку ПО показало, что почти всегда решение проблемы во время поддержки программы обходилось дороже, чем во время разработки дизайна. Конечно, было лучше мобилизовать все ресурсы и всех специалистов, чтобы избежать расходов во время поддержки ПО. Несомненно, разумней сначала проложить всю систему канализации, прежде чем возводить стены и потом делать в них дыры. Семь раз отмерь, один раз отрежь.
Одна из причин, почему каскадная модель смогла добиться процветания еще поколение назад заключается в том, что требования к компьютерам и бизнесу менялись в довольно медленном темпе. Аппаратное обеспечение было очень дорогим, поэтому зарплаты программистам, которых нанимали для работы с этим обеспечением приходилось очень сильно сокращать. Пользовательские интерфейсы, по сегодняшним стандартам, были примитивными. Можно было получить любой пользовательский интерфейс, какой вам только хотелось, при условии, что это был буквенно-числовой «зеленый экран». Еще одна причина популярности каскадной модели заключалась в её сходстве с практиками, применяемыми в более развитых инженерных и производственных областях, что было очень удобно.
Современным дизайнерам приходится иметь дело с натиском постоянно меняющихся требований. Частично, это объясняется стремительным ростом самой технологии; частично, это связано с быстрыми изменениями делового климата (некоторые изменения вызваны технологией). Клиенты привыкли к более продвинутому ПО и хотят получать более широкий выбор и большую гибкость. Продукты, которые когда-то были разработаны «с нуля» программистами-одиночками, теперь должны быть интегрированы со сторонним кодом и приложениями. Пользовательские интерфейсы стали сложными как изнутри, так и снаружи. Действительно, иногда приходится выделять целый уровень системы, чтобы обслуживать пользовательский интерфейс. Есть угроза, что изменения будут опережать наши возможности угнаться за ними.
Генеральные планы часто строгие, некорректные и устаревшие. Пользователям со временем будут нужны изменения.
Изменение: фундаментальная проблема с проектирование сверху вниз заключается в том, что требования реального мира — это неизбежно движущиеся мишени. Нельзя просто надеяться на решение проблемы раз и навсегда, потому что к тому времени как вы с ней закончите, проблема уже изменится. Нельзя просто делать то, что просят клиенты, так как часто они сами не знают, чего они хотят. Вы не можете просто планировать, так как планирование должно обеспечивать вам возможность адаптироваться. Если нельзя полностью предугадать, что происходит, то нужно быть готовым к гибкости и быстрому реагированию.
Эстетика: цель проектирования сверху вниз заключается в том, чтобы иметь возможность заранее распознавать и определять значимые архитектурные элементы системы. С точки зрения такого понимания, качественный дизайн элегантно и в полной мере определяет структуру системы, до того как будет написана даже одна строка кода. Расхождения между этими черновыми планами и реальностью считаются отклонениями от нормы и рассматриваются как ошибки со стороны дизайнера. Если дизайн качественный, то в нем заранее будут предусмотрены подобные упущения. При наличии непостоянных требований, надежды на такой безупречный дизайн так же тщетны, как и желание всегда попадать мячом в лунку с первого раза.
Для того чтобы избежать этой неловкости, дизайнер может попытаться прикрыть себя, предложив более сложное, более обобщенное решение некоторых проблем, зная, что другим придется брать на себя задачу по созданию этих артефактов. Когда такие предположения о сложности оказываются верны, они могут быть источником силы и удовлетворения. Это и есть та красота (Venustas), о которой говорил Витрувий. Однако, иногда ожидаемые обстоятельства так никогда и не наступают и получается, что дизайнер и разработчики напрасно потратили время на решение проблемы, с которой никто не столкнулся. В другой ситуации, не только не возникло ожидаемой проблемы, но и само решение должно было развиваться в другом направлении. В таких случаях, теоретическая сложность может стать ненужным препятствием для последующей адаптации. Парадоксально, но стремление к элегантности может оказаться непреднамеренным источником сложности и беспорядка.
В своей самой неприглядной форме, желание предугадать и предотвратить изменение может привести к «аналитическому параличу», так как уплотняющая сеть предполагаемых расхождений разрастается до такой отметки, когда возможности дизайна окажутся слишком ограниченными.
Таким образом надо постоянно обращать внимание на те силы, которые способствуют изменению и росту. Пусть возможности роста будут сначала использованы локально. Постоянно проводите рефакторинг.
Хорошее ПО привлекает более широкую аудиторию, которая, в свою очередь, может предъявлять больше требований к программе. Эти новые требования часто могут быть удовлетворены, но ценой разработки решений полностью противоречащих исходной архитектуре. [Foote, 1988] назвал это архитектурное разрушение «потерей общности среднего возраста».
Когда дизайнеры сталкиваются с выбором между созданием с нуля чего-то элегантного или разрушением архитектуры существующей системы, чтобы быстро решить проблему, то архитектура проигрывает. Это естественная фаза в эволюции системы [Foote и Opdyke, 1995]. Эту фазу можно назвать «неубранной кухней», во время которой части системы разбросаны по всему столу и ждут, когда же их, наконец, уберут. Опасность в том, что уборки можно и не дождаться. Что касается настоящих кухонь в заведениях общественного питания, то в ситуацию вмешается санитарно-эпидемическая станция. В случае с ПО, увы, редко где можно найти специальное агентство, которое контролировало бы подобную запущенность. Бесконтрольный рост может, в конечном итоге, стать вредоносной силой. А результатом пренебрежения станет большой комок грязи.
В своей книге «Как здания учатся» Стюарт Брэнд [Brand, 1994] заметил, что то, что он называет архитектурой «большой дороги» (high road architecture) часто приводит к появлению дорогих зданий, которые трудно изменить; в то время как здания народной архитектуры, такие как бунгало и склады были более адаптируемы. Брэнд также отметил, что функция постепенно переходит в форму и что народные здания более приспособлены к изменениям. Аналогично и с программным обеспечением, вам вряд ли захочется осквернять святое место другого программиста.
В свое книге «Эксперимент Орегона» [Brand, 1994] [Alexander, 1988], Кристофер Александер написал:
Крупная разработка основана на идее замены. Поэтапный рост (Piecemeal Growth) основан на идее исправления. Крупная разработка основана на заблуждении, что можно построить идеальные здания. Поэтапный рост основан на более здоровой и реалистичной точке зрения о том, что ошибки неизбежны. Если нет средств на исправления этих ошибок, то каждое здание, как только оно построено, приговорено к тому, чтобы, до некоторой степени, быть нерабочим… Поэтапный рост основан на предположении, что процесс адаптации между зданиями и их пользователями обязательно медленный и продолжительный и этого нельзя ни при каких обстоятельствах добиться одним махом.
Александер также отметил, что наша политика ипотечных залогов и капитальных затрат делает доступными крупные суммы денег, но эта политика не предоставляет никаких ресурсов для поддержки, улучшения и развития [Brand, 1994] [Alexander, 1988]. В мире программного обеспечения, мы с самого начала жизненного цикла задействуем наших самых талантливых и опытных людей. Позже, поддержка ПО осуществляется уже младшим звеном сотрудников, а ресурсы могут быть очень скудными. Так называемый этап поддержки — это часть жизненного цикла, в котором приходится на самом деле платить цену за фиктивный генеральный план. Приглашают программистов технической поддержки, чтобы они справились с все растущими расхождениями между уже установленным дизайном и постоянно меняющимся миром. Если гипотеза о том, что детальное понимание архитектуры приходит на позднем этапе жизненного цикла, тогда эту практику следует пересмотреть.
Брэнд заметил, что поддержка — это учение. Он выделяет три уровня учения в контексте систем. Первый уровень — это привычка, когда система должным образом выполняет свои функции в рамках тех параметров, для которых она была разработана. Второй уровень вступает в игру, когда система должна адаптироваться к изменению. Здесь систему обычно приходиться менять, а ее способность выдержать такие изменения определяет степень ее адаптируемости. Третий уровень самый интересный: учиться, чтобы научиться. В случае со зданиями, в качестве примера можно привести возведение дополнительного этажа. Так как система вынуждена перенести серьезные изменения структуры, то она адаптируется, и последующие адаптации будут менее болезненными.
Поэтапный рост можно применять, как альтернативное решение в зависимости от сложившихся обстоятельств, начиная с существующей, живой, дышащей системы и работая снаружи, шаг за шагом, чтобы не повредить жизнеспособность системы. Вы укрепляете программу, по мере того как используете ее. Масштабные продвижения по всем фронтам отсутствуют. Вместо этого, изменение разбивается на небольшие, посильные задачи.
Что удивляет в поэтапном росте — это роль, которую играет обратная свазь(Feedback). Герберт Саймон [Simon, 1969] заметил, что лишь немного системы, которые были созданы в результате эволюции или созданы человеком, зависели от прогноза( который является нашим основным средством справляться с будущим). Он также отметил, что вспомогательные механизмы, такие как гомеостаз (саморегуляция) и ретроспективная ответная реакция являются намного более эффективными средствами. Гомеостаз ограждает систему от кратковременных колебаний в среде, а механизмы ответной реакции реагируют на долгосрочные расхождения между фактическим и желаемым поведением системы и осуществляют соответствующие корректировки. Александер [Alexander 1964] очень подробно изложил роли, которые играют гомеостаз и ответная реакция в адаптации.
Если вы умеете быстро адаптироваться к изменениям, то прогнозирование изменений становится менее важным. Брэнд отмечает, что ретроспективный взгляд лучше предвидения [Brand, 1994]. Такая быстрая адаптация лежит в основе одной из мантр экстремального программирования [Beck, 2000]: тебе это не понадобится.
Сторонники экстремального программирования говорят, что нужно притвориться, что ты не такой умный, как думаешь и подождать, пока твоя умная идея не потребуется, не нужно поспешно озвучивать эту идею. В тех случаях, когда вы окажетесь правы, вы скажете, что так и думали, что так будет, поэтому знаете, что делать. В тех случаях, когда вы ошибетесь, вам не придется прилагать усилия, чтобы решить проблему, которой нет.
Экстремальное программирование очень сильно зависит от обратной связи, чтобы все требования были синхронизированы с кодом, делая акцент на краткосрочных (три недели) итерациях и обширных, длительных консультациях с пользователями, касательно приоритетов в области дизайна и разработки в ходе всего процесса разработки. Экстремальные программисты не занимаются масштабным заблаговременным планированием. Вместо этого, они как можно быстрее пишут код и направляют эти прототипы в нужное русло, в зависимости от того, что хотят пользователи на основании обратной связи.
Обратная связь также играет свою роль в определении владельца кода. Если разработчики не укладываются в сроки, то во время следующей итерации им дают другое задание, независимо от того, насколько они близки к завершению предыдущей задачи.
В экстремальном программировании, тестирование — это неотъемлемая часть процесса разработки. В идеале, тесты разрабатываются до написания самого кода. Код тестируют постоянно в процессе его разработки. В экстремальном программировании есть что-то от «возврата к будущему». Во многих отношениях, такой подход напоминает метод «компилируй и исправляй». Единственное, что отличает экстремальное программирование — это центральная роль обратной связи, которая способствует развитию системы. Развитию системы также способствует современные объектно-ориентированные языки программирования и мощные инструменты рефакторинга.
Сторонники экстремального программирования называют это минимальным вниманием к планированию и предварительному дизайну. Вместо этого, они полагаются на обратную связь и постоянную интеграцию. Мы уверены, что предварительное планирование и дизайн в некоторой степени — это не только важно, но и неизбежно. Никто не будет заниматься проектом вслепую. Необходимо заложить фундамент, принять решение об инфраструктуре, выбрать инструменты и задать общее направление. На ранних этапах необходимо сконцентрироваться на общем архитектурном видении и стратегии.
Если оставить изменения без контроля, то они подорвут жизнеспособность системы. А запланированные изменения укрепят систему. Изменения могут породить вредоносное распространение или здоровый и надлежащий рост.
В объектно-ориентированной среде за последние десять лет пришли к общему согласию, что объекты появляются из итеративного и инкрементального эволюционного процесса. См. например [Booch, 1994]. Модель тектоника программного обеспечения (SOFTWARE TECTONICS) [Foote и Yoder, 1996] изучает, как системы могут инкрементально справляться с изменением.
Самый большой риск, связанный с поэтапным ростом заключается в том, что этот рост постепенно разрушит всю структуру системы и неизбежно превратить ее в большой комок грязи. Стратегия «замести под половик» идет рука об руку с поэтапным ростом. Оба паттерна придают особое значение острым, локальным проблемам и не обращают внимание на большие проблемы с архитектурой.
Для того, чтобы противостоять этим силам, необходимо постоянно заниматься консолидацией (CONSOLIDATION) и проводить рефакторинг. Именно такими процессами со временем урегулируются локальные и глобальные силы. Такая перспектива жизненного цикла дублирует фрактальную модель [Foote и Opdyke, 1995]. Процитируем Александера [Brand, 1994] [Alexander, 1988]:
Органический процесс роста и восстановления должен создавать постепенную последовательность изменений, и эти изменения должны равномерно распространяться по всем уровням. [Разрабатывая университетский городок], необходимо уделять не меньше внимания восстановлению деталей — комнаты, пролеты зданий, окна, дорожки — чем созданию совершенно нового здания. Только в этом случае мы можем говорить как о сбалансированной среде в целом, так и о ее элементах на каждом этапе истории.
Другие части статьи
1 часть
Комментарии (2)
AlexZaharow
05.04.2018 06:37можно написать прототип на таком языке или с использованием такого инструмента, чтобы сделать версию для производства не представлялось возможным
Сначала надо найти специалиста по такому языку. Представляю как обрадуются компании такому предложению? Особенно если после создания прототипа выяснится, что переписать его на целевом языке не получится в принципе. Дада, мы все тут обожаем делать одну и туже работу по два раза.
На такую длинную простыню ОДИН маленький отрывок кода, на основе которого делается вывод эмоционального клише?
odissey_nemo
«Российский космический комплекс «Мир»» — несомненно, советский комплекс, а добавленные к нему после 1991 года части — лишь остатки инерция советской технической цивилизации. РФ космонавтика обслуживает чужие комплексы, это однозначно.