Что лучший способ состоит в том, чтобы создать варианты того же приложения C/C++

Изменение атрибута

[ForeignKey("id")]
public virtual ICollection<SerStaHis> SerStaHis{ get; set; }

на

[ForeignKey("service_id")]
public virtual ICollection<SerStaHis> SerStaHis{ get; set; }

ForeignKey работает по-разному при применении к свойству FK, свойству навигационной ссылки и свойству навигации по коллекции. При применении к свойству навигации по коллекции оно задает имя свойства FK связанного с объекта объекта.

Я лично нахожу ForeignKey атрибут запутанным и подверженным ошибкам. Свободный API намного более интуитивен и обеспечивает намного лучший контроль. Свободная конфигурация для вашего сценария выглядит следующим образом:

modelBuilder.Entity<Ser>()
    .HasMany(ser => ser.SerStaHis) // collection navigation property
    .WithOne() // no reference navigation property
    .HasForeignKey(serStaHis => serStaHis.service_id); // foreign key property
6
задан Brian Tompsett - 汤莱恩 3 February 2016 в 10:15
поделиться

11 ответов

Необходимо не всегда вызывать отношения наследования в приложениях, которые совместно используют общую кодовую базу.В самом деле.

Существует старый прием UNIX, где Вы адаптируете поведение Вас приложение на основе argv [0], т.е., имя приложения. Если я вспоминаю правильно (и это были 20 лет, с тех пор как я посмотрел на него), rsh, и rlogin являются той же командой. Вы просто реализовываете конфигурацию во время выполнения на основе значения argv [0].

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

#define APP_A 1
#define APP_B 2

#ifndef APP_CONFIG
#error "APP_CONFIG needs to be set
#endif

#if APP_CONFIG == APP_A
#define APP_CONFIG_DEFINED
// other defines
#endif

#if APP_CONFIG == APP_B
#define APP_CONFIG_DEFINED
// other defines
#endif

#ifndef APP_CONFIG_DEFINED
#error "Undefined configuration"
#endif

Этот шаблон осуществляет это, конфигурация является определенной командной строкой и действительна.

12
ответ дан 8 December 2019 в 04:10
поделиться

То, что Вы пытаетесь сделать, кажется очень похожим на "Линейки продуктов". Университет Дыни Carnigie имеет превосходную страницу на шаблоне здесь: http://www.sei.cmu.edu/productlines/

Это - в основном способ создать различные версии одной части программного обеспечения с различными возможностями. Если Вы предполагаете, что чему-то нравится, Ускоряются Домой/Pro/Бизнес затем, Вы на правильном пути.

В то время как это не может быть точно, что Вы попытка, методы должны быть полезными.

7
ответ дан 8 December 2019 в 04:10
поделиться

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

Затем управляйте, которые из этих частей входят в сборку, которой заголовочные файлы используются в компиляции верхнего уровня и какие .obj файлы Вы включаете в фазу компоновщика.

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

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

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

Это - та же игра, используете ли Вы классы C++ или действуете в значительной степени на общеязыковом уровне C/C++.

2
ответ дан 8 December 2019 в 04:10
поделиться

При использовании C++ не был должен A, B, и приложения C наследовались от общего предка? Это было бы OO способ решить проблему.

1
ответ дан 8 December 2019 в 04:10
поделиться

Можно также найти некоторую справку в этой подобной, которую я спросил: Запись межплатформенных приложений в C

1
ответ дан 8 December 2019 в 04:10
поделиться

Проблема состоит в том, что с помощью #if директивы с именем это - неопределенные действия, как будто это определяется как 0. Этого можно было избежать, всегда делая #ifdef сначала, но это является и громоздким и подверженным ошибкам.

Немного лучший путь состоит в том, чтобы использовать искажение пространства имен и пространство имен.

Например.

namespace AppA {
     // application A specific
}

namespace AppB {
    // application B specific
}

И используйте Вас app_defines.h, чтобы сделать искажение пространства имен

#if compiler_option_for_appA
     namespace Application = AppA;
#elif compiler_option_for_appB
     namespace Application = AppB;
#endif

Или, если более сложные комбинации, вложение пространства имен

namespace Application
{
  #if compiler_option_for_appA
     using namespace AppA;
  #elif compiler_option_for_appB
     using namespace AppB;
  #endif
}

Или любая комбинация вышеупомянутого.

Преимущество состоит в том, что, когда Вы забываете заголовок, Вы получите неизвестные ошибки пространства имен из своего компилятора i.s.o. тихого сбоя, потому что ПРИЛОЖЕНИЕ принято значение по умолчанию к 0.

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

Это работает немного лучше в моем opionon, но я знаю, что это, оказывается, очень специализировано, YMMV.

1
ответ дан 8 December 2019 в 04:10
поделиться

Сделайте что-то вроде этого:


CommonApp   +-----   AppExtender                        + = containment
                      ^    ^    ^
                      |    |    |                       ^ = ineritance
                    AppA  AppB  AppC                    |

Поместите свой общий код в класс CommonApp и поместите вызовы в интерфейс 'AppExtender' в стратегических местах. Например, интерфейс AppExtender будет иметь функции как afterStartup, afterConfigurationRead, beforeExit, getWindowTitle...

Затем в основном каждого приложения, создайте корректный расширитель и передайте его CommonApp:


    --- main_a.cpp

    CommonApp application;
    AppA appA;
    application.setExtender(&appA);
    application.run();

    --- main_a.cpp

    CommonApp application;
    AppB appB;
    application.setExtender(&appB);
    application.run();
1
ответ дан 8 December 2019 в 04:10
поделиться

Однако я выстрелил себе в ногу этим утром и пропал впустую далеко к большому количеству времени путем простого исключения строки к #include "app_defines.h" из одного файла. Все скомпилировало прекрасный, но приложение, разрушенное с AVS при запуске.

Существует простая фиксация к этой проблеме, включите предупреждения так, чтобы, если APP_B не определяется затем, Ваш проект не компилировал (или по крайней мере производит достаточно предупреждений так, чтобы Вы знали, что что-то неправильно).

1
ответ дан 8 December 2019 в 04:10
поделиться

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

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

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

0
ответ дан 8 December 2019 в 04:10
поделиться

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

Вместо -

#define APP_A 0
#define APP_B 1
#define APP_C 2

Использование -

#define APP_A() 0
#define APP_B() 1
#define APP_C() 2

И в том месте, где запрашиваются версии, -

#if APPLICATION >= APP_B()
// extra features for APPB and APP_C
#endif

(возможно, что-то сделать с APPLICATION в том же духе).

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

0
ответ дан 8 December 2019 в 04:10
поделиться

Посмотрите Современный дизайн C ++ Александреску . Он представляет разработку на основе политики с использованием шаблонов. По сути, этот подход является расширением шаблона стратегии, с той лишь разницей, что все выборы делаются во время компиляции. Я думаю, что подход Александреску похож на использование идиомы PIMPL, но реализуется с помощью шаблонов.

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

0
ответ дан 8 December 2019 в 04:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: