图形语言中的面向对象编程

面向对象编程(OOP)是一个概念,旨在通过引入比功能和过程编程语言更接近现实世界的新概念来促进复杂系统的开发。 正如Wikipedia所写,“普通人类语言整体上反映了OOP的意识形态,从以对象的名称形式封装对象的概念开始,到以具象味的方式使用该单词的多态性,最终通过对象的名称将表示的表达发展为成熟的概念-类。”




但是,从最早接触到这些抽象的每个人的角度来看,在经典的程序语言之后,它并没有变得更加清晰,相反,它似乎仍然更加混乱。


另一方面,该程序有一些图形表示法,它们与人类的语言并不接近,但是比起任何代码,都比OOP更易于理解。 对我来说,这可能更容易被工程教育所破坏,但是像我这样的人很多,这本书是针对那些不了解高级抽象的被宠坏的物理学家的。


例如,以下是NPP闸阀控制算法的图形符号的真实描述:



图1. NPP控制程序示例的图形表示法

左边是输入信号,右边是命令。

在我看来,即使是孩子,也可以阅读这样的算法:

  • 如果打开泵60秒钟且流量小于10,则打开再循环阀。
  • 如果泵已打开,则发出命令在5秒内打开阀门001和002。
  • 如果流量大于20且泵已打开,则在5秒钟内向关闭阀003发送关闭命令。

当我还是学生的时候,我通过为Delphi创建组件库来兼职工作,并且对OOP有直接的了解。 然后,当我遇到真正的核电厂控制程序时,令我感到非常惊讶的是,没有抽象,封装,也没有多态性,只有纯C和MISRA C的建议被规则所限制,因此一切都是可靠 ,可移植,安全的。


在我的实践中,对于RBMK反应堆控制系统,C截止的峰值是FIL。 在其中,函数用C语言预先编写,编译,然后在文本文件的基础上调用,并在其中以FIL语言描述它们。 结果,仅可以调用有限但经过仔细测试和调试的一组函数。 所有这些都是以安全性和可靠性为名的。


但是同时,反应堆控制系统和NPP控制系统作为一个整体,只是应将OOP原理充分发挥其潜力。 实际上,有许多类似的设备-阀门,泵,传感器,所有东西都易于分类,有现成的对象对应于真实的设备。 似乎这里是-使用OOP,类,继承,抽象和多态。 但是不,您需要纯C语言,这是安全性要求。


然后-更加有趣。 实际上,管理核电站的程序不是由程序员编写的,而是由技术人员编写的-只有他知道什么时候以及什么时候关闭,打开,打开,最重要的是-他知道什么时候关闭独木舟以免崩溃。 并且程序员必须小心地用C代码实现所有这些。 甚至更好的是,根本没有程序员,技术人员本人以图形形式绘制了控制程序的技术算法,自动生成了C代码并将其加载到控制设备中。 国际安全标准建议这样做;在这种情况下,不需要像小提琴手那样的程序员。 他仅介绍了在实施技术专家的思想时出现的其他错误和变形。




当我发现NPP的技术人员和设计人员(独立于程序员之外)开发并成功使用了面向对象的程序设计,甚至是图形表示法时,我感到惊讶的是,所得到的代码完全满足安全性要求并且不包含OOP方法论的构件。 。


实际上,如果您看一下从图1中的电路生成的代码,我们将看到其中没有任何类的纯C。
例如,算法条目表:


/* Index=0 UID=0 GeneratorClassName=TSignalReader Name=KBA__AA.KBA31EY001.alg_inp Type=  */ state_vars->kbaalgsv0_out_1_ = kba31ap001_xb01; state_vars->kbaalgsv0_out_4_ = kba31cf001_xq01; 

只是分配变量。
考虑到常数列表中指定的参数,将任何块描述为通过输入计算输出。 例如,“更多”块在代码中如下所示:


 /* Index=5 UID=5 GeneratorClassName=TLogBlock Name=KBA__AA.KBA31EY001.smu.GT2 Type=  */ locals->v5_out_0_ = state_vars->kbaalgsv0_out_4_ > consts->kbaalgsv3_a_; 

块输出是将输入信号与常数值进行比较的结果。


因此,在其他块中,将顺序计算来自输入变量的局部变量,并在程序循环结束时将变量写入输出变量。


 /* Index=14 UID=14 GeneratorClassName=TSignalWriter Name=KBA__AA.KBA31EY001.alg_out Type=  */ if((action==f_InitState)||(action==f_GoodStep)||(action==f_RestoreOuts)){ kba31ey001_yb01 = locals->v8_out_0_; kba31ey001_yb11 = state_vars->kbaalgsv9_out_0_; kba31ey001_yb12 = state_vars->kbaalgsv12_out_0_; kba31ey001_yb02 = locals->v13_out_0_; }; 

您问这里的课程在哪里?


与OOP相关的整个方法都以变量名表示。 看来这可能是在变量名中? 而且可能有一个深渊。 例如,变量名称为kba31ap001_xb01,仅是C代码中满足变量名称要求的变量。 但是,对于设计工程师来说,它看起来像这样:“反应室,工业供水系统,第一台泵,启动”。 由于出色的德国编码系统(Kraftwerk-Kennzeichensystem)KKS,所有这些转换魔术发生了,引用:


