Насколько проекты должны быть независимы друг от друга?
У меня есть очень большое решение Visual Studio, в котором все проекты зависят друг от друга. Я не могу взять один проект из решения и добавить его в другое решение на другом компьютере, потому что все они связаны друг с другом.
Я правильно все делаю?
Например;
Рассмотрим эти три моих проекта (пары «Дисковый файл», «Конвертер данных» и «Math — .h» и «.cpp» — это классы C ++; я упомяну их под соответствующим именем):
The Solution
|
|---- Disk File
| |
| |---- BinaryFile.h, BinaryFile.cpp
| |---- TextFile.h, TextFile.cpp
|
|---- Data Converter
| |
| |---- Utf8.h, Utf8.cpp
| |---- XmlParser.h, XmlParser.cpp
| |---- StringFormatter.h, StringFormatter.cpp
|
|---- Math
|
|---- Plotter2D.h, Plotter2D.cpp
|---- Matrix.h, Matrix.cpp
TextFile
использования Utf8
для кодировки символов. Что делает Disk File
зависит от Data Converter
, XmlParser
использования TextFile
, Что делает Data Converter
зависит от Disk File
, Plotter2D
использования TextFile
для сброса некоторых данных для использования с внешним программным обеспечением, и Matrix
использует некоторые инструменты форматирования строки в его ::ToString()
метод. Что делает Math
зависит от обоих Disk File
а также Data Converter
,Это просто пример зависимости между несколькими классами. На самом деле, у меня гораздо больше файлов в моем решении. Это полный беспорядок кодовых зависимостей.
Я начну проект с одним из моих друзей. Ему нужен мой Math
проект в своем решении. Но ему будет нелегко адаптировать его к собственному решению, потому что это даст много ошибок компилятора в отношении этих зависимостей.
Это количество зависимостей нормально? Я делаю это правильно? Как насчет того, чтобы хранить копии всех общих файлов в каждом проекте, в котором они нужны (это может быть глупо, я просто спрашиваю об этом)?
Мне нужны ваши предложения.
Такие зависимости всегда будут, но вы можете избежать их, используя некоторые методы:
чтобы сохранить .h файлы независимыми, не включая межмодульные заголовки, вместо этого используйте там предварительное объявление и используйте фактические заголовочные файлы в .cpp файлах.
Чтобы перечисления, определенные в других заголовках, передавались в функцию, можно использовать указатели void для передачи и проверки значения в файлах .cpp.
Также вы можете использовать функции «extern C».
Управление зависимостями обычно является сложной проблемой. Главное, что вы уже поняли, заключается в том, что зависимости должны создавать ациклический граф.
Кроме того, вы должны постараться максимально разорвать зависимости. Например, делает XmlParser
очень нужно TextFile
? Или может приложение, которое хочет проанализировать текстовый файл, создать последний, прочитать содержимое в строку и передать его XmlParser
? Если вам удастся до второго, то XmlParser
больше не зависит от TextFile
,
Еще одна вещь, чтобы рассмотреть это тип зависимости, которую вы создаете. Используя тот же пример, TextFile
используется в общедоступном интерфейсе XmlParser
? Это нужно использовать там? Если XmlParser
зависит от TextFile
вам нужно будет связать библиотеку, если она является частью интерфейса, то пользователи XmlParser
придется включать заголовки TextFile
создавая высшую связь. В этом случае вы можете, например, передать имя файла XmlParser
вместо TextFile
удалить зависимость от интерфейса.
В конце концов, это немного искусства. Сосредоточьтесь на том, чтобы иметь как можно меньшее количество зависимостей, и для тех, которые требуются, постарайтесь сделать соединение минимальным.
Другое дело, математическая библиотека. Я бы сломал зависимость TextFile
, Дополнительные функции могут быть предоставлены в отдельной библиотеке, которая обрабатывает сериализацию математических компонентов. Это позволило бы пользователям Math
которые не требуют резервного копирования файлов, чтобы не зависеть от TextFile
составная часть.
Лучшим подходом было избежать цикла зависимости между проектами, в вашем случае классы утилит, такие как «Дисковый файл» и «Конвертер данных», могли существовать в одном проекте, и вы можете использовать пространства имен для обеспечения модульности.
И чтобы иметь представление о ваших зависимостях, рекомендуется использовать такие инструменты, как Doxygen или же CppDepend чтобы обнаружить все зависимости между вашими проектами и, возможно, выиграть время при поиске всех зависимостей, необходимых для конкретной функции, которую вы хотите дать своему другу.