распутывание .h зависимостей - PullRequest
4 голосов
/ 07 июня 2009

Что вы делаете, когда у вас есть набор файлов .h, который стал жертвой классической ситуации 'Гордиев узел', где #include один .h означает, что вы в конечном итоге включили почти весь лот? Профилактика, безусловно, лучшее лекарство, но что вы делаете, когда это произошло до того, как продавец (!) Отправил библиотеку?

Вот расширение вопроса, и, возможно, это более уместный вопрос - следует вы даже пытаетесь сначала распутать зависимости ?;

Ответы [ 4 ]

4 голосов
/ 07 июня 2009

Я сделал это на базе кода C ++, которая уже была разбита на множество библиотек (что было хорошим началом).

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

Я по очереди посмотрел на каждый модуль (* .cpp файлы) и удостоверился, что его собственный заголовок был сначала #included и закомментировал остальные, затем я закомментировал все #include в этом заголовочном файле и затем перекомпилировал просто этот модуль, чтобы позволить компилятору сказать мне, что было нужно. Я бы откомментировал первый заголовок, который показался мне необходимым, и пересмотрел его, повторяя при необходимости. Было интересно посмотреть, сколько заголовков оказалось ненужным.

Если требуется только имя (поскольку у вас есть указатель или ссылка), используйте class name; или struct name;, что называется предварительным объявлением, и избегайте #include заголовочного файла.

Компилятор очень полезен, чтобы рассказать вам, каковы зависимости, когда вы закомментируете #includes (вам нужно перекомпилировать с ВСЕМИ компиляторами, которые вам нужны для поддержки переносимости).

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

1 голос
/ 07 июня 2009

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

Недостатком, который я обнаружил, была условная компиляция. Кто-то может удалить заголовочный файл, потому что он думает, что он нам не нужен, но оказывается, что он нам не нужен, потому что у VxWorks есть некоторые испорченные заголовки ... в Solaris (или любой разумной системе Posix), которая вам нужна это.

1 голос
/ 07 июня 2009

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

Другой вариант - использовать #defines для включения и выключения разделов. Независимо от этого, для существующей кодовой базы решение состоит в том, чтобы перейти к единству пакета.

Читайте: http://ivanov.files.wordpress.com/2007/02/sedpackages.pdf и вопросы исследования, связанные с сцеплением упаковки.

0 голосов
/ 08 июня 2009

Необходимо соблюдать баланс между огромным количеством прекрасно организованных заголовков и одним заголовком, который включает в себя все. Рассмотрим стандартную библиотеку C; Есть некоторые большие заголовки, такие как <stdio.h>, которые объявляют множество функций, но все они связаны с вводом / выводом. Есть и другие заголовки, которые больше похожи на сборник - особенно <stdlib.h>.

Руководства Центра космических полетов им. Годдарда для Си стоят того, чтобы их выследить.

Основное правило заключается в том, что каждый заголовок должен объявлять средства, предоставляемые подходящим (обычно небольшим) набором исходных файлов. Средства и заголовок должны быть автономными. То есть, если кому-то нужен код в заголовке "something.h", то это должен быть единственный заголовок, который необходимо добавить в компиляцию. Если "something.h" необходимы средства, которые не объявлены в заголовке, то он должен включать соответствующие заголовки. Это может означать, что заголовки в конечном итоге включают <stddef.h>, потому что одна из функций использует, например, size_t.

Как указывает @quamrana, вы можете использовать предварительные объявления для структур (не для классов, поскольку вопрос помечен как C, а не C ++), когда это уместно, что в первую очередь означает, что интерфейс принимает указатели и ему не нужно знать размер структуры или любой из членов.

...