c – 避免嵌入式编程中的全局变量

前端之家收集整理的这篇文章主要介绍了c – 避免嵌入式编程中的全局变量前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在我所涉及的嵌入式编程类型中,运行代码的确定性和透明性受到高度重视.我透露的意思是,例如,能够查看内存的任意部分并知道存储的变量.因此,正如我确信嵌入式程序员所期望的那样,如果可能的话,应该避免使用new,如果无法避免,则仅限于初始化.

我理解这种需要,但不同意我的同事这样做的方式,也不知道更好的选择.

我们拥有几个全局结构数组和一些全局类.有一个用于互斥锁的结构数组,一个用于信号量,一个用于消息队列(这些是在main中初始化的).对于每个运行的线程,拥有它的类是全局变量.

我遇到的最大问题是单元测试.当我想测试的类#includes全局变量时,我如何插入模拟对象?

这是伪代码的情况:

foo.h中

  1. #include "Task.h"
  2. class Foo : Task {
  3. public:
  4. Foo(int n);
  5. ~Foo();
  6. doStuff();
  7. private:
  8. // copy and assignment operators here
  9. }

bar.h

  1. #include <pthread.h>
  2. #include "Task.h"
  3.  
  4. enum threadIndex { THREAD1 THREAD2 NUM_THREADS };
  5. struct tThreadConfig {
  6. char *name,Task *taskptr,pthread_t threadId,...
  7. };
  8. void startTasks();

bar.cpp

  1. #include "Foo.h"
  2.  
  3. Foo foo1(42);
  4. Foo foo2(1337);
  5. Task task(7331);
  6.  
  7. tThreadConfig threadConfig[NUM_THREADS] = {
  8. { "Foo 1",&foo1,... },{ "Foo 2",&foo2,{ "Task",&task,... }
  9. };
  10.  
  11. void FSW_taskStart() {
  12. for (int i = 0; i < NUMBER_OF_TASKS; i++) {
  13. threadConfig[i].taskptr->createThread( );
  14. }
  15. }

如果我想要更多或更少的任务怎么办? foo1的构造函数中有一组不同的参数?我想我必须有一个单独的bar.h和bar.cpp,这似乎比必要的工作要多得多.

解决方法

如果你想先对这些代码进行单元测试,我建议你阅读 Working Effectively With Legacy Code另见 this.

基本上使用链接器插入模拟/伪对象和函数应该是最后的手段,但仍然是完全有效的.

但是,您也可以使用控制反转,如果没有框架,这可能会对客户端代码产生一些责任.但它确实有助于测试.例如,测试FSW_taskStart()

  1. tThreadConfig threadConfig[NUM_THREADS] = {
  2. { "Foo 1",%foo1,%foo2,%task,... }
  3. };
  4.  
  5. void FSW_taskStart(tThreadConfig configs[],size_t len) {
  6. for (int i = 0; i < len; i++) {
  7. configs[i].taskptr->createThread( );
  8. }
  9. }
  10.  
  11. void FSW_taskStart() {
  12. FSW_taskStart(tThreadConfig,NUM_THREADS);
  13. }
  14.  
  15. void testFSW_taskStart() {
  16. MockTask foo1,foo2,foo3;
  17. tThreadConfig mocks[3] = {
  18. { "Foo 1",&foo3,... }
  19. };
  20. FSW_taskStart(mocks,3);
  21. assert(foo1.started);
  22. assert(foo2.started);
  23. assert(foo3.started);
  24. }

现在你可以将你的线程的模拟版本传递给’FSW_taskStart’,以确保该函数确实根据需要启动线程.不幸的是,您必须依赖原始FSW_taskStart传递正确参数的事实,但您现在正在测试更多代码.

猜你在找的C&C++相关文章