1

我正在考虑重构一些非常复杂的代码,这是我正在工作的项目的子系统。我对这段代码的部分检查是它非常复杂,并且包含大量输入、中间值和输出,具体取决于某些核心业务逻辑。

我想重新设计这段代码,使其更易于维护,并且执行得更快,所以一开始我一直在尝试查看每个参数及其相互依赖关系。这导致了一个相当大而复杂的图,我想要一种简化这个图的机制。

不久前,我在一本名为“矩阵设计分解”的关于 SOA 设计的书中遇到了一种技术,它使用输出矩阵以及它们对输入的依赖关系,应用某种形式的矩阵代数,并且可以为这些依赖关系生成业务流程图.

我知道http://www.designdecomposition.com/上有一个可用的网络工具,但是它在您可以拥有的输入/输出依赖项的数量方面受到限制。我曾尝试四处寻找该工具的算法来源(因此我可以尝试自己实现它而不受大小限制),但是我没有运气。

有人知道我可以使用的类似技术吗?目前我什至正在考虑采用依赖矩阵并应用一些遗传算法来看看进化是否可以提出一个更简单的工作流程......

干杯,

艾多斯

编辑:

我将解释动机:

原始代码是为每次用户执行操作(添加、删除或修改项目的某些属性)时计算所有值(大约 60)的系统编写的。这段代码是十多年前写的,而且肯定显示出老化的迹象——其他人在系统中添加了更复杂的计算,现在我们得到了完全不合理的性能(在控制权返回给用户之前最多 2 分钟)。已决定将计算从用户操作中分离出来,并提供一个按钮来“重新计算”这些值。

我的问题出现了,因为有太多的计算正在进行,并且它们基于这样一个假设,即所有必需的数据都可用于计算 - 现在当我尝试重新实现计算时,我一直遇到问题,因为我没有'没有得到这个计算所依赖的不同计算的结果。

这是我想使用矩阵分解方法的地方。MD 方法允许我指定所有输入和输出,并为我提供可用于生成所有输出的“最简单”工作流程。

然后我可以使用这个“工作流程”来了解我需要执行的计算的优先级以获得相同的结果而不会产生任何异常。它还向我展示了我可以并行化计算系统的哪些部分以及分叉点和连接点的位置(我暂时不会担心那部分)。目前我所拥有的只是一个非常大的矩阵,其中显示了许多依赖项,不知道从哪里开始。

我将从我的评论中详细说明:

我不想在实际程序中使用 EA 流程中的解决方案。我想获取依赖矩阵并将其分解为模块,然后我将手动编码——这纯粹是一种设计辅助——我只是对这些模块的输入/输出感兴趣。基本上是这些计算之间复杂的相互依赖关系的表示,以及一些优先级的概念。

假设我有 A 需要 B 和 C。D 需要 A 和 E。F 需要 B、A 和 E,我想有效地将​​问题空间从一组复杂的依赖项划分为一个“工作流程”,我可以检查它以获得更好的理解。一旦我有了这种理解,我就可以提出一个更好的设计/实现,它仍然是人类可读的,所以对于这个例子,我知道我需要计算 A,然后是 C,然后是 D,​​然后是 F。

--

我知道这看起来有点奇怪,如果你看一下我在基于矩阵的分解之前链接到的网站,应该会让你对我的想法有所了解......

4

4 回答 4

2

kquinn,如果这是我认为他所指的那段代码(我曾经在那里工作过),它已经是一个没有人能理解的黑盒解决方案。他不想让它变得更复杂,事实上更少。他试图实现的是一大堆相互关联的计算。

目前发生的情况是,无论何时发生任何变化,都会引发大量事件,导致大量计算启动,进而导致更多事件继续发生,直到最终达到平衡状态。

我假设他想要做的是找到那些外围计算的依赖关系并从那里开始工作,这样它们就可以被重写并找到一种方法让计算发生,而不是因为他们需要。

关于简化图表,我无法提供太多建议,因为不幸的是,这不是我有太多经验的事情。也就是说,我会开始寻找那些没有依赖关系的离群计算,然后从那里遍历图表。开始构建一个新的框架,以最简单的方式包含每个计算的核心业务逻辑,并在此过程中重构其中的废话。

于 2009-04-30T08:14:38.357 回答
0

如果正如您所说,这是“核心业务逻辑”,那么您真的不想搞乱花哨的分解和进化算法,这些算法会产生世界上没有人理解或无法理解的“黑匣子”解决方案修改。如果这些技术中的任何一种实际上产生了任何有用的结果,我会感到非常惊讶。在解开复杂的关系方面,人脑的能力仍然比任何机器都要强大得多。

你要做的是传统的重构:清理各个过程,简化它们并在可能的情况下合并它们。你的目标是让代码清晰,这样你的继任者就不必经历同样的过程。

于 2009-04-30T06:20:08.430 回答
0

您使用什么语言?您的问题应该很容易使用 Java Executors 和 Future<> 任务建模,但是您选择的平台上可能也有类似的框架可用?

另外,如果我理解正确,您想为大量相互依赖的计算生成一条关键路径——这是动态完成的,还是您“只是”需要静态分析?

关于算法解决方案;拿起最接近您的数值分析教科书的副本,并刷新您对奇异值分解和 LU 分解的记忆;我从头顶猜测,这就是您链接到的工具背后的原因。

编辑:由于您使用的是 Java,我将简要概述一个建议:

-> 使用线程池执行器轻松并行化所有计算

-> 使用 Future<> 或 FutureTask<>:s 的对象映射解决相互依赖关系,即如果变量是 A、B 和 C,其中 A = B + C,请执行以下操作:

static final Map<String, FutureTask<Integer>> mapping = ...
static final ThreadPoolExecutor threadpool = ...
FutureTask<Integer> a = new FutureTask<Integer>(new Callable<Integer>() {
            public Integer call() {
               Integer b = mapping.get("B").get();
               Integer c = mapping.get("C").get();
               return b + c;
            }
        }
    );
FutureTask<Integer> b = new FutureTask<Integer>(...);
FutureTask<Integer> c = new FutureTask<Integer>(...);
map.put("A", a);
map.put("B", a);
map.put("C", a);
for ( FutureTask<Integer> task : map.values() )
      threadpool.execute(task);

现在,如果我还没有完全离开(我很可能已经离开了,因为我在 Java 中工作已经有一段时间了),你应该能够通过调整线程池大小来解决明显的死锁问题,或者使用增长的线程水池。(您仍然必须确保没有相互依赖的任务,例如如果 A = B + C 和 B = A + 1...)

于 2009-04-30T08:17:06.073 回答
0

如果黑盒是线性的,您可以通过简单地连接许多输入向量和许多输出向量来发现所有系数。

你有输入 x[i] 和输出 y[i],然后你创建一个矩阵 Y,其列是 y[0]、y[1]、... y[n],以及一个矩阵 X,其列是 x[ 0],x[1],...,x[n]。会有一个变换 Y = T * X,然后你可以确定 T = Y * inverse(X)。

但既然你说它很复杂,我敢打赌它不是线性的。然后,如果您仍然想要一个通用框架,您可以使用这个因子图

https://ieeexplore.ieee.org/document/910572

如果你能做到这一点,我会很好奇。

我认为更容易理解代码并使用最佳实践重写它。

于 2021-02-21T19:51:44.483 回答