我偶然发现了一个 Stack Overflow 的问题:什么是差分执行?,其中有一个非常长并且详细的回答。虽然所有内容都很有道理... 但是当我看完后,我仍然不知道到底什么是差分执行。那它究竟是什么?
我偶然发现了一个 Stack Overflow 的问题:什么是差分执行?,其中有一个非常长并且详细的回答。虽然所有内容都很有道理... 但是当我看完后,我仍然不知道到底什么是差分执行。那它究竟是什么?
修改。这是我第N次尝试解释它。
假设您有一个简单的确定性过程,重复执行,始终按照相同的语句执行或过程调用顺序。 过程调用本身会按顺序将任何内容写入FIFO,并从FIFO的另一端读取相同数量的字节,如下所示:
初始执行在01模式下完成,因此仅进行写入操作。 过程调用可以看到模式,因此它们知道没有先前的历史记录。 如果他们想要创建对象,可以将标识信息放入FIFO中(无需存储在变量中)。
中间执行在11模式下完成,因此读写都会发生,并且过程调用可以检测数据更改。 如果有要保持更新的对象, 它们的标识信息从FIFO中读取和写入, 因此它们可以被访问并且必要时可以修改。
最终执行在10模式下完成,因此仅发生读取操作。 在该模式下,过程调用知道它们只是在清理。 如果存在任何正在维护的对象,则从FIFO中读取其标识符,并且可以将其删除。
它在图形用户界面中的使用是使一些控件或其他对象与程序状态信息保持一致。对于这种用途,三种模式分别称为SHOW(01),UPDATE(11)和ERASE(10)。 该过程最初在SHOW模式下执行,在此模式下创建控件,并填充与其相关的信息到FIFO。 然后,在UPDATE模式下进行任意数量的执行,必要时修改控件以保持与程序状态的同步。 最后,在ERASE模式下执行,其中从UI中删除控件,并清空FIFO。
这样做的好处是,一旦你编写了创建所有控件的程序过程,作为程序状态的函数,你就不必编写任何其他内容来保持其更新或清理。你不必写任何东西意味着减少犯错误的机会。(有一种简单的方法可以处理用户输入事件,而无需编写事件处理程序并为其创建名称。这在下面链接的其中一个视频中有解释。)(在这个示例中,更改的顺序与它们被执行的顺序相反,但这不是必要的。更改可以按任何顺序进行。)
请注意,始终包含Old和New连接在一起的FIFO恰好包含可见按钮的参数以及布尔值。
这个例子的目的是展示如何使用单个“绘制”过程,在不改变的情况下,进行任意自动增量更新和擦除。 希望清楚地表明它适用于任意深度的子程序调用和任意嵌套的条件语句,包括 switch、while 和 for 循环,调用基于指针的函数等。 如果我必须解释这一点,那么我愿意承受解释过于复杂的抨击。最后,在这里发布了几个简短而粗糙的视频。
** 从技术上讲,他们必须读取与上次写入的相同字节数。例如,他们可能已经写入了一个由字符计数前缀的字符串,这是可以接受的。
添加:我花了很长时间才确定这样做总是可行的,最终我证明了它。它基于一个名为同步的属性,大致意思是在程序的任何时刻,在上一遍写入的字节数等于下一遍读取的字节数。证明的想法是通过对程序长度进行归纳来完成的。最难证明的情况是程序部分由s1和IF(test)s2 ENDIF组成的情况,其中s1和s2是程序的子部分,每个部分都满足同步属性。仅用文本进行说明是枯燥无味的,但这里我尝试着用图表来解释:
它定义了Sync属性,并显示代码中每个点写入和读取的字节数,并显示它们相等。关键点是:1)在当前传递中读取的测试表达式(0或1)的值必须等于上一次传递中写入的值,2)满足Sync(s2)的条件。这满足了组合程序的Sync属性。在所有的示例中,
缺失的链接
发明者从未明确说明,但一个关键思想是,每当我们预计任何组合的布尔函数值B已更改时,我们都会在表示所有可能目标集合(屏幕)的程序上运行DSL解释器。解释器通过发出Add、Delete和Modify操作序列来处理使集合(屏幕)与新的B值一致的繁琐工作。
还有一个最终的隐藏假设:DSL解释器包括某种算法,可以根据当前运行期间执行的Creates历史记录提供Add和Modify操作的参数。在GUI上下文中,这是布局算法,而Create提示是布局提示。
关键点
该技术的强大之处在于DSL解释器封装了复杂性。一个愚蠢的解释器会从删除集合(屏幕)中的所有对象(小部件)开始,然后随着通过DSL程序的步骤看到每个创建命令,为每个命令添加一个新对象(小部件)。修改永远不会发生。
差分执行只是解释器的一种更聪明的策略。它相当于保持解释器上次执行的序列化记录。这是有道理的,因为记录捕捉到目前在屏幕上的内容。在当前运行期间,解释器查询记录以决定如何使用成本最低的操作实现目标集合(小部件配置)。这意味着永远不会删除一个对象(小部件),以后再添加它,成本为2。DE总是进行修改,成本为1。如果我们在某些情况下运行解释器时B值没有更改,那么DE算法将根本不生成任何操作:记录的流已经表示目标。
当解释器执行命令时,它还在为下一次运行设置记录。
类似的算法
该算法与最小编辑距离 (MED) 有相同的味道。然而,DE比MED更简单,因为在DE序列化执行字符串中没有"重复字符",而在MED中存在。这意味着我们可以使用直接的在线贪婪算法而不是动态规划找到最优解。这就是发明者的算法所做的事情。 优点 我认为这是一种实现具有许多复杂表单的系统的良好模式,在该模式中,您希望使用自己的布局算法和/或“if else”逻辑对微件的放置进行完全控制。如果在表单逻辑中存在K个“if elses”的N层嵌套,则需要正确地获取K * 2 ^ N个不同的布局。传统的表单设计系统(至少我使用过的那些)并不支持较大的K,N值。您往往会得到大量类似的布局以及难看且难以维护的特定逻辑来选择它们。这种DSL模式似乎可以避免所有这些问题。在具有足够多的表单以抵消DSL解释器成本的系统中,即使在初始实施期间,它也将更便宜。关注点分离也是一种优势。DSL程序抽象了表单的内容,而解释器则是布局策略,根据DSL提供的提示进行操作。正确获取DSL和布局提示设计似乎是一个重要且酷炫的问题。总结
发明者目前关注于解释器如何做出决策的深入细节。这很令人困惑,因为它是针对树而不是更重要的森林。这是对森林的描述。