Использование директив компилятора для поддержки нескольких платформ - PullRequest
1 голос
/ 26 марта 2011

Это общий вопрос разработки программного обеспечения.

Хорошая ли идея использовать директиву компилятора #if для поддержки нескольких платформ.Например, у меня есть три файла:

IScreen.cs

public interface IScreen {
   ...
}

ScreenWin.cs

#if WIN

public class Screen : IScreen {
  ...
}

#endif

ScreenMac.cs

#if WIN

public class Screen : IScreen {
   ...
}

#endif

Что мне нравится в этом, так это то, что я могу использовать BDD и иметь что-то вроде:

Given a Screen exists with width: 1920 and height: 1080

, и будет использоваться правильный экран на основе директивы компилятора.

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

Каковы некоторые недостатки?

Ответы [ 2 ]

2 голосов
/ 27 марта 2011

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

Еще одним недостатком #if является то, что многие инструменты Visual Studio рассматривают только «текущий активный» код. Например, средства Intellisense и инструменты рефакторинга - если вы захотите переименовать IScreen в IDisplay, то вы обнаружите, что рефакторинг сработал, и весь код вашего ПК был обновлен безупречно, но весь ваш код Mac был бы сильно поврежден, поскольку инструменты рефакторинга просто не смогли бы » смотрите "другую ветку кода". Точно так же легко внести изменения в код в ветке ПК и забыть внести соответствующее изменение в ветку Mac, снова нарушив его.

Преимущество фабрики вместо "#if" заключается в том, что один двоичный образ потенциально может быть запущен на каждой платформе, и вам нужно проверять платформу хоста только один раз при создании конкретной реализации (так что она все еще очень эффективна в время выполнения, но будет больше, поскольку вам нужно будет отправить все варианты платформы в одном дистрибутиве)

Однако, можно получить лучшее из обоих миров, используя более модульный шаблон проектирования вместо #if: используйте спутниковую сборку для реализаций для конкретной платформы. При таком подходе основной код приложения будет указывать интерфейс IScreen , и тогда у вас будут классы Concrete Screen (Mac) и Screen (PC) в отдельных зависящих от платформы вариантах Сборка ScreenImplementation.dll. Вы также можете отправить один установщик, который охватывает все платформы (просто развернув соответствующий сателлитный dll для хост-платформы). Это дает вам незначительное улучшение эффективности / размера при использовании #if, но без необходимости путать ваш код с условными выражениями. (Конечно, этот модульный подход имеет смысл как для конструкций #if, так и для Factory - они становятся скорее вариантом развертывания, чем архитектурой базовой реализации, когда вы разделяете реализации для конкретной платформы на отдельные сборки)

1 голос
/ 26 марта 2011

Недостатки включают необходимость компилировать несколько двоичных файлов - по одному на платформу.

Если не соблюдать осторожность, вы можете загромождать ваш код директивой препроцессора во многих частях кода. См. этот ТАК вопрос об изменении одной такой кодовой базы.

Если вы можете обнаружить платформу в коде, это лучший подход.

...