Другой способ спросить это; почему программы имеют тенденцию быть монолитными?
Я думаю о чем-то вроде пакета анимации, такого как Maya, который люди используют для различных рабочих процессов.
Если бы возможности анимации и моделирования были разделены на их собственное отдельное приложение и разрабатывались отдельно, а файлы передавались между ними, разве им было бы легче поддерживать?
If the animation and modelling capabilities were split into their own separate application and developed separately, with files being passed between them, would they not be easier to maintain?
Не смешивайте, проще расширять с более легким в обслуживании модулем - ведь он не свободен от сложностей или сомнительных конструкций. Майя может быть адом на земле, чтобы поддерживать, в то время как его плагины - нет. Или наоборот.Ответы:
Да. Как правило, два меньших менее сложных приложения гораздо легче поддерживать, чем одно большое.
Однако вы получаете новый тип ошибки, когда все приложения работают вместе для достижения цели. Чтобы заставить их работать вместе, они должны обмениваться сообщениями, и эта оркестровка может идти не так, как надо, даже если каждое приложение может работать отлично. Наличие миллиона крошечных приложений имеет свои особые проблемы.
Монолитное приложение - это действительно вариант по умолчанию, с которым вы сталкиваетесь, когда добавляете все больше и больше функций в одно приложение. Это самый простой подход, когда вы рассматриваете каждую функцию отдельно. Только после того, как оно станет большим, вы можете посмотреть на все и сказать: «Вы знаете, что, это будет работать лучше, если мы отделим X и Y».
источник
Вещи редко так просты в реальности.
Разделение, безусловно, не помогает предотвратить эти ошибки в первую очередь. Иногда это может помочь найти ошибки быстрее. Приложение, которое состоит из небольших изолированных компонентов, может позволить проводить более индивидуальные (своего рода «единичные» -) тесты для этих компонентов, что иногда облегчает выявление первопричины определенных ошибок и, таким образом, позволяет быстрее их устранять.
Тем не мение,
даже приложение, которое кажется монолитным снаружи, может состоять из множества компонентов, проверяемых модулем, поэтому модульное тестирование не обязательно сложнее для монолитного приложения.
Как уже упоминал Эван, взаимодействие нескольких компонентов создает дополнительные риски и ошибки. А отладка прикладной системы со сложным межпроцессным взаимодействием может быть значительно сложнее, чем отладка однопроцессного приложения.
Это также во многом зависит от того, насколько хорошо крупное приложение может быть разделено на компоненты, и насколько широки интерфейсы между компонентами и как эти интерфейсы используются.
Короче говоря, это часто компромисс, и ничего, где ответ «да» или «нет» не является правильным в целом.
Они? Посмотрите вокруг, в мире есть миллионы веб-приложений, которые не выглядят для меня монолитными, как раз наоборот. Есть также много доступных программ, которые предоставляют модель плагина (AFAIK, даже программное обеспечение Maya, которое вы упомянули).
«Упрощение обслуживания» здесь часто происходит из-за того, что разные группы могут легче разрабатывать различные части приложения, что обеспечивает лучшую распределенную нагрузку, специализированные группы с более четкой ориентацией и т. Д.
источник
Я должен не согласиться с большинством в этом. Разделение приложения на два отдельных компонента само по себе не делает код более легким в обслуживании или обдумывании.
Разделение кода на два исполняемых файла просто меняет физическую структуру кода, но это не главное. От того, насколько сложным является приложение, зависит то, насколько тесно связаны различные составляющие его приложения. Это не физическое свойство, а логическое .
У вас может быть монолитное приложение с четким разделением различных задач и простых интерфейсов. Вы можете иметь микросервисную архитектуру, которая опирается на детали реализации других микросервисов и тесно связана со всеми остальными.
Что действительно верно, так это то, что процесс разделения одного большого приложения на более мелкие очень полезен при попытке установить четкие интерфейсы и требования для каждой части. В DDD говорите, что подходили бы к вашим ограниченным контекстам. Но если вы затем создадите множество крошечных приложений или одно большое с такой же логической структурой, это скорее техническое решение.
источник
Легче поддерживать, когда вы закончите их разделять, да. Но разделить их не всегда легко. Попытка разбить часть программы на многократно используемую библиотеку показывает, где разработчики оригинала не задумывались о том, где должны быть швы . Если одна часть приложения проникает глубоко в другую часть приложения, это может быть трудно исправить. Разрыв швов заставляет вас более четко определять внутренние API-интерфейсы, и это в конечном итоге облегчает поддержку базы кода. Возможность повторного использования и ремонтопригодности являются продуктами четко определенных швов.
источник
Важно помнить, что корреляция - это не причинно-следственная связь.
Строительство большого монолита с последующим разделением его на несколько мелких частей может привести к хорошему дизайну или не привести к нему. (Это может улучшить дизайн, но это не гарантировано.)
Но хороший дизайн часто приводит к тому, что система строится в виде нескольких небольших частей, а не большого монолита. (Монолит может быть лучшим дизайном, просто гораздо менее вероятно.)
Почему мелкие детали лучше? Потому что их легче рассуждать. И если о правильности рассуждать легко, вы, скорее всего, получите правильный результат.
Чтобы процитировать CAR Hoare:
Если это так, зачем кому-то строить излишне сложное или монолитное решение? Хоар дает ответ в следующем предложении:
А позже в том же источнике (лекция премии Тьюринга 1980 года):
источник
Это не вопрос с ответом да или нет. Вопрос не только в простоте обслуживания, но и в вопросе эффективного использования навыков.
Как правило, хорошо написанное монолитное приложение является эффективным. Межпроцессное взаимодействие между устройствами не дешево. Разбиение одного процесса снижает эффективность. Однако выполнение всего на одном процессоре может привести к перегрузке процессора и снижению производительности. Это основная проблема масштабируемости. Когда сеть входит в картину, проблема становится более сложной.
Хорошо написанное монолитное приложение, которое может эффективно работать как один процесс на одном сервере, может быть легко обслуживаемым и не содержать дефектов, но все же не может эффективно использовать навыки кодирования и архитектуры. Первый шаг - разбить процесс на библиотеки, которые по-прежнему выполняются как один и тот же процесс, но кодируются независимо, следуя принципам сплоченности и слабой связи. Хорошая работа на этом уровне улучшает ремонтопригодность и редко влияет на производительность.
Следующий этап - разделить монолит на отдельные процессы. Это сложнее, потому что вы входите в хитрую территорию. Легко ввести ошибки состояния гонки. Затраты на связь возрастают, и вы должны быть осторожны с «болтливыми интерфейсами». Награды велики, потому что вы преодолеваете барьер масштабируемости, но увеличивается вероятность появления дефектов. Многопроцессные приложения легче поддерживать на уровне модулей, но в целом система более сложна и ее сложнее устранить. Исправления могут быть чертовски сложными.
Когда процессы распределяются по отдельным серверам или в облачной реализации, проблемы становятся сложнее, а выгоды - больше. Масштабируемость взлетает. (Если вы рассматриваете облачную реализацию, которая не дает масштабируемости, задумайтесь.) Но проблемы, которые возникают на этом этапе, могут быть невероятно трудными для выявления и анализа.
источник
Нет . это не облегчает обслуживание. Во всяком случае, добро пожаловать в новые проблемы.
Почему?
Теперь у вас есть два продукта, которые нужны:
Теперь у вас есть три потребительских рынка: модельеры, аниматоры и аниматоры модельеров
При том, что меньшие базы кода проще поддерживать на уровне приложений, вы просто не получите бесплатный обед. Это та же проблема, которая лежит в основе Micro-Service / Any-Modular-Architecture. Это не панацея, сложность обслуживания на уровне приложения обменивается на сложности обслуживания на уровне оркестровки. Эти проблемы все еще остаются проблемами, их просто больше нет в кодовой базе, их нужно либо избегать, либо решать.
Если решение проблемы на уровне оркестровки проще, чем решение на каждом уровне приложения, то имеет смысл разделить ее на две базы кода и заняться проблемами оркестровки.
Иначе нет, просто не делайте этого, вы бы лучше обслуживали, улучшая внутреннюю модульность самого приложения. Разместите фрагменты кода в связные и простые в обслуживании библиотеки, для которых приложение выступает в качестве плагина. В конце концов, монолит - это просто слой оркестровки библиотечного ландшафта.
источник
Было много хороших ответов, но так как там почти мертвый раскол, я тоже брошу свою шляпу на ринг.
По своему опыту инженера-программиста я обнаружил, что это не простая проблема. Это действительно зависит от размера , масштаба и цели приложения. Старые приложения в силу инерции, необходимой для их изменения, как правило, являются монолитными, поскольку это было обычной практикой в течение длительного времени (Майя подходила бы для этой категории). Я предполагаю, что вы говорите о новых приложениях в целом.
В достаточно небольших приложениях, которые более или менее одинаковы, накладные расходы, необходимые для обслуживания многих отдельных частей, обычно превышают полезность разделения. Если он может поддерживаться одним человеком, он может быть сделан монолитным, не вызывая слишком много проблем. Исключением из этого правила является случай, когда у вас есть много разных частей (фронтенд, бэкэнд, возможно, несколько слоев данных между ними), которые удобно разделены (логически).
В очень больших приложениях даже одной задачи разделение на части имеет смысл в моем опыте. Вы можете уменьшить подмножество возможных классов ошибок в обмен на другие (иногда более простые для устранения) ошибки. В целом, у вас также могут быть группы людей, работающих изолированно, что повышает производительность. Многие приложения в наши дни, однако, делятся довольно хорошо, иногда в ущерб себе. Я также участвовал в командах, где приложение было излишне разделено на множество микросервисов, что создавало много накладных расходов, когда вещи перестали общаться друг с другом. Кроме того, необходимость хранить все знания о том, как каждая часть общается с другими частями, становится намного сложнее с каждым последующим разделением. Существует баланс, и, как вы можете судить по ответам здесь, способ сделать это не очень ясно,
источник
Для приложений пользовательского интерфейса маловероятно, что общее количество ошибок уменьшится, но сдвинет баланс ошибок в сторону проблем, вызванных коммуникацией.
Говоря о пользовательских интерфейсных приложениях / сайтах - пользователи крайне не терпеливы и требуют небольшого времени отклика. Это превращает любые задержки связи в ошибки. В результате можно торговать потенциальным уменьшением ошибок из-за уменьшенной сложности одного компонента с очень жесткими ошибками и требованием синхронизации межпроцессного / межмашинного взаимодействия.
Если единицы данных, с которыми работает программа, большие (то есть изображения), то любые задержки между процессами будут длиннее и труднее устранить - что-то вроде «применить преобразование к 10 МБ изображению» мгновенно получит + 20 МБ дискового / сетевого ввода-вывода в дополнение 2 преобразования из формата в памяти в сериализованный формат и обратно. На самом деле вы мало что можете сделать, чтобы скрыть время, необходимое для этого от пользователя.
Кроме того, любая коммуникация, особенно дисковый ввод-вывод, подлежит проверкам Антивирусом / Брандмауэром - это неизбежно добавляет еще один слой, который трудно воспроизвести, и еще больше задержек.
Расщепление монолитной «программы» светит там, где задержки связи не являются критическими или уже неизбежны
Обратите внимание, что это относится как к настольным приложениям, так и к веб-сайтам - часть программы, обращенная к пользователю, имеет тенденцию быть «монолитной» - весь код взаимодействия с пользователем, привязанный к одному фрагменту данных, обычно выполняется в одном процессе (это не является необычным для разделения обрабатывает на основе отдельных данных, таких как HTML-страница или изображение, но это ортогонально этому вопросу). Даже для большинства базовых сайтов с пользовательским вводом вы увидите, что логика проверки работает на стороне клиента, даже если сделать ее на стороне сервера более модульной и снизить сложность / дублирование кода.
источник
Предотвращать? Ну нет, не совсем.
А именно, все ошибки, о которых вы даже не подозревали, которые вы обнаружили только тогда, когда пытались разбить весь этот беспорядок на более мелкие части. Таким образом, в некотором смысле, это предотвратило появление этих ошибок в производстве - но ошибки уже были.
Ошибки в монолитных приложениях могут повредить всю систему и вообще не дать пользователю взаимодействовать с вашим приложением. Если вы разделите это приложение на компоненты, большинство ошибок - по дизайну - затронут только один из компонентов.
Если вы хотите, чтобы взаимодействие с пользователем оставалось неизменным, вам нужно будет включить новую логику для взаимодействия всех этих компонентов (через службы REST, через системные вызовы ОС, что у вас есть), чтобы они могли беспрепятственно взаимодействовать с POV пользователя.
В качестве простого примера: ваше монолитное приложение позволяет пользователям создавать модели и анимировать их, не выходя из приложения. Вы разделяете приложение на два компонента: моделирование и анимация. Теперь ваши пользователи должны экспортировать модель приложения моделирования в файл, затем найти файл и затем открыть его с помощью приложения анимации ... Посмотрим правде в глаза, некоторым пользователям это не понравится, поэтому вы должны включить новую логику для приложение для моделирования для экспорта файла иавтоматически запустите приложение анимации и откройте файл. И эта новая простая логика может содержать множество ошибок, касающихся сериализации данных, доступа к файлам и разрешений, пользователей, меняющих путь установки приложений и т. Д.
Когда вы решаете разделить монолитное приложение на более мелкие компоненты, вы (надеюсь) делаете это с гораздо большим знанием и опытом работы с системой, чем когда она была впервые разработана, и благодаря этому вы можете применить ряд рефакторингов для создания кода. чище, проще, эффективнее, эластичнее, безопаснее. И этот рефакторинг может, в некотором смысле, помочь предотвратить ошибки. Конечно, вы можете также применить тот же рефакторинг к монолитному приложению, чтобы предотвратить те же ошибки, но вы не делаете этого, потому что это настолько монолитно, что вы боитесь прикоснуться к чему-либо в пользовательском интерфейсе и нарушить бизнес-логику ¯ \ _ (ツ) _ / ¯
Поэтому я бы не сказал, что вы предотвращаете ошибки, просто разбивая монолитное приложение на более мелкие компоненты, но вы действительно облегчаете достижение точки, в которой ошибки можно легче предотвратить.
источник