Во многих встроенных приложениях существует компромисс между тем, чтобы сделать код очень эффективным или изолировать код от конкретной конфигурации системы, чтобы быть невосприимчивым к изменяющимся требованиям.
Какие типы C-конструкций вы обычно используете для достижения лучшего из обоих миров (гибкость и реконфигурируемость без потери эффективности)?
Если у вас есть время, пожалуйста, продолжайте читать, чтобы точно понять, о чем я говорю.
Когда я разрабатывал встроенное ПО для контроллеров подушек безопасности, у нас была проблема, заключающаяся в том, что нам приходилось менять некоторые части кода каждый раз, когда заказчик передумал в отношении конкретных требований. Например, комбинация условий и событий, которые могли бы вызвать срабатывание подушки безопасности, менялась каждые две недели во время разработки. Мы ненавидели так часто менять этот кусок кода.
В то время я присутствовал на конференции по встраиваемым системам и услышал блестящую презентацию Стивена Меллора под названием «Как справиться с изменяющимися требованиями». Вы можете прочитать статью здесь (они регистрируют вас, но это бесплатно).
Основная идея этого заключалась в том, чтобы реализовать поведение ядра в вашем коде, но сконфигурировать конкретные детали в форме данных. Данные - это то, что вы можете легко изменить, и они могут даже программироваться в EEPROM или другом разделе флэш-памяти.
Эта идея звучала замечательно, чтобы решить нашу проблему. Я поделился этим со своим коллегой, и мы сразу же приступили к переработке некоторых модулей программного обеспечения.
При попытке использовать эту идею в нашем коде мы столкнулись с некоторыми трудностями в реальной реализации. Наши конструкции кода стали ужасно тяжелыми и сложными для встроенной системы с ограниченными возможностями.
Чтобы проиллюстрировать это, я остановлюсь на примере, который я упомянул выше. Вместо того, чтобы иметь кучу операторов if, чтобы решить, находилась ли комбинация входов в состоянии, которое требовало развертывания подушки безопасности, мы перешли на большую таблицу таблиц. Некоторые из условий не были тривиальными, поэтому мы использовали много указателей на функции, чтобы иметь возможность вызывать множество маленьких вспомогательных функций, которые каким-то образом решали некоторые из условий. У нас было несколько уровней косвенности, и все стало трудно понять. Короче говоря, мы использовали много памяти, времени выполнения и сложность кода. Отладка не была простой. Босс заставил нас изменить некоторые вещи обратно, потому что модули становились слишком тяжелыми (и он, возможно, был прав!).
PS: Есть такой же вопрос в SO, но похоже, что фокус другой. Адаптация к меняющимся требованиям бизнеса?