Избегание зависимостей увеличивает количество проектов в моем решении VS

Я работаю в C++; Я новичок в Visual Studio и все еще пытаюсь понять, как эффективно его использовать.

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

  • Проект зависит от устройства, поэтому я определил DeviceInterface и у меня есть FakeDevice а также RealDevice реализация интерфейса.
  • Мой основной проект Foo Я написал это статическая библиотека, определенная с помощью DeviceInterface, Foo библиотека не знакома ни с одной из конкретных реализаций.
  • У меня есть несколько тестовых исполняемых файлов, давайте назовем их TestExe1, TestExe2, и так далее. Эти тесты имеют общий код, FooTestUtils,
  • С помощью RealDevice требует некоторой инициализации и демонтажа до и после использования. Это не относится к реализации интерфейса; клиентский код естественно несет ответственность за это.
    • Это означает, что исполняемый тест может работать только с использованием RealDevice если я положу в сильной зависимости от RealDevice и ресурсы init/teardown. Который мне не нужен или не нужен для тестов с использованием Fake.
    • Мое настоящее решение состоит в том, чтобы разделить исполняемые файлы теста - один для FakeDevice другое для RealDevice который выполняет инициализацию, а затем отправляет и вызывает тот же тестовый код.

TL; DR: базовая библиотека Foo, в зависимости от DeviceInterface, который имеет несколько реализаций. Несколько тестовых исполняемых файлов, большинство из которых могут работать с любой реализацией DeviceInterface, но одна из этих реализаций требует дополнительной настройки в клиентском коде.

Это кажется мне разумным уровнем сложности. Но это приводит к такому большому количеству проектов:

  • Статические библиотеки:
    • Foo
    • RealDevice реализация
    • FooTestUtils (примечание: включает в себя FakeDevice реализация)
    • gtest (используется для некоторых испытаний)
    • Библиотека из другого решения, необходимого для RealDevice использование
  • исполняемые:
    • 2 TestExe$i проекты для каждого исполняемого файла теста, который я хочу

В среде *nix, к которой я привык, я бы разделил код на разумное дерево каталогов, и многие из этих "проектов" были бы просто одним объектным файлом или одним.cpp с некоторым клиентским кодом для основная логика.

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

(Опять же, я новичок в Visual Studio, поэтому проблема может заключаться в том, что я не знаю, как управлять несколькими связанными проектами, а не просто количеством самих проектов.)

1 ответ

Решение

Хотя то, что вы делаете, довольно стандартно - и для небольшого проекта, который вы описываете, ваше решение кажется совершенно стандартным. Однако Visual Studio предоставляет некоторые способы минимизировать влияние этих проблем для опытных разработчиков:

build-конфигурации и листы свойств:
Короче, зачем нужен проект для fakeDevice и RealDevice?

Создайте проект для "Устройства", который в зависимости от выбранной конфигурации создает источники fakeDevice или RealDevice. Это также позволяет вам запускать ваш проект в "тестовой" конфигурации и автоматически загружать fakeDevice, при этом выбор "Debug" или "release" предоставит RealDevice.

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

пример из реального мира
Моя компания выпускает плагин для Adobe-Illustrator, существует семь поддерживаемых версий Adobe (каждая со своим собственным SDK), а также 32- и 64-битные варианты, а также дальнейшие сборки отладки и выпуска (и снова удваиваем это до 28+ вариантов, так как есть). две почти идентичные фирменные версии плагина). Мое решение заключается в следующем: Plugin-Solution [Debug][Release] / (win32/x64) Plugin [Debug AI4][Debug AI5][Debug AI6][Debug AI7][Release AI4] [Release AI5][Release AI6][Release AI7] / (win32/x86) {libraries with similar setups...} В своей повседневной работе я просто "нажимаю на воспроизведение" в конфигурации отладки, однако, когда приходит время выпуска (или требуется тестирование конкретной версии), я "Пакетная сборка" - правильная комбинация проектов для отладки или упаковки.

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

тестирование исполняемых файлов
Что касается исполняемых модулей модульного тестирования, я бы порекомендовал создать отдельное решение для них - Visual Studio не имеет проблем с несколькими открытыми одновременно решениями - у меня, однако, есть один совет

Создайте отдельное решение и создайте в нем все свои модульные тесты, затем в основное решение добавьте простой проект "тесты", в его событии после сборки запустите сценарий powershell/batch.

Затем этот сценарий может вызвать набор инструментов MSVCC для решения модульных тестов, а затем запустить тесты, сопоставляя результаты (если вы в правильной конфигурации). Это позволит вам создавать / запускать свои тесты из одного проекта, даже если вам нужно нажать alt+tab для создания нового модульного теста.

Персональный (самоуверенный) совет
Разработанный в системах 'Nix, Windows и Apple, вот хороший метафора макета. "Nix ожидает, что вы создадите свои собственные make-файлы и макет папки, он предполагает, что вы точно знаете, что делаете (в терминале!), И макет станет вашей игрушкой (с достаточным количеством скриптов).
Студия Windows/Visual предназначена для пользователей любого уровня, восьмилетних обучающих программ на Visual Basic или опытного разработчика C++, создающего аппаратные драйверы. Как таковой, интерфейс разработан так, чтобы быть очень расширяемым - "проекты" в "решениях" являются основной идеей (многие начинающие не понимают, что у вас может быть несколько проектов. Однако, если вам нужно больше вариантов, есть один способ сделать это: Что касается MS (в данном случае, конфигураций и таблиц свойств) - если вы пишете make-файл или создаете макет, вы "делаете это неправильно" (в любом случае, на взгляд Microsoft).

Если вы взглянете на то, как за последние несколько лет возникли проблемы с встраиванием в экосистемы окон, вы, как правило, поймете проблему. На 'nix иметь несколько десятков разделяемых библиотек из пакета apt/yum, установленного как зависимость, это нормально! Однако Windows (кажется, что) с несколькими DLL - плохая идея. Там нет менеджера пакетов, так что либо положитесь на.Net, либо поставьте один пакет надстройки вместе с вашим продуктом. (именно поэтому я предпочитаю статические ссылки на окнах).

РЕДАКТИРОВАТЬ:
Когда у вас есть несколько конфигураций, выбор того, что источники делают и не строят для каждого, может быть сделан двумя способами.

один: вручную
Щелкните правой кнопкой мыши по любому исходному файлу в обозревателе решений и выберите свойства. В разделе "Общие" вы можете выбрать "Исключено из сборки" (это работает, если вы выбираете группу и также щелкаете правой кнопкой мыши).

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

Другие вопросы по тегам