“该编码分类系统是为发电厂设计的,具有巨大的潜力,并且还考虑了可自由编程的微处理器硬件的功能。


除了标记技术设备,执行机构(关闭,安全,关闭等阀门,辅助机构),测量点,安装单元,自动化设备,建筑物和结构外,KKS系统还可以标记各种算法和程序和目的(用于测量的技术参数,信号,自动调节,技术保护,逻辑控制的处理算法:锁,ABP,分步程序,-t的计算 hniko经济指标和技术设备的诊断),输入,输出和的算法和程序中间信号,各级录像显示在视频终端,电缆等......“


但是名称的最后一部分中最有趣的是_xb01 ,它是通过下划线指定的。 如果您查看管理项目的信号基础,那么我们将看到在那里对那些曾经对OOP感兴趣的每个人都可以理解和熟悉的类(见图2)。



图2.核电站控制系统的信号基础结构示例。

在图中,我们有类或表,这是“类别”列。 例如,“ KD1”具有模式信号表,类别“ 测量上限”,“测量下限”,“传感器读数 ”等字段。 是一个抽象。


还有一个此类的实现—特定的传感器,例如TK21F02B1,位于电路中,您可能会从其名称中猜出它位于“反应器室,工业供水系统中的第一个泵”中,并且这是流量传感器在此标题中,但不准确。


在程序执行过程中,此类的此类实例具有特定的信号及其值,并且可以通过此类的字段名称进行访问。 例如,变量TK21F02B1_XQ04指示传感器读数。


现在,我们可以说,等等,这根本不是OOP,甚至根本不是OOP,它只是一个数据结构,在标准C语言中。 类中方法的封装在哪里? 数据处理应该在该类中,这才是真正的Kosher OOP方法。
让我们看看传感器可靠性控制子例程以图形形式显示的样子。 图3是信号处理电路的一部分:



图3.信号处理程序的示例。

可以看出,在处理子程序中使用了变量名称TK21F02B1_XQ04,该变量名称是根据KKS规则并基于类字段表形成的。 在上面的示例中,根据TK21F02B1_Xmin和TK21F02B1_Xmax等类实例的字段的设置值,以TK21F02B1_XQ03百分比计算传感器读数。


如果我们看一下从该方案生成的代码,我们将看到一个简单的将值赋给变量的过程,即纯C,没有加号和OOP。


  /* Index=12 UID=12 GeneratorClassName=TSignalReader Name=KD1.kd3_45.SR6 Type=    */ state_vars->su100v12_out_0_ = tk21f02b1_ai; 

以及计算结果的分配,也可以作为变量的简单分配(检查数字的有效性,以便在信号处理结果中收到错误时,不会丢失系统)


 /* Index=100 UID=100 GeneratorClassName=TSignalWriter Name=KD1.kd3_45.SW3 Type=    */ if(isfinite(locals->v63_out_0_)){ tk21f02b1_xq04 = locals->v63_out_0_; }; 

在什么时候出现这些处理方法类的字段的并集? 实际上,我对此焦点很熟悉。 现在我们将分析其中之一。 ( 第二个选项在这里解析..
让我们看看在图中如何配置处理程序电路所在的块(见图4)。


我们有一个电路,在该电路上放置了图形编程语言子模型的块;在这些块内是一个图形电路,图3中显示了其中的一部分,该电路是用于处理来自传感器的信号的程序。


在该块的属性中,我们看到信号数据库的字段和一个下拉列表,其中包含数据库中已经存在的信号,类的实例,这种类型的特定传感器。 选择所需的传感器,按名称命名该类的一个实例就足够了,奇迹就发生了。 在该方案中,所有读写块都接收类型为TK21F02B1_XQ03的名称(类实例传感器名称+字段名称)。


现在,当生成C代码时,所有变量都将接收所需传感器的值。 而且不需要程序员,技术人员在用图形编程语言开发用于NPP控制算法的方案时,自己做了一切。



图4.设置传感器处理电路的示例。

为了分配名称,在控制系统设计环境中使用了一种特殊的自动化脚本,该脚本与图5大致相同。为图中的所有读取块分配了名称,这些名称包括对象名称和类中的字段名称(请参见图5)。



图5.在读取块中设置变量名称。

显然,可以类似的方式创建无限数量的信号处理选项,这实际上是OOP方法中该类的方法。 以相同的方式,可以为传感器形成它们,将其汇总显示在SCADA系统视频帧上,或者例如处理更改设置的过程。 图表以图形形式创建,另存为块并在必要时使用。


总结一下:在图形编程语言中,OOP方法也被使用并且是有益的。 并且在生成控制程序的源代码之后,OOP方法的所有工件都消失了,并且保持纯净,安全,可靠,经过验证的C。


显然,这种自动化工具的应用,除了加速开发之外,还可以大大减少开发时间,减少控制程序中的错误数量。

Source: https://habr.com/ru/post/zh-CN451148/


All Articles