Утверждает для ловли чего-то, что разработчик сделал неправильно (не только самостоятельно - другой разработчик в Вашей команде также). Если разумно, что пользовательская ошибка могла создать это условие, то это должно быть исключение.
Аналогично думают о последствиях. Утверждение обычно закрывает приложение. Если существует реалистическое ожидание, что условие могло быть восстановлено с, необходимо, вероятно, использовать исключение.
, С другой стороны, если проблема может только произойти из-за ошибки программиста затем используют утверждение, потому что Вы хотите знать об этом как можно скорее. Исключение могло бы быть поймано и обработано, и Вы никогда не будете узнавать об этом. И да, необходимо отключить, утверждает в коде выпуска, потому что там Вы хотите, чтобы приложение восстановилось, если существует малейший шанс, это могло бы. Даже если состояние Вашей программы глубоко повреждается, пользователь просто смог сохранять их работу.
Вы можете использовать элемент [id $ = Идентификатор], который ищет идентификатор, заканчивающийся указанным вами текстом (это идентификатор, который вы указываете в разметке ASPX). Вот пример, показывающий, как вы можете его использовать (см. Слайд № 30): Создание приложений интрасети с помощью ASP.NET AJAX и jQuery .
без фреймворка это может наложить некоторую ответственность на клиентский код. Но это действительно помогает тестированию. Например, для проверки FSW_taskStart ()
tThreadConfig threadConfig[NUM_THREADS] = {
{ "Foo 1", %foo1, 0, ... },
{ "Foo 2", %foo2, 0, ... },
{ "Task", %task, 0, ... }
};
void FSW_taskStart(tThreadConfig configs[], size_t len) {
for (int i = 0; i < len; i++) {
configs[i].taskptr->createThread( );
}
}
void FSW_taskStart() {
FSW_taskStart(tThreadConfig, NUM_THREADS);
}
void testFSW_taskStart() {
MockTask foo1, foo2, foo3;
tThreadConfig mocks[3] = {
{ "Foo 1", &foo1, 0, ... },
{ "Foo 2", &foo2, 0, ... },
{ "Task", &foo3, 0, ... }
};
FSW_taskStart(mocks, 3);
assert(foo1.started);
assert(foo2.started);
assert(foo3.started);
}
Теперь вы можете передать фиктивную версию ваших потоков в 'FSW_taskStart', чтобы убедиться, что функция действительно запускает потоки по мере необходимости. К сожалению, вы должны полагаться на тот факт, что исходный FSW_taskStart
передает правильные аргументы, но теперь вы тестируете гораздо больше своего кода.
Вы можете выделить память с помощью malloc, а затем получить новый оператор для создания объекта в этой позиции
void* mem = malloc(3*sizeof(SomeClass));
SomeClass *a = new(mem) SomeClass();
mem += sizeof(SomeClass);
SomeClass *b = new(mem) SomeClass();
mem += sizeof(SomeClass);
SomeClass *c = new(mem) SomeClass();
, чтобы вы могли выделить всю память, а затем распределить ее по своему усмотрению. Примечание: убедитесь, что вы вызываете деконструкцию вручную, как это не происходит при вызове delete
Поможет ли внедрение зависимостей в вашей ситуации? Это может избавить от всех глобальных переменных и позволить легко заменять зависимости в ваших модульных тестах.
Каждой основной функции потока передается карта, содержащая зависимости (драйверы, почтовые ящики и т. Д.), И они сохраняются в классах, которые будут использовать их (вместо доступа к какой-то глобальной переменной).
Для каждой среды (цель, симулятор, модульный тест ...) вы создаете одну функцию "конфигурации", которая создает все необходимые объекты, драйверы и все потоки, предоставляя потокам их список зависимостей. Например, целевая конфигурация может создать драйвер USB и внедрить его в некоторый поток связи, в то время как конфигурация модульного теста связи может создать заглушку драйвера USB, которую контролируют тесты.
Если вам абсолютно необходима эта «прозрачность» для важной переменной , создайте для них классы, которые будут хранить их по известным адресам, и внедрить эти классы там, где это необходимо.
Это немного больше работы, чем статические списки объектов, но гибкость фантастическая, особенно когда вы сталкиваетесь с некоторой сложной интеграцией проблемы и хочу поменять местами компоненты для тестирования.
Примерно:
// Config specific to one target.
void configure_for_target_blah(System_config& cfg)
{ // create drivers
cfg.drivers.push_back("USB", new USB_driver(...))
// create threads
Thread_cfg t;
t.main = comms_main; // main function for that thread
t.drivers += "USB"; // List of driver names to pass as dependencies
cfg.threads += t;
}
// Main function for the comms thread.
void comms_main(Thread_config& cfg)
{
USB_driver* usb = cfg.get_driver("USB");
// check for null, then store it and use it...
}
// Same main for all configs.
int main()
{
System_config& cfg;
configure_for_target_blah(cfg);
//for each cfg.drivers
// initialise driver
//for each cfg.threads
// create_thread with the given main, and pass a Thread_config with dependencies
}