重构大型事例语句、外部语句、静态局部语句
Refactoring large case statement, externs, static locals
我正在尝试进行一些重构,并希望找出最佳的前进道路。
我有
myonce{
static int i //for operation 1
switch(commandid) {
case 1: operation 1
i = 1;
...
其中myonce是在循环中调用的函数。这不是我的代码,我正在努力让它变得更好。操作1(或每种情况)是一系列命令,我想把它们放在自己的翻译单元中(每个文件一个函数)。
由于myonce在循环中运行,原始作者有许多静态变量用于保持状态,其中一些状态集用于多个操作。请注意,这些不是静态文件范围,而是静态块范围。
为了简单起见,作为概念的证明,我想知道以下是否可行。考虑使用1组静态变量的1个操作。
main.cpp
myonce {
static int i //for op 1
switch(commandid) {
case 1: operation1();
operation1.cpp
extern int i;
void operation1() {
i = 1;
}
在多个操作使用相同的状态集的情况下,我会制作一个标头来声明它们都是外部的。
目前,这个文件的编译是以分钟为单位的,我的第一个目标是将它分解成更小的编译单元,以便作者可以更自由地工作。这种重构需要很长时间,但我提到这一点是为了解释我使用这种方法的动机。
我知道其他翻译单元(其他文件中的extern)无法访问静态文件范围变量,所以我想区分一下,我处理的不是这种情况。我现在不知道的是,我应该在哪里向main声明operation1(),它应该是吗
static int i
extern void operation1();
那么int被声明为对函数可见?
如果能在这方面提出任何建议,我将不胜感激。谢谢
将状态变量放入一个结构中。将此结构传递给每个函数。
示例。
// foo.h
struct TheState
{
int x;
char *y;
// ...
};
void func1(TheState &);
void func2(TheState &);
// main.cc
#include "foo.h"
void main_loop()
{
TheState the_state; // initialize this however you want
for (;;)
{
if ( blah) func1(the_state);
else func2(the_state);
}
}
// func1.cc
#include "foo.h"
void func1(TheState &the_state)
{
++the_state.x;
}
不,你不能那样做。static
对象在其他源文件中永远不可见。
你的switch
有多大?修改它的原因是什么?
也许最初的程序员有充分的理由使用局部静态变量?您说它是在循环中调用的,一些静态变量用于保持从一次迭代到下一次迭代的状态,在交换机的分支之间共享。这当然是一种奇怪的代码结构方式。我可以考虑做这样的事情来运行某种有限自动机,但在这种情况下,我会将自动机写成每个状态的一系列代码片段,并通过直接的goto
s在它们之间传输。我会使确定在某个非常接近的地方,以更可读的形式对自动机进行描述。
但我可能完全偏离了底线。你能分享更多关于这个代码的功能吗?
首先,开关通常可以通过使用其函数创建更好的数据结构来避免(例如,具有虚拟成员函数command
的类,其实现做了正确的事情)。
在一个不那么雄心勃勃的级别上,您可以将特定情况下所需的静态指针传递给函数,以便它可以读取和修改这些变量的状态。
根据函数的作用,还可以将状态信息作为值参数(副本)传递,让函数根据该状态进行工作,接收结果,然后根据结果更改主开关中的全局状态。然后状态变化是清晰可见的(即功能中没有副作用),并且嘈杂的分散注意力的细节被禁止进入另一个文件。
如果每种情况都倾向于使用许多静态变量,那么您可以将它们全部放在一个结构中;这种改变应该可以通过文本编辑器实现(用mystruct.x等替换变量名x)。然后每个函数只获得一个指向该结构的指针。编辑:正如我在评论中所说:也许命令自然地形成了只与状态的一部分有关的组(例如,有些命令只读取,其他命令只写入数据等)。然后,全局状态可以划分为相应的数据组。每个函数只能查看与其相关的数据组,这限制了潜在的副作用。
但总的来说,随着时间的推移,现在的功能似乎设计/发展得很糟糕;处理一大组静态变量意味着在代码中到处都有"副作用"——很难看出代码的任何给定部分是做什么的,以及它是如何与其他部分交互的。信息流并不明确。即使没有任何虚拟成员函数,分析属于一起的数据集群、将它们组织在类中并将它们分离在文件中也是一项任务。
至于您的最后一个问题:您创建的"case函数"(operation1();
等)只需要在调用它们的文件中已知即可。如果它们在一个或多个单独的文件中,则应该创建一个包含原型的标头。
- 我的简单if-else语句是如何无法访问的代码
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- 为什么是0;C++中的有效语句
- 在函数内部的声明中初始化数组,并在外部使用它
- Insert函数不适用于2 if语句C++
- If语句未被求值C++
- C++嵌套if语句,基本货币交换
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 是否可以使用if constexpr删除控制流语句
- 使外部项目可用于find_package CMake
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- 如何在开关语句(C )内或外部使用IF语句
- C# 读取完全锁定的文本文件或读取 if 语句外部的输出
- 如何访问在 if 语句内、外部创建的指针
- 包括外部包括警卫的语句
- C++ 嵌套'if'语句中的所有代码都会运行,即使这会更改外部语句的布尔值?
- C++字符串在if语句外部消失
- 重构大型事例语句、外部语句、静态局部语句
- 如何使用 break 语句停止内部和外部循环