在编程过程当中,我时常会感到自己的代码存在问题,却又说不上究竟是什么。最近在读《代码大全》,读到代码耦合度的部分,发现里面提到的一些问题,正是自己隐隐约约觉得自己的代码有缺陷的地方。我打算结合书中的内容,重新审视下自己的代码中的不足之处,并且记录下来。
高能预警:下面的文字中会包含可能引起读者不适的内容。对于有代码洁癖的读者,这种不适感会极为强烈,请不要继续阅读;未成年人请在家长的陪同下观看。
The most insidious kind of coupling occurs when one module makes use not of some syntactic element of another module but of some semantic knowledge of another module’s inner workings. Here are some examples:
- Module1 passes a control flag to Module2 that tells Module2 what to do. This approach requires Module1 to make assumptions about the internal workings of Module2, namely what Module2 is going to do with the control flag. If Module2 defines a specific data type for the control flag (enumerated type or object), this usage is probably OK.
——Chapter 5: Design in Construction
这段话使我想起了自己的一个接口设计。需求是这样的:根据当前对某项业务的操作,取得该业务的一些属性,并返回与状态相关的提示文本。
我的解决方案是,设计一个文本表用来存放提示文本:
字段名 |
类型 |
是否为主键 |
描述 |
Transaction |
CHAR4 |
是 |
表示业务类型的代码 |
Status |
固定值N或U或C |
是 |
表示现有的3种业务状态 |
Text |
CHAR255 |
否 |
需要输出的文本 |
在接口ZMKT_GET_MSG中指定业务唯一标识、状态码:
输入参数 |
|
GUID |
全球唯一标识符 |
Status |
表示现有的3种业务状态 |
输出参数 |
|
Text |
与状态相关的提示文本 |
Attributes |
查询到的业务属性 |
现在看来,这种设计是存在问题的。因为调用者必须了解Status的值的意义才能使用它。需要把这种信息隐藏起来,在内部处理。
还有一个我犯过的错误:
-
Module2 uses global data after the global data has been modified by Module1. This approach requires Module2 to assume that Module1 has modified the data in the ways Module2 needs it to be modified, and that Module1 has been called at the right time.
在ABAP代码中,这似乎是一种常见现象。一个report中会有很多子程序使用using或changing关键字来对全局数据进行引用传递,并且进行修改操作。当程序规模较小的时候,这种情况还可以接受。但程序规模较大的情况下,应该警惕在这种情况下可能产生的问题。特别是,如果一个程序中包含着不同来源的代码时,如果不能有效地隔离数据,这些代码很容易因为微小的改动造成连锁影响,比如在某些增强代码中。