Справочная информация:
Мы моделируем прошивку для новой встроенной системы.В настоящее время микропрограммное обеспечение моделируется в UML, но возможности генерации кода инструмента моделирования UML не будут использоваться.
Целевым языком будет C (C99, если быть точным).
Низкиймощность (т.е. производительность, быстрое выполнение) и правильность важны, но правильность является главным приоритетом , превыше всего, включая размер кода и скорость выполнения.
При моделировании системы мы 'Мы определили набор четко определенных компонентов.Каждый компонент имеет свой собственный интерфейс, и многие из компонентов взаимодействуют со многими компонентами.
Большинство компонентов в модели будут отдельными задачами (потоками) в операционной системе реального времени (RTOS), хотя некоторые компоненты являются не более чем библиотеками.Задачи общаются друг с другом исключительно посредством передачи сообщений / публикации в очереди.Взаимодействие с библиотеками будет осуществляться в форме синхронных вызовов функций.
Поскольку советы / рекомендации могут зависеть от масштаба, я предоставлю некоторую информацию.Сейчас может быть около 12-15 компонентов, может вырасти до ~ 20?Не сотня компонентов.Скажем, в среднем каждый компонент взаимодействует с 25% других компонентов.
На диаграмме компонентов имеются порты / разъемы, используемые для представления интерфейсов между компонентами, т.е. один компонент обеспечивает то, что требуется другому компоненту.Пока все хорошо.
Вот в чем проблема: во многих случаях мы не хотим, чтобы «Компонент А» имел доступ к всем «Компонентам В»."интерфейс, т. е. мы хотим ограничить компонент A подмножеством интерфейса, предоставляемого компонентом B.
Вопрос / проблема:
Есть ли систематический, довольно простойспособ обеспечить - предпочтительно во время компиляции - контракты интерфейса, определенные на диаграмме компонентов?
Очевидно, что решения во время компиляции предпочтительнее решений во время выполнения (более раннее обнаружение, лучшая производительность, возможно меньший код).
Например, предположим, что компонент библиотеки "B" предоставляет функции X (), Y () и Z (), но я только хочу, чтобы компонент "A" мог вызывать функцию Z (), а неX () и Y ().Точно так же, хотя компонент «А» может быть способен принимать и обрабатывать целое множество различных сообщений через свою очередь сообщений, мы не имеем возможности отправлять какие-либо сообщения любому компоненту.
лучшее, что я мог бы придумать, - это иметь разные заголовочные файлы для каждого интерфейса компонента-компонента и предоставлять только (через заголовочный файл) части интерфейса, которые компоненту разрешено использовать.Очевидно, это может привести к большому количеству заголовочных файлов.Это также означает, что передача сообщений между компонентами будет осуществляться не напрямую с API-интерфейсом ОС, а скорее через вызовы функций, каждый из которых создает и отправляет определенное (разрешенное) сообщение.Для синхронных вызовов / библиотек будет отображаться только разрешенное подмножество API.
В этом упражнении можно предположить, что люди будут вести себя хорошо. Другими словами, небеспокоиться о людях, которые обманывают, обрезают и вставляют прототипы функций напрямую, или включают заголовочные файлы, которые им запрещены.Они не будут напрямую публиковать сообщение от «A» до «B», если оно не разрешено, и так далее ...
Может быть, есть способ обеспечить выполнение контрактов с утверждениями во время компиляции.Может быть, есть более элегантный способ проверить / применить это во время выполнения, даже если это повлечет за собой некоторые накладные расходы.
Код должен будет скомпилировать и аккуратно компилировать, поэтому подход «прототип функции межсетевого экрана» приемлемно кажется, что есть более идиоматический способ сделать это.