打破”信息茧房“:以耦合的视角读《编程风格指南》

已锁定

'Razor

西门子1847工业学习平台

  • 帖子

    3208
  • 精华

    41
  • 被关注

    222

论坛等级:至圣

注册时间:2008-03-31

钻石 钻石 如何晋级?

打破”信息茧房“:以耦合的视角读《编程风格指南》

1425

4

2025-02-11 16:18:06

    《编程指南》指的是全球资源库中的

ID109478084_Programming_Styleguide_DOC_v20_CN.PDF

ID81318674_Programming_Styleguide_DOC_v20_EN.PDF

两份文档,在文档中有几条内容是和“耦合”联系密切的,在此详细说明一下。


    提及“耦合”(Coupling)则必提“内聚”(Cohesion),这就像一枚硬币的两面一样。


    耦合和内聚的概念,有着悠久的历史,在传统文化中有很多它们的身影;要是从西方的软件工程溯源的话,早在20世纪60年代,结构化编程强调代码的逻辑清晰和可维护性,推动了模块化设计的发展。模块化要求将系统分解为独立的功能单元(模块),而内聚与耦合成为衡量模块设计质量的核心指标。概念最早由软件工程先驱Larry Constantine提出,并于1968年正式确立。


    1974年,一些学者在论文《Structured Design》中系统化提出了模块内聚与耦合的分类标准,奠定了现代软件设计的基础。强调模块应具备“高内聚(即模块内部应该高度协作)、低耦合(却模块间应尽量减少依赖)”的特性以提升系统可维护性。


    一句话,耦合和内聚的概念已经是存在了很久很久,没有什么好神秘的,更没有什么好炫耀的。


    耦合可以分为七种,按耦合度从高到低排列如下:   

一、内容耦合

二、公共耦合

三、外部耦合

四、控制耦合

五、标记耦合

六、数据耦合

七、非直接耦合


而指南中,有对应的相关细则,只是指南并没有说它是哪种耦合。

-----------------------------------------------------------------------------

1、内容耦合

一个模块直接访问另一模块的内容,则称这两个模块为内容耦合。

若在程序中出现下列情况之一,则说明两个模块之间发生了内容耦合:

1)一个模块直接访问另一个模块的内部数据。

2)一个模块不通过正常入口而直接转入到另一个模块的内部。

3)两个模块有一部分代码重叠(该部分代码具有一定的独立功能)。

4)一个模块有多个入口。


指南内容:

DA006 规则: 仅从块内访问静态变量
函数块的静态数据只能在声明它们的块内使用。
说明: 通过直接访问实例的静态变量, 兼容性无法保证, 因为将来的更新会影响到
相应的访问。 此外, 静态变量的修改对 FB 执行的影响无法判断。


说明,这种耦合度最强,上面1)和2)结合起来则对应了《指南》中的DA006,静态变量的直接访问,是需要格外规避的,也是不推荐的。

-----------------------------------------------------------------------------

2、公共耦合

一组模块都访问同一个全局数据结构,则称之为公共耦合。

公共数据环境可以是全局数据结构、共享的通信区、内存的公共覆盖区等。如果模块只是向公共数据环境写数据,或是只从公共数据环境读数据,这属于比较松散的公共耦合;如果模块既向公共数据环境写数据又从公共数据环境读数据,这属于比较紧密的公共耦合。

公共耦合会引起以下问题:

1)无法控制各个模块对公共数据的读写,严重影响了程序模块的可靠性和适应性。

2)使程序的可维护性变差。若一个模块修改了公共数据,则会影响相关模块。

3)降低了程序的可理解性。不容易清楚知道哪些数据被哪些模块所共享,排错困难。

一般地,仅当模块间共享的数据很多且通过参数参数很不方便时,才使用公共耦合。


指南内容:

