Опасности огромного монолитного применения


20

Большой проект, над которым я работаю уже пару лет, - это приложение для управления (и все остальное) продвинутого устройства, сердце его прошивки.

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

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

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

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

Но с другой стороны, размер, масштаб этой штуки меня просто пугают, это похоже на пилотирование Титаника. Меня всегда учили модульности, и объединение всего в один гигантский файл кажется неправильным. Одна проблема, которую я знаю, это серьезный сбой одного (даже незначительного) модуля, который дает сбой всем, но качество кода гарантирует, что этого не произойдет в выпусках. Иначе, внутреннее разделение и защитное программирование гарантируют, что это все еще будет работать в основном правильно, даже если половина внутренних модулей по какой-либо причине обычно выходит из строя.

Какие еще опасности я упустил из виду? Почему это меня пугает? Это просто иррациональный страх неизвестного? Является ли создание серьезных крупных проектов таким способом принятой практикой? Либо успокойте мои страхи, либо дайте мне вескую причину для реорганизации версии 2.0 в несколько меньших двоичных файлов.


7
Если солнце встанет слишком рано, Англия уйдет в море.
Макс

1
Или давление в ядре Земли немного возрастает.
StuperUser

1
@Maxpm Я вижу, что ты там делал ... xkcd.com/687
teto

3
@Maxpm: К счастью, наше приложение не управляет восходами и закатами. Мы верим, что принцесса Селестия не подведет на работе.
SF.

1
@ rwong: 1. Устройство остановлено для обновлений. Несмотря на то, что обновления будут действовать на лету, мы не хотим никаких неожиданных результатов, если обновление по какой-либо причине пойдет не так. 2. Одноядерный ARM9 со встроенным Linux. Есть второй, контролирующий ЦП, работающий без ОС, проверяющий, что основной ЦП производит нормальный вывод.
SF.

Ответы:


5

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

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

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


Спасибо - никакие «лучшие практики, которым нужно следовать / пожертвовать» и «взвешивание потенциальных выгод по сравнению с потенциальными недостатками», никогда не будут такими полезными, как кто-то из первых рук с другой стороны забора.
SF.

23

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

Вы сказали это сами - это вполне ремонтопригодно, хорошо модульно ...

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

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

Какие еще опасности я упустил из виду? Почему это меня пугает? Это просто иррациональный страх неизвестного? Является ли создание серьезных крупных проектов таким способом принятой практикой? Либо успокойте мои страхи, либо дайте мне вескую причину для реорганизации версии 2.0 в несколько меньших двоичных файлов.

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

Если бы вы переписали его, вы бы сделали то же самое, но в то же время испортили бы его для всех тех, кто привык к предыдущей организации кода. Таким образом, только вы должны «адаптироваться».


16

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

Наличие набора тестов улучшит ваше понимание приложения и сообщит вам, когда изменение в приложении что-то нарушает.


2
Но это относится к обеим возможным архитектурам ...
SF.

3
Да, это так ...
Роберт Харви

10
... и поэтому этот ответ не добавляет ничего к обсуждению, кроме как для продвижения модульного тестирования.
Бензадо

2
@benzado: Что в сценарии ОП имеет первостепенное значение.
Роберт Харви

2
@ironcode: взгляните на книгу типа «Эффективная работа с устаревшим кодом». Первое, что он говорит в этой книге: «Если у вас уже нет набора модульных тестов с высоким охватом кода, сначала напишите их, прежде чем делать что-либо еще». Я бы сказал, что этот совет более чем уместен здесь, учитывая, что ОП конкретно спросил: «Какие еще опасности я упустил из виду?»
Роберт Харви

8

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

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

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

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

Вынуждение сбоя при необходимости также проще с монолитным исполняемым файлом.


1
+1, инженерия - это компромиссы, меньшие двоичные файлы тоже имеют свою стоимость
benzado

+1 Я согласен от всего сердца. Там нет конкретной причины, чтобы гарантировать несколько исполняемых файлов. Связь и координация между исполняемыми файлами имеет свою цену.
Эрик Робертсон

+1: если ничего не сломано, не чините.
Боб Мерфи

1

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

Как только это происходит, тестирование становится кошмаром, и вы уже на пути к моральному старению.

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

Вы действительно хотите иметь хорошие тесты на месте, хотя.


1

В идеале ответ - да. Наличие нескольких двоичных файлов может сделать его более стабильным ....

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

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

Было бы разумно двигаться вперед, помещая новые фрагменты кода в свои собственные двоичные файлы, но, вероятно, возвращение и рефакторинг не стоит вашего времени.


1

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

Если вы используете разные процессы, вы, по крайней мере, не используете одну и ту же кучу или стек вызовов, и также может быть проще перезапустить один подпроцесс.

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

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

Это, как говорится, это, вероятно, сложная задача.

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


Вы очень много думаете об аппаратном обеспечении и среде ОС, особенно когда речь идет о встроенном программном обеспечении и встроенных устройствах.
Патрик Хьюз

0

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.