Как я понимаю, нисходящий дизайн заключается в преобразовании абстрактной концепции высокого уровня в более мелкие конкретные и понятные части, пока не будет определен наименьший строительный блок. С другой стороны, снизу вверх определяются низкоуровневые части, затем постепенно накапливаются блоки более высокого уровня, пока не будет сформирована вся система.
На практике говорят, что лучше всего объединить два метода: начинается с высокоуровневой спецификации, чтобы полностью определить знания предметной области, ее взаимосвязь и ограничения. Как только проблема понятна, создаются самые маленькие строительные блоки для построения системы.
Процесс:
- Создание спецификации требования
- Создать спецификацию дизайна (с диаграммами)
- Воплощать в жизнь
- доставить
- Повторите (в итеративной разработке, вместо того, чтобы делать целую порцию на каждом этапе, мы выполняем каждый раз по несколько штук и получаем ежедневные встречи, чтобы приспособиться к динамическим требованиям клиента)
выглядит совершенно нормально для меня (со спецификациями в планах). У него есть свои недостатки, но именно поэтому мы получили итеративную разработку: вместо того, чтобы тратить время на одну фазу, говорит анализ требований, чтобы изучить все возможные вещи в предметной области, которые подвержены изменениям (возможно, ежедневно), мы проводим небольшой анализ, немного дизайна, а затем реализовать его.
Другой способ заключается в том, что каждая итерация представляет собой мини-водопад, где анализ выполняется за несколько дней (или неделю). То же самое относится и к дизайну. Остальное время уходит на реализацию. Есть ли что-то не так с подходом сверху вниз в сочетании с итеративной разработкой?
В своем эссе « Программирование снизу вверх» Пол Грэм, кажется, поощряет сборку полностью снизу вверх или программирует ее снизу вверх, но не на этапе анализа требований / проектирования:
Опытные программисты на Лисп делят свои программы по-разному. Как и дизайн сверху вниз, они следуют принципу, который можно назвать дизайном снизу вверх - изменяя язык в соответствии с проблемой.
Насколько я понимаю, он имел в виду, что Лиспер по-прежнему выполняет нисходящее проектирование, но программа снизу вверх, это правда? Еще один момент, он написал:
Стоит подчеркнуть, что дизайн снизу вверх не означает просто написание одной и той же программы в другом порядке. Когда вы работаете снизу вверх, у вас обычно получается другая программа. Вместо одной монолитной программы вы получите больший язык с большим количеством абстрактных операторов и меньшую программу, написанную на нем. Вместо перемычки вы получите арку.
Означает ли это, что в период написания программы на Лиспе вы получаете универсальный инструмент?
Ответы:
Сверху вниз - отличный способ описать вещи, которые вы знаете, или восстановить вещи, которые вы уже создали.
Сверху вниз самая большая проблема в том, что довольно часто просто нет «вершины». Вы передумаете о том, что должна делать система при разработке системы и при изучении домена. Как может быть ваша отправная точка чего-то, чего вы не знаете (то есть, что вы хотите, чтобы система делала)?
«Локальный» нисходящий - это хорошо ... некоторые мысли об кодировании явно хороши. Но слишком много думать и планировать, потому что то, что вы представляете, не является реальным сценарием (если вы уже не были там раньше, то есть если вы не строите, а восстанавливаете). Глобальный нисходящий при создании новых вещей это просто глупость.
Подход «снизу вверх» должен быть (глобальным) подходом, если вы не знаете 100% проблемы, вам нужно просто закодировать известное решение, и вам не нужно искать возможные альтернативные решения.
Лисп-подход - это перегнанный снизу вверх. Вы можете не только строить снизу вверх, но и формировать кирпичи так, как вам нужно. Ничто не исправлено, свобода полная. Конечно, свобода берет на себя ответственность, и вы можете делать ужасные вещи, злоупотребляя этой силой.
Но ужасный код можно написать на любом языке. Даже в языках, которые имеют форму клеток для разума, они рассчитаны на то, что с этими языками даже обезьяны смогут запустить и запустить хорошие программы (идея настолько ошибочна на столь многих уровнях, что больно даже думать об этом).
Ваш пример о веб-сервере. Сейчас, в 2012 году, это четко определенная проблема, у вас есть спецификации, которым нужно следовать. Веб-сервер - это просто проблема реализации. Особенно, если вы нацелены на написание веб-сервера, по существу идентичного другим гаджиллионам веб-серверов, которые там существуют, тогда нет ничего действительно неясного, кроме некоторых мелочей. Даже ваш комментарий о RSA все еще говорит о четко определенной проблеме с формальными спецификациями.
С четко определенной проблемой, с формальными спецификациями и уже известными решениями, кодирование просто соединяется в точках. Сверху вниз это нормально. Это менеджер проекта рай.
Однако во многих случаях не существует проверенного общеизвестного подхода для соединения точек. На самом деле очень часто трудно сказать даже, каковы точки.
Предположим, например, что вас попросили дать автоматическому отрезному станку команду выровнять детали, которые нужно разрезать, по печатному материалу, который не полностью соответствует теоретическому повторяющемуся логотипу. Вам предоставляются детали и фотографии материала, снятые машиной.
Что такое правило выравнивания? Вам решать. Что такое шаблон, как его представить? Вам решать. Как выровнять части? Вам решать. Можно ли согнуть детали? Это зависит, некоторые нет, а некоторые да, но, конечно, не слишком много. Что делать, если материал слишком деформирован, чтобы деталь могла его разрезать приемлемо? Вам решать. Все ли рулоны материала идентичны? Конечно, нет, но вы не можете заставить пользователя адаптировать правила выравнивания для каждого броска ... это было бы нецелесообразно. Какие картинки видят камеры? Материал, что бы это ни значило ... это может быть цвет, он может быть черным над черным, где только светлый рефлекс делает рисунок очевидным. Что значит распознать шаблон? Вам решать.
Теперь попробуйте разработать общую структуру решения этой проблемы и дать цитату, в деньгах и времени. Держу пари, что даже ваша системная архитектура ... (да, архитектура) будет неправильной. Стоимость и время оценки будут случайными числами.
Мы внедрили его и теперь это работающая система, но много раз меняли свое мнение о самой форме системы. Мы добавили целые подсистемы, которые сейчас даже недоступны из меню. Мы переключали главные / подчиненные роли в протоколах более одного раза. Вероятно, теперь у нас достаточно знаний, чтобы попытаться восстановить его лучше.
Конечно, другие компании решили ту же проблему ... но если вы не в одной из этих компаний, скорее всего, ваш подробный проект сверху вниз будет шуткой. Мы можем спроектировать его сверху вниз. Вы не можете, потому что вы никогда не делали этого раньше.
Вы, вероятно, можете решить ту же проблему тоже. Работая снизу вверх однако. Начиная с того, что вы знаете, изучая то, что вы не делаете и складывая.
Новые сложные программные системы выращиваются, а не проектируются. Время от времени кто-то начинает с нуля разрабатывать новую сложную плохо определенную программную систему (обратите внимание, что в большом сложном программном проекте есть только три возможности: а) спецификация нечеткая, б] спецификация неправильная и противоречивая. или с] оба ... и чаще всего [с] имеет место).
Это типичные проекты огромных компаний, в которые тысячи и тысячи часов добавляются только слайды PowerPoint и диаграммы UML. Они неизменно терпят неудачу полностью после сжигания смущающего количества ресурсов ... или в каком-то очень исключительном случае они, наконец, поставляют переоцененную часть программного обеспечения, которая реализует только крошечную часть начальных спецификаций. И это программное обеспечение неизменно глубоко ненавидят пользователи ... не то, какое программное обеспечение вы бы купили, а то, какое программное обеспечение вы используете, потому что вы вынуждены.
Значит ли это, что я думаю, что вы должны думать только о коде? Конечно нет. Но, по моему мнению, строительство должно начинаться снизу (кирпичи, конкретный код) и должно идти вверх ... и ваше внимание и внимание к деталям должны в некотором смысле «исчезать» по мере того, как вы становитесь дальше от того, что у вас есть. Нисходящий поток часто представляется так, как будто вы должны поместить один и тот же уровень детализации во всю систему сразу: просто делайте это, разделяя каждый узел, пока все не станет очевидным ... в реальных модулях подсистема "выросла" из подпрограмм. Если у вас нет опыта работы с конкретной проблемой, ваш дизайн подсистемы, модуля или библиотеки будет ужасным. Вы можете создать хорошую библиотеку, когда будете знать, какие функции вставлять, а не наоборот.
Многие идеи Lisp становятся все более популярными (первоклассные функции, замыкания, динамическая типизация по умолчанию, сборка мусора, метапрограммирование, интерактивная разработка), но Lisp все еще сегодня (среди известных мне языков) совершенно уникален в том, как легко формировать код за то что тебе нужно.
Например, параметры ключевого слова уже присутствуют, но если они отсутствуют, их можно добавить. Я сделал это (включая проверку ключевых слов во время компиляции) для игрушечного компилятора Lisp, с которым я экспериментировал, и он не занимал много кода.
С C ++ вместо этого вы можете получить всего лишь кучу экспертов C ++, которые скажут вам, что параметры ключевых слов не так уж полезны, или невероятно сложную, сломанную, полуобеспеченную реализацию шаблона, которая действительно не так полезна. Являются ли классы C ++ первоклассными объектами? Нет, и с этим ничего не поделаешь. Можете ли вы провести самоанализ во время выполнения или во время компиляции? Нет, и с этим ничего не поделаешь.
Гибкость языка в Лиспе делает его идеальным для построения снизу вверх. Вы можете создавать не только подпрограммы, но также синтаксис и семантику языка. И в каком-то смысле сам Lisp является восходящим.
источник
Я не уверен, как этот ответ будет применяться к Лиспу, но я только что закончил читать Agile Принципы, Шаблоны и Практики , и автор, дядя Боб , решительно поддерживает нисходящий подход для C # (также применимый к C ++), с которым я полностью дать согласие.
Однако, в отличие от некоторых других ответов, в которых сделан вывод о том, что подход «сверху вниз» означает, что при первом взаимодействии вы предоставляете только документы и общий дизайн, книга указывает на другой метод: TDD в сочетании с эволюционным дизайном.
Идея состоит в том, что вы начинаете с вершины и определяете свои наивысшие уровни абстракции (или локальные наивысшие), и как только они определены, вы заставляете их выполнять полезную работу, чтобы функция # 1 сразу работала. Затем, когда вы добавляете все больше и больше функций, вы реорганизуете свой код и развиваете дизайн по мере необходимости, всегда оставаясь в курсе принципов SOLID., Таким образом, вы не получите слишком много уровней абстракции и не получите низкоуровневый дизайн, который не соответствует общей архитектуре. Если вы не уверены, что это значит, в упомянутой выше книге есть целая глава с примером, в котором разработчики берут концепции и начинают с UML-диаграмм и низкоуровневых классов, но только для того, чтобы понять, что половина этих классов не нужна, когда кодирование действительно начинается. В сущности, при таком подходе низкоуровневый код естественным образом отталкивается, так как в проекте определяются более высокоуровневые детали.
И, наконец, если вы практикуете SOLID, вы не должны сталкиваться с ситуацией, когда у вас определены высокоуровневые абстракции, а затем попадаете в детали и вдруг обнаруживаете, что нет OOD или абстракций. Это не вина дизайн сверху вниз, но ленивый инжиниринг.
Если вам интересно узнать больше о XP и эволюционном дизайне, вот хорошее прочтение Мартина Фаулера, другого великого автора: «Является ли Design Dead?»
источник
Для меня наиболее важные замечания, которые Пол Грэм делает в своей статье:
Или, как известно в кругах C ++: дизайн библиотеки - это дизайн языка (Бьярне Страуструп)
Основная идея дизайна сверху вниз: сначала вы планируете, а потом кодируете. Beanow прав, когда пишет , что есть проблемы, когда исполняемый код опаздывает в процессе. В дизайне снизу вверх у вас всегда есть код и тот код, который можно протестировать.
Кроме того, ваш код не плоский. Под этим я подразумеваю, что он имеет тенденцию иметь больше уровней меньших абстракций. В дизайне сверху вниз люди часто заканчивают большими абстракциями вплоть до какого-то произвольного уровня, а ниже этого уровня вообще нет абстракций. Код, разработанный снизу вверх OTOH, часто содержит менее низкоуровневый контроль и структуры данных, поскольку они, вероятно, будут абстрагированы.
источник
В идеале, написание программы на любом языке, не только на Лиспе, позволяет вам написать целый набор универсальных инструментов, которые могут ускорить выполнение следующей программы или усовершенствовать текущую.
На практике отслеживание этих инструментов может быть затруднено. Документация плохая и неорганизованная, и люди, которые о них знают, уходят. На практике повторное использование кода часто доставляет больше хлопот, чем оно того стоит. Но если код задокументирован и организован должным образом, а программисты остаются (или сохраняют свои запасы полезного кода), можно сэкономить огромный объем работы, извлекая код из хранилища, а не перестраивая его.
Весь дизайн должен быть сверху вниз, иначе вы не знаете, что делаете. Вы строите сарай или машину? Вы не можете понять это с восходящим дизайном. Но если вы собираетесь построить левое переднее колесо, вы можете подумать, что вам может понадобиться больше колес позже, как для этого проекта, так и для других. И если вы построите многоразовое колесо, у вас будет четыре по цене одного. (И 18 для того тракторного прицепа, который вы строите рядом, все бесплатно.)
Обратите внимание, что в отличие от реальных автомобилей и настоящих колес, если вы создали одно программное «колесо», вы создали их бесконечное количество.
Более подробно о дизайне сверху вниз: хотя вы должны начать с этого, я чувствую себя обязанным отметить, что если вы не можете построить колесо, вы должны это выяснить, прежде чем выполнять большую работу над своим автомобилем. Таким образом, вам нужно работать снизу вверх почти параллельно с работой сверху вниз. Кроме того, знание того, что вы можете построить колесо, может предложить множество проектов, о которых вы раньше не думали, например, тягач с прицепом. Я думаю, что подход сверху вниз должен доминировать, но с очень легким оттенком.
Итак, чтобы продолжить перефразировать Пола Грэма, в идеале, когда вы пишете программу, у вас получается много повторно используемых частей, которые могут сэкономить много времени как в исходной программе, так и в других. Чтобы немного дистанцироваться от Пола Грэма, это работает на любом языке (хотя некоторые поощряют процесс больше, чем другие).
Врагом этого почти волшебного процесса являются программисты с очень краткосрочными перспективами. Это может быть вызвано личностными дефектами, но чаще - слишком быстрым переключением должностей и обязанностей как внутри, так и между компаниями-работодателями.
источник
Использование нисходящего подхода с итеративной разработкой не дает никакого рабочего кода на первых итерациях. Он предоставляет проектную документацию и такую информацию, о которой клиенту будет сложно дать отзыв. Ответы типа «да, я думаю (это слишком абстрактно для меня)» не помогут вам в дальнейшем уточнении специфики желаемой системы клиентом.
Вместо этого вы создаете только общий обзор того, что запрашивается. (Требования), чтобы использовать в качестве общего руководства для того, что определяет готовый продукт и что заслуживает приоритет для реализации. После этого вы создаете рабочие продукты для каждой итерации, с которыми клиент может поиграть, чтобы увидеть, имелось ли это в виду. Если нет, то это не будет проблемой, поскольку на разработку системы, которая работает не так, как того требует клиент, не потрачены сотни часов.
Я не буду говорить за другого человека. Также я не читал его эссе. Ответ, который я даю вам, зависит от моего образования и опыта.
Использование этого подхода означает, что вы получите более абстрактные строительные блоки. Просто потому, что вам придется создавать автономные подсистемы, которые могут быть представлены сразу, вы не можете создать нисходящий дизайн, который тесно переплетен и должен быть реализован сразу. Это улучшает возможность повторного использования, ремонтопригодность, но, прежде всего, позволяет более гибко реагировать на изменения.
источник