RU004 规则: 只使用局部变量
在可重用块中, 只能使用局部变量, 不允许从 FC 或 FB 内访问全局数据。 全局数据可以通过块接口的形参传入。
RU005 规则: 使用本地符号常量
为了进一步封装块, 可以使用局部常量。 当需要使用全局常量时, 必须通过块接口的形参将它们传递到块中。 全局常量应在其自身的 PLC 变量表中定义。

说明:论坛中昵称为“宝冬”的朋友发的帖子中,对在HMI/SCADA等UI上的操作,便抽象为了read()和write()两部分,可说是很妙。

如何解决公共耦合的问题,那是另一个话题,以待后述。

-----------------------------------------------------------------------------

3、外部耦合

一组模块都访问同一全局简单变量,而且不通过参数表传递该全局变量的信息,则称为外部耦合。


指南内容参见上一条,这两种耦合有部分共同点。

-----------------------------------------------------------------------------

4、控制耦合

模块之间传递的不是数据信息,而是控制信息例如标志、开关量等,一个模块控制了另一个模块的功能。


指南内容:

PE005 建议: 避免形参 “mode”
避免开发根据输入参数(例如“mode”) 操作不同功能的块。
说明: 这可以防止不需要的代码片段(“死代码”), 因为模式参数通常是静态连接的。
相反, 您应该将不同功能分到不同的程序块:
? 这减少了内存消耗, 并通过减少代码来提高性能
? 它通过更好的区分和更好的命名来增加可读性
? 它通过更小的代码片段来增加可维护性, 这些代码片段彼此独立

-----------------------------------------------------------------------------

5、标记耦合

调用模块和被调用模块之间传递数据结构而不是简单数据,同时也称作特征耦合。表示模块间传递的不是简单变量,而是像高级语言中的数据名、记录名和文件名等结果,这些名字即为标记,其实传递的是地址。


指南内容:

PE003 建议: 使用引用传递结构化参数
为了保证最大性能(内存和运行最佳) 的将数据传递到块接口的形参中, 建议使用“按引用调用”模式。
说明:调用块时, 将传递对实际参数的引用, 不复制实际参数。
注意: 使用这种方法,可以修改原始数据。
在调用块时,如果将优化的数据传递给禁用了“优化的块访问”属性的块(反之亦然), 则该数据总是作为复制进行传递。 如果块包含许多结构化参数, 这会导致块的临时内存区域溢出。 您可以通过为两个块设置“优化”访问类型来避免这种情况。


说明:详见相关文档“传址”部分说明。

另外,现在的TIA Portal平台中有了REF_TO数据类型,在接口区的”数据类型“下的清单中已经有了REF_TO_BLOCK_FB和REF_TO_BLOCK_FC,还有引用的其它类型,相信不久便可以真的使用了。到时,给程序设计带来的将是更大的便利和快捷。

-----------------------------------------------------------------------------

6、数据耦合

调用模块和被调用模块之间只传递简单的数据项参数。相当于高级语言中的值传递。


说明:详见相关文档“传值”部分说明。

-----------------------------------------------------------------------------

7、非直接耦合

两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的。耦合度最弱,模块独立性最强。

-----------------------------------------------------------------------------

结束语:

    上文中耦合的分类引用自网络内容,同样“内聚”也可以系统地细分为种,在此不多言,感兴趣者可以自行搜索,同样在相关书籍中也有详细描述。至于和《指南》中的相关内容是否能够完全对应地起来,纯属个人观点,仅供参考


    OO-面向对象不是万灵丹,更不是救命草,从OOA到OOD到OOP,人,才是起关键作用的主体,其它皆是工具。



    

-----------------------------------------------------------------------------


    

打破”信息茧房“:以耦合的视角读《编程风格指南》 已锁定
编辑推荐: 关闭

请填写推广理由:

本版热门话题

SIMATIC S7-1200系列

共有15100条技术帖

相关推荐

热门标签

相关帖子推荐

guzhang

恭喜,你发布的帖子

评为精华帖!

快扫描右侧二维码晒一晒吧!

再发帖或跟帖交流2条,就能晋升VIP啦!开启更多专属权限!

  • 分享

  • 只看
    楼主

top
您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。