打印

关于一个C语言模块间交互实现低耦合性的问题

[复制链接]
5893|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xuyh3307|  楼主 | 2010-9-26 21:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
模块间的耦合性就是指当修改其中某个模块时会影起其他模块运行结果发生不可预料的变化。如果模块间是通过直接调用对方内部的全局变量来实现交互,则两个模块间的耦合性将会变得复杂而且难以控制。而模块间的交互通过一个统一的接口函数来实现,使得模块都无需知道对方模块内部的具体实现(这也就是面向对象里面的封装)。当某个模块内的实现发生改写或升级时,只要确保模块接口不变即可。这就大大降低两模块间的耦合。在规划设计模块时就应认真考虑好模块的接口,以及与其他模块的调用关系。所以要记住编程原则:针对接口编程,而不是针对实现。

我的疑问是:如何构造这样的接口函数来取代全局变量式的交互?


                     如果仅仅是 #define GetCount()  (Count)
                                       #define SetCount(num) (Count=(num))
                                       #define ReloadCount() (Count=0)
                     Count 是全局变量——这样来实现交互,跟直接调用Count也没啥区别啊。

相关帖子

沙发
原野之狼| | 2010-9-26 22:29 | 只看该作者
确实是一回事
楼主可以找本软件工程的书看看先

使用特权

评论回复
板凳
HWM| | 2010-9-26 22:53 | 只看该作者
此类用法必须在C++环境下使用,其变量也不是全局变量,而是对象的成员变量。

给一例:

class A
{
    int X;

public:

    set_X(int X0) { X = X0; };
    int get_X { return X; };

};

使用特权

评论回复
地板
xuyh3307|  楼主 | 2010-9-27 06:37 | 只看该作者
3# HWM
将X的类型和行为整合到一个Class里面,
这就是面向对象里所谓的封装啊?
看来我得好好学学什么是面向对象了。

使用特权

评论回复
5
HWM| | 2010-9-27 08:34 | 只看该作者
to 4L:

模快设计就是要将某一功能或对象封装起来,没有封装便没有模快,也就无低藕合性之说。通常除特殊情况外,尽量少用全局变量。若真要用,必须有明确的含义和使用规则,决不能用它来作为模快间传递信息的渠道(OS中的某些特殊情况除外)。

使用特权

评论回复
6
fzu_csc| | 2010-9-27 08:47 | 只看该作者
全局变量也有全局变量的好处,毕竟传递参数是需要堆栈和时间消耗的。

使用特权

评论回复
7
HWM| | 2010-9-27 08:57 | 只看该作者
to 6L:

利用公共存储空间传输信息,必须规范好各模快的行为准则。否则伴随着所谓效率而来的是混乱。因此说,除非必须计较那么点效率,否则尽量使用“接口”渠道。

使用特权

评论回复
8
john_light| | 2010-9-27 10:20 | 只看该作者
C++方法只是这种需求的一个实现,非必须。

使用特权

评论回复
9
batsong| | 2010-9-27 13:53 | 只看该作者
我认为底层没什么区别,只是访问权限更严格一点,如果程序员有能力管理全局变量,全局变量当然更好

使用特权

评论回复
10
john_light| | 2010-9-27 14:29 | 只看该作者
尽可能不使用全局变量之类。

编程除了实现功能之外还要考虑不安全的因素,犹如建桥时要在两边筑起栏杆。
你要想到这条桥不止你一个人在走,你也不止走这几天。
你水平高超,走的稳健,别人认识有欠缺,TA就很容易掉下去。
你现在水平高超,过些时日难免老眼昏花,也有机会掉下去。

使用特权

评论回复
评分
参与人数 1威望 +2 收起 理由
原野之狼 + 2 我很赞同
11
john_light| | 2010-9-27 14:48 | 只看该作者
本帖最后由 john_light 于 2010-9-30 15:26 编辑

举一个不一定恰当的例子,有某个量CalcRlt只能由某个功能模块CalcFunc计算得出,其他地方需要读取使用该量。

static unsigned int CalcRlt;

void CalcFunc(void)
{
    ...
    CalcRlt = ...;
    ...
}
我们可以考虑定义一个函数CalcRltGet读取该值。

unsigned int CalcRltGet(void)
{
    return CalcRlt;
}
这样,CalcRlt被我们制作成一个只读的量,菜鸟同事或老眼昏花的我们都不大会意外写入CalcRlt。
如果把CalcRlt声明成一个全局变量,就存在隐患。

使用特权

评论回复
12
xuyh3307|  楼主 | 2010-9-27 20:13 | 只看该作者
11# john_light
当然,我也希望每个函数都能写成这样的形式。
只是就算都能构造成这种样子,有时也会很难避免全局变量在各个模块间来回穿梭呵呵。
其实有时发现模块——尤其是应用程序方面的模块划分也是一件很麻烦的事。
水平有限啊,
前辈们多多指点了。

使用特权

评论回复
13
highgear| | 2010-9-27 20:54 | 只看该作者
当你意识到C语言变量耦合的问题时, 意味着你对程序已经逐渐的失去了控制, 也说明你的程序大到了一定的规模。这时候到了该使用 c++ 来解决此类问题, 或者是把封装,多态等概念应用到 c 里来缓解这种症状。最好的封装例子就是 windows api, 提供了 8000 到 14000 个函数, 没有一个变量。

使用特权

评论回复
14
HWM| | 2010-9-28 08:28 | 只看该作者
to 12L:

建议找本《软件工程》或《模块化结构程序设计》之类的书看看,内有相关的内容。摸块化设计不是一下子就把所有的模块细节都设计出来的,通常是根据系统分析给出大致的几个粗框,然后在逐步细化。这称之为由顶向下的设计方法。通常依此会得到一个模块的层次结构——即大模块由数个小模块组成(以此类推)。最终会得到一个树状的结构关系。自然的会发现此层次结构中的同层间原则上没有联系,而只是上下层间的调用和传输关系,这就是我们所需要的模块化层次结构。摸块化设计也可以由底向上的设计途经,那是个积累过程,通常的库系统就是这样累积而成的。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

18

帖子

1

粉